فهرست منبع

完成薪资管理跟我的薪资

@sun-chaoqun 2 سال پیش
والد
کامیت
2ece02671b

+ 2 - 0
components.d.ts

@@ -21,6 +21,8 @@ declare module '@vue/runtime-core' {
     ElCol: typeof import('element-plus/es')['ElCol']
     ElContainer: typeof import('element-plus/es')['ElContainer']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
+    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
+    ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
     ElDropdown: typeof import('element-plus/es')['ElDropdown']

+ 1 - 1
src/api/salary/index.ts

@@ -12,4 +12,4 @@ export const Salary_Send = (params: any) => $http.post('/api/salary/Salary/Send'
 // 添加
 export const Salary_Post = (params: any) => $http.post('/api/salary/Salary/Post', params)
 // 导出Excel
-export const Salary_Excel = (params: any) => $http.post('/api/salary/Salary/Excel', params)
+export const Salary_Excel = (params?: any) => $http.post('/api/salary/Salary/Excel', params)

+ 2 - 2
src/components/TableBase/index.scss

@@ -1,7 +1,7 @@
 .table-header {
   background-color: #fff;
   height: 5rem;
-  margin-bottom: 1rem;
+  margin-bottom: 0.75rem;
   border: 1px solid var(--el-border-color-light);
   border-radius: 4px;
   padding: 20px;
@@ -16,7 +16,7 @@
 }
 
 .card {
-  height: calc(100% - 5rem - 1rem);
+  height: calc(100% - 5rem - 0.75rem);
   box-sizing: border-box;
   padding: 20px;
   overflow-x: hidden;

+ 6 - 3
src/components/TableBase/index.vue

@@ -16,7 +16,6 @@ interface ProTableProps extends Partial<Omit<TableProps<any>, 'data'>> {
   border?: boolean // 是否带有纵向边框 ==> 非必传(默认为true)
   toolButton?: boolean // 是否显示表格功能按钮 ==> 非必传(默认为true)
   selectId?: string // 当表格数据多选时,所指定的 id ==> 非必传(默认为 id)
-  // searchCol?: number | Record<BreakPoint, number> // 表格搜索项 每列占比配置 ==> 非必传 { xs: 1, sm: 2, md: 2, lg: 3, xl: 4 }
 }
 
 // 接受父组件参数,配置默认值
@@ -30,7 +29,6 @@ const props = withDefaults(defineProps<ProTableProps>(), {
   selectId: 'id',
   searchCol: () => ({ xs: 1, sm: 2, md: 2, lg: 3, xl: 4 })
 })
-// console.log(props)
 
 // 表格操作 Hooks
 const {
@@ -88,7 +86,12 @@ defineExpose({
         >
           <slot v-if="item.fixed" :name="item.fixed" :row="scope.row"></slot>
         </el-table-column>
-        <el-table-column v-bind="item" :align="item.align ?? 'center'" v-if="item.name === item.prop" v-slot="scope">
+        <el-table-column
+          v-bind="item"
+          :align="item.align ?? 'center'"
+          v-if="item.name === item.prop && item.type !== 'index'"
+          v-slot="scope"
+        >
           <slot :name="item.prop" :row="scope.row"></slot>
         </el-table-column>
       </template>

+ 1 - 1
src/router/modules/staticRouter.ts

@@ -39,7 +39,7 @@ export const staticRouter: RouteRecordRaw[] = [
       {
         path: '/salary',
         name: 'Salary',
-        component: () => import('@/views/salary/Salary.vue'),
+        component: () => import('@/views/salary/salary/Salary.vue'),
         meta: {
           title: '薪资管理'
         }

+ 0 - 1
src/views/account/roles/Roles.vue

@@ -54,7 +54,6 @@ const getMenuList = async (code: string) => {
   // User_Power_Get
   const res: any = await User_Power_Get({ User_tokey: globalStore.GET_User_tokey, T_code: code, T_id: currentVal.T_id })
   const sys = SysList.value.find(item => item.T_sys === code) as InSys
-  console.log(res)
   sys.children = res.Data.Menu[0].Children
   if (res.Data.Menu_checked) {
     sys.checkList = sys.children.map((m: any) => {

+ 0 - 1
src/views/account/users/components/DrawerFrom.vue

@@ -90,7 +90,6 @@ const AddUser = (formEl: FormInstance | undefined) => {
         })
       }
     } else {
-      console.log('error submit!')
       return false
     }
   })

+ 190 - 5
src/views/salary/SalaryCount.vue

@@ -1,13 +1,198 @@
 <script setup lang="ts">
+import { ref, reactive } from 'vue'
+import type { TableColumnCtx } from 'element-plus'
+import { Salary_List, Salary_Send, Salary_Excel } from '@/api/salary/index'
+import { ElMessage } from 'element-plus'
+let date = new Date()
+const year = date.getFullYear()
+const month = date.getMonth()
+const salaryFromData = reactive({
+  year: year + '',
+  month: (month < 10 ? '0' : '') + month,
+  T_uuid: ''
+})
+const tableTH = [
+  { type: 'index', label: '序号', width: '60px' },
+  { prop: 'T_user_name', label: '姓名' },
+  { prop: 'T_user_dept', label: '部门' },
+  { prop: 'T_user_post', label: '岗位' },
+  { prop: 'T_base', label: '基本工资', sortable: true, width: '120px' },
+  { prop: 'T_post', label: '岗位工资', sortable: true, width: '120px' },
+  { prop: 'T_seniority', label: '工龄工资', sortable: true, width: '120px' },
+  { prop: 'T_perf', label: '绩效金额', sortable: true, width: '120px' },
+  { prop: 'T_perf_score', label: '绩效得分', sortable: true, width: '120px' },
+  { prop: 'T_actual_Perf', label: '实发绩效', sortable: true, width: '120px' },
+  { prop: 'T_back_payment', label: '其他补款', sortable: true, width: '120px' },
+  { prop: 'T_attendance', label: '考勤扣款', sortable: true, width: '120px' },
+  { prop: 'T_cut_payment', label: '其他扣款', sortable: true, width: '120px' },
+  { prop: 'T_laballot', label: '应发合计', sortable: true, width: '120px' },
+  { prop: 'T_pension_insurance', label: '养老保险', sortable: true, width: '120px' },
+  { prop: 'T_unemployment_insurance', label: '失业保险', sortable: true, width: '120px' },
+  { prop: 'T_medical_insurance', label: '基本医疗保险', sortable: true, width: '140px' },
+  { prop: 'T_large_medical_insurance', label: '大额医疗保险', sortable: true, width: '140px' },
+  { prop: 'T_housing_fund', label: '公积金', sortable: true, width: '100px' },
+  { prop: 'T_tax', label: '个税扣款', sortable: true, width: '120px' },
+  { prop: 'T_laborage', label: '扣款合计', sortable: true, width: '120px' },
+  { prop: 'T_total', label: '实发合计', sortable: true, width: '120px' }
+]
+interface User {
+  Id: number
+  T_user_name: string
+  T_base: number
+  T_post: number
+  T_seniority: number
+  T_Perf: number
+  T_Perf_score: number
+  T_back_payment: number
+  T_tax: number
+  T_attendance: number
+  T_cut_payment: number
+  T_pension_insurance: number
+  T_unemployment_insurance: number
+  T_medical_insurance: number
+  T_Large_medical_insurance: number
+  T_housing_fund: number
+}
+interface SpanMethodProps {
+  row: User
+  column: TableColumnCtx<User>
+  rowIndex: number
+  columnIndex: number
+}
+const arraySpanMethod = ({ rowIndex, columnIndex }: SpanMethodProps) => {
+  if (rowIndex === tableData.value.length - 1) {
+    if (columnIndex === 2) {
+      return [1, 3]
+    } else if (columnIndex === 3 || columnIndex === 4) {
+      return [0, 0]
+    }
+  }
+}
+const initParam = {
+  T_date: `${year}-${month < 10 ? '0' : ''}${month}`,
+  page: 1,
+  page_z: 10
+}
+const total = ref(0)
+const getSalary_List = async () => {
+  const res: any = await Salary_List(initParam)
+  tableData.value = res.Data.Data
+  total.value = res.Data.Num
+}
+getSalary_List()
 
+const exportSalaryExcel = async () => {
+  await Salary_Excel()
+}
+const publishSalary = async () => {
+  // Salary_Send
+  if (multipleSelection.value.length === 0 || multipleSelection.value[0]?.Id === 0) {
+    ElMessage({
+      message: '请选择用户!!!',
+      type: 'warning'
+    })
+    return
+  }
+  multipleSelection.value.pop()
+  for await (let item of multipleSelection.value) {
+    Salary_Send({ T_id: item.Id })
+  }
+}
+const multipleSelection = ref<User[]>([])
+const handleSelectionChange = (val: User[]) => {
+  multipleSelection.value = val
+}
+const tableData = ref<User[]>([])
 </script>
 
 <template>
-  <div class="role">
-    Salary count
+  <div class="SalaryCount">
+    <el-card class="m-b-3">
+      <el-row :gutter="24">
+        <el-col :span="12" class="d-flex">
+          <span class="demonstration">年:</span>
+          <el-date-picker
+            v-model="salaryFromData.year"
+            style="width: 100px"
+            value-format="YYYY"
+            type="year"
+            placeholder="请选择年"
+          />
+          <span class="demonstration">月:</span>
+          <el-date-picker
+            v-model="salaryFromData.month"
+            style="width: 100px"
+            value-format="MM"
+            type="month"
+            placeholder="请选择月"
+          />
+        </el-col>
+        <el-col :span="12" class="d-flex">
+          <el-button type="primary" @click="exportSalaryExcel">导出表格</el-button>
+          <el-button type="success" @click="publishSalary">发布</el-button>
+        </el-col>
+      </el-row>
+    </el-card>
+    <el-card class="table-card">
+      <el-table
+        :data="tableData"
+        @selection-change="handleSelectionChange"
+        :span-method="arraySpanMethod"
+        border
+        style="width: 100%"
+      >
+        <el-table-column type="selection" width="55" />
+        <template v-for="(item, index) in tableTH" :key="index">
+          <el-table-column
+            v-if="item.type === 'index'"
+            :type="item.type"
+            :width="item.width"
+            align="center"
+            :label="item.label"
+          />
+          <el-table-column
+            v-else
+            :prop="item.prop"
+            :label="item.label"
+            :width="item.width"
+            align="center"
+            label-class-name="label-table"
+            :sortable="item.sortable"
+          />
+        </template>
+      </el-table>
+      <div class="pagination">
+        <el-pagination background layout="total,prev, pager, next" :total="total" />
+      </div>
+    </el-card>
   </div>
 </template>
 
-<style scoped>
-
-</style>
+<style scoped lang="scss">
+.SalaryCount {
+  height: 100%;
+  .table-card {
+    height: calc(100% - 72px - 12px);
+    :deep(.el-card__body) {
+      height: 100%;
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+    }
+  }
+}
+.label-table {
+  white-space: nowrap;
+}
+.d-flex {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  flex-wrap: nowrap;
+}
+.pagination {
+  display: flex;
+  justify-content: end;
+  margin-top: 2rem;
+}
+</style>

+ 115 - 5
src/views/salary/SalaryMy.vue

@@ -1,13 +1,123 @@
 <script setup lang="ts">
+import { reactive, ref } from 'vue'
+import { Salary_User_Get } from '@/api/salary/index'
+let date = new Date()
+const year = date.getFullYear()
+const month = date.getMonth()
+const salaryFromData = reactive({
+  year: year + '',
+  month: (month < 10 ? '0' : '') + month,
+  T_uuid: ''
+})
 
+const MySalary = ref({
+  T_base: '',
+  T_post: '',
+  T_seniority: '',
+  T_Perf: '',
+  T_Perf_score: '',
+  T_back_payment: '',
+  T_tax: '',
+  T_attendance: '',
+  T_cut_payment: '',
+  T_pension_insurance: '',
+  T_unemployment_insurance: '',
+  T_medical_insurance: '',
+  T_Large_medical_insurance: '',
+  T_housing_fund: ''
+})
+
+const getMySalary = async () => {
+  let T_date = year + '-' + (month < 10 ? '0' : '') + month
+  const res: any = await Salary_User_Get({ T_date })
+  if (res.Code) {
+    MySalary.value = { ...res.Data }
+  }
+}
+getMySalary()
 </script>
 
 <template>
-  <div class="role">
-    Salary my
+  <div class="SalaryMy">
+    <el-card class="m-b-3">
+      <el-row :gutter="24">
+        <el-col :span="5">
+          <span class="demonstration">年:</span>
+          <el-date-picker
+            v-model="salaryFromData.year"
+            style="width: 100px"
+            value-format="YYYY"
+            type="year"
+            placeholder="请选择年"
+          />
+        </el-col>
+        <el-col :span="5">
+          <span class="demonstration">月:</span>
+          <el-date-picker
+            v-model="salaryFromData.month"
+            style="width: 100px"
+            value-format="MM"
+            type="month"
+            placeholder="请选择月"
+          />
+        </el-col>
+        <el-col :span="5">
+          <el-button type="primary">查询</el-button>
+        </el-col>
+      </el-row>
+    </el-card>
+    <el-card>
+      <el-descriptions class="margin-top" title="我的薪资" :column="3" border>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <i class="iconfont">{{ '\ue663' }}</i>
+              基础工资
+            </div>
+          </template>
+          kooriookami
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <i class="iconfont">{{ '\ue663' }}</i>
+              岗位工资
+            </div>
+          </template>
+          18100000000
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <i class="iconfont">{{ '\ue7cd' }}</i>
+              工龄工资
+            </div>
+          </template>
+          Suzhou
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <i class="iconfont">{{ '\ue663' }}</i>
+              绩效金额
+            </div>
+          </template>
+          <el-tag size="small">School</el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label>
+            <div class="cell-item">
+              <el-icon :style="iconStyle">
+                <office-building />
+              </el-icon>
+              Address
+            </div>
+          </template>
+          No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangsu Province
+        </el-descriptions-item>
+      </el-descriptions>
+    </el-card>
   </div>
 </template>
 
-<style scoped>
-
-</style>
+<style scoped></style>

+ 46 - 58
src/views/salary/Salary.vue → src/views/salary/salary/Salary.vue

@@ -1,21 +1,13 @@
 <script setup lang="ts">
-import { ref, onMounted, reactive } from 'vue'
+import { ref, reactive } from 'vue'
 import TableBase from '@/components/TableBase/index.vue'
-import { Salary_List, Salary_User_List, Salary_Get } from '@/api/salary/index'
 import { User_List } from '@/api/user/index'
 import { ColumnProps } from '@/components/TableBase/interface/index'
 import { GlobalStore } from '@/stores/index'
+import SalaryFrom from './SalaryFrom.vue'
 const globalStore = GlobalStore()
 
-const getSalary_List = async () => {
-  const res = await Salary_User_List({ page: 1, page_z: 10 })
-  console.log(res)
-}
-
-onMounted(() => {
-  getSalary_List()
-})
-
+const TableRef = ref()
 // 搜索以及参数
 const columns: ColumnProps[] = [
   { prop: 'T_name', label: '姓名', name: 'T_name' },
@@ -23,33 +15,59 @@ const columns: ColumnProps[] = [
 ]
 const searchHandle = () => {
   console.log(searchs)
+  initParam.T_name = searchs.T_name
+  initParam.T_dept = searchs.T_dept
+  TableRef.value.searchTable()
 }
 const searchs = reactive({
   T_name: '',
   T_dept: ''
 })
+let date = new Date()
+const year = date.getFullYear()
+const month = date.getMonth()
+const salaryFromData = reactive({
+  year: year + '',
+  month: (month < 10 ? '0' : '') + month,
+  T_uuid: ''
+})
+
 const initParam = {
   User_tokey: globalStore.GET_User_tokey,
   T_name: '',
   T_dept: ''
 }
-const getSalary = async (val: string) => {
-  const res = await Salary_Get({ T_uuid: val })
-  console.log(res)
+const getSalary = (row: any) => {
+  userInfo.name = row.T_name
+  userInfo.T_dept = row.T_dept_name
+  userInfo.T_post = row.T_post_name
+
+  salaryFromData.T_uuid = row.T_uuid
 }
-const squareUrl = 'https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png'
+const userInfo = reactive({
+  squareUrl: 'https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png',
+  name: '',
+  T_dept: '',
+  T_post: ''
+})
 </script>
 
 <template>
   <el-row :gutter="20" class="h-100">
-    <el-col :span="8" class="padding-right-0">
-      <TableBase :columns="columns" :requestApi="User_List" :initParam="initParam" layout="prev, pager, next">
+    <el-col :span="8" class="padding-right-0 h-100">
+      <TableBase
+        ref="TableRef"
+        :columns="columns"
+        :requestApi="User_List"
+        :initParam="initParam"
+        layout="prev, pager, next"
+      >
         <template #table-header>
           <div class="input-suffix">
             <el-row :gutter="24">
               <el-col :span="10" class="d-flex padding-left-0 padding-right-0">
                 <span class="inline-flex">部门:</span>
-                <el-select v-model="searchs.T_dept" class="m-2" placeholder="请选择部门">
+                <el-select v-model="searchs.T_dept" class="m-2" clearable placeholder="请选择部门">
                   <el-option
                     v-for="item in globalStore.GET_Dept_List"
                     :key="item.Id"
@@ -67,20 +85,20 @@ const squareUrl = 'https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dp
           </div>
         </template>
         <template #T_name="{ row }">
-          <el-button type="primary" text @click="getSalary(row.T_uuid)">{{ row.T_name }}</el-button>
+          <el-button type="primary" text @click="getSalary(row)">{{ row.T_name }}</el-button>
         </template>
       </TableBase></el-col
     >
-    <el-col :span="16">
+    <el-col :span="16" class="h-100" style="overflow: hidden">
       <el-card class="m-b-3">
         <h3 class="title m-b-5">员工基本信息</h3>
         <div class="info-content">
-          <el-avatar shape="square" size="large" :src="squareUrl" />
+          <el-avatar shape="square" size="large" :src="userInfo.squareUrl" />
           <div class="info-name">
-            <h4 class="m-b-3">名字:张三</h4>
+            <h4 class="m-b-3">名字:{{ userInfo.name }}</h4>
             <h4>
-              <span>部门:软件组</span>
-              <span>岗位:前端工程师</span>
+              <span>部门:{{ userInfo.T_dept }}</span>
+              <span>岗位:{{ userInfo.T_post }}</span>
             </h4>
           </div>
         </div>
@@ -89,49 +107,19 @@ const squareUrl = 'https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dp
         <el-row :gutter="20">
           <el-col :span="10" class="d-flex">
             <span class="demonstration">年:</span>
-            <el-date-picker v-model="value3" type="year" placeholder="请选择年" />
+            <el-date-picker v-model="salaryFromData.year" value-format="YYYY" type="year" placeholder="请选择年" />
           </el-col>
           <el-col :span="10" class="d-flex">
             <span class="demonstration">月:</span>
-            <el-date-picker v-model="value3" type="month" placeholder="请选择月" />
+            <el-date-picker v-model="salaryFromData.month" value-format="MM" type="month" placeholder="请选择月" />
           </el-col>
         </el-row>
       </el-card>
-      <el-card class="">
-        <div v-for="o in 4" :key="o" class="text item">{{ 'List item ' + o }}</div>
-      </el-card>
+      <SalaryFrom v-bind="salaryFromData"></SalaryFrom>
     </el-col>
   </el-row>
 </template>
 
 <style scoped lang="scss">
-.input-suffix {
-  width: 100%;
-  .w-50 {
-    width: 12.5rem;
-  }
-  .d-flex {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-  }
-  .inline-flex {
-    white-space: nowrap;
-    display: inline-flex;
-  }
-}
-.title {
-  text-align: center;
-}
-.info-content {
-  display: flex;
-  .info-name {
-    display: flex;
-    flex-direction: column;
-    padding-left: 0.75rem;
-    span:first-child {
-      margin-right: 2rem;
-    }
-  }
-}
+@import './index.scss';
 </style>

+ 131 - 0
src/views/salary/salary/SalaryFrom.vue

@@ -0,0 +1,131 @@
+<script setup lang="ts">
+import { ref, reactive, onMounted, onUnmounted } from 'vue'
+import type { FormInstance, FormRules } from 'element-plus'
+import { ElNotification } from 'element-plus'
+import { reuls_validator } from './relus'
+import { Salary_Post } from '@/api/salary/index'
+const formRef = ref<FormInstance>()
+const form = reactive({
+  T_base: '',
+  T_post: '',
+  T_seniority: '',
+  T_Perf: '',
+  T_Perf_score: '',
+  T_back_payment: '',
+  T_tax: '',
+  T_attendance: '',
+  T_cut_payment: '',
+  T_pension_insurance: '',
+  T_unemployment_insurance: '',
+  T_medical_insurance: '',
+  T_Large_medical_insurance: '',
+  T_housing_fund: ''
+})
+const rules = reactive<FormRules>(reuls_validator)
+const resetForm = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.resetFields()
+}
+const formLabelWidth = ref('9.5rem')
+const submitSalary = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.validate(async valid => {
+    if (valid) {
+      const T_date = props.year + '-' + props.month
+      const res: any = await Salary_Post({ T_uuid: props.T_uuid, T_date, ...form })
+      if (res.Code === 200) {
+        ElNotification({
+          title: '提交成功',
+          message: '薪资已添加!!!',
+          type: 'success'
+        })
+        resetForm(formRef.value)
+      }
+    } else {
+      return false
+    }
+  })
+}
+
+let cardHeight = ref(0)
+const resize = () => {
+  const height = document.documentElement.clientHeight
+  cardHeight.value = height - 4 * 12 - 140 - 72 - 60
+}
+interface PropsType {
+  T_uuid: string
+  year: string
+  month: string
+}
+const props = defineProps<PropsType>()
+
+onMounted(() => {
+  resize()
+})
+onUnmounted(() => {
+  window.onresize = null
+})
+window.onresize = resize
+</script>
+
+<template>
+  <el-card class="form-card" :style="{ height: cardHeight + 'px' }">
+    <el-form :model="form" ref="formRef" :rules="rules">
+      <el-row :gutter="24">
+        <el-col :span="12" class="form-card-left">
+          <el-form-item label="基础工资:" :label-width="formLabelWidth" prop="T_base">
+            <el-input v-model="form.T_base" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="岗位工资:" :label-width="formLabelWidth" prop="T_post">
+            <el-input v-model="form.T_post" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="工龄工资:" :label-width="formLabelWidth" prop="T_seniority">
+            <el-input v-model="form.T_seniority" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="绩效金额:" :label-width="formLabelWidth" prop="T_Perf">
+            <el-input v-model="form.T_Perf" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="绩效得分:" :label-width="formLabelWidth" prop="T_Perf_score">
+            <el-input v-model="form.T_Perf_score" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="其他补款:" :label-width="formLabelWidth" prop="T_back_payment">
+            <el-input v-model="form.T_back_payment" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="需缴个人所得税:" :label-width="formLabelWidth" prop="T_tax">
+            <el-input v-model="form.T_tax" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12" class="form-card-right">
+          <el-form-item label="考勤扣款:" :label-width="formLabelWidth" prop="T_attendance">
+            <el-input v-model="form.T_attendance" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="其他扣款:" :label-width="formLabelWidth" prop="T_cut_payment">
+            <el-input v-model="form.T_cut_payment" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="需缴养老保险:" :label-width="formLabelWidth" prop="T_pension_insurance">
+            <el-input v-model="form.T_pension_insurance" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="需缴医疗保险:" :label-width="formLabelWidth" prop="T_unemployment_insurance">
+            <el-input v-model="form.T_unemployment_insurance" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="需缴住房公积金:" :label-width="formLabelWidth" prop="T_medical_insurance">
+            <el-input v-model="form.T_medical_insurance" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="需缴纳失业保险:" :label-width="formLabelWidth" prop="T_Large_medical_insurance">
+            <el-input v-model="form.T_Large_medical_insurance" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+          <el-form-item label="需缴大额医疗保险:" :label-width="formLabelWidth" prop="T_housing_fund">
+            <el-input v-model="form.T_housing_fund" autocomplete="off" placeholder="¥" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+    <div class="d-flex">
+      <el-button type="primary" class="submit" @click="submitSalary(formRef)">提交</el-button>
+    </div>
+  </el-card>
+</template>
+
+<style scoped lang="scss">
+@import './index.scss';
+</style>

+ 50 - 0
src/views/salary/salary/index.scss

@@ -0,0 +1,50 @@
+.submit {
+  padding: 0.5rem 1.875rem;
+  margin-top: 1.25rem;
+}
+.form-card {
+  overflow: auto;
+  .form-card-right,
+  .form-card-left {
+    display: flex;
+    flex-direction: column;
+  }
+  .form-card-right {
+    align-items: end;
+  }
+  .form-card-left {
+    align-items: start;
+  }
+}
+.d-flex {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  flex-wrap: nowrap;
+}
+.input-suffix {
+  width: 100%;
+  .w-50 {
+    width: 12.5rem;
+  }
+
+  .inline-flex {
+    white-space: nowrap;
+    display: inline-flex;
+  }
+}
+.title {
+  text-align: center;
+}
+.info-content {
+  display: flex;
+  color: #303133;
+  .info-name {
+    display: flex;
+    flex-direction: column;
+    padding-left: 0.75rem;
+    span:first-child {
+      margin-right: 2rem;
+    }
+  }
+}

+ 32 - 0
src/views/salary/salary/relus.ts

@@ -0,0 +1,32 @@
+import type { FormRules } from 'element-plus'
+
+const floatReg = /^[-\+]?\d+(\.\d+)?$/
+
+const validate_float = (rule: any, value: any, callback: any) => {
+  if (value === '') {
+    callback(new Error('请输入金额'))
+  } else {
+    if (floatReg.test(value) || /\d+/.test(value)) {
+      callback()
+    } else {
+      callback(new Error('金额必须是数字或小数'))
+    }
+  }
+}
+
+export const reuls_validator: FormRules = {
+  T_base: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_post: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_seniority: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_Perf: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_Perf_score: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_back_payment: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_tax: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_attendance: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_cut_payment: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_pension_insurance: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_unemployment_insurance: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_medical_insurance: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_Large_medical_insurance: [{ required: true, validator: validate_float, trigger: 'blur' }],
+  T_housing_fund: [{ required: true, validator: validate_float, trigger: 'blur' }]
+}