Parcourir la source

完成账户管理与薪资管理

@sun-chaoqun il y a 2 ans
Parent
commit
1c858e42c6

+ 5 - 0
components.d.ts

@@ -13,12 +13,14 @@ declare module '@vue/runtime-core' {
     Dialog: typeof import('./src/components/dialog/Dialog.vue')['default']
     Drawer: typeof import('./src/components/Drawer/index.vue')['default']
     ElAside: typeof import('element-plus/es')['ElAside']
+    ElAvatar: typeof import('element-plus/es')['ElAvatar']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCard: typeof import('element-plus/es')['ElCard']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElContainer: typeof import('element-plus/es')['ElContainer']
+    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
     ElDropdown: typeof import('element-plus/es')['ElDropdown']
@@ -36,12 +38,15 @@ declare module '@vue/runtime-core' {
     ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
+    ElRadio: typeof import('element-plus/es')['ElRadio']
+    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+    ElTag: typeof import('element-plus/es')['ElTag']
     HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
     Loading: typeof import('./src/components/Loading/index.vue')['default']
     Pagination: typeof import('./src/components/TableBase/components/Pagination.vue')['default']

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

@@ -1,5 +1,5 @@
 import $http from '../index'
-// 用户列表
+// 列表 === 薪资统计
 export const Salary_List = (params: any) => $http.post('/api/salary/Salary/List', params)
 // 员工列表
 export const Salary_User_List = (params: any) => $http.post('/api/salary/Salary/User_List', params)

+ 22 - 2
src/assets/iconfont.css

@@ -1,7 +1,7 @@
 @font-face {
   font-family: 'iconfont'; /* Project id 3967191 */
-  src: url('./iconfont.woff2?t=1679447680399') format('woff2'), url('./iconfont.woff?t=1679447680399') format('woff'),
-    url('./iconfont.ttf?t=1679447680399') format('truetype');
+  src: url('./iconfont.woff2?t=1679533850838') format('woff2'), url('./iconfont.woff?t=1679533850838') format('woff'),
+    url('./iconfont.ttf?t=1679533850838') format('truetype');
 }
 
 .iconfont {
@@ -12,6 +12,26 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-kaoqin:before {
+  content: '\ue619';
+}
+
+.icon-qingjia:before {
+  content: '\ue627';
+}
+
+.icon-jiaban:before {
+  content: '\ue64c';
+}
+
+.icon-qingjiashenqing:before {
+  content: '\ue6aa';
+}
+
+.icon-jiabanshenqing:before {
+  content: '\ue690';
+}
+
 .icon-money:before {
   content: '\ue663';
 }

BIN
src/assets/iconfont.ttf


BIN
src/assets/iconfont.woff


BIN
src/assets/iconfont.woff2


+ 2 - 1
src/components/TableBase/components/Pagination.vue

@@ -8,6 +8,7 @@ interface Pageable {
 }
 
 interface PaginationProps {
+  layout: string
   pageable: Pageable
   handleSizeChange: (size: number) => void
   handleCurrentChange: (currentPage: number) => void
@@ -24,7 +25,7 @@ defineProps<PaginationProps>()
       :small="pageable.small"
       :disabled="pageable.disabled"
       :background="true"
-      layout="total, sizes, prev, pager, next, jumper"
+      :layout="layout"
       :total="pageable.total"
       @size-change="handleSizeChange"
       @current-change="handleCurrentChange"

+ 16 - 4
src/components/TableBase/index.vue

@@ -11,6 +11,7 @@ interface ProTableProps extends Partial<Omit<TableProps<any>, 'data'>> {
   dataCallback?: (data: any) => any // 返回数据的回调函数,可以对数据进行处理 ==> 非必传
   title?: string // 表格标题,目前只在打印的时候用到 ==> 非必传
   pagination?: boolean // 是否需要分页组件 ==> 非必传(默认为true)
+  layout?: string
   initParam?: any // 初始化请求参数 ==> 非必传(默认为{})
   border?: boolean // 是否带有纵向边框 ==> 非必传(默认为true)
   toolButton?: boolean // 是否显示表格功能按钮 ==> 非必传(默认为true)
@@ -22,6 +23,7 @@ interface ProTableProps extends Partial<Omit<TableProps<any>, 'data'>> {
 const props = withDefaults(defineProps<ProTableProps>(), {
   columns: () => [],
   pagination: true,
+  layout: 'total, sizes, prev, pager, next, jumper',
   initParam: {},
   border: true,
   toolButton: true,
@@ -37,7 +39,7 @@ const {
   // searchParam,
   // searchInitParam,
   getTableList,
-  // search,
+  searchTable,
   // reset,
   handleSizeChange,
   handleCurrentChange
@@ -50,7 +52,8 @@ onMounted(() => {
 })
 
 defineExpose({
-  getTableList
+  getTableList,
+  searchTable
 })
 </script>
 
@@ -73,13 +76,21 @@ defineExpose({
         >
         </el-table-column>
         <!-- expand 支持 tsx 语法 && 作用域插槽 (tsx > slot) -->
-        <el-table-column v-bind="item" :align="item.align ?? 'center'" v-if="item.type == 'expand'" v-slot="scope">
+        <el-table-column v-bind="item" :align="item.align ?? 'center'" v-if="item.type === 'expand'" v-slot="scope">
           <component :is="item.render" :row="scope.row" v-if="item.render"> </component>
           <slot :name="item.type" :row="scope.row" v-else></slot>
         </el-table-column>
-        <el-table-column v-bind="item" :align="item.align ?? 'center'" v-if="!item.type && item.prop" v-slot="scope">
+        <el-table-column
+          v-bind="item"
+          :align="item.align ?? 'center'"
+          v-if="!item.type && item.prop && item.name !== item.prop"
+          v-slot="scope"
+        >
           <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">
+          <slot :name="item.prop" :row="scope.row"></slot>
+        </el-table-column>
       </template>
       <!-- 插入表格最后一行之后的插槽 -->
       <template #append>
@@ -94,6 +105,7 @@ defineExpose({
     <slot name="pagination">
       <Pagination
         v-if="pagination"
+        :layout="layout"
         :pageable="pageable"
         :handleSizeChange="handleSizeChange"
         :handleCurrentChange="handleCurrentChange"

+ 1 - 0
src/components/TableBase/interface/index.ts

@@ -42,5 +42,6 @@ export interface ColumnProps<T = any>
   fieldNames?: { label: string; value: string } // 指定 label && value 的 key 值
   headerRender?: (row: ColumnProps) => any // 自定义表头内容渲染(tsx语法)
   render?: (scope: { row: T }) => any // 自定义单元格内容渲染(tsx语法)
+  name?: string
   _children?: ColumnProps<T>[] // 多级表头
 }

+ 6 - 1
src/hooks/useTable.ts

@@ -75,12 +75,17 @@ export const useTable = (
     getTableList()
   }
 
+  const searchTable = () => {
+    state.pageable.pageNum = 1
+    getTableList()
+  }
+
   return {
     ...toRefs(state),
     // searchParam,
     // searchInitParam,
     getTableList,
-    // search,
+    searchTable,
     // reset,
     handleSizeChange,
     handleCurrentChange

+ 1 - 1
src/main.ts

@@ -13,7 +13,7 @@ import store from '@/stores/index'
 
 // 覆盖element默认样式
 import '@/styles/element.scss'
-import '@/styles/element-variables.scss'
+// import '@/styles/element-variables.scss'
 
 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 

+ 48 - 0
src/router/modules/staticRouter.ts

@@ -59,6 +59,54 @@ export const staticRouter: RouteRecordRaw[] = [
         meta: {
           title: '我的薪资'
         }
+      },
+      {
+        path: '/records',
+        name: 'Records',
+        component: () => import('@/views/workAttendance/Records.vue'),
+        meta: {
+          title: '统筹管理'
+        }
+      },
+      {
+        path: '/recordsFinance',
+        name: 'RecordsFinance',
+        component: () => import('@/views/workAttendance/RecordsFinance.vue'),
+        meta: {
+          title: '统筹管理(财务)'
+        }
+      },
+      {
+        path: '/overtime',
+        name: 'Overtime',
+        component: () => import('@/views/workAttendance/Overtime.vue'),
+        meta: {
+          title: '加班审批'
+        }
+      },
+      {
+        path: '/leave',
+        name: 'Leave',
+        component: () => import('@/views/workAttendance/Leave.vue'),
+        meta: {
+          title: '请假审批'
+        }
+      },
+      {
+        path: '/myOvertime',
+        name: ' MyOvertime',
+        component: () => import('@/views/workAttendance/MyOvertime.vue'),
+        meta: {
+          title: '我的加班'
+        }
+      },
+      {
+        path: '/myLeave',
+        name: 'MyLeave',
+        component: () => import('@/views/workAttendance/MyLeave.vue'),
+        meta: {
+          title: '我的请假'
+        }
       }
     ]
   },

+ 7 - 6
src/style.scss

@@ -1,12 +1,6 @@
 :root {
   font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
-  // line-height: 1.5;
-  // font-weight: 400;
-
   color-scheme: light dark;
-  // color: rgba(255, 255, 255, 0.87);
-  // background-color: #242424;
-
   font-synthesis: none;
   text-rendering: optimizeLegibility;
   -webkit-font-smoothing: antialiased;
@@ -57,6 +51,13 @@ body,
   height: 100%;
 }
 
+.m-b-3 {
+  margin-bottom: 0.75rem;
+}
+.m-b-5 {
+  margin-bottom: 1.25rem;
+}
+
 ::-webkit-scrollbar {
   width: 3px;
   height: 3px;

+ 0 - 1
src/styles/element-variables.scss

@@ -1 +0,0 @@
-

+ 11 - 0
src/styles/element.scss

@@ -11,3 +11,14 @@
 .el-select {
   width: 100%;
 }
+
+.el-form-item__content {
+  :deep(.el-date-editor.el-input) {
+    width: 100% !important;
+  }
+}
+.el-form-item__content {
+  :deep(.el-input__wrapper) {
+    width: 100% !important;
+  }
+}

+ 46 - 16
src/views/Index.vue

@@ -102,44 +102,74 @@ const routerList = [
     ]
   },
   {
-    path: '',
+    path: 'mangage',
     name: '薪资管理',
-    iocn: '',
     meta: {
-      icon: 'HomeFilled',
-      title: '首页',
+      unicode: '\ue619',
+      title: '薪资管理',
       isKeepAlive: true
     },
     children: [
       {
-        path: '',
+        path: '/records',
         name: '统筹管理',
         meta: {
-          icon: 'HomeFilled',
-          title: '首页',
+          icon: 'Memo',
+          title: '统筹管理',
           isKeepAlive: true
         }
       },
       {
-        path: '',
+        path: '/recordsFinance',
         name: '统筹管理(财务)',
         meta: {
-          icon: 'HomeFilled',
-          title: '首页',
+          icon: 'Notebook',
+          title: '统筹管理(财务)',
+          isKeepAlive: true
+        }
+      },
+      {
+        path: '/overtime',
+        name: '加班审批',
+        meta: {
+          unicode: '\ue690',
+          title: '加班审批',
+          isKeepAlive: true
+        }
+      },
+      {
+        path: '/leave',
+        name: '请假审批',
+        meta: {
+          unicode: '\ue627',
+          title: '请假审批',
+          isKeepAlive: true
+        }
+      },
+      {
+        path: '/myOvertime',
+        name: '我的加班',
+        meta: {
+          unicode: '\ue64c',
+          title: '我的加班',
+          isKeepAlive: true
+        }
+      },
+      {
+        path: '/myLeave',
+        name: '我的请假',
+        meta: {
+          unicode: '\ue6aa',
+          title: '我的请假',
           isKeepAlive: true
         }
       }
-      // { index: '5-3', path: '', name: '加班审批', iocn: '' },
-      // { index: '5-4', path: '', name: '请假审批', iocn: '' },
-      // { index: '5-5', path: '', name: '我的加班', iocn: '' },
-      // { index: '5-6', path: '', name: '我的请假', iocn: '' }
     ]
   }
 ]
+
 onMounted(() => {
-  // store
   globalStore.SET_User_Dept_List()
-  // globalStore.SET_User_Post_List()
 })
 
 const route = useRoute()

+ 22 - 17
src/views/account/roles/Roles.vue

@@ -65,8 +65,6 @@ const getMenuList = async (code: string) => {
   }
 }
 const submitUserRole = async (item: InSys) => {
-  console.log(checkList.value, currentVal, item, SysList)
-
   let Sys: any = SysList.value.find(sys => item.T_sys === sys.T_sys)
   let childs = Sys?.children.filter((child: InSys) => Sys.checkList.includes(child.T_name))
   let T_menu = ''
@@ -84,17 +82,16 @@ const submitUserRole = async (item: InSys) => {
     T_code: item.T_sys,
     T_menu
   }
-  console.log(params)
 
-  // const res = await User_Power_Edit_Menu(params)
-  // if (res.Code === 200) {
-  //   ElMessage({
-  //     type: 'success',
-  //     message: '修改成功!'
-  //   })
-  //   dialog.value.DialogClose()
-  //   checkList.value = []
-  // }
+  const res = await User_Power_Edit_Menu(params)
+  if (res.Code === 200) {
+    ElMessage({
+      type: 'success',
+      message: '修改成功!'
+    })
+    dialog.value.DialogClose()
+    checkList.value = []
+  }
 }
 
 const initParam = {
@@ -163,13 +160,21 @@ const AddUserName = (formEl: FormInstance | undefined) => {
 // 删除
 const UserDelete = (row: any) => {
   ElMessageBox.confirm('您确定要删除吗?', '警告', {
-    confirmButtonText: 'OK',
-    cancelButtonText: 'Cancel',
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
     type: 'warning'
   })
     .then(async () => {
-      const res = await User_Power_Del({ User_tokey: globalStore.GET_User_tokey, T_id: row.T_id })
-      console.log(res)
+      const res: any = await User_Power_Del({ User_tokey: globalStore.GET_User_tokey, T_id: row.T_id })
+      if (res.Code === 200) {
+        ElMessage({
+          type: 'success',
+          message: '删除成功!'
+        })
+        nextTick(() => {
+          TableRef.value.getTableList()
+        })
+      }
     })
     .catch(() => {
       ElMessage({
@@ -183,7 +188,7 @@ const UserDelete = (row: any) => {
 const search = ref('')
 const searchHandle = () => {
   initParam.T_name = search.value
-  TableRef.value.getTableList()
+  TableRef.value.searchTable()
 }
 </script>
 

+ 79 - 17
src/views/account/users/Users.vue

@@ -2,13 +2,15 @@
 import TableBase from '@/components/TableBase/index.vue'
 import { ColumnProps } from '@/components/TableBase/interface/index'
 import { Edit, Delete } from '@element-plus/icons-vue'
-import { ref, reactive, onMounted } from 'vue'
+import { ref, nextTick } from 'vue'
 import { GlobalStore } from '@/stores/index'
-import { User_List, User_Add, User_Edit, User_Del, User_Post_List, User_Dept_List } from '@/api/user/index'
+import { User_List, User_Del } from '@/api/user/index'
 import DrawerFrom from './components/DrawerFrom.vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
 const globalStore = GlobalStore()
 const action = ref(true)
 const drawerFromRef = ref()
+const TableRef = ref()
 const columns: ColumnProps[] = [
   { type: 'index', label: '#', width: 80 },
   { prop: 'T_name', label: '姓名', search: { el: 'input' } },
@@ -16,52 +18,112 @@ const columns: ColumnProps[] = [
   { prop: 'T_dept_name', label: '部门' },
   { prop: 'T_phone', label: '联系电话' },
   { prop: 'T_nation', label: '民族' },
+  { prop: 'T_sex', label: '性别', name: 'T_sex' },
   { prop: 'T_school', label: '毕业院校' },
   { prop: 'T_major', label: '专业' },
   { prop: 'T_education', label: '学历' },
   { prop: 'T_entry_time', label: '入职时间' },
   { prop: 'T_positive_time', label: '转正时间' },
-  { prop: 'T_entry_type', label: '入职类型' },
+  { prop: 'T_entry_type', label: '入职类型', name: 'T_entry_type' },
   { prop: 'T_contract_start_time', label: '劳动合同开始时间' },
   { prop: 'T_contract_end_time', label: '劳动合同结束时间' },
-  { prop: 'T_remark', label: '备注' },
+  { prop: 'T_expire', label: '是否到期', name: 'T_expire' },
+  { prop: 'T_marry', label: '婚否', name: 'T_marry' },
   { prop: 'operation', label: '操作', width: 200, fixed: 'right' }
 ]
-
-// const callbackDrawerFrom = () => {
-//   drawerFromRef.value.callbackDrawer()
-// }
 const openDrawerFrom = () => {
   drawerFromRef.value.openDrawer()
 }
 
+const UpdateTableList = () => {
+  TableRef.value.getTableList()
+}
+
+const UpdateAction = (val: boolean) => {
+  action.value = val
+}
+
+const EditUserInfo = (row: any) => {
+  action.value = false
+  drawerFromRef.value.openDrawer()
+  drawerFromRef.value.DataEcho(row)
+}
+const DeleteUserInfo = (row: any) => {
+  ElMessageBox.confirm('您确定要删除吗?', '警告', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  })
+    .then(async () => {
+      const res: any = await User_Del({ User_tokey: globalStore.GET_User_tokey, T_uuid: row.T_uuid })
+      if (res.Code === 200) {
+        ElMessage({
+          type: 'success',
+          message: '删除成功!'
+        })
+        nextTick(() => {
+          TableRef.value.getTableList()
+        })
+      }
+    })
+    .catch(() => {
+      ElMessage({
+        type: 'warning',
+        message: '取消成功!'
+      })
+    })
+}
+
+// search
+const search = ref<string>('')
+const SearchInfo = () => {
+  initParam.T_name = search.value
+  TableRef.value.searchTable()
+}
+
 const initParam = {
   User_tokey: globalStore.GET_User_tokey,
-  page: 1,
-  page_z: 10
+  T_name: ''
 }
 </script>
 
 <template>
-  <TableBase :columns="columns" :requestApi="User_List" :initParam="initParam">
+  <TableBase ref="TableRef" :columns="columns" :requestApi="User_List" :initParam="initParam">
     <template #table-header>
       <div class="input-suffix">
         <el-row :gutter="20">
           <el-col :span="12">
             <span class="ml-3 w-35 text-gray-600 inline-flex items-center">账户查询:</span>
-            <el-input type="text" class="w-50 m-2" />
-            <el-button type="primary">搜索</el-button>
+            <el-input type="text" class="w-50 m-2" v-model="search" />
+            <el-button type="primary" @click="SearchInfo">搜索</el-button>
           </el-col>
           <el-col :span="6" :offset="6"><el-button type="primary" @click="openDrawerFrom">添加</el-button></el-col>
         </el-row>
       </div>
     </template>
-    <template #right>
-      <el-button link type="primary" size="small" :icon="Edit">编辑</el-button>
-      <el-button link type="danger" size="small" :icon="Delete">删除</el-button>
+    <template #T_sex="{ row }">
+      <el-tag class="ml-2" type="success" v-if="row.T_sex === 1">男</el-tag>
+      <el-tag class="ml-2" type="danger" v-else>女</el-tag>
+    </template>
+    <template #T_expire="{ row }">
+      <el-tag class="ml-2" type="success" v-if="row.T_expire === 0">否</el-tag>
+      <el-tag class="ml-2" type="danger" v-else>是</el-tag>
+    </template>
+    <template #T_marry="{ row }">
+      <el-tag class="ml-2" type="success" v-if="row.T_marry === 0">未婚</el-tag>
+      <el-tag class="ml-2" type="danger" v-else>已婚</el-tag>
+    </template>
+    <template #T_entry_type="{ row }">
+      <el-tag class="ml-2" type="success" v-if="+row.T_entry_type === 1">全职</el-tag>
+      <el-tag class="ml-2" type="warning" v-else-if="+row.T_entry_type === 2">兼职</el-tag>
+      <el-tag class="ml-2" type="danger" v-else>实习生</el-tag>
+    </template>
+    <template #right="{ row }">
+      <el-button link type="primary" size="small" :icon="Edit" @click="EditUserInfo(row)">编辑</el-button>
+      <el-button link type="danger" size="small" :icon="Delete" @click="DeleteUserInfo(row)">删除</el-button>
     </template>
   </TableBase>
-  <DrawerFrom ref="drawerFromRef" :action="action" />
+  <DrawerFrom ref="drawerFromRef" :action="action" @onTableList="UpdateTableList" @onaction="UpdateAction" />
 </template>
 
 <style scoped lang="scss">

+ 148 - 77
src/views/account/users/components/DrawerFrom.vue

@@ -1,10 +1,16 @@
 <script setup lang="ts">
-import { ref, reactive, onMounted } from 'vue'
-import Drawer from '../../../../components/Drawer/index.vue'
+import { ref, reactive, onMounted, nextTick } from 'vue'
+import Drawer from '@/components/Drawer/index.vue'
 import { User_Power_List } from '@/api/role/index'
 import { User_Post_List, User_Add, User_Edit } from '@/api/user/index'
 import { GlobalStore } from '@/stores/index'
+import type { FormInstance, FormRules } from 'element-plus'
+import { ElMessage } from 'element-plus'
+import { reuls_validator } from './relus'
+import md5 from 'js-md5'
+
 const globalStore = GlobalStore()
+const _PASS = '******'
 let userPowerList: any = []
 const getUserPowerList = async () => {
   const res: any = await User_Power_List({ User_tokey: globalStore.GET_User_tokey, page: 1, page_z: 9999 })
@@ -15,9 +21,14 @@ const changeDept = async (val: number) => {
   const res = await User_Post_List({ T_dept: val })
   userPostList.value = res.Data
 }
+const resetForm = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.resetFields()
+}
+const formRef = ref()
 const drawerRef = ref()
-const formLabelWidth = ref('90px')
-const form = reactive({
+const formLabelWidth = ref('95px')
+let form = ref({
   T_power: '',
   T_name: '',
   T_user: '',
@@ -42,15 +53,58 @@ const form = reactive({
   T_spouse_phone: '',
   T_expire: ''
 })
+const rules = reactive<FormRules>(reuls_validator)
 type Fn = () => void
 const callbackDrawer = (done: Fn) => {
-  console.log('触发回调')
   done()
+  nextTick(() => {
+    resetForm(formRef.value)
+  })
 }
+
 const openDrawer = () => {
   drawerRef.value.openDrawer()
 }
-const AddUser = () => {}
+const AddUser = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.validate(async valid => {
+    if (valid) {
+      let res: any = {}
+      if (props.action) {
+        form.value.T_pass = md5(form.value.T_pass)
+        res = await User_Add(form.value)
+      } else {
+        form.value.T_pass === _PASS && (form.value.T_pass = '')
+        res = await User_Edit(form.value)
+      }
+      if (res.Code === 200) {
+        ElMessage({
+          type: 'success',
+          message: `${props.action ? '添加' : '编辑'}成功!`
+        })
+        nextTick(() => {
+          drawerRef.value.closeDrawer()
+          emit('onTableList')
+          resetForm(formRef.value)
+          emit('onaction', true)
+        })
+      }
+    } else {
+      console.log('error submit!')
+      return false
+    }
+  })
+}
+
+const DataEcho = async (row: any) => {
+  row.T_entry_type = +row.T_entry_type
+  row.T_pass = _PASS
+  const res = await User_Post_List({ T_dept: row.T_dept })
+  userPostList.value = res.Data
+  nextTick(() => {
+    form.value = { ...row }
+  })
+}
 
 onMounted(() => {
   if (userPowerList.length <= 0) {
@@ -58,13 +112,16 @@ onMounted(() => {
   }
 })
 
+const emit = defineEmits<{ (event: 'onTableList'): void; (event: 'onaction', val: boolean): void }>()
+
 interface PropsType {
   action: boolean
 }
-defineProps<PropsType>()
+const props = defineProps<PropsType>()
 defineExpose({
   openDrawer,
-  callbackDrawer
+  callbackDrawer,
+  DataEcho
 })
 </script>
 <template>
@@ -72,111 +129,125 @@ defineExpose({
     <template #header="{ params }">
       <h4 :id="params.titleId" :class="params.titleClass">{{ action ? '添加' : '编辑' }} - 账户管理</h4>
     </template>
-    <el-form :model="form" class="form">
-      <el-form-item label="角色权限:" :label-width="formLabelWidth">
+    <el-form :model="form" ref="formRef" :rules="rules">
+      <el-form-item label="角色权限:" :label-width="formLabelWidth" prop="T_power">
         <el-select v-model="form.T_power" placeholder="请选择角色">
           <el-option v-for="item in userPowerList" :key="item.T_id" :label="item.T_name" :value="item.T_id" />
         </el-select>
       </el-form-item>
-      <el-form-item label="名称:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_name" autocomplete="off" />
+      <el-form-item label="名称:" :label-width="formLabelWidth" prop="T_name">
+        <el-input v-model="form.T_name" autocomplete="off" placeholder="名称" />
       </el-form-item>
-      <el-form-item label="账号:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_user" autocomplete="off" />
+      <el-form-item label="账号:" :label-width="formLabelWidth" prop="T_user">
+        <el-input v-model="form.T_user" autocomplete="off" placeholder="账号" />
       </el-form-item>
-      <el-form-item label="密码:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_pass" autocomplete="off" />
+      <el-form-item label="密码:" :label-width="formLabelWidth" prop="T_pass">
+        <el-input v-model="form.T_pass" type="password" autocomplete="off" placeholder="密码" />
       </el-form-item>
-      <el-form-item label="部门:" :label-width="formLabelWidth">
+      <el-form-item label="部门:" :label-width="formLabelWidth" prop="T_dept">
         <el-select v-model="form.T_dept" placeholder="请选择部门" @change="changeDept">
           <el-option v-for="item in globalStore.GET_Dept_List" :key="item.Id" :label="item.T_name" :value="item.Id" />
         </el-select>
       </el-form-item>
-      <el-form-item label="岗位:" :label-width="formLabelWidth">
+      <el-form-item label="岗位:" :label-width="formLabelWidth" prop="T_post">
         <el-select v-model="form.T_post" placeholder="请选择岗位">
           <el-option v-for="item in userPostList" :key="item.Id" :label="item.T_name" :value="item.Id" />
         </el-select>
       </el-form-item>
-      <el-form-item label="性别:" :label-width="formLabelWidth">
+      <el-form-item label="性别:" :label-width="formLabelWidth" prop="T_sex">
         <el-radio-group v-model="form.T_sex" class="ml-4">
-          <el-radio label="1">男</el-radio>
-          <el-radio label="2">女</el-radio>
+          <el-radio :label="1">男</el-radio>
+          <el-radio :label="2">女</el-radio>
         </el-radio-group>
       </el-form-item>
-      <el-form-item label="身份证号:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_id_card" autocomplete="off" />
-      </el-form-item>
-      <el-form-item label="民族:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_nation" autocomplete="off" />
+      <el-form-item label="身份证号:" :label-width="formLabelWidth" prop="T_id_card">
+        <el-input v-model="form.T_id_card" autocomplete="off" placeholder="身份证号" />
       </el-form-item>
-      <el-form-item label="毕业院校:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_school" autocomplete="off" />
+      <el-form-item label="民族:" :label-width="formLabelWidth" prop="T_nation">
+        <el-input v-model="form.T_nation" autocomplete="off" placeholder="民族" />
       </el-form-item>
-      <el-form-item label="专业:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_major" autocomplete="off" />
+      <el-form-item label="毕业院校:" :label-width="formLabelWidth" prop="T_school">
+        <el-input v-model="form.T_school" autocomplete="off" placeholder="毕业院校" />
       </el-form-item>
-      <el-form-item label="学历:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_education" autocomplete="off" />
+      <el-form-item label="专业:" :label-width="formLabelWidth" prop="T_major">
+        <el-input v-model="form.T_major" autocomplete="off" placeholder="专业" />
       </el-form-item>
-      <el-form-item label="联系电话:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_phone" autocomplete="off" />
+      <el-form-item label="学历:" :label-width="formLabelWidth" prop="T_education">
+        <el-input v-model="form.T_education" autocomplete="off" placeholder="学历" />
       </el-form-item>
-      <el-form-item label="婚否:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_marry" autocomplete="off" />
+      <el-form-item label="联系电话:" :label-width="formLabelWidth" prop="T_phone">
+        <el-input v-model="form.T_phone" autocomplete="off" placeholder="联系电话" />
       </el-form-item>
-      <el-form-item label="入职时间:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_entry_time" autocomplete="off" />
+      <el-form-item label="婚否:" :label-width="formLabelWidth" prop="T_marry">
+        <el-radio-group v-model="form.T_marry" class="ml-4">
+          <el-radio :label="0">未婚</el-radio>
+          <el-radio :label="1">已婚</el-radio>
+        </el-radio-group>
       </el-form-item>
-      <el-form-item label="转正时间:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_positive_time" autocomplete="off" />
+      <el-form-item label="入职时间:" :label-width="formLabelWidth" prop="T_entry_time">
+        <el-date-picker
+          v-model="form.T_entry_time"
+          type="date"
+          placeholder="入职时间"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD"
+        />
+      </el-form-item>
+      <el-form-item label="转正时间:" :label-width="formLabelWidth" prop="T_positive_time">
+        <el-date-picker
+          v-model="form.T_positive_time"
+          type="date"
+          placeholder="转正时间"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD"
+        />
       </el-form-item>
       <el-form-item label="配偶姓名:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_spouse_name" autocomplete="off" />
+        <el-input v-model="form.T_spouse_name" autocomplete="off" placeholder="配偶姓名" />
       </el-form-item>
       <el-form-item label="配偶联系电话:" label-width="110px">
-        <el-input v-model="form.T_spouse_phone" autocomplete="off" />
-      </el-form-item>
-      <el-form-item label="入职类型:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_entry_type" autocomplete="off" />
-      </el-form-item>
-      <el-form-item label="劳动合同开始时间:" label-width="140px">
-        <el-input v-model="form.T_contract_start_time" autocomplete="off" />
+        <el-input v-model="form.T_spouse_phone" autocomplete="off" placeholder="配偶联系电话" />
       </el-form-item>
-      <el-form-item label="劳动合同结束时间:" label-width="140px">
-        <el-input v-model="form.T_contract_end_time" autocomplete="off" />
+      <el-form-item label="入职类型:" :label-width="formLabelWidth" prop="T_entry_type">
+        <el-radio-group v-model="form.T_entry_type" class="ml-4">
+          <el-radio :label="1">全职</el-radio>
+          <el-radio :label="2">兼职</el-radio>
+          <el-radio :label="3">实习生</el-radio>
+        </el-radio-group>
       </el-form-item>
-      <el-form-item label="是否到期:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_expire" autocomplete="off" />
+      <el-form-item label="劳动合同开始时间:" label-width="150px" prop="T_contract_start_time">
+        <el-date-picker
+          v-model="form.T_contract_start_time"
+          type="date"
+          placeholder="劳动合同开始时间"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD"
+        />
+      </el-form-item>
+      <el-form-item label="劳动合同结束时间:" label-width="150px" prop="T_contract_end_time">
+        <el-date-picker
+          v-model="form.T_contract_end_time"
+          type="date"
+          placeholder="劳动合同结束时间"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD"
+        />
+      </el-form-item>
+      <el-form-item label="是否到期:" :label-width="formLabelWidth" prop="T_expire">
+        <el-radio-group v-model="form.T_expire" class="ml-4">
+          <el-radio :label="0">否</el-radio>
+          <el-radio :label="1">是</el-radio>
+        </el-radio-group>
       </el-form-item>
-
       <el-form-item label="备注:" :label-width="formLabelWidth">
-        <el-input v-model="form.T_remark" autocomplete="off" />
+        <el-input v-model="form.T_remark" type="textarea" autocomplete="off" placeholder="备注" />
       </el-form-item>
+
       <el-form-item :label-width="formLabelWidth">
-        <el-button color="#626aef" @click="AddUser">添加</el-button>
-      </el-form-item>
-      <!-- <el-form-item label="角色名:" :label-width="formLabelWidth">
-        <el-select v-model="form.password" placeholder="请选择角色">
-          <el-option label="Area1" value="shanghai" />
-          <el-option label="Area2" value="beijing" />
-        </el-select>
+        <el-button v-if="action" color="#626aef" @click="AddUser(formRef)">添加</el-button>
+        <el-button v-else color="#626aef" @click="AddUser(formRef)">编辑</el-button>
       </el-form-item>
-      <el-form-item label="部门:" :label-width="formLabelWidth">
-        <el-select v-model="form.password" placeholder="请选择部门">
-          <el-option label="Area1" value="shanghai" />
-          <el-option label="Area2" value="beijing" />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="岗位:" :label-width="formLabelWidth">
-        <el-select v-model="form.password" placeholder="请选择岗位">
-          <el-option label="Area1" value="shanghai" />
-          <el-option label="Area2" value="beijing" />
-        </el-select>
-      </el-form-item>
-      <el-form-item :label-width="formLabelWidth">
-        <el-button color="#626aef" @click="AddUser">添加</el-button>
-      </el-form-item> -->
     </el-form>
   </Drawer>
 </template>
-<style scoped></style>
+<style scoped lang="scss"></style>

+ 69 - 0
src/views/account/users/components/relus.ts

@@ -0,0 +1,69 @@
+import type { FormRules } from 'element-plus'
+
+export const validate_T_phone = (rule: any, value: any, callback: any) => {
+  if (value === '') {
+    callback(new Error('请输入手机号码'))
+  } else {
+    if (/^[1][3,4,5,6,7,8,9][0-9]{9}$/.test(value)) {
+      callback()
+    } else {
+      callback(new Error('请输入正确的手机号码'))
+    }
+  }
+}
+
+let card_reg = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
+
+export const validate_T_id_card = (rule: any, value: any, callback: any) => {
+  if (value === '') {
+    callback(new Error('请输入身份证号码'))
+  } else {
+    if (card_reg.test(value)) {
+      callback()
+    } else {
+      callback(new Error('请输入正确的身份证号码'))
+    }
+  }
+}
+
+export const validate_T_spouse_phone = (rule: any, value: any, callback: any) => {
+  if (/^[1][3,4,5,6,7,8,9][0-9]{9}$/.test(value)) {
+    callback()
+  } else {
+    callback(new Error('请输入正确的手机号码'))
+  }
+}
+export const reuls_validator: FormRules = {
+  T_power: [{ required: true, message: '请选择角色', trigger: 'change' }],
+  T_name: [{ required: true, message: '请输入名字', trigger: 'blur' }],
+  T_user: [{ required: true, message: '请输入账户', trigger: 'blur' }],
+  T_pass: [{ required: true, message: '请输入密码', trigger: 'blur' }],
+  T_dept: [{ required: true, message: '请选择部门', trigger: 'change' }],
+  T_post: [{ required: true, message: '请选择岗位', trigger: 'change' }],
+  T_sex: [{ required: true, message: '请选择性别', trigger: 'change' }],
+  T_id_card: [{ required: true, validator: validate_T_id_card, trigger: 'blur' }],
+  T_nation: [{ required: true, message: '请输入民族', trigger: 'blur' }],
+  T_school: [{ required: true, message: '请输入毕业院校', trigger: 'blur' }],
+  T_major: [{ required: true, message: '请输入专业', trigger: 'blur' }],
+  T_education: [{ required: true, message: '请输入学历', trigger: 'blur' }],
+  T_marry: [{ required: true, message: '请选择婚否', trigger: 'change' }],
+  T_phone: [{ required: true, validator: validate_T_phone, trigger: 'blur' }],
+  T_entry_time: [{ required: true, message: '请选择入职时间', trigger: 'blur' }],
+  T_positive_time: [{ required: true, message: '请选择转正时间', trigger: 'blur' }],
+  T_entry_type: [{ required: true, message: '请选择入职类型', trigger: 'change' }],
+  T_contract_start_time: [{ required: true, message: '请选择开始时间', trigger: 'blur' }],
+  T_contract_end_time: [{ required: true, message: '请选择结束时间', trigger: 'blur' }],
+  T_expire: [{ required: true, message: '请选择是否到期', trigger: 'change' }],
+  T_spouse_phone: [{ required: true, validator: validate_T_spouse_phone, trigger: 'blur' }]
+}
+
+export const getEntry_type = (val: number) => {
+  switch (val) {
+    case 1:
+      return '全职'
+    case 2:
+      return '兼职'
+    case 3:
+      return '实习生'
+  }
+}

+ 53 - 3
src/views/salary/Salary.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import { ref, onMounted, reactive } from 'vue'
 import TableBase from '@/components/TableBase/index.vue'
-import { Salary_List, Salary_User_List } from '@/api/salary/index'
+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'
@@ -17,7 +17,10 @@ onMounted(() => {
 })
 
 // 搜索以及参数
-const columns: ColumnProps = []
+const columns: ColumnProps[] = [
+  { prop: 'T_name', label: '姓名', name: 'T_name' },
+  { prop: 'T_post_name', label: '职位' }
+]
 const searchHandle = () => {
   console.log(searchs)
 }
@@ -30,12 +33,17 @@ const initParam = {
   T_name: '',
   T_dept: ''
 }
+const getSalary = async (val: string) => {
+  const res = await Salary_Get({ T_uuid: val })
+  console.log(res)
+}
+const squareUrl = 'https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png'
 </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">
+      <TableBase :columns="columns" :requestApi="User_List" :initParam="initParam" layout="prev, pager, next">
         <template #table-header>
           <div class="input-suffix">
             <el-row :gutter="24">
@@ -58,9 +66,37 @@ const initParam = {
             </el-row>
           </div>
         </template>
+        <template #T_name="{ row }">
+          <el-button type="primary" text @click="getSalary(row.T_uuid)">{{ row.T_name }}</el-button>
+        </template>
       </TableBase></el-col
     >
     <el-col :span="16">
+      <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" />
+          <div class="info-name">
+            <h4 class="m-b-3">名字:张三</h4>
+            <h4>
+              <span>部门:软件组</span>
+              <span>岗位:前端工程师</span>
+            </h4>
+          </div>
+        </div>
+      </el-card>
+      <el-card class="m-b-3">
+        <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-col>
+          <el-col :span="10" class="d-flex">
+            <span class="demonstration">月:</span>
+            <el-date-picker v-model="value3" 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>
@@ -84,4 +120,18 @@ const initParam = {
     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;
+    }
+  }
+}
 </style>

+ 7 - 0
src/views/workAttendance/Leave.vue

@@ -0,0 +1,7 @@
+<template>
+  <div>请假审批</div>
+</template>
+
+<script setup lang="ts"></script>
+
+<style scoped></style>

+ 7 - 0
src/views/workAttendance/MyLeave.vue

@@ -0,0 +1,7 @@
+<template>
+  <div>我的请假</div>
+</template>
+
+<script setup lang="ts"></script>
+
+<style scoped></style>

+ 7 - 0
src/views/workAttendance/MyOvertime.vue

@@ -0,0 +1,7 @@
+<template>
+  <div>我的加班</div>
+</template>
+
+<script setup lang="ts"></script>
+
+<style scoped></style>

+ 7 - 0
src/views/workAttendance/Overtime.vue

@@ -0,0 +1,7 @@
+<template>
+  <div>加班审批</div>
+</template>
+
+<script setup lang="ts"></script>
+
+<style scoped></style>

+ 7 - 0
src/views/workAttendance/Records.vue

@@ -0,0 +1,7 @@
+<template>
+  <div>统筹管理</div>
+</template>
+
+<script setup lang="ts"></script>
+
+<style scoped></style>

+ 7 - 0
src/views/workAttendance/RecordsFinance.vue

@@ -0,0 +1,7 @@
+<template>
+  <div>统筹管理-财务</div>
+</template>
+
+<script setup lang="ts"></script>
+
+<style scoped></style>