Просмотр исходного кода

Merge remote-tracking branch 'origin/liuheng' into wuguojie

# Conflicts:
#	.env.development
wuguojie 1 год назад
Родитель
Сommit
6bbe55f292

+ 49 - 34
package-lock.json

@@ -1,5 +1,5 @@
 {
-  "name": "operation-Backend",
+  "name": "tenant-Platform",
   "version": "4.12.1",
   "lockfileVersion": 3,
   "requires": true,
@@ -21,6 +21,7 @@
         "eruda": "^3.4.1",
         "floating-vue": "5.2.2",
         "hotkeys-js": "^3.13.7",
+        "js-pinyin": "^0.2.7",
         "lodash-es": "^4.17.21",
         "mitt": "^3.0.1",
         "mockjs": "^1.1.0",
@@ -6407,7 +6408,7 @@
       "version": "4.1.2",
       "resolved": "https://registry.npmmirror.com/camel-case/-/camel-case-4.1.2.tgz",
       "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "pascal-case": "^3.1.2",
@@ -6452,7 +6453,7 @@
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/capital-case/-/capital-case-1.0.4.tgz",
       "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "no-case": "^3.0.4",
@@ -6485,25 +6486,12 @@
       }
     },
     "node_modules/change-case": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmmirror.com/change-case/-/change-case-4.1.2.tgz",
-      "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==",
-      "devOptional": true,
+      "version": "5.4.4",
+      "resolved": "https://registry.npmmirror.com/change-case/-/change-case-5.4.4.tgz",
+      "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==",
       "license": "MIT",
-      "dependencies": {
-        "camel-case": "^4.1.2",
-        "capital-case": "^1.0.4",
-        "constant-case": "^3.0.4",
-        "dot-case": "^3.0.4",
-        "header-case": "^2.0.4",
-        "no-case": "^3.0.4",
-        "param-case": "^3.0.4",
-        "pascal-case": "^3.1.2",
-        "path-case": "^3.0.4",
-        "sentence-case": "^3.0.4",
-        "snake-case": "^3.0.4",
-        "tslib": "^2.0.3"
-      }
+      "optional": true,
+      "peer": true
     },
     "node_modules/character-entities": {
       "version": "2.0.2",
@@ -6984,7 +6972,7 @@
       "version": "3.0.4",
       "resolved": "https://registry.npmmirror.com/constant-case/-/constant-case-3.0.4.tgz",
       "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "no-case": "^3.0.4",
@@ -7708,7 +7696,7 @@
       "version": "3.0.4",
       "resolved": "https://registry.npmmirror.com/dot-case/-/dot-case-3.0.4.tgz",
       "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "no-case": "^3.0.4",
@@ -10226,7 +10214,7 @@
       "version": "2.0.4",
       "resolved": "https://registry.npmmirror.com/header-case/-/header-case-2.0.4.tgz",
       "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "capital-case": "^1.0.4",
@@ -11834,6 +11822,12 @@
       "dev": true,
       "license": "BSD-3-Clause"
     },
+    "node_modules/js-pinyin": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmmirror.com/js-pinyin/-/js-pinyin-0.2.7.tgz",
+      "integrity": "sha512-Dbm7qJDwlC2MRHRXQo7GrVrL5w975tEOX6sfc0M8Z3oL9VhR4uUqgkwaETMqh4bAJ14w4zVs3tXsi9pDxWUmNg==",
+      "license": "MIT License"
+    },
     "node_modules/js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -12464,7 +12458,7 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/lower-case/-/lower-case-2.0.2.tgz",
       "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "tslib": "^2.0.3"
@@ -13840,7 +13834,7 @@
       "version": "3.0.4",
       "resolved": "https://registry.npmmirror.com/no-case/-/no-case-3.0.4.tgz",
       "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "lower-case": "^2.0.2",
@@ -13912,6 +13906,27 @@
         "url": "https://github.com/chalk/chalk?sponsor=1"
       }
     },
+    "node_modules/node-plop/node_modules/change-case": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmmirror.com/change-case/-/change-case-4.1.2.tgz",
+      "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "camel-case": "^4.1.2",
+        "capital-case": "^1.0.4",
+        "constant-case": "^3.0.4",
+        "dot-case": "^3.0.4",
+        "header-case": "^2.0.4",
+        "no-case": "^3.0.4",
+        "param-case": "^3.0.4",
+        "pascal-case": "^3.1.2",
+        "path-case": "^3.0.4",
+        "sentence-case": "^3.0.4",
+        "snake-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
     "node_modules/node-plop/node_modules/cli-cursor": {
       "version": "3.1.0",
       "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz",
@@ -14770,7 +14785,7 @@
       "version": "3.0.4",
       "resolved": "https://registry.npmmirror.com/param-case/-/param-case-3.0.4.tgz",
       "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "dot-case": "^3.0.4",
@@ -14892,7 +14907,7 @@
       "version": "3.1.2",
       "resolved": "https://registry.npmmirror.com/pascal-case/-/pascal-case-3.1.2.tgz",
       "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "no-case": "^3.0.4",
@@ -14919,7 +14934,7 @@
       "version": "3.0.4",
       "resolved": "https://registry.npmmirror.com/path-case/-/path-case-3.0.4.tgz",
       "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "dot-case": "^3.0.4",
@@ -16954,7 +16969,7 @@
       "version": "3.0.4",
       "resolved": "https://registry.npmmirror.com/sentence-case/-/sentence-case-3.0.4.tgz",
       "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "no-case": "^3.0.4",
@@ -17209,7 +17224,7 @@
       "version": "3.0.4",
       "resolved": "https://registry.npmmirror.com/snake-case/-/snake-case-3.0.4.tgz",
       "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "dot-case": "^3.0.4",
@@ -19277,7 +19292,7 @@
       "version": "2.8.1",
       "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
       "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
-      "devOptional": true,
+      "dev": true,
       "license": "0BSD"
     },
     "node_modules/tsx": {
@@ -20183,7 +20198,7 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/upper-case/-/upper-case-2.0.2.tgz",
       "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "tslib": "^2.0.3"
@@ -20193,7 +20208,7 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/upper-case-first/-/upper-case-first-2.0.2.tgz",
       "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "dependencies": {
         "tslib": "^2.0.3"

+ 1 - 0
package.json

@@ -35,6 +35,7 @@
     "eruda": "^3.4.1",
     "floating-vue": "5.2.2",
     "hotkeys-js": "^3.13.7",
+    "js-pinyin": "^0.2.7",
     "lodash-es": "^4.17.21",
     "mitt": "^3.0.1",
     "mockjs": "^1.1.0",

+ 23 - 0
src/api/dict.ts

@@ -0,0 +1,23 @@
+// import { ApiInstance } from './type'
+
+
+import { AxiosResponse } from 'axios';
+import api from "./index"
+
+
+
+
+// 定义获取字典项的函数
+const getDictItems = async (item:any): Promise<any> => {
+  try{
+    const response = await api.areaApi.systemList(item)
+    
+    return response.data
+    
+  }catch(error){
+    throw error;
+  }
+ 
+  
+};
+export { getDictItems };

+ 1 - 0
src/api/modules/area.ts

@@ -6,6 +6,7 @@ const areaApi = (axiosInstance: ApiInstance) => ({
 
   systemList: (params:any) => axiosInstance.get('dict/get',{ params }),
   
+  fileUpload: (data:any) => axiosInstance.post('file/upload',data,{})
 })
 
 export default areaApi

+ 2 - 0
src/api/modules/institution.ts

@@ -16,6 +16,8 @@ const institutionApi = (axiosInstance: ApiInstance) => ({
   //删除
   institutionDel: (data: institutionData) => axiosInstance.post('/dept/delete', data, {}),
 
+  //设置机构负责人
+  setDeptLeader: (data: institutionData) => axiosInstance.post('/dept/setDeptLeader', data, {})
 
 })
 

+ 15 - 1
src/api/modules/role.ts

@@ -5,7 +5,7 @@ interface roleData {
   system: string,
   permsId: number[],
   perms: string[],
-  [key:string]:any,
+  [property:string]:any,
 }
 const roleApi = (axiosInstance: ApiInstance) => ({
   // 新增角色
@@ -16,6 +16,20 @@ const roleApi = (axiosInstance: ApiInstance) => ({
 
   //查询角色信息
   roleInfo:(params: roleData) => axiosInstance.get('userRole/roleGet', {params}),
+
+  //编辑角色信息
+  roleUpdate:(data: roleData) => axiosInstance.post('userRole/roleUpdate', data,{}),
+
+  //角色删除检测
+  roleDeleteValid:(data: roleData) => axiosInstance.post('userRole/roleDeleteValid', data,{}),
+
+  //角色删除检测
+  roleDelete:(data: roleData) => axiosInstance.post('userRole/roleDelete', data,{}),
+
+  //配置路由
+  updateConfig:(data: any) => axiosInstance.post('system/updateConfig', data,{})
+  
+ 
 })
 
 export default roleApi

+ 313 - 0
src/api/modules/user.ts

@@ -10,6 +10,285 @@ interface PasswordEditData {
   password: string
   newpassword: string
 }
+/**
+ * SysUserVo,平台用户表VO
+ */
+/**
+ * SysUserVo,平台用户表VO
+ */
+export interface Request {
+  /**
+   * 用户状态 : 1 正常 0 锁定
+   */
+  accountStatus?: number;
+  /**
+   * 应聘表
+   */
+  applicant?: string;
+  /**
+   * 银行卡
+   */
+  bankCard?: string;
+  /**
+   * 银行卡号
+   */
+  bankCardId?: string;
+  /**
+   * 开户行
+   */
+  bankName?: string;
+  /**
+   * 出生日期
+   */
+  birthday?: string;
+  /**
+   * 市
+   */
+  city?: string;
+  /**
+   * 劳动合同
+   */
+  contract?: string;
+  /**
+   * 部门id
+   */
+  deptId?: string;
+  /**
+   * 区
+   */
+  district?: string;
+  /**
+   * 学历
+   */
+  education?: string;
+  /**
+   * 紧急联系人姓名
+   */
+  emergencyContactName?: string;
+  /**
+   * 紧急联系人电话
+   */
+  emergencyContactTel?: string;
+  /**
+   * 毕业时间
+   */
+  graduationTime?: string;
+  /**
+   * 健康状况
+   */
+  health?: string;
+  /**
+   * 平台用户id
+   */
+  id?: string;
+  /**
+   * 身份证号
+   */
+  identity?: string;
+  /**
+   * 身份证有效期止期
+   */
+  identityTimeEnd?: string;
+  /**
+   * 身份证有效期起期
+   */
+  identityTimeStart?: string;
+  /**
+   * 是否是计算机专业 1 是 0 否
+   */
+  isComputer?: string;
+  /**
+   * 是否启用 1 启用 0禁用
+   */
+  isEnable?: number;
+  /**
+   * 户籍
+   */
+  koseki?: string;
+  /**
+   * 领导人id
+   */
+  leaderId?: string;
+  /**
+   * 领导人姓名
+   */
+  leaderName?: string;
+  /**
+   * 离职表
+   */
+  leaveTable?: string;
+  /**
+   * 详细地址
+   */
+  liveAddress?: string;
+  /**
+   * 婚姻状况
+   */
+  maritalStatus?: string;
+  /**
+   * 手机号
+   */
+  mobile?: string;
+  /**
+   * 姓名
+   */
+  name?: string;
+  /**
+   * 民族
+   */
+  nations?: string;
+  page?: Page;
+  pages?: number;
+  /**
+   * 密码
+   */
+  password?: string;
+  /**
+   * 政治面貌
+   */
+  politicsStatus?: string;
+  /**
+   * 邮政编码
+   */
+  postalCode?: string;
+  /**
+   * 省
+   */
+  province?: string;
+  /**
+   * 展业资格证
+   */
+  qualification?: string;
+  /**
+   * 推荐人id
+   */
+  referrerId?: string;
+  /**
+   * 推荐人id
+   */
+  referrerName?: string;
+  /**
+   * 角色名称集合
+   */
+  roleNameList?: string[];
+  /**
+   * 薪资
+   */
+  salary?: string;
+  /**
+   * 薪资等级
+   */
+  salaryLevel?: string;
+  /**
+   * 定薪表
+   */
+  salaryTable?: string;
+  /**
+   * 毕业学校
+   */
+  school?: string;
+  /**
+   * 性别
+   */
+  sex?: string;
+  /**
+   * 身份证正面
+   */
+  sfz1?: string;
+  /**
+   * 身份证反面
+   */
+  sfz2?: string;
+  size?: number;
+  /**
+   * 系统编码
+   */
+  systemCode?: string;
+  /**
+   * 用户类型1.前线人员 2:后线人员 3:合伙人 4:工作室管理员 5:团队长 6:个代 7:电销 8 渠道
+   */
+  typeAttr?: string;
+  /**
+   * 平台信息id
+   */
+  userInfoId?: string;
+  /**
+   * 用户名
+   */
+  username?: string;
+  [property: string]: any;
+}
+
+/**
+* Page
+*/
+
+
+/**
+* PageObject
+*/
+
+
+/**
+* OrderItem
+*/
+
+
+/**
+* Page
+*/
+export interface Page {
+  countId?: string;
+  current?: number;
+  maxLimit?: number;
+  optimizeCountSql?: PageObject;
+  optimizeJoinOfCountSql?: boolean;
+  orders?: OrderItem[];
+  pages?: number;
+  records?: { [key: string]: any }[];
+  searchCount?: PageObject;
+  size?: number;
+  total?: number;
+  [property: string]: any;
+}
+
+/**
+* PageObject
+*/
+export interface PageObject {
+  countId?: string;
+  current?: number;
+  maxLimit?: number;
+  optimizeCountSql?: PageObject;
+  optimizeJoinOfCountSql?: boolean;
+  orders?: OrderItem[];
+  pages?: number;
+  records?: { [key: string]: any }[];
+  searchCount?: PageObject;
+  size?: number;
+  total?: number;
+  [property: string]: any;
+}
+
+/**
+* OrderItem
+*/
+export interface OrderItem {
+  asc?: boolean;
+  column?: string;
+  [property: string]: any;
+}
+
+/**
+* SysRoleVo,角色列表
+*/
+export interface SysRoleVo {
+  /**
+   * 角色id
+   */
+  id?: string;
+  [property: string]: any;
+}
 
 const userApi = (axiosInstance: ApiInstance) => ({
   // 登录
@@ -24,6 +303,40 @@ const userApi = (axiosInstance: ApiInstance) => ({
   passwordEdit: (data: PasswordEditData) => axiosInstance.post('user/password/edit', data, {
     baseURL: '/mock/',
   }),
+
+  //成员列表分页
+  memberList: (data: Page) => axiosInstance.post('/userInfo/getUserInfoList', data, { }),
+
+  //成员全部列表
+  AllMemberList: (data: SysRoleVo) => axiosInstance.post('/userInfo/getUser', data, { }),
+
+  //成员详情
+  getUserInfo: (params: Request) => axiosInstance.get('/userInfo/getUserInfo', {params}),
+
+  //编辑成员
+  updateUserInfo: (data: SysRoleVo) => axiosInstance.post('/userInfo/update', data, { }),
+
+  //获取是否可以资源转移信息
+  getTransferInfo: (params: Request) => axiosInstance.get('/userInfo/getTransferInfo', {params}),
+  
+  //资源转移
+  transfer: (data: Request) => axiosInstance.post('/userInfo/transfer', data, { }),
+
+  //检测是否可进行机构变更
+  checkChangeDept: (data: Request) => axiosInstance.post('/userInfo/checkChangeDept', data, { }),
+
+  //机构变更
+  changeDept: (data: Request) => axiosInstance.post('/userInfo/changeDept', data, { }),
+
+  //删除成员
+  userDelete: (data: {id:string[]}) => axiosInstance.post('/userInfo/delete', data, { }),
+
+  //离职
+  userQuitApply: (data: {id:string[]}) => axiosInstance.post('/userInfo/userQuitApply', data, { }),
+  
+  
+  
+  
 })
 
 export default userApi

+ 264 - 0
src/components/DialogSetDeptLeader/index.vue

@@ -0,0 +1,264 @@
+<template>
+  <div>
+    <el-dialog
+      v-model="props.dialogVisible"
+      :title="props.title"
+      width="1000"
+      append-to-body
+      draggable
+    >
+      <el-select
+        v-model="userId"
+        filterable
+        remote
+        reserve-keyword
+        placeholder="输入姓名,手机号,工号查找"
+        :remote-method="remoteMethod"
+        :loading="loading"
+        style="width: 240px"
+        clearable
+      >
+        <el-option
+          v-for="item in options"
+          :key="item.value"
+          :label="`${item.label}-${item.mobile}`"
+          :value="item.value"
+        >
+        </el-option>
+      </el-select>
+      <div class="dialog-mian">
+        <div v-show="userId == '' || userId == null">
+          <el-tree
+            ref="treeRef"
+            style="max-width: 600px"
+            class="filter-tree"
+            :data="deptList"
+            :props="defaultProps"
+            :default-expand-all="true"
+            :expand-on-click-node="false"
+            @node-click="treeClick"
+          >
+          </el-tree>
+        </div>
+        <div>
+          <el-radio-group v-model="userId" v-show="userId">
+            <div style="display: flex; flex-direction: column">
+              <el-radio
+                v-for="item in options"
+                :key="item.value"
+                :value="item.value"
+                style="margin-bottom: 15px"
+              >
+                <p style="margin: 0">{{ item.label }}</p>
+                <p style="margin: 0">{{ item.value }}</p>
+              </el-radio>
+            </div>
+          </el-radio-group>
+
+          <el-radio-group v-model="treeReId" v-show="userList.length > 0 && !userId">
+            <div style="display: flex; flex-direction: column">
+              <el-radio
+                v-for="item in userList"
+                :key="item.id"
+                :value="item.id"
+                style="margin-bottom: 15px"
+              >
+                <p style="margin: 0">{{ item.name }}</p>
+                <p style="margin: 0">{{ item.id }}</p>
+              </el-radio>
+            </div>
+          </el-radio-group>
+        </div>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="dialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="submit">
+            确认
+          </el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { defineProps, ref, onMounted, defineEmits } from "vue";
+import api from "@/api";
+type tableType = {
+  id: string;
+  name: string;
+};
+
+const defaultProps = {
+  children: "children",
+  label: "name",
+};
+const props = defineProps<{
+  dialogVisible: boolean;
+  deptIds: Array<[]>;
+  deptList: Array<tableType>;
+  title: string;
+}>();
+
+interface ListItem {
+  value: string;
+  label: string;
+}
+
+const list = ref<ListItem[]>([]);
+const options = ref<ListItem[]>([]);
+const userId = ref<string>("");
+const loading = ref(false);
+const treeReId=ref<string>("");
+
+const emits=defineEmits(["closeDialog"]);
+
+
+const userList = ref<any[]>([]);
+const remoteMethod = (query: string) => {
+  if (query) {
+    loading.value = true;
+    api.userApi
+      .AllMemberList({
+        name: query,
+      })
+      .then((res: any) => {
+        
+        if (res.code === 200) {
+          // userList.value = res.data;
+          let arr: any = [];
+          res.data.forEach((item) => {
+            arr.push({
+              label: item.name,
+              value: item.id,
+              mobile: item.mobile,
+            });
+          });
+          loading.value = false;
+          options.value = arr;
+        }
+      });
+    // setTimeout(() => {
+    //   loading.value = false
+    //   options.value = list.value.filter((item) => {
+    //     return item.label.toLowerCase().includes(query.toLowerCase())
+    //   })
+    // }, 200)
+  } else {
+    options.value = [];
+  }
+};
+function treeClick(node: any) {
+  api.userApi
+    .AllMemberList({
+      deptId: node.id,
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        userList.value = res.data;
+
+        // options.value=arr
+      }
+    });
+}
+
+function submit(){
+ 
+  if(props.title=='设置负责人'){
+    if(userId.value){
+      
+     const obj=options.value.map((item:any)=>{
+        if(item.value==userId.value){
+          return {
+            name:item.label,
+            id:item.value,
+            mobile:item.mobile
+          }
+        }
+      })
+      api.institutionApi.setDeptLeader({
+        deptId:props.deptIds,
+        leaderId:obj[0].userId
+      }).then(res=>{
+        
+        if(res.code==200){
+          emits('closeDialog')
+        }
+      })
+      
+      
+    }else{
+      let flag={}
+     userList.value.some((item:any)=>{
+     
+         if( item.id==treeReId.value){
+          flag={...item}
+          return true
+         }
+         return false
+        
+      })
+    
+      api.institutionApi.setDeptLeader({
+        deptId:props.deptIds,
+        leaderId:flag.userId
+      }).then(res=>{
+        if(res.code==200){
+          emits('closeDialog')
+        }
+      })
+      // emits('closeDialog',flag)
+    }
+  }else{
+    if(userId.value){
+     const obj=options.value.map((item:any)=>{
+        if(item.value==userId.value){
+          return {
+            name:item.label,
+            id:item.value,
+            mobile:item.mobile
+          }
+        }
+      })
+      
+      emits('closeDialog',obj[0])
+    }else{
+      let flag={}
+      userList.value.some((item:any)=>{
+     
+         if( item.id==treeReId.value){
+          flag={...item}
+          return true
+         }
+         return false
+        
+      })
+      emits('closeDialog',flag)
+    }
+  }
+ 
+   
+}
+
+
+</script>
+<style lang="scss" scoped>
+.dialog-mian {
+  display: flex;
+  border: 1px solid #ccc;
+  border-radius: 10px;
+  min-height: 500px;
+  margin-top: 20px;
+  > div {
+    flex: 1;
+    padding: 15px;
+    box-sizing: border-box;
+    max-height: 500px;
+    overflow-y: auto;
+  }
+  > div:last-child {
+    border-left: 1px solid #ccc;
+  }
+}
+</style>

+ 173 - 168
src/components/Table/index.vue

@@ -1,185 +1,190 @@
-<<<<<<< HEAD
-
 <template>
-	<div class="container">
-		<div class="table_box">
+  <div class="container">
+    <div class="table_box">
       <div class="table-title-btn">
         <slot name="table-title-btn"></slot>
       </div>
-			<el-table ref="multipleTableRef"  :header-cell-style="{'background-color': '#f2f2f2'}" :data="props.tableData" style="width: 100%">
-				<el-table-column type="selection" v-if="showSelect" :selectable="selectable" width="55" />
+      <el-table
+        ref="multipleTableRef"
+        :header-cell-style="{ 'background-color': '#f2f2f2' }"
+        :data="props.tableData"
+        style="width: 100%"
+        row-key="id"
+        :tree-props="props.treeProps"
+      >
+        <el-table-column
+          type="selection"
+          v-if="showSelect"
+          :selectable="selectable"
+          width="55"
+        />
+
+        <el-table-column
+          v-if="showIndex"
+          type="index"
+          label="序号"
+          width="55"
+        />
+        <el-table-column
+          v-for="column in columns"
+          :key="column.prop"
+          :prop="column.prop"
+          :label="column.label"
+          :sortable="column.sortable ? 'custom' : false"
+          :width="column.width"
+        >
+          <template #header>
+            <slot name="search" :slotData="column"></slot>
+          </template>
+          <template #default="scope">
+            
+          
+              
+              <component v-if="column.formatter" :is="column.formatter(scope.row, column, scope.row[column.prop], scope.$index)" class="routerlick" />
+              <span v-else>{{ scope.row[column.prop] }}</span>
+            
+            
+          </template>
+        </el-table-column>
+        <el-table-column label="操作">
+          <template #default="scope">
+            <slot name="operation" :operationData="scope"></slot>
+          </template>
+          <!-- <template #default="scope">
+						<div v-if="scope.row._edit">
+							<el-button type="primary" @click="handleSave(scope)"> 保存 </el-button>
+							<el-button @click="handleCancle(scope)"> 取消 </el-button>
+						</div>
+						<el-button v-else type="primary" @click="handleEdit(scope)"> 编辑 </el-button>
+					</template> -->
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="page_box" v-show="props.pageInfo.show">
+      <el-pagination
 
-				<el-table-column v-if="showIndex" type="index" label="序号" width="55" />
-				<el-table-column
-					v-for="column in columns"
-					:key="column.prop"
-					:prop="column.prop"
-					:label="column.label"
-					:sortable="column.sortable ? 'custom' : false"
-					:width="column.width"
-				>
-					<template #header>
-						<slot name="search" :slotData="column"></slot>
-					</template>
-					<template #default="{ row }">
-						<template v-if="row._edit">
-							<el-input
-								v-if="
-									column.prop === 'Date' || column.prop === 'Name' || column.prop === 'Organization'
-								"
-								v-model="row[column.prop]"
-							/>
-							<el-select v-if="column.prop === 'Tag'" v-model="Tagvalue">
-								<el-option
-									v-for="(type, label) in tagTypes"
-									:key="label"
-									:label="label"
-									:value="label"
-								/>
-							</el-select>
-						</template>
-						<template v-else>
-							<span v-if="column.prop !== 'Tag'">{{ row[column.prop] }}</span>
-							<el-tag v-if="column.prop === 'Tag'" :type="getTagType(row[column.prop])">{{
-								row[column.prop]
-							}}</el-tag>
-						</template>
-					</template>
-				</el-table-column>
-				<el-table-column label="操作">
-                    <template #default="scope">
-                        <slot name="operation" :operationData="scope"></slot>
-                    </template>
-				</el-table-column>
-			</el-table>
-		</div>
-		<div class="page_box">
-			<el-pagination
-                v-model:current-page="props.pageInfo.pageNum"
-                v-model:page-size="props.pageInfo.pageSize"
-                :page-sizes="props.pageInfo.sizes"
-                layout="total, sizes, prev, pager, next, jumper"
-                :total="props.pageInfo.total"
-                @size-change="handleSizeChange"
-                @current-change="handleCurrentChange"
-            />
-		</div>
-	</div>
+        v-model:current-page="props.pageInfo.pageNum"
+        v-model:page-size="props.pageInfo.pageSize"
+        :page-sizes="props.pageInfo.sizes"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="props.pageInfo.total"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+    </div>
+  </div>
 </template>
 
 <script lang="ts" setup>
-	import { defineProps, ref, onMounted,defineEmits  } from "vue";
-	import type { TableInstance } from "element-plus";
-
-	interface TableRow {
-		[key: string]: any;
-	}
-    interface TagTypes{
-        [key:string]:string;
-    }
-    const emit = defineEmits(['getList']);
-	const props = defineProps<{
-		tableData: Array<TableRow>;
-		columns: {
-			prop: string;
-			label: string;
-			sortable?: boolean;
-			width?: string;
-			style?: string;
-		}[];
-        pageInfo:{
-            pageNum: number;
-            pageSize: number;
-            sizes: number[];
-            total: number;
-        };
-        showSelect:boolean;
-        showIndex:boolean;
-
-	}>();
-	const multipleTableRef = ref<TableInstance>();
-	const TableData = ref<TableRow[]>();
-	onMounted(() => {
-		let counter = 1;
-		TableData.value = props.tableData.map((row) => ({
-			...row,
-			_edit: false, // 设置默认非编辑状态
-			counter: counter++
-		}));
-	});
-	const selectable = () => true;
-	const Tagvalue = ref("");
-	const tagTypes:TagTypes = {
-		'公司': "primary",
-		'甲方': "success",
-		'合作伙伴': "primary"
-	};
-    const handleSizeChange = (val: number) => {
-
-        props.pageInfo.pageSize=val
-
-        emit('getList', props.pageInfo);
-    }
-    const handleCurrentChange = (val: number) => {
+import { defineProps, ref, onMounted, defineEmits } from "vue";
+import type { TableInstance } from "element-plus";
 
-        props.pageInfo.pageNum=val
-        emit('getList', props.pageInfo);
+interface TableRow {
+  [key: string]: any;
+}
+interface TagTypes {
+  [key: string]: string;
+}
+const emit = defineEmits(["getList"]);
+const props = defineProps<{
+  tableData: Array<TableRow>;
+  columns: {
+    prop: string;
+    label: string;
+    sortable?: boolean;
+    width?: string;
+    style?: string;
+    formatter?: (row: any, column: any, cellValue: any, index: number) => any;
+  }[];
+  pageInfo: {
+    pageNum: number;
+    pageSize: number;
+    sizes: number[];
+    total: number;
+    show:boolean;
+  };
+  showSelect: boolean;
+  showIndex: boolean;
+  treeProps:{}
+}>();
+const multipleTableRef = ref<TableInstance>();
+const TableData = ref<TableRow[]>();
+onMounted(() => {
+  let counter = 1;
+  TableData.value = props.tableData.map((row) => ({
+    ...row,
+    _edit: false, // 设置默认非编辑状态
+    counter: counter++,
+  }));
+});
+const selectable = () => true;
+const Tagvalue = ref("");
+const tagTypes: TagTypes = {
+  公司: "primary",
+  甲方: "success",
+  合作伙伴: "primary",
+};
+const handleSizeChange = (val: number) => {
+  props.pageInfo.pageSize = val;
 
-
-    }
-	const getTagType = (tag: string) => {
-		return tagTypes[tag] || tagTypes["公司"];
-	};
-	const handleEdit = (scope: { row: TableRow }) => {
-		Tagvalue.value = scope.row.Tag || "";
-		scope.row._edit = true;
-	};
-	const handleSave = (scope: { row: TableRow }) => {
-		scope.row.Tag = Tagvalue.value;
-		scope.row._edit = false;
-	};
-	const handleCancle = (scope: { row: TableRow }) => {
-		scope.row._edit = false;
-	};
-  const headClass= (scope: { row: TableRow }) =>  {
-      // return 'background:#F8F8F9'
-    }
+  emit("getList", props.pageInfo);
+};
+const handleCurrentChange = (val: number) => {
+  props.pageInfo.pageNum = val;
+  emit("getList", props.pageInfo);
+};
+const getTagType = (tag: string) => {
+  return tagTypes[tag] || tagTypes["公司"];
+};
+const handleEdit = (scope: { row: TableRow }) => {
+  Tagvalue.value = scope.row.Tag || "";
+  scope.row._edit = true;
+};
+const handleSave = (scope: { row: TableRow }) => {
+  scope.row.Tag = Tagvalue.value;
+  scope.row._edit = false;
+};
+const handleCancle = (scope: { row: TableRow }) => {
+  scope.row._edit = false;
+};
+const headClass = (scope: { row: TableRow }) => {
+  // return 'background:#F8F8F9'
+};
 </script>
 <style lang="scss" scoped>
-	.container {
-		width: 100%;
-		height: auto;
-		margin: 5px;
-		display: flex;
-		flex-direction: column;
-	}
- .table_box {
-		flex: 1;
-		margin-bottom: 10px;
-		overflow-y: auto;
-		.table_item_container {
-			margin-left: 20px;
-			padding: 0;
-			.table_item {
-				margin: 5px 0;
-			}
-		}
-    :deep(.cell){
-      display: flex;
-      align-items: center;
-      justify-content: center;
-    }
-    .table-title-btn {
-      margin-bottom: 20px;
-      :deep(.el-button){
-        margin-right: 20px;
-      }
+.container {
+  width: 100%;
+  height: auto;
+  margin: 5px;
+  display: flex;
+  flex-direction: column;
+}
+.table_box {
+  flex: 1;
+  margin-bottom: 10px;
+  overflow-y: auto;
+  .table_item_container {
+    margin-left: 20px;
+    padding: 0;
+    .table_item {
+      margin: 5px 0;
     }
-
-	}
-  .page_box{
+  }
+  :deep(.cell) {
     display: flex;
     align-items: center;
-    justify-content: flex-end;
+    justify-content: center;
+  }
+  .table-title-btn {
+    margin-bottom: 20px;
+    :deep(.el-button) {
+      margin-right: 20px;
+    }
   }
+}
+.page_box {
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+}
 </style>

+ 1 - 0
src/main.ts

@@ -39,6 +39,7 @@ app.use(Message)
 app.use(pinia)
 app.use(router)
 app.use(ui)
+
 directive(app)
 if (icons.isOfflineUse) {
   for (const info of icons.collections) {

+ 22 - 3
src/router/modules/personnel.ts

@@ -18,17 +18,36 @@ const routes: RouteRecordRaw = {
       meta: {
         title: '成员管理',
 
-
       },
+      children:[
+        {
+          path: 'memberMessage',
+          name: 'personnelMemberMessage',
+          component: () => import('@/views/personnel/modules/memberMessage.vue'),
+          meta: {
+            title: '成员详情',
+            menu:false
+          }, 
+        },
+        {
+          path: 'memberEdit',
+          name: 'personnelMemberEdit',
+          component: () => import('@/views/personnel/modules/addOperation.vue'),
+          meta: {
+            title: '成员管理',
+            menu:false
+          }, 
+        },
+      ]
     },
+    
+    
     {
       path: 'institution',
       name: 'personnelInstitution',
       component: () => import('@/views/personnel/institutionManage.vue'),
       meta: {
         title: '机构管理',
-
-
       },
     },
     {

+ 1 - 0
src/types/components.d.ts

@@ -8,6 +8,7 @@ export {}
 declare module 'vue' {
   export interface GlobalComponents {
     Auth: typeof import('./../components/Auth/index.vue')['default']
+    DialogSetDeptLeader: typeof import('./../components/DialogSetDeptLeader/index.vue')['default']
     FileUpload: typeof import('./../components/FileUpload/index.vue')['default']
     FixedActionBar: typeof import('./../components/FixedActionBar/index.vue')['default']
     HButton: typeof import('./../layouts/ui-kit/HButton.vue')['default']

+ 5 - 4
src/utils/composables/routeUtils.ts

@@ -26,11 +26,11 @@ export interface TreeNode {
   [key: string]: any; // 允许任意其他属性
 }
 
-let idCounter = 0;
+let idCounter = ref(0);
 
 // 生成唯一 ID
 const generateId = (): number => {
-  return ++idCounter;
+  return ++idCounter.value;
 };
 
 // 预处理函数:确保 children 和 auth 类型正确
@@ -73,7 +73,8 @@ const parseAuthToChildren = (authList: string[]): TreeNode[] => {
 };
 
 // 将 RouteItem 转换为 TreeNode
-export const convertToTreeData = (routes: RouteItem[]): TreeNode[] => {
+export const convertToTreeData = (id:number,routes: RouteItem[]): TreeNode[] => {
+  idCounter.value=id;
   return routes.map(route => {
     const node: TreeNode = {
       id: generateId(),
@@ -83,7 +84,7 @@ export const convertToTreeData = (routes: RouteItem[]): TreeNode[] => {
     };
 
     if (route.children && route.children.length > 0) {
-      node.children = convertToTreeData(route.children);
+      node.children = convertToTreeData(idCounter.value,route.children);
     }
 
     if (route.meta?.auth) {

+ 58 - 31
src/views/personnel/institutionManage.vue

@@ -30,6 +30,7 @@
         :pageInfo="pageInfo"
         @getList="getList"
         :treeProps="{ children: 'children', hasChildren: 'hasChildren' }"
+        
       >
         <template v-slot:table-title-btn>
           <div>
@@ -45,7 +46,7 @@
               <template #dropdown>
                 <el-dropdown-menu>
                   <el-dropdown-item>删除</el-dropdown-item>
-                  <el-dropdown-item>设置负责人</el-dropdown-item>
+                  <el-dropdown-item v-on:click="manySetDeptUser()">设置负责人</el-dropdown-item>
                 </el-dropdown-menu>
               </template>
             </el-dropdown>
@@ -69,7 +70,7 @@
                 <el-dropdown-item v-on:click="del(scope.operationData.row)">
                   删除
                 </el-dropdown-item>
-                <el-dropdown-item command="set">设置负责人</el-dropdown-item>
+                <el-dropdown-item v-on:click="setDeptUser(scope.operationData.row)">设置负责人</el-dropdown-item>
               </el-dropdown-menu>
             </template>
           </el-dropdown>
@@ -184,10 +185,10 @@
                 clearable
               >
                 <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value"
+                  v-for="item in memberList"
+                  :key="item.id"
+                  :label="item.name"
+                  :value="item.id"
                 />
               </el-select>
             </el-form-item>
@@ -203,6 +204,12 @@
         </div>
       </template>
     </el-dialog>
+    <setDept :dialogVisible="deptDialogVisible"
+      :dept-list="tableData"
+      :dept-ids="deptIdList"
+      :title="'设置负责人'"
+      @close-dialog="confirmCharge"
+    ></setDept>
   </div>
 </template>
 
@@ -216,7 +223,7 @@ import type Node from "element-plus/es/components/tree/src/model/node";
 import { ElMessage, ElMessageBox, ElPopconfirm, ElTree } from "element-plus";
 import api from "@/api";
 import { h } from "vue";
-
+import setDept from "@/components/DialogSetDeptLeader/index.vue"
 interface Tree {
   [key: string]: any;
 }
@@ -228,6 +235,27 @@ const defaultProps = {
   children: "children",
   label: "label",
 };
+//设置负责人弹框
+const deptDialogVisible=ref(false)
+const deptIdList=ref([])
+function setDeptUser(item:any){
+  
+  deptIdList.value=[item.id]
+  deptDialogVisible.value=true
+}
+
+//批量设置负责人
+
+function manySetDeptUser(){
+  
+  // deptIdList.value=[item.id]
+  // deptDialogVisible.value=true
+}
+
+function confirmCharge(){
+  deptDialogVisible.value=false
+}
+
 
 watch(filterText, (val) => {
   treeRef.value!.filter(val);
@@ -265,31 +293,11 @@ interface PageInfo {
   pageSize: number;
   sizes: number[];
   total: number;
+  show:boolean;
 }
 const value = ref("");
 const dialogVisible = ref(false);
-const options = [
-  {
-    value: "Option1",
-    label: "Option1",
-  },
-  {
-    value: "Option2",
-    label: "Option2",
-  },
-  {
-    value: "Option3",
-    label: "Option3",
-  },
-  {
-    value: "Option4",
-    label: "Option4",
-  },
-  {
-    value: "Option5",
-    label: "Option5",
-  },
-];
+
 
 const rules = reactive<FormRules<RuleForm>>({
   name: [
@@ -344,7 +352,7 @@ const columns = [
     },
   },
   { prop: "address", label: "所属地区" },
-  { prop: "status", label: "负责人" },
+  { prop: "leaderHame", label: "负责人" },
 ];
 
 const pageInfo = {
@@ -352,6 +360,7 @@ const pageInfo = {
   pageSize: 10,
   sizes: [10, 20, 30, 40, 50],
   total: 100,
+  show:false
 };
 //分页列表功能
 const getList = (item: PageInfo) => {
@@ -517,6 +526,19 @@ const getInstitutionList = () => {
   // pageInfo.pageSize=item.pageSize
 };
 
+//成员列表
+const memberList=ref([])
+const getAllMemberList = () => {
+  // pageInfo.pageNum=item.pageNum
+  api.userApi.AllMemberList({}).then((res:any) => {
+    
+    if(res.code===200)
+    memberList.value=res.data
+  });
+  // pageInfo.pageSize=item.pageSize
+};
+
+
 const confirm = async (formEl: FormInstance | undefined) => {
   if (!formEl) return;
   await formEl.validate((valid, fields) => {
@@ -532,6 +554,7 @@ const confirm = async (formEl: FormInstance | undefined) => {
             province: form.area[0],
             city: form.area[1],
             area: form.area[2],
+            parentId:obj.parentId[obj.parentId.length-1]
           })
           .then((res) => {
             if (res.code === 200) {
@@ -548,12 +571,15 @@ const confirm = async (formEl: FormInstance | undefined) => {
             province: form.area[0],
             city: form.area[1],
             area: form.area[2],
+            parentId:obj.parentId[obj.parentId.length-1]
+
           })
           .then((res) => {
-            console.log(res);
+           
             if (res.code === 200) {
               ElMessage.success("操作成功");
               dialogVisible.value = false;
+              getInstitutionList(); //机构列表
             }
           });
       }
@@ -578,6 +604,7 @@ onMounted(() => {
   getAreaList(); //省市区级联数据
   getSystemList(); //机构类型字典
   getExhibitionScopeSystemList(); //展业范围字段
+  getAllMemberList();//成员列表
 });
 </script>
 <style lang="scss" scoped>

+ 146 - 199
src/views/personnel/memberManagement.vue

@@ -7,17 +7,23 @@
         placeholder="姓名,手机号,工号查询"
         :prefix-icon="Search"
       />
-
+      <div style="display: flex;justify-content: space-between;margin: 10px 0;">
+        <!-- <el-button type="primary" link @click="$router.push({path:'/personnel/institution'})">机构管理</el-button> -->
+        <el-button type="primary" link @click="expandTree">
+        
+          {{ isExpand?'全部收起':'全部展开' }}
+        </el-button>
+      </div>
       <el-tree
         ref="treeRef"
         style="max-width: 600px"
         class="filter-tree"
-        :data="data"
+        :data="deptTreeData"
         :props="defaultProps"
-        default-expand-all
+        :default-expand-all="isExpand"
         :filter-node-method="filterNode"
         :expand-on-click-node="false"
-      >
+        >
         <template #default="{ node, data }">
           <span class="custom-tree-node">
             <span>{{ node.label }}</span>
@@ -40,40 +46,7 @@
       </el-tree>
     </div>
     <div class="member-main">
-      <!-- <el-form label-position="left" label-width="auto">
-        <el-row :gutter="16">
-          <el-col :span="6">
-            <el-form-item label="成员信息">
-              <el-input
-                v-model="formAccessibility.firstName"
-                placeholder="输入姓名,手机号,工号查询"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="6">
-            <el-form-item label="状态">
-              <el-select
-                v-model="value"
-                placeholder="成员状态"
-                style="width: 240px"
-              >
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value"
-                />
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="4">
-            <el-form-item label="">
-              <el-button type="primary">查询</el-button>
-              <el-button type="primary" plain @click="reset">重置</el-button>
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form> -->
+      
 
       <Table
         :tableData="tableData"
@@ -113,7 +86,7 @@
         </template>
         <template v-slot:operation="scope">
           <el-button type="primary" link @click="editor(scope)">
-            编辑
+            详情
           </el-button>
           <el-dropdown placement="bottom-start">
             <span class="el-dropdown-link"> 更 多 </span>
@@ -131,82 +104,67 @@
         </template>
       </Table>
     </div>
+    
 
-    <el-dialog v-model="dialogVisible" title="基本信息" width="800" draggable>
-      <el-form
-        label-position="top"
-        label-width="auto"
-        :rules="rules"
-        :model="form"
-        ref="ruleFormRef"
-      >
-        <el-row :gutter="24">
-          <el-col :span="12">
-            <el-form-item label="姓名" prop="name">
-              <el-input
-                v-model.trim="form.name"
-                maxlength="20"
-                placeholder="输入人员姓名"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="手机号" prop="phone">
-              <el-input
-                v-model.number.trim="form.phone"
-                maxlength="11"
-                placeholder="输入人员手机号"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="登录密码" prop="password">
-              <el-input
-                v-model.trim="form.password"
-                maxlength="20"
-                placeholder="输入登录密码(8-20位,包含字母和数字)"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="角色" prop="role">
-              <el-select
-                v-model="form.role"
-                placeholder="选择角色"
-                style="width: 240px"
-              >
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value"
-                />
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button @click="dialogVisible = false">取 消</el-button>
-          <el-button type="primary" @click="dialogVisible = false">
-            保 存
-          </el-button>
-        </div>
-      </template>
-    </el-dialog>
+    <!-- <el-dialog v-model="dialogVisible" title="基本信息" width="800" draggable> -->
+      <!-- <addOperation @closeDialog="closeAddOperation"></addOperation> -->
+      
+    <!-- </el-dialog> -->
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, watch } from "vue";
+import { ref, reactive, watch,onMounted ,h} from "vue";
+import {useRouter} from "vue-router"
 import type { ComponentSize, FormInstance, FormRules } from "element-plus";
 import { Plus, Search } from "@element-plus/icons-vue";
 
+
 import type Node from "element-plus/es/components/tree/src/model/node";
 // import universalTable from "../"
 import { ElTree } from "element-plus";
+import api from "@/api";
+import { getDictItems } from "@/api/dict";
+interface dictType {
+  value: string;
+  id: string;
+  label: string;
+
+  [property: string]: any;
+}
+onMounted(async () => {
+  // 对 asyncRoutes 进行预处理并转换为树形结构
+
+
+  getInstitutionList();
+  getUserList()
+  statusList.value = await getDictItems({ dictCode: "person_status" });
+  
+ 
+});
 
+//性别字典
+const statusList = ref<dictType[]>([]);
+//机构列表
+
+type tableType = {
+  id: string;
+  name: string;
+};
+//获取机构列表
+const deptTreeData = ref<tableType[]>([]);
+
+const getInstitutionList = () => {
+  // pageInfo.pageNum=item.pageNum
+  api.institutionApi.institutionList({}).then((res) => {
+    // if(res.code===200){
+
+    // }
+    deptTreeData.value = [...res.data];
+    // deptTreeData.value = JSON.parse(JSON.stringify(res.data));
+  });
+  // pageInfo.pageSize=item.pageSize
+};
 interface Tree {
   [key: string]: any;
 }
@@ -216,7 +174,7 @@ const treeRef = ref<InstanceType<typeof ElTree>>();
 
 const defaultProps = {
   children: "children",
-  label: "label",
+  label: "name",
 };
 
 watch(filterText, (val) => {
@@ -224,59 +182,23 @@ watch(filterText, (val) => {
 });
 
 const filterNode = (value: string, data: Tree) => {
+  // console.log(data)
   if (!value) return true;
-  return data.label.includes(value);
+  return data.name.includes(value);
 };
-const data: Tree[] = [
-  {
-    id: 1,
-    label: "Level one 1",
-    children: [
-      {
-        id: 4,
-        label: "Level two 1-1",
-        children: [
-          {
-            id: 9,
-            label: "Level three 1-1-1",
-          },
-          {
-            id: 10,
-            label: "Level three 1-1-2",
-          },
-        ],
-      },
-    ],
-  },
-  {
-    id: 2,
-    label: "Level one 2",
-    children: [
-      {
-        id: 5,
-        label: "Level two 2-1",
-      },
-      {
-        id: 6,
-        label: "Level two 2-2",
-      },
-    ],
-  },
-  {
-    id: 3,
-    label: "Level one 3",
-    children: [
-      {
-        id: 7,
-        label: "Level two 3-1",
-      },
-      {
-        id: 8,
-        label: "Level two 3-2",
-      },
-    ],
-  },
-];
+//全部展示机构树,或全部收起
+const isExpand=ref(false)
+function expandTree(){
+  // console.log(treeRef.value)
+  
+
+  isExpand.value=!isExpand.value
+  // treeRef.value!.defaultExpandAll=!isExpand.value;
+  const nodes = treeRef.value?.store._getAllNodes();
+  if (nodes) {
+    nodes.forEach((item: any) => item.expanded = isExpand.value);
+  }
+}
 
 const formAccessibility = reactive({
   fullName: "",
@@ -303,31 +225,11 @@ interface PageInfo {
   pageSize: number;
   sizes: number[];
   total: number;
+  show:boolean
 }
-const value = ref("");
+
 const dialogVisible = ref(false);
-const options = [
-  {
-    value: "Option1",
-    label: "Option1",
-  },
-  {
-    value: "Option2",
-    label: "Option2",
-  },
-  {
-    value: "Option3",
-    label: "Option3",
-  },
-  {
-    value: "Option4",
-    label: "Option4",
-  },
-  {
-    value: "Option5",
-    label: "Option5",
-  },
-];
+
 const validatePhone = (rule: any, value: string, callback: any) => {
   const reg = /^1[3-9]\d{9}$/;
   if (!value) {
@@ -359,21 +261,34 @@ const rules = reactive<FormRules<RuleForm>>({
 });
 // import Select from "@/components/select/selectMain.vue";
 // import TestTable from "@/components/Table/index.vue";
-const tableData = [
-  {
-    size: "2024/12/1",
-    Name: "Dec",
-    Phone: "13333333333",
-    role: "公司",
-    status: "123",
-  },
-];
+
+interface Page {
+   
+   [key: string]: any 
+   
+}
+const tableData = ref<Page>([])
 const columns = [
-  { prop: "Name", label: "姓名" },
-  { prop: "Phone", label: "手机号" },
-  { prop: "size", label: "工号" },
-  { prop: "role", label: "角色" },
-  { prop: "status", label: "状态" },
+  { prop: "name", label: "姓名" },
+  { prop: "mobile", label: "手机号" },
+  { prop: "deptName", label: "所属机构" },
+  { prop: "userId", label: "工号" },
+  { prop: "roleName", label: "角色" },
+  { prop: "status", label: "状态",
+  formatter: (row: any, column: any, cellValue: any) => {
+    // console.log(row)
+      let comType = "";
+      statusList.value.forEach((item:any)=>{
+        if(item.value==row.status){
+          comType=item.label
+        }
+      })
+        
+      
+
+      return () => h("div", {}, comType);
+    },
+   },
   // { prop: "operation", label: "操作",fixed:true },
 
   // {
@@ -384,29 +299,57 @@ const columns = [
   //     }]
   // },
 ];
-const pageInfo = {
+const pageInfo =reactive( {
   pageNum: 1,
   pageSize: 10,
   sizes: [10, 20, 30, 40, 50],
-  total: 100,
-};
+  total: 0,
+  show:true
+});
 const getList = (item: PageInfo) => {
   pageInfo.pageNum = item.pageNum;
   pageInfo.pageSize = item.pageSize;
 };
+
+const getUserList= () => {
+  api.userApi.memberList({
+    ...pageInfo
+  }).then((res:any)=>{
+    console.log(res)
+    if(res.code===200){
+      tableData.value=res.data.records
+      pageInfo.total=res.data.total
+    }
+  })
+};
 const editor = (item: any) => {
-  dialogVisible.value = true;
+  console.log(item)
+  router.push({
+    path:"/personnel/member/memberMessage",
+    query:{
+      id:item.operationData.row.userId
+    }
+  })
   // pageInfo.pageNum=item.pageNum
   // pageInfo.pageSize=item.pageSize
 };
+const router=useRouter()
 const add = (formEl: FormInstance | undefined) => {
-  dialogVisible.value = true;
+  
+  
+  router.push({
+    path:"/personnel/member/memberEdit"
+  })
   if (!formEl) return;
   formEl.resetFields();
   // pageInfo.pageNum=item.pageNum
   // pageInfo.pageSize=item.pageSize
 };
 
+const closeAddOperation = (bool: boolean) => {
+  dialogVisible.value = bool
+}
+
 const operationMany = (item: any) => {
   // pageInfo.pageNum=item.pageNum
   // pageInfo.pageSize=item.pageSize
@@ -433,7 +376,11 @@ const reset = (item: any) => {
   // ElMessage({})
 };
 </script>
-<style lang="scss" scoped>
+<style lang="scss" scoped>、
+:deep(.date-picker-custom.el-input__inner){
+  display: flex;
+  flex-direction: row-reverse;
+}
 :deep(.table-title-btn){
   display: flex;
   align-items: center;
@@ -451,7 +398,7 @@ const reset = (item: any) => {
   display: flex;
   .member-tree {
     flex: none;
-    width: 20%;
+    width: 18%;
     padding: 20px;
     box-sizing: border-box;
     border-right: 1px solid #ccc;

+ 1127 - 0
src/views/personnel/modules/addOperation.vue

@@ -0,0 +1,1127 @@
+<template>
+  <div>
+    <el-form
+      :model="operationForm"
+      ref="OperationFormRef"
+      :rules="operationRules"
+      label-width="120"
+      label-position="top"
+      style="background-color: #fff; padding: 20px; box-sizing: border-box"
+    >
+      <el-descriptions title="基本信息">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="name" label="姓名">
+                  <el-input
+                    v-model="operationForm.name"
+                    placeholder="请填写姓名"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="mobile" label="手机号">
+                  <el-input
+                    v-model="operationForm.mobile"
+                    placeholder="请填写手机号"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="roleIds" label="角色">
+                  
+                  <el-select
+                    v-model="operationForm.roleIds"
+                    placeholder="请选择性别"
+                    multiple
+                  >
+                    <el-option
+                      v-for="item in roleList"
+                      :key="item.id"
+                      :value="item.id"
+                      :label="item.name"
+                    ></el-option>
+                  </el-select>
+                  <!-- <el-input
+                    v-model="operationForm.name"
+                    placeholder="请填写姓名"
+                  ></el-input> -->
+                </el-form-item>
+              </el-col>
+              <el-col :span="12" >
+                <el-form-item  :prop="$route.query.id ? '':'password'" label="登录密码">
+                  <el-input
+                    :disabled="$route.query.id ? true:false"
+                    type="password"
+                    v-model="operationForm.password"
+                    placeholder="请填写登录密码"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="deptId" label="所属机构">
+                  <!-- <el-select v-model="operationForm.deptId" placeholder="请选择所属机构">
+                    <el-option key="1" value="机构1"></el-option>
+                  </el-select> -->
+                  <el-cascader
+                    clearable
+                    style="width: 100%"
+                    v-model="operationForm.deptId"
+                    :options="tableData"
+                    :props="tableProps"
+                    @change="deptChange"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="identity" label="证件号">
+                  <el-input
+                    v-model="operationForm.identity"
+                    placeholder="请填写证件号"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="identityTimeStart" label="证件有效期始">
+                  <el-date-picker
+                    v-model="operationForm.identityTimeStart"
+                    type="date"
+                    placeholder="请选择"
+                    value-format="YYYY-MM-DD"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="identityTimeEnd" label="证件有效期止">
+                  <el-date-picker
+                    v-model="operationForm.identityTimeEnd"
+                    type="date"
+                    placeholder="请选择"
+                    value-format="YYYY-MM-DD"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+
+      <el-divider />
+      <el-button
+        v-if="!recordShow"
+        link
+        type="primary"
+        icon="plus"
+        @click="recordShow = !recordShow"
+        >填写人事档案(选填)</el-button
+      >
+      <el-button
+        v-else
+        link
+        type="primary"
+        icon="ArrowUp"
+        @click="recordShow = !recordShow"
+        >收起人事档案(选填)</el-button
+      >
+      <br /><br />
+      <el-descriptions title="个人信息" v-show="recordShow">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="sex" label="性别">
+                  <el-select
+                    v-model="operationForm.sex"
+                    placeholder="请选择性别"
+                  >
+                    <el-option
+                      v-for="item in genderList"
+                      :key="item.id"
+                      :value="item.value"
+                      :label="item.label"
+                    ></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="born" label="出生日期">
+                  <el-date-picker
+                    v-model="operationForm.birthday"
+                    type="date"
+                    placeholder="请选择"
+                    value-format="YYYY-MM-DD"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="type" label="民族">
+                  <el-select
+                    v-model="operationForm.nations"
+                    placeholder="请选择名族"
+                  >
+                    <el-option
+                      v-for="item in nation"
+                      :key="item.id"
+                      :value="item.value"
+                      :label="item.label"
+                    ></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="team" label="户籍">
+                  <el-input
+                    v-model="operationForm.koseki"
+                    placeholder="请填写户籍"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="type" label="婚姻状况">
+                  <el-select
+                    v-model="operationForm.maritalStatus"
+                    placeholder="请选择婚姻状况"
+                  >
+                    <el-option
+                      v-for="item in marriage"
+                      :key="item.id"
+                      :value="item.value"
+                      :label="item.label"
+                    ></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="team" label="政治面貌">
+                  <el-select
+                    v-model="operationForm.politicsStatus"
+                    placeholder="请选择政治面貌"
+                  >
+                    <el-option
+                      v-for="item in political_status"
+                      :key="item.id"
+                      :value="item.value"
+                      :label="item.label"
+                    ></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="type" label="健康状况">
+                  <el-select
+                    v-model="operationForm.health"
+                    placeholder="请选择健康状况"
+                  >
+                    <el-option
+                      v-for="item in health_status"
+                      :key="item.id"
+                      :value="item.value"
+                      :label="item.label"
+                    ></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="team" label="居住地区">
+                  <!-- <el-select
+                    v-model="operationForm.address"
+                    placeholder="请选择居住地区"
+                  >
+                    <el-option key="1" value="团队1"></el-option>
+                  </el-select> -->
+                  <el-cascader
+                    clearable
+                    style="width: 100%"
+                    v-model="operationForm.address"
+                    :options="areaOptins"
+                    :props="areaProps"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="team" label="详细地址">
+                  <el-input
+                    v-model="operationForm.liveAddress"
+                    placeholder="请填写详细地址"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="team" label="邮政编码">
+                  <el-input
+                    v-model="operationForm.postalCode"
+                    placeholder="请填写邮政编码"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions title="学历信息" v-show="recordShow">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="sex" label="学历">
+                  <el-select
+                    v-model="operationForm.education"
+                    placeholder="请选择学历"
+                  >
+                    <el-option
+                      v-for="item in educational"
+                      :key="item.id"
+                      :value="item.value"
+                      :label="item.label"
+                    ></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="born" label="毕业时间">
+                  <el-date-picker
+                    v-model="operationForm.graduationTime"
+                    type="date"
+                    placeholder="请选择"
+                    value-format="YYYY-MM-DD"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="type" label="毕业院校">
+                  <el-input
+                    v-model="operationForm.school"
+                    placeholder="请填写毕业院校"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="team" label="是否计算机专业">
+                  <el-select
+                    v-model="operationForm.isComputer"
+                    placeholder="请选择是否计算机专业"
+                  >
+                    <el-option label="是" value="1"></el-option>
+                    <el-option label="否" value="0"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions title="紧急联系人信息" v-show="recordShow">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="team" label="姓名">
+                  <el-input
+                    v-model="operationForm.emergencyContactName"
+                    placeholder="请填写姓名"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="team" label="手机号">
+                  <el-input
+                    v-model="operationForm.emergencyContactTel"
+                    placeholder="请填写手机号"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions title="工资信息" v-show="recordShow">
+        <el-descriptions-item>
+          <template #default>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="team" label="工资">
+                  <el-input
+                    v-model="operationForm.salary"
+                    placeholder="请填写工资"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="team" label="工资等级">
+                  <el-input
+                    v-model="operationForm.salaryLevel"
+                    placeholder="请填写工资等级"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <el-form-item prop="team" label="银行卡号">
+                  <el-input
+                    v-model="operationForm.bankCardId"
+                    placeholder="请填写银行卡号"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="team" label="开户行">
+                  <el-input
+                    v-model="operationForm.bankName"
+                    placeholder="请填写开户行"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-divider v-show="recordShow" />
+      <el-descriptions v-show="recordShow" title="其它附件">
+        <el-descriptions-item>
+          <template #default>
+            <el-form-item
+              prop=""
+              label="身份证(人像面)"
+              label-width="150"
+              label-position="left"
+            >
+              <el-upload
+                :auto-upload="false"
+                v-if="!IDCardFront"
+                action="#"
+                :show-file-list="false"
+                accept=".png, .jpg, .jpeg"
+                @change="uploadImage($event, 1)"
+              >
+                <el-button link type="primary">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <div class="fileName">{{ IDCardFrontName }}</div>
+                <div class="fileBtn">
+                  <el-upload
+                    :auto-upload="false"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 1)"
+                    style="display: flex; align-items: center"
+                  >
+                    <el-icon class="btn-icon"><Upload /></el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(1)"
+                    ><View
+                  /></el-icon>
+                  <el-icon class="btn-icon"><Download /></el-icon>
+                  <el-icon class="btn-icon"><Delete /></el-icon>
+                </div>
+              </div>
+            </el-form-item>
+            <el-form-item
+              prop=""
+              label="身份证(国徽面)"
+              label-width="150"
+              label-position="left"
+            >
+              <el-upload
+                :auto-upload="false"
+                v-if="!IDCardBack"
+                action="#"
+                :show-file-list="false"
+                accept=".png, .jpg, .jpeg"
+                @change="uploadImage($event, 2)"
+              >
+                <el-button link type="primary">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <div class="fileName">{{ IDCardBackName }}</div>
+                <div class="fileBtn">
+                  <el-upload
+                    :auto-upload="false"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 2)"
+                    style="display: flex; align-items: center"
+                  >
+                    <el-icon class="btn-icon"><Upload /></el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(2)"
+                    ><View
+                  /></el-icon>
+                  <el-icon class="btn-icon"><Download /></el-icon>
+                  <el-icon class="btn-icon"><Delete /></el-icon>
+                </div>
+              </div>
+            </el-form-item>
+            <el-form-item
+              prop=""
+              label="银行卡"
+              label-width="150"
+              label-position="left"
+            >
+              <el-upload
+                :auto-upload="false"
+                v-if="!bankSize"
+                action="#"
+                :show-file-list="false"
+                accept=".png, .jpg, .jpeg"
+                @change="uploadImage($event, 3)"
+              >
+                <el-button link type="primary">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <div class="fileName">{{ bankName }}</div>
+                <div class="fileBtn">
+                  <el-upload
+                    :auto-upload="false"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 3)"
+                    style="display: flex; align-items: center"
+                  >
+                    <el-icon class="btn-icon"><Upload /></el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(3)"
+                    ><View
+                  /></el-icon>
+                  <el-icon class="btn-icon"><Download /></el-icon>
+                  <el-icon class="btn-icon"><Delete /></el-icon>
+                </div>
+              </div>
+            </el-form-item>
+            <el-form-item
+              prop=""
+              label="劳动合同"
+              label-width="150"
+              label-position="left"
+            >
+              <el-upload
+                :auto-upload="false"
+                v-if="!contract"
+                action="#"
+                :show-file-list="false"
+                accept=".png, .jpg, .jpeg"
+                @change="uploadImage($event, 4)"
+              >
+                <el-button link type="primary">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <div class="fileName">{{ contractName }}</div>
+                <div class="fileBtn">
+                  <el-upload
+                    :auto-upload="false"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 4)"
+                    style="display: flex; align-items: center"
+                  >
+                    <el-icon class="btn-icon"><Upload /></el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(4)"
+                    ><View
+                  /></el-icon>
+                  <el-icon class="btn-icon"><Download /></el-icon>
+                  <el-icon class="btn-icon"><Delete /></el-icon>
+                </div>
+              </div>
+            </el-form-item>
+            <el-form-item
+              prop=""
+              label="应聘表"
+              label-width="150"
+              label-position="left"
+            >
+              <el-upload
+                :auto-upload="false"
+                v-if="!applicant"
+                action="#"
+                :show-file-list="false"
+                accept=".png, .jpg, .jpeg"
+                @change="uploadImage($event, 5)"
+              >
+                <el-button link type="primary">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <div class="fileName">{{ applicantName }}</div>
+                <div class="fileBtn">
+                  <el-upload
+                    :auto-upload="false"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 5)"
+                    style="display: flex; align-items: center"
+                  >
+                    <el-icon class="btn-icon"><Upload /></el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(5)"
+                    ><View
+                  /></el-icon>
+                  <el-icon class="btn-icon"><Download /></el-icon>
+                  <el-icon class="btn-icon"><Delete /></el-icon>
+                </div>
+              </div>
+            </el-form-item>
+            <el-form-item
+              prop=""
+              label="定薪表"
+              label-width="150"
+              label-position="left"
+            >
+              <el-upload
+                :auto-upload="false"
+                v-if="!decidePay"
+                action="#"
+                :show-file-list="false"
+                accept=".png, .jpg, .jpeg"
+                @change="uploadImage($event, 6)"
+              >
+                <el-button link type="primary">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <div class="fileName">{{ decidePayName }}</div>
+                <div class="fileBtn">
+                  <el-upload
+                    :auto-upload="false"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 6)"
+                    style="display: flex; align-items: center"
+                  >
+                    <el-icon class="btn-icon"><Upload /></el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(6)"
+                    ><View
+                  /></el-icon>
+                  <el-icon class="btn-icon"><Download /></el-icon>
+                  <el-icon class="btn-icon"><Delete /></el-icon>
+                </div>
+              </div>
+            </el-form-item>
+            <el-form-item
+              prop=""
+              label="离职表"
+              label-width="150"
+              label-position="left"
+            >
+              <el-upload
+                :auto-upload="false"
+                v-if="!dimission"
+                action="#"
+                :show-file-list="false"
+                accept=".png, .jpg, .jpeg"
+                @change="uploadImage($event, 7)"
+              >
+                <el-button link type="primary">上传</el-button>
+              </el-upload>
+              <div class="fileInfo" v-else>
+                <div class="fileName">{{ dimissionName }}</div>
+                <div class="fileBtn">
+                  <el-upload
+                    :auto-upload="false"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 7)"
+                    style="display: flex; align-items: center"
+                  >
+                    <el-icon class="btn-icon"><Upload /></el-icon>
+                  </el-upload>
+                  <el-icon class="btn-icon" @click="imageView(7)"
+                    ><View
+                  /></el-icon>
+                  <el-icon class="btn-icon"><Download /></el-icon>
+                  <el-icon class="btn-icon"><Delete /></el-icon>
+                </div>
+              </div>
+            </el-form-item>
+          </template>
+        </el-descriptions-item>
+      </el-descriptions>
+      <div style="display: flex; justify-content: flex-end">
+        <el-button @click="onSubmit(0)">取消</el-button>
+        <el-button type="primary" @click="onSubmit(OperationFormRef, 1)"
+          >确定</el-button
+        >
+      </div>
+    </el-form>
+    <div class="image-view" v-if="imageShow" @click="imageShow = false">
+      <img :src="imageUrl" />
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, defineEmits, onMounted } from "vue";
+import { memberType } from "@/api/modules/user";
+import type { FormRules, FormInstance } from "element-plus";
+import api from "@/api";
+import { ElMessage } from "element-plus";
+import { getDictItems } from "@/api/dict";
+import { useRoute,useRouter } from "vue-router";
+
+interface dictType {
+  value: string;
+  id: string;
+  label: string;
+
+  [property: string]: any;
+}
+interface institutionData {
+  name: string;
+  system: string;
+}
+const info = ref<institutionData>({
+  name: "",
+  system: "",
+});
+//
+const route = useRoute();
+const router=useRouter()
+onMounted(async () => {
+  genderList.value = await getDictItems({ dictCode: "gender" });
+  nation.value = await getDictItems({ dictCode: "nation" });
+  marriage.value = await getDictItems({ dictCode: "marriage" });
+  political_status.value = await getDictItems({ dictCode: "political_status" });
+  health_status.value = await getDictItems({ dictCode: "health_status" });
+  educational.value = await getDictItems({ dictCode: "educational" });
+  getAreaList(); //省市区级联数据
+  getRoleList();//获取角色列表
+  api.institutionApi.institutionList(info.value).then((res) => {
+    // if(res.code===200){
+
+    // }
+    tableData.value = [...res.data];
+  });
+  if(route.query.id)
+  api.userApi
+    .getUserInfo({
+      id: route.query.id || "",
+    })
+    .then((res: any) => {
+      // console.log(res);
+      if (res.code === 200) {
+        operationForm.value = res.data;
+        if(res.data.address==null){
+          operationForm.value.address=[]
+        }
+      }
+    });
+});
+const areaOptins = ref([]);
+const areaProps = ref({
+  value: "areaCode",
+  label: "areaCname",
+  children: "child",
+});
+const getAreaList = () => {
+  api.areaApi.areaList({}).then((res) => {
+    areaOptins.value = res.data;
+  });
+};
+//性别字典
+const genderList = ref<dictType[]>([]);
+//民族
+const nation = ref<dictType[]>([]);
+//婚姻状况
+const marriage = ref<dictType[]>([]);
+//政治面貌
+const political_status = ref<dictType[]>([]);
+//健康状况
+const health_status = ref<dictType[]>([]);
+//学历
+const educational = ref<dictType[]>([]);
+
+interface OperationFormProps extends memberType {
+  deptId: string;
+  leaderNumber: string;
+  referrerNumber: string;
+  address?: string[];
+  [key:string]:any
+}
+// console.log(memberType,5555)
+
+let emits = defineEmits(["closeDialog"]);
+
+const OperationFormRef = ref<FormInstance>();
+// 添加/编辑业务员表单
+let operationForm = ref<OperationFormProps>({
+  deptId: "",
+  name: "",
+  mobile: "",
+  identity: "",
+  identityTimeStart: "",
+  identityTimeEnd: "",
+  leaderId: "",
+  leaderNumber: "",
+  referrerId: "",
+  referrerNumber: "",
+  roleIds:[],
+  password:"",
+  sex: "",
+  birthday: "",
+  nations: "",
+  koseki: "",
+  maritalStatus: "",
+  politicsStatus: "",
+  health: "",
+  province: "",
+  city: "",
+  district: "",
+  address: [],
+  liveAddress: "",
+  postalCode: "",
+  education: "",
+  graduationTime: "",
+  school: "",
+  isComputer: "",
+  emergencyContactName: "",
+  emergencyContactTel: "",
+  salary: "",
+  salaryLevel: "",
+  bankCardId: "",
+  bankName: "",
+});
+// 添加/编辑业务员表单校验
+const operationRules = ref<FormRules>({
+  name: [{ required: true, trigger: "blur", message: "请填写姓名" }],
+  roleIds: [{ required: true, trigger: "change", message: "请选择角色" }],
+  password: [{ required: true, trigger: "blur", message: "请输入登录密码" },
+    {
+      pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^]{8,16}$/,
+      message: "密码至少包含大写字母,小写字母,数字,且不少于8位",
+      trigger: "blur",
+    },
+  ],
+  mobile: [
+    { required: true, trigger: "blur", message: "请填写手机号" },
+    {
+      pattern: /^1[34578][0-9]{9}$/,
+      message: "请填写正确的手机号",
+      trigger: "blur",
+    },
+  ],
+  deptId: [{ required: true, trigger: "change", message: "请选择所属机构" }],
+  identity: [
+    { required: true, trigger: "blur", message: "请填写证件号" },
+    {
+      pattern:
+        /^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9X]$/,
+      message: "请填写正确的身份证号",
+      trigger: "blur",
+    },
+  ],
+  identityTimeStart: [
+    { required: true, trigger: "change", message: "请选择证件有效期始" },
+  ],
+  identityTimeEnd: [
+    { required: true, trigger: "change", message: "请选择证件有效期止" },
+  ],
+  leaderId: [{ required: true, trigger: "change", message: "请选择管理人" }],
+  leaderNumber: [
+    { required: true, trigger: "blur", message: "请填写管理人工号" },
+  ],
+  referrerId: [{ required: true, trigger: "change", message: "请选择推荐人" }],
+  referrerNumber: [
+    { required: true, trigger: "blur", message: "请填写推荐人工号" },
+  ],
+});
+// 身份证人像面
+let IDCardFrontName = ref("");
+let IDCardFront = ref("");
+let sfz1= ref("");
+// 身份证国徽面
+let IDCardBackName = ref("");
+let IDCardBack = ref("");
+let sfz2= ref("");
+// 银行卡
+let bankName = ref("");
+let bankSize = ref("");
+let bankCard=ref("");
+// 劳务合同
+let contractName = ref("");
+let contract = ref("");
+let contractId=ref("");
+// 应聘表
+let applicantName = ref("");
+let applicant = ref("");
+let applicantId = ref("");
+// 定薪表
+let decidePayName = ref("");
+let decidePay = ref("");
+let salaryTable=ref('')
+// 离职表
+let dimissionName = ref("");
+let dimission = ref("");
+let leaveTable= ref("");
+// 图片预览地址
+let imageShow = ref(false);
+let imageUrl = ref("");
+
+//机构列表
+type tableType = {
+  id: string;
+  name: string;
+};
+const tableData = ref<tableType[]>([]);
+const tableProps = ref({
+  value: "id",
+  label: "name",
+  children: "children",
+  checkStrictly: true,
+});
+
+//根据所属id 判断组织架构权限是否可选
+function deptChange(e: any) {
+  // console.log(e)
+  if (e != undefined) {
+    let deptId = e[e?.length - 1];
+    operationForm.deptId = deptId;
+  } else {
+    operationForm.deptId = "";
+  }
+}
+
+//数组去重
+
+// 上传图片
+const uploadImage = (file, type) => {
+  let files = file.raw;
+  let url = window.URL.createObjectURL(files); //转临时路径
+  const params = new FormData(); // 声明formData数据类型
+  params.append("file", files);
+
+  // params.append("multipartFile", files);
+  // params.append("type", "image");
+  api.areaApi.fileUpload(params).then((res: any) => {
+   
+    if (res.code === 200) {
+      switch (type) {
+        case 1:
+          IDCardFrontName.value = res.data.fileName;
+          IDCardFront.value = res.data.downloadUrl;
+          sfz1.value=res.data.id
+          break;
+        case 2:
+          IDCardBackName.value = res.data.fileName;
+          IDCardBack.value = res.data.downloadUrl;
+          sfz2.value=res.data.id
+          break;
+        case 3:
+          bankName.value = res.data.fileName;
+          bankSize.value = res.data.downloadUrl;
+          bankCard.value=res.data.id
+          break;
+        case 4:
+          contractName.value = res.data.fileName;
+          contract.value = res.data.downloadUrl;
+          contractId.value=res.data.id
+
+          break;
+        case 5:
+          applicantName.value = res.data.fileName;
+          applicant.value = res.data.downloadUrl;
+          applicantId.value=res.data.id
+
+          break;
+        case 6:
+          decidePayName.value = res.data.fileName;
+          decidePay.value = res.data.downloadUrl;
+          salaryTable.value=res.data.id
+
+          break;
+        case 7:
+          dimissionName.value = res.data.fileName;
+          dimission.value = res.data.downloadUrl;
+          leaveTable.value = res.data.id;
+          break;
+      }
+    }
+  });
+};
+
+// 人事档案
+let recordShow = ref(false);
+
+const imageView = (type) => {
+  imageShow.value = true;
+  switch (type) {
+    case 1:
+      imageUrl.value = IDCardFront.value;
+      break;
+    case 2:
+      imageUrl.value = IDCardBack.value;
+      break;
+    case 3:
+      imageUrl.value = bankSize.value;
+      break;
+    case 4:
+      imageUrl.value = contract.value;
+      break;
+    case 5:
+      imageUrl.value = applicant.value;
+      break;
+    case 6:
+      imageUrl.value = decidePay.value;
+      break;
+    case 7:
+      imageUrl.value = dimission.value;
+      break;
+  }
+};
+
+const onSubmit = async (OperationFormRef: FormInstance, type: number) => {
+  if (!OperationFormRef) {
+    emits("closeDialog", false);
+    return;
+  }
+  await OperationFormRef.validate((valid) => {
+    if (valid) {
+      if(!route.query.id){
+      api.operationApi.addOperation({
+        ...operationForm.value,
+        province:operationForm.value.address.length?operationForm.value.address[0]:'',
+        city:operationForm.value.address.length?operationForm.value.address[1]:'',
+        district:operationForm.value.address.length?operationForm.value.address[2]:'',
+        deptId:operationForm.value.deptId[operationForm.value.deptId.length-1],
+        typeAttr:2,
+        sfz1:sfz1.value,
+        sfz2:sfz2.value,
+        bankCard:bankCard.value,
+        contractId:contractId.value,
+        applicantId:applicantId.value,
+        salaryTable:salaryTable.value,
+        leaveTable:leaveTable.value,
+        
+      }).then((res:any) => {
+        // console.log(123, res);
+        if(res.code===200){
+          ElMessage.success(res.msg)
+          router.back()
+        }
+      });
+    }else{
+      api.userApi.updateUserInfo({
+        ...operationForm.value,
+        province:operationForm.value.address.length?operationForm.value.address[0]:'',
+        city:operationForm.value.address.length?operationForm.value.address[1]:'',
+        district:operationForm.value.address.length?operationForm.value.address[2]:'',
+        deptId:operationForm.value.deptId[operationForm.value.deptId.length-1],
+        typeAttr:2,
+        sfz1:sfz1.value,
+        sfz2:sfz2.value,
+        bankCard:bankCard.value,
+        contractId:contractId.value,
+        applicantId:applicantId.value,
+        salaryTable:salaryTable.value,
+        leaveTable:leaveTable.value,
+        id:operationForm.value.id
+        
+      }).then((res:any) => {
+        // console.log(123, res);
+        if(res.code===200){
+          ElMessage.success(res.msg)
+          router.back()
+        }
+      });
+    }
+    } else {
+      ElMessage({
+        message: "请正确填写相关信息!",
+        type: "warning",
+      });
+    }
+  });
+};
+
+//获取角色列表
+const roleList=ref([])
+function getRoleList() {
+  api.roleApi
+    .roleList({
+      system: localStorage.getItem("login_system") || "",
+      name: "",
+      desc: "",
+      permsId: [],
+      perms: [],
+    })
+    .then((res) => {
+      roleList.value = res.data;
+      // roleId.value = res.data[0].id;
+    });
+}
+</script>
+
+<style scoped lang="scss">
+.fileInfo {
+  display: flex;
+  align-items: center;
+  justify-content: flex-start;
+  padding: 2px 20px;
+  border-radius: 5px;
+  margin: 0 10px;
+  &:hover {
+    background: #ccc;
+  }
+  .fileName {
+    width: 200px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .fileBtn {
+    display: flex;
+    align-items: center;
+    .btn-icon {
+      margin: 0 10px;
+      font-size: 16px;
+      cursor: pointer;
+      &:hover {
+        color: #00a0f4;
+      }
+    }
+  }
+}
+.image-view {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, 0.6);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 9999;
+  img {
+    width: 800px;
+    height: 800px;
+    border-radius: 5px;
+  }
+}
+</style>

+ 1318 - 0
src/views/personnel/modules/memberMessage.vue

@@ -0,0 +1,1318 @@
+<template>
+  <div class="message-info">
+    <div class="error"></div>
+    <div style="background-color: #fff; padding: 15px; box-sizing: border-box">
+      <el-row :gutter="24">
+        <el-col :span="20">
+          <div style="display: flex; align-items: center">
+            <div class="img-title">
+              {{ pinyin.getFullChars(operationForm.name).substring(0, 1) }}
+            </div>
+            <h4>{{ operationForm.name }}</h4>
+          </div>
+        </el-col>
+        <el-col :span="4">
+          <el-button type="primary" @click="editMember">编辑</el-button>
+          <el-dropdown style="margin-left: 15px">
+            <el-button type="primary"> 更多 </el-button>
+            <template #dropdown>
+              <el-dropdown-menu>
+                <el-dropdown-item v-on:click="changeDept()"
+                  >变更机构</el-dropdown-item
+                >
+                <el-dropdown-item v-on:click="resign()">操作离职</el-dropdown-item>
+                <el-dropdown-item v-on:click="transfer()"
+                  >资源转移</el-dropdown-item
+                >
+                <el-dropdown-item v-on:click="delUser()">删除</el-dropdown-item>
+              </el-dropdown-menu>
+            </template>
+          </el-dropdown>
+        </el-col>
+      </el-row>
+      <el-row :gutter="24">
+        <el-col :span="18">
+          <el-descriptions title="" class="info-list" :column="2">
+            <el-descriptions-item label="工号:">{{
+              operationForm.userId
+            }}</el-descriptions-item>
+            <el-descriptions-item label="手机号:">{{
+              operationForm.mobile
+            }}</el-descriptions-item>
+            <el-descriptions-item label="所在机构:">
+              {{ operationForm.deptName }}
+            </el-descriptions-item>
+            <el-descriptions-item label="角色:">
+              {{ operationForm.deptName }}
+            </el-descriptions-item>
+            <el-descriptions-item label="创建人:">
+              {{ operationForm.createBy }}
+            </el-descriptions-item>
+            <el-descriptions-item label="创建时间:">
+              {{ operationForm.createTime }}
+            </el-descriptions-item>
+          </el-descriptions>
+        </el-col>
+        <el-col :span="6">
+          <h2>
+            {{
+              statusList
+                .map((item) => {
+                  return item.value == operationForm.status ? item.label : "";
+                })
+                .join("")
+            }}
+          </h2>
+          <p>状态</p>
+        </el-col>
+      </el-row>
+    </div>
+    <el-form
+      :model="operationForm"
+      ref="OperationFormRef"
+      label-width="120"
+      style="background-color: #fff; padding: 20px; box-sizing: border-box"
+    >
+      <el-tabs v-model="activeName" class="demo-tabs">
+        <el-tab-pane label="基本信息" name="first">
+          <el-descriptions title="个人信息">
+            <el-descriptions-item>
+              <template #default>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="name" label="姓名:">
+                      {{ operationForm.name }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="mobile" label="手机号:">
+                      {{ operationForm.mobile }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="deptId" label="所属机构:">
+                      {{ operationForm.deptName || "--" }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="identity" label="证件号:">
+                      {{ operationForm.identity }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item
+                      prop="identityTimeStart"
+                      label="证件有效期始:"
+                    >
+                      {{ operationForm.identityTimeStart }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="identityTimeEnd" label="证件有效期止:">
+                      {{ operationForm.identityTimeEnd }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="sex" label="性别:">
+                      {{
+                        genderList
+                          .map((item) => {
+                            return item.value == operationForm.sex
+                              ? item.label
+                              : "";
+                          })
+                          .join("")
+                      }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="born" label="出生日期:">
+                      {{ operationForm.birthday }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="type" label="民族:">
+                      {{
+                        nation
+                          .map((item) => {
+                            return item.value == operationForm.nations
+                              ? item.label
+                              : "";
+                          })
+                          .join("")
+                      }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="户籍:">
+                      {{ operationForm.koseki }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="type" label="婚姻状况:">
+                      {{
+                        marriage
+                          .map((item) => {
+                            return item.value == operationForm.maritalStatus
+                              ? item.label
+                              : "";
+                          })
+                          .join("")
+                      }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="政治面貌:">
+                      {{
+                        political_status
+                          .map((item) => {
+                            return item.value == operationForm.politicsStatus
+                              ? item.label
+                              : "";
+                          })
+                          .join("")
+                      }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="type" label="健康状况:">
+                      {{
+                        health_status
+                          .map((item) => {
+                            return item.value == operationForm.health
+                              ? item.label
+                              : "";
+                          })
+                          .join("")
+                      }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="居住地区:">
+                      <!-- <el-select
+                    v-model="operationForm.address"
+                    placeholder="请选择居住地区"
+                  >
+                    <el-option key="1" value="团队1"></el-option>
+                  </el-select> -->
+                      {{ operationForm.region || "--" }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="详细地址:">
+                      {{ operationForm.liveAddress }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="邮政编码:">
+                      {{ operationForm.postalCode }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+              </template>
+            </el-descriptions-item>
+          </el-descriptions>
+
+          <el-descriptions title="学历信息" v-show="recordShow">
+            <el-descriptions-item>
+              <template #default>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="sex" label="学历:">
+                      {{
+                        educational
+                          .map((item) => {
+                            return item.value == operationForm.education
+                              ? item.label
+                              : "";
+                          })
+                          .join("")
+                      }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="born" label="毕业时间:">
+                      {{ operationForm.graduationTime }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="type" label="毕业院校:">
+                      {{ operationForm.school }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="是否计算机专业:">
+                      {{ operationForm.isComputer }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+              </template>
+            </el-descriptions-item>
+          </el-descriptions>
+          <el-descriptions title="紧急联系人信息" v-show="recordShow">
+            <el-descriptions-item>
+              <template #default>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="姓名:">
+                      {{ operationForm.emergencyContactName }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="手机号:">
+                      {{ operationForm.emergencyContactTel }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+              </template>
+            </el-descriptions-item>
+          </el-descriptions>
+          <el-descriptions title="工资信息" v-show="recordShow">
+            <el-descriptions-item>
+              <template #default>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="工资:">
+                      {{ operationForm.salary }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="工资等级:">
+                      {{ operationForm.salaryLevel }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+                <el-row :gutter="24">
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="银行卡号:">
+                      {{ operationForm.bankCardId }}
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="team" label="开户行:">
+                      {{ operationForm.bankName }}
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+              </template>
+            </el-descriptions-item>
+          </el-descriptions>
+        </el-tab-pane>
+        <el-tab-pane label="资料附件" name="second">
+          <el-descriptions v-show="recordShow" title="资料附件">
+            <el-descriptions-item>
+              <template #default>
+                <el-form-item
+                  prop=""
+                  label="身份证(人像面)"
+                  label-width="150"
+                  label-position="left"
+                >
+                  <el-upload
+                    :auto-upload="false"
+                    v-if="!IDCardFront"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 1)"
+                  >
+                    <el-button link type="primary">上传</el-button>
+                  </el-upload>
+                  <div class="fileInfo" v-else>
+                    <div class="fileName">{{ IDCardFrontName }}</div>
+                    <div class="fileBtn">
+                      <el-upload
+                        :auto-upload="false"
+                        action="#"
+                        :show-file-list="false"
+                        accept=".png, .jpg, .jpeg"
+                        @change="uploadImage($event, 1)"
+                        style="display: flex; align-items: center"
+                      >
+                        <el-icon class="btn-icon"><Upload /></el-icon>
+                      </el-upload>
+                      <el-icon class="btn-icon" @click="imageView(1)"
+                        ><View
+                      /></el-icon>
+                      <el-icon class="btn-icon"><Download /></el-icon>
+                      <el-icon class="btn-icon"><Delete /></el-icon>
+                    </div>
+                  </div>
+                </el-form-item>
+                <el-form-item
+                  prop=""
+                  label="身份证(国徽面)"
+                  label-width="150"
+                  label-position="left"
+                >
+                  <el-upload
+                    :auto-upload="false"
+                    v-if="!IDCardBack"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 2)"
+                  >
+                    <el-button link type="primary">上传</el-button>
+                  </el-upload>
+                  <div class="fileInfo" v-else>
+                    <div class="fileName">{{ IDCardBackName }}</div>
+                    <div class="fileBtn">
+                      <el-upload
+                        :auto-upload="false"
+                        action="#"
+                        :show-file-list="false"
+                        accept=".png, .jpg, .jpeg"
+                        @change="uploadImage($event, 2)"
+                        style="display: flex; align-items: center"
+                      >
+                        <el-icon class="btn-icon"><Upload /></el-icon>
+                      </el-upload>
+                      <el-icon class="btn-icon" @click="imageView(2)"
+                        ><View
+                      /></el-icon>
+                      <el-icon class="btn-icon"><Download /></el-icon>
+                      <el-icon class="btn-icon"><Delete /></el-icon>
+                    </div>
+                  </div>
+                </el-form-item>
+                <el-form-item
+                  prop=""
+                  label="银行卡"
+                  label-width="150"
+                  label-position="left"
+                >
+                  <el-upload
+                    :auto-upload="false"
+                    v-if="!bankSize"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 3)"
+                  >
+                    <el-button link type="primary">上传</el-button>
+                  </el-upload>
+                  <div class="fileInfo" v-else>
+                    <div class="fileName">{{ bankName }}</div>
+                    <div class="fileBtn">
+                      <el-upload
+                        :auto-upload="false"
+                        action="#"
+                        :show-file-list="false"
+                        accept=".png, .jpg, .jpeg"
+                        @change="uploadImage($event, 3)"
+                        style="display: flex; align-items: center"
+                      >
+                        <el-icon class="btn-icon"><Upload /></el-icon>
+                      </el-upload>
+                      <el-icon class="btn-icon" @click="imageView(3)"
+                        ><View
+                      /></el-icon>
+                      <el-icon class="btn-icon"><Download /></el-icon>
+                      <el-icon class="btn-icon"><Delete /></el-icon>
+                    </div>
+                  </div>
+                </el-form-item>
+                <el-form-item
+                  prop=""
+                  label="劳动合同"
+                  label-width="150"
+                  label-position="left"
+                >
+                  <el-upload
+                    :auto-upload="false"
+                    v-if="!contract"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 4)"
+                  >
+                    <el-button link type="primary">上传</el-button>
+                  </el-upload>
+                  <div class="fileInfo" v-else>
+                    <div class="fileName">{{ contractName }}</div>
+                    <div class="fileBtn">
+                      <el-upload
+                        :auto-upload="false"
+                        action="#"
+                        :show-file-list="false"
+                        accept=".png, .jpg, .jpeg"
+                        @change="uploadImage($event, 4)"
+                        style="display: flex; align-items: center"
+                      >
+                        <el-icon class="btn-icon"><Upload /></el-icon>
+                      </el-upload>
+                      <el-icon class="btn-icon" @click="imageView(4)"
+                        ><View
+                      /></el-icon>
+                      <el-icon class="btn-icon"><Download /></el-icon>
+                      <el-icon class="btn-icon"><Delete /></el-icon>
+                    </div>
+                  </div>
+                </el-form-item>
+                <el-form-item
+                  prop=""
+                  label="应聘表"
+                  label-width="150"
+                  label-position="left"
+                >
+                  <el-upload
+                    :auto-upload="false"
+                    v-if="!applicant"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 5)"
+                  >
+                    <el-button link type="primary">上传</el-button>
+                  </el-upload>
+                  <div class="fileInfo" v-else>
+                    <div class="fileName">{{ applicantName }}</div>
+                    <div class="fileBtn">
+                      <el-upload
+                        :auto-upload="false"
+                        action="#"
+                        :show-file-list="false"
+                        accept=".png, .jpg, .jpeg"
+                        @change="uploadImage($event, 5)"
+                        style="display: flex; align-items: center"
+                      >
+                        <el-icon class="btn-icon"><Upload /></el-icon>
+                      </el-upload>
+                      <el-icon class="btn-icon" @click="imageView(5)"
+                        ><View
+                      /></el-icon>
+                      <el-icon class="btn-icon"><Download /></el-icon>
+                      <el-icon class="btn-icon"><Delete /></el-icon>
+                    </div>
+                  </div>
+                </el-form-item>
+                <el-form-item
+                  prop=""
+                  label="定薪表"
+                  label-width="150"
+                  label-position="left"
+                >
+                  <el-upload
+                    :auto-upload="false"
+                    v-if="!decidePay"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 6)"
+                  >
+                    <el-button link type="primary">上传</el-button>
+                  </el-upload>
+                  <div class="fileInfo" v-else>
+                    <div class="fileName">{{ decidePayName }}</div>
+                    <div class="fileBtn">
+                      <el-upload
+                        :auto-upload="false"
+                        action="#"
+                        :show-file-list="false"
+                        accept=".png, .jpg, .jpeg"
+                        @change="uploadImage($event, 6)"
+                        style="display: flex; align-items: center"
+                      >
+                        <el-icon class="btn-icon"><Upload /></el-icon>
+                      </el-upload>
+                      <el-icon class="btn-icon" @click="imageView(6)"
+                        ><View
+                      /></el-icon>
+                      <el-icon class="btn-icon"><Download /></el-icon>
+                      <el-icon class="btn-icon"><Delete /></el-icon>
+                    </div>
+                  </div>
+                </el-form-item>
+                <el-form-item
+                  prop=""
+                  label="离职表"
+                  label-width="150"
+                  label-position="left"
+                >
+                  <el-upload
+                    :auto-upload="false"
+                    v-if="!dimission"
+                    action="#"
+                    :show-file-list="false"
+                    accept=".png, .jpg, .jpeg"
+                    @change="uploadImage($event, 7)"
+                  >
+                    <el-button link type="primary">上传</el-button>
+                  </el-upload>
+                  <div class="fileInfo" v-else>
+                    <div class="fileName">{{ dimissionName }}</div>
+                    <div class="fileBtn">
+                      <el-upload
+                        :auto-upload="false"
+                        action="#"
+                        :show-file-list="false"
+                        accept=".png, .jpg, .jpeg"
+                        @change="uploadImage($event, 7)"
+                        style="display: flex; align-items: center"
+                      >
+                        <el-icon class="btn-icon"><Upload /></el-icon>
+                      </el-upload>
+                      <el-icon class="btn-icon" @click="imageView(7)"
+                        ><View
+                      /></el-icon>
+                      <el-icon class="btn-icon"><Download /></el-icon>
+                      <el-icon class="btn-icon"><Delete /></el-icon>
+                    </div>
+                  </div>
+                </el-form-item>
+              </template>
+            </el-descriptions-item>
+          </el-descriptions>
+        </el-tab-pane>
+      </el-tabs>
+
+      <!-- <div style="display: flex; justify-content: flex-end">
+        <el-button @click="onSubmit(0)">取消</el-button>
+        <el-button type="primary" @click="onSubmit(OperationFormRef, 1)"
+          >确定</el-button
+        >
+      </div> -->
+    </el-form>
+    <div class="image-view" v-if="imageShow" @click="imageShow = false">
+      <img :src="imageUrl" />
+    </div>
+    <el-dialog
+      v-model="dialogVisible"
+      title="资源转移"
+      width="800"
+      draggable
+      append-to-body
+    >
+      <el-row :gutter="24">
+        <el-col :span="20">
+          <div style="display: flex; align-items: center">
+            <div class="img-title">
+              {{ pinyin.getFullChars(operationForm.name).substring(0, 1) }}
+            </div>
+            <h4>{{ operationForm.name }}</h4>
+          </div>
+        </el-col>
+      </el-row>
+      <p style="margin-left: 50px">工号:{{ transferInfo.userId }}</p>
+      <p style="margin-left: 50px">所在机构:{{ transferInfo.deptName }}</p>
+      <p style="margin-left: 50px">需要转移的资源</p>
+      <el-table :data="[{}]" style="width: 100%">
+        <el-table-column prop="date" label="资源" width="120">
+          <template #default="scope"> 业务员 </template>
+        </el-table-column>
+        <el-table-column prop="name" label="描述" width="180">
+          <template #default="scope"> 转让该成员维护的业务员 </template>
+        </el-table-column>
+        <el-table-column prop="address" label="数量" width="80">
+          <template #default="scope"> {{ transferInfo.count }}人 </template>
+        </el-table-column>
+        <el-table-column prop="address" label="资源接收人">
+          <template #default="scope">
+            <el-input
+              :value="receiveInfo?.name"
+              @click="deptDialogVisible = true"
+              placeholder="输入姓名,手机号,工号查找"
+            ></el-input>
+          </template>
+        </el-table-column>
+      </el-table>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="dialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="confirmTransfer">
+            确认转移
+          </el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <setDept
+      :dialogVisible="deptDialogVisible"
+      :dept-list="tableData"
+      :dept-ids="[]"
+      @close-dialog="confirmDialogInfo"
+      title="选择交接人"
+    ></setDept>
+    <el-dialog
+      v-model="changeDeptDialog"
+      title="变更机构"
+      width="600"
+      append-to-body
+      draggable
+    >
+      <div>
+        <el-input
+          v-model="filterText"
+          style="width: 240px"
+          placeholder="请输入机构名称查找"
+          :prefix-icon="Search"
+        />
+        <el-tree
+          ref="treeRef"
+          style="max-width: 600px"
+          class="filter-tree"
+          :data="tableData"
+          :props="tableProps"
+          :default-expand-all="true"
+          :expand-on-click-node="false"
+          :filter-node-method="filterNode"
+          @node-click="treeClick"
+        >
+          <template #default="{ node, data }">
+            <span class="custom-tree-node">
+              <span>{{ node.label }}</span>
+              <span>
+                <a style="color: #00a0f4">
+                  {{ node.label == deptItem.name ? "已选" : "" }}
+                </a>
+              </span>
+            </span>
+          </template>
+        </el-tree>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="changeDeptDialog = false">取消</el-button>
+          <el-button type="primary" @click="submitChangeDept"> 确认 </el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, defineEmits, onMounted, watch } from "vue";
+import { memberType } from "@/api/modules/user";
+import type { FormRules, FormInstance, ElTree } from "element-plus";
+import api from "@/api";
+import { Search } from "@element-plus/icons-vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { getDictItems } from "@/api/dict";
+import { useRoute } from "vue-router";
+import pinyin from "js-pinyin";
+import { useRouter } from "vue-router";
+import setDept from "@/components/DialogSetDeptLeader/index.vue";
+interface dictType {
+  value: string;
+  id: string;
+  label: string;
+
+  [property: string]: any;
+}
+
+interface institutionData {
+  name: string;
+  system: string;
+}
+const info = ref<institutionData>({
+  name: "",
+  system: "",
+});
+//转移资源
+const dialogVisible = ref(false);
+
+//选择交接人
+const deptDialogVisible = ref(false);
+const route = useRoute();
+
+const activeName = ref("first");
+const statusList = ref<dictType[]>([]);
+onMounted(async () => {
+  genderList.value = await getDictItems({ dictCode: "gender" });
+  nation.value = await getDictItems({ dictCode: "nation" });
+  marriage.value = await getDictItems({ dictCode: "marriage" });
+  political_status.value = await getDictItems({ dictCode: "political_status" });
+  health_status.value = await getDictItems({ dictCode: "health_status" });
+  educational.value = await getDictItems({ dictCode: "educational" });
+  statusList.value = await getDictItems({ dictCode: "person_status" });
+  getAreaList(); //省市区级联数据
+  api.institutionApi.institutionList(info.value).then((res) => {
+    tableData.value = [...res.data];
+  });
+  api.userApi
+    .getUserInfo({
+      id: route.query.id || "",
+    })
+    .then((res: any) => {
+      console.log(res);
+      if (res.code === 200) {
+        operationForm.value = res.data;
+      }
+    });
+});
+const areaOptins = ref([]);
+
+const getAreaList = () => {
+  api.areaApi.areaList({}).then((res) => {
+    areaOptins.value = res.data;
+  });
+};
+//性别字典
+const genderList = ref<dictType[]>([]);
+//民族
+const nation = ref<dictType[]>([]);
+//婚姻状况
+const marriage = ref<dictType[]>([]);
+//政治面貌
+const political_status = ref<dictType[]>([]);
+//健康状况
+const health_status = ref<dictType[]>([]);
+//学历
+const educational = ref<dictType[]>([]);
+
+interface OperationFormProps extends memberType {
+  deptId: string;
+  leaderNumber: string;
+  referrerNumber: string;
+  address?: [];
+  [key: string]: any;
+}
+// console.log(memberType,5555)
+
+let emits = defineEmits(["closeDialog"]);
+
+const OperationFormRef = ref<FormInstance>();
+// 添加/编辑业务员表单
+let operationForm = ref<OperationFormProps>({
+  deptId: "",
+  name: "",
+  mobile: "",
+  identity: "",
+  identityTimeStart: "",
+  identityTimeEnd: "",
+  leaderId: "",
+  leaderNumber: "",
+  referrerId: "",
+  referrerNumber: "",
+
+  sex: "",
+  birthday: "",
+  nations: "",
+  koseki: "",
+  maritalStatus: "",
+  politicsStatus: "",
+  health: "",
+  province: "",
+  city: "",
+  district: "",
+  address: [],
+  liveAddress: "",
+  postalCode: "",
+  education: "",
+  graduationTime: "",
+  school: "",
+  isComputer: "",
+  emergencyContactName: "",
+  emergencyContactTel: "",
+  salary: "",
+  salaryLevel: "",
+  bankCardId: "",
+  bankName: "",
+});
+// 添加/编辑业务员表单校验
+const operationRules = ref<FormRules>({
+  name: [{ required: true, trigger: "blur", message: "请填写姓名" }],
+  mobile: [
+    { required: true, trigger: "blur", message: "请填写手机号" },
+    {
+      pattern: /^1[34578][0-9]{9}$/,
+      message: "请填写正确的手机号",
+      trigger: "blur",
+    },
+  ],
+  deptId: [{ required: true, trigger: "change", message: "请选择所属机构" }],
+  identity: [
+    { required: true, trigger: "blur", message: "请填写证件号" },
+    {
+      pattern:
+        /^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9X]$/,
+      message: "请填写正确的身份证号",
+      trigger: "blur",
+    },
+  ],
+  identityTimeStart: [
+    { required: true, trigger: "change", message: "请选择证件有效期始" },
+  ],
+  identityTimeEnd: [
+    { required: true, trigger: "change", message: "请选择证件有效期止" },
+  ],
+  leaderId: [{ required: true, trigger: "change", message: "请选择管理人" }],
+  leaderNumber: [
+    { required: true, trigger: "blur", message: "请填写管理人工号" },
+  ],
+  referrerId: [{ required: true, trigger: "change", message: "请选择推荐人" }],
+  referrerNumber: [
+    { required: true, trigger: "blur", message: "请填写推荐人工号" },
+  ],
+});
+// 身份证人像面
+let IDCardFrontName = ref("");
+let IDCardFront = ref("");
+let sfz1 = ref("");
+// 身份证国徽面
+let IDCardBackName = ref("");
+let IDCardBack = ref("");
+let sfz2 = ref("");
+// 银行卡
+let bankName = ref("");
+let bankSize = ref("");
+let bankCard = ref("");
+// 劳务合同
+let contractName = ref("");
+let contract = ref("");
+let contractId = ref("");
+// 应聘表
+let applicantName = ref("");
+let applicant = ref("");
+let applicantId = ref("");
+// 定薪表
+let decidePayName = ref("");
+let decidePay = ref("");
+let salaryTable = ref("");
+// 离职表
+let dimissionName = ref("");
+let dimission = ref("");
+let leaveTable = ref("");
+// 图片预览地址
+let imageShow = ref(false);
+let imageUrl = ref("");
+
+//机构列表
+type tableType = {
+  id: string;
+  name: string;
+};
+const tableData = ref<tableType[]>([]);
+const tableProps = ref({
+  value: "id",
+  label: "name",
+  children: "children",
+  checkStrictly: true,
+});
+
+//跳转编辑页面
+const router = useRouter();
+function editMember(e: any) {
+  router.push({
+    path: "/personnel/member/memberEdit",
+    query: {
+      id: operationForm.value.userId,
+    },
+  });
+  // console.log(e)
+  // if (e != undefined) {
+  //   let deptId = e[e?.length - 1];
+  //   operationForm.deptId = deptId;
+  // } else {
+  //   operationForm.deptId = "";
+  // }
+}
+
+//数组去重
+
+// 上传图片
+const uploadImage = (file: any, type: number) => {
+  let files = file.raw;
+  let url = window.URL.createObjectURL(files); //转临时路径
+  const params = new FormData(); // 声明formData数据类型
+  params.append("file", files);
+
+  // params.append("multipartFile", files);
+  // params.append("type", "image");
+  api.areaApi.fileUpload(params).then((res: any) => {
+    console.log(res);
+    if (res.code === 200) {
+      switch (type) {
+        case 1:
+          IDCardFrontName.value = res.data.fileName;
+          IDCardFront.value = res.data.downloadUrl;
+          sfz1.value = res.data.id;
+          break;
+        case 2:
+          IDCardBackName.value = res.data.fileName;
+          IDCardBack.value = res.data.downloadUrl;
+          sfz2.value = res.data.id;
+          break;
+        case 3:
+          bankName.value = res.data.fileName;
+          bankSize.value = res.data.downloadUrl;
+          bankCard.value = res.data.id;
+          break;
+        case 4:
+          contractName.value = res.data.fileName;
+          contract.value = res.data.downloadUrl;
+          contractId.value = res.data.id;
+
+          break;
+        case 5:
+          applicantName.value = res.data.fileName;
+          applicant.value = res.data.downloadUrl;
+          applicantId.value = res.data.id;
+
+          break;
+        case 6:
+          decidePayName.value = res.data.fileName;
+          decidePay.value = res.data.downloadUrl;
+          salaryTable.value = res.data.id;
+
+          break;
+        case 7:
+          dimissionName.value = res.data.fileName;
+          dimission.value = res.data.downloadUrl;
+          leaveTable.value = res.data.id;
+          break;
+      }
+    }
+  });
+};
+
+// 人事档案
+let recordShow = ref(true);
+
+const imageView = (type: number) => {
+  imageShow.value = true;
+  switch (type) {
+    case 1:
+      imageUrl.value = IDCardFront.value;
+      break;
+    case 2:
+      imageUrl.value = IDCardBack.value;
+      break;
+    case 3:
+      imageUrl.value = bankSize.value;
+      break;
+    case 4:
+      imageUrl.value = contract.value;
+      break;
+    case 5:
+      imageUrl.value = applicant.value;
+      break;
+    case 6:
+      imageUrl.value = decidePay.value;
+      break;
+    case 7:
+      imageUrl.value = dimission.value;
+      break;
+  }
+};
+
+const onSubmit = async (OperationFormRef: FormInstance, type: number) => {
+  if (!OperationFormRef) {
+    emits("closeDialog", false);
+    return;
+  }
+  await OperationFormRef.validate((valid) => {
+    if (valid) {
+      api.operationApi
+        .addOperation({
+          ...operationForm.value,
+          province: operationForm.value.address[0],
+          city: operationForm.value.address[1],
+          district: operationForm.value.address[2],
+          deptId:
+            operationForm.value.deptId[operationForm.value.deptId.length - 1],
+          typeAttr: 2,
+          sfz1: sfz1.value,
+          sfz2: sfz2.value,
+          bankCard: bankCard.value,
+          contractId: contractId.value,
+          applicantId: applicantId.value,
+          salaryTable: salaryTable.value,
+          leaveTable: leaveTable.value,
+        })
+        .then((res: any) => {
+          // console.log(123, res);
+          if (res.code === 200) {
+            ElMessage.success(res.msg);
+          }
+        });
+    } else {
+      ElMessage({
+        message: "请正确填写相关信息!",
+        type: "warning",
+      });
+    }
+  });
+};
+interface transfer {
+  [key: string]: any;
+}
+//资源转移信息
+const transferInfo = ref<transfer>({});
+function transfer() {
+  // console.log(123)
+
+  api.userApi
+    .getTransferInfo({
+      userId: operationForm.value.userId,
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        transferInfo.value = res.data;
+        if (res.data.count < 1) {
+          ElMessage.error("当前用户没有可转移的资源");
+        } else {
+          dialogVisible.value = true;
+        }
+      }
+    });
+}
+
+//操作离职
+
+function resign() {
+  // console.log(123)
+
+  api.userApi
+    .getTransferInfo({
+      userId: operationForm.value.userId,
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        transferInfo.value = res.data;
+        if (res.data.count < 1) {
+          // ElMessage.error("当前用户没有可转移的资源");
+          ElMessageBox.confirm(
+          "账号删除后,该账号将无法使用访问本企业,请确定是否删除 ",
+          "确认要删除账号吗?",
+          {
+            confirmButtonText: "确认",
+            cancelButtonText: "取消",
+            type: "warning",
+          }
+        )
+          .then(() => {
+            api.userApi
+              .userQuitApply({
+                id: [operationForm.value.id],
+                
+              })
+              .then((res: any) => {
+                if(res.code==200){
+                  ElMessage.success(res.msg)
+                  router.back()
+                }
+              });
+            // console.log(123);
+          })
+          .catch(() => {
+            ElMessage.warning("用户取消操作");
+          });
+        } else {
+          dialogVisible.value = true;
+        }
+      }
+    });
+}
+
+//确认弹框提交信息
+const receiveInfo = ref<transfer>({});
+function confirmDialogInfo(item: any) {
+  deptDialogVisible.value = false;
+  receiveInfo.value = item;
+}
+
+//资源转移确认
+function confirmTransfer() {
+  api.userApi
+    .transfer({
+      originalUserId: transferInfo.value.userId,
+      transferUserId: receiveInfo.value.id,
+    })
+    .then((res: any) => {
+      // console.log(res)
+      if (res.code === 200) {
+        ElMessage.success(res.msg);
+        dialogVisible.value = false;
+      }
+    });
+}
+
+//变更机构弹框
+interface Tree {
+  [key: string]: any;
+}
+const filterText = ref("");
+const treeRef = ref<InstanceType<typeof ElTree>>();
+
+watch(filterText, (val) => {
+  treeRef.value!.filter(val);
+});
+const filterNode = (value: string, data: Tree) => {
+  // console.log(data)
+  if (!value) return true;
+  return data.name.includes(value);
+};
+//判断当前机构是否可以进行变更
+const changeDeptDialog = ref(false);
+function changeDept() {
+  // changeDeptDialog.value=true
+  api.userApi
+    .checkChangeDept({
+      userId: operationForm.value.userId,
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        // transferInfo.value=res.data
+
+        changeDeptDialog.value = false;
+      }
+    });
+}
+//选择变更的机构
+const deptItem = ref({});
+function treeClick(node: any) {
+  deptItem.value = node;
+}
+
+//提交变更机构信息
+
+function submitChangeDept() {
+  // changeDeptDialog.value=true
+  api.userApi
+    .changeDept({
+      userId: operationForm.value.userId,
+      deptId: deptItem.value.id,
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        // transferInfo.value=res.data
+        ElMessage.success(res.msg);
+        changeDeptDialog.value = true;
+      }
+    });
+}
+
+//删除成员
+function delUser() {
+  api.userApi
+    .checkChangeDept({
+      userId: operationForm.value.userId,
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        // transferInfo.value=res.data
+
+        ElMessageBox.confirm(
+          "账号删除后,该账号将无法使用访问本企业,请确定是否删除 ",
+          "确认要删除账号吗?",
+          {
+            confirmButtonText: "确认删除",
+            cancelButtonText: "取消",
+            type: "warning",
+          }
+        )
+          .then(() => {
+            api.userApi
+              .userDelete({
+                id: [operationForm.value.id],
+                
+              })
+              .then((res: any) => {
+                if(res.code==200){
+                  ElMessage.success(res.msg)
+                  router.back()
+                }
+              });
+            // console.log(123);
+          })
+          .catch(() => {
+            ElMessage.warning("用户取消操作");
+          });
+      }
+    });
+}
+</script>
+
+<style scoped lang="scss">
+.message-info {
+  // background: #fff;
+  padding: 15px;
+  box-sizing: border-box;
+  h4 {
+    margin: 0;
+  }
+}
+.img-title {
+  border-radius: 50%;
+  width: 30px;
+  height: 30px;
+  color: #fff;
+  background: #00a0f4;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 20px;
+}
+.fileInfo {
+  display: flex;
+  align-items: center;
+  justify-content: flex-start;
+  padding: 2px 20px;
+  border-radius: 5px;
+  margin: 0 10px;
+  &:hover {
+    background: #ccc;
+  }
+  .fileName {
+    width: 200px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .fileBtn {
+    display: flex;
+    align-items: center;
+    .btn-icon {
+      margin: 0 10px;
+      font-size: 16px;
+      cursor: pointer;
+      &:hover {
+        color: #00a0f4;
+      }
+    }
+  }
+}
+.image-view {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, 0.6);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 9999;
+  img {
+    width: 800px;
+    height: 800px;
+    border-radius: 5px;
+  }
+}
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  padding-right: 8px;
+}
+</style>

+ 201 - 35
src/views/personnel/roleManagement.vue

@@ -46,7 +46,8 @@
             <div class="flex j-s a-c">
               <span class="strong">角色管理</span>
               <div>
-                <ElButton type="danger" @click="roleSubmit">删除</ElButton>
+                <ElButton type="primary" @click="roleSubmit">提交</ElButton>
+                <ElButton type="danger" @click="deleteRole">删除</ElButton>
               </div>
             </div>
           </template>
@@ -75,6 +76,7 @@
                 v-model="roleInfo.deptId"
                 :options="tableData"
                 :props="tableProps"
+                @change="deptChange"
               />
             </ElFormItem>
             <ElFormItem prop="desc" label="角色描述">
@@ -108,12 +110,15 @@
                   show-checkbox
                   node-key="id"
                   :default-expand-all="true"
-                  :default-checked-keys="[6]"
+                  :default-checked-keys="checkedKeys"
                   @check="handleCheckChange"
                 />
               </el-tab-pane>
               <el-tab-pane label="组织架构权限">
-                <el-radio-group v-model="roleInfo.dataMark">
+                <el-radio-group
+                  v-model="roleInfo.dataMark"
+                  @change="dataMarkChange"
+                >
                   <el-radio value="1" size="large">可见本机构下的数据</el-radio>
                   <el-radio value="2" size="large"
                     >可见本机构及下级机构数据</el-radio
@@ -122,13 +127,15 @@
                 </el-radio-group>
                 <ElTree
                   style="max-height: 500px; overflow-y: auto"
-                  :data="tableData"
+                  :data="deptTreeData"
                   :props="deptProps"
                   show-checkbox
                   node-key="id"
+                  :check-strictly="true"
                   :default-expand-all="true"
-                  :default-checked-keys="[6]"
+                  :default-checked-keys="roleInfo.deptIds"
                   @check="handleDeptCheckChange"
+                  ref="deptTree"
                 />
               </el-tab-pane>
             </el-tabs>
@@ -141,8 +148,13 @@
 
 <script lang="ts" setup>
 import { asyncRoutes } from "@/router/routes"; // 请根据实际路径调整
-import { ref, reactive, onMounted } from "vue";
-import type { FormRules } from "element-plus";
+import { ref, reactive, onMounted, onBeforeMount, } from "vue";
+import {
+  type FormRules,
+  type ElTree,
+  ElMessage,
+  ElMessageBox,
+} from "element-plus";
 import {
   preprocessRoutes,
   convertToTreeData,
@@ -156,9 +168,9 @@ let roleInfo = reactive<{
   desc: string;
   system: string;
   permsId: number[];
-  perms: string[];
+  perms: any[];
   deptId: string;
-  deptIds: [];
+  deptIds: any[];
   dataMark: string;
 }>({
   name: "", //角色
@@ -200,12 +212,9 @@ const handleCheckChange = (
   // console.log(checkedInfo.checkedNodes);
   roleInfo.permsId = checkedInfo.checkedKeys;
   roleInfo.perms = [];
-  checkedInfo.checkedNodes.forEach((val) => {
-    if (val.type === "2") {
-      roleInfo.perms.push(val.auth);
-    }
-  });
+  roleInfo.perms = checkedInfo.checkedNodes;
 };
+
 const handleDeptCheckChange = (
   _checkedNodes: TreeNode[],
   checkedInfo: {
@@ -217,7 +226,9 @@ const handleDeptCheckChange = (
 ) => {
   // console.log('Checked keys:', checkedInfo.checkedKeys);
   // console.log(checkedInfo.checkedNodes);
+
   roleInfo.deptIds = checkedInfo.checkedKeys;
+
   // roleInfo.perms = [];
   // checkedInfo.checkedNodes.forEach((val) => {
   //   if (val.type === "2") {
@@ -247,18 +258,24 @@ const info = ref<institutionData>({
   system: "",
 });
 //获取机构列表
+const deptTreeData = ref<tableType[]>([]);
 const getInstitutionList = () => {
   // pageInfo.pageNum=item.pageNum
   api.institutionApi.institutionList(info.value).then((res) => {
     // if(res.code===200){
 
     // }
-    tableData.value = res.data;
+    tableData.value = [...res.data];
+    deptTreeData.value = JSON.parse(JSON.stringify(res.data));
   });
   // pageInfo.pageSize=item.pageSize
 };
 
 const showRole = ref(false);
+interface Perm {
+  id: string; // 根据实际情况,id 可能是数字或字符串
+}
+const checkedKeys = ref<string[]>([]);
 //选择角色
 function chooseRole(item: any) {
   roleId.value = item.id;
@@ -272,10 +289,23 @@ function chooseRole(item: any) {
       perms: [],
     })
     .then((res) => {
-      console.log(res);
+      // console.log(res);
       roleInfo.name = res.data.name;
+
       roleInfo.desc = res.data.remark;
       roleInfo.deptId = res.data.deptId;
+      roleInfo.permsId = res.data.perms.map((val: Perm) => val.id);
+      roleInfo.perms = res.data.perms;
+      checkedKeys.value = res.data.perms.map((val: Perm) => val.id);
+      if(res.data.dataScope?.deptIds){
+        deptTree.value!.setCheckedKeys(res.data.dataScope?.deptIds, true);
+        roleInfo.dataMark = res.data.dataScope?.dataMark;
+      }else{
+        deptTree.value!.setCheckedKeys([], false);
+        roleInfo.dataMark = '1';
+      }
+      
+      roleInfo.deptIds = res.data.dataScope?.deptIds;
     });
   operationType.value = "edit";
   // roleInfo.name=item.name
@@ -294,29 +324,153 @@ function addRole() {
   showRole.value = true;
   operationType.value = "add";
 }
-
+//提交角色信息
 function roleSubmit() {
-  let role = { ...roleInfo };
-
   if (operationType.value == "add") {
-    api.roleApi.roleAdd({
-      // roleId: roleInfo.id,
-      name: roleInfo.name,
-      desc: roleInfo.desc,
-      system: localStorage.getItem("login_system") || '',
-      permsId: roleInfo.permsId,
-      perms: roleInfo.perms,
-      deptId:roleInfo.deptId[roleInfo.deptId.length-1],
-      dataScope:{
-        deptIds:roleInfo.deptIds,
-        dataMark:roleInfo.dataMark,
-
-      }
-     }).then((res) => {
+    api.roleApi
+      .roleAdd({
+        name: roleInfo.name,
+        desc: roleInfo.desc,
+        system: localStorage.getItem("login_system") || "",
+        permsId: roleInfo.permsId,
+        perms: roleInfo.perms,
+        deptId: roleInfo.deptId,
+        dataScope: {
+          deptIds: roleInfo.deptIds,
+          dataMark: roleInfo.dataMark,
+        },
+      })
+      .then((res) => {
+        // console.log(res);
+        ElMessage.success("操作成功");
+        getRoleList();
+      });
+  } else {
+    api.roleApi
+      .roleUpdate({
+        // roleId: roleInfo.id,
+        id: roleId.value,
+        name: roleInfo.name,
+        desc: roleInfo.desc,
+        system: localStorage.getItem("login_system") || "",
+        permsId: roleInfo.permsId,
+        perms: roleInfo.perms,
+        deptId: roleInfo.deptId,
+        dataScope: {
+          deptIds: roleInfo.deptIds,
+          dataMark: roleInfo.dataMark,
+        },
+      })
+      .then((res) => {
+        // console.log(res);
+        ElMessage.success("操作成功");
+        getRoleList();
+      });
+  }
+}
+//删除角色
+function deleteRole() {
+  api.roleApi
+    .roleDeleteValid({
+      id: roleId.value,
+    })
+    .then((res) => {
       console.log(res);
+      if (res.code == 200) {
+        ElMessageBox.confirm("确认要删除当前数据吗?", "提示", {
+          confirmButtonText: "确认",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+          .then(() => {
+            api.roleApi
+              .roleDelete({
+                id: roleId.value,
+              })
+              .then((res) => {
+                ElMessage.success("操作成功");
+                getRoleList();
+              });
+          })
+          .catch(() => {
+            ElMessage.warning("用户取消操作");
+          });
+      }
     });
+}
+// const deptIds=re
+//机构单选切换
+const dataMarkChange = () => {
+  deptIds.value = [];
+  disabledTree(deptTreeData.value, roleInfo.deptId);
+  roleInfo.deptIds = deptIds.value;
+  if (deptIds.value.length == 0) {
+    deptTree.value!.setCheckedKeys([], false);
   } else {
+    deptTree.value!.setCheckedKeys(deptIds.value, true);
+  }
+};
 
+//根据所属id 判断组织架构权限是否可选
+function deptChange(e:any) {
+  // console.log(e)
+  if (e != undefined) {
+    let deptId = e[e?.length - 1];
+    roleInfo.deptId = deptId;
+    // if(roleInfo.dataMark=='1'){
+    // let arr=[...deptTreeData.value]
+    deptIds.value=[]
+    disabledTree(deptTreeData.value, deptId);
+    deptTree.value!.setCheckedKeys(deptIds.value, true);
+    roleInfo.deptIds = deptIds.value;
+  }else{
+    roleInfo.deptId=''
+  }
+
+  // deptTree.value.defaultCheckedKeys=roleInfo.deptIds
+  // }
+}
+const deptIds = ref([]);
+const deptTree = ref<InstanceType<typeof ElTree>>();
+//禁用机构选择
+function disabledTree(list: any[], id: string) {
+  for (let i = 0; i < list.length; i++) {
+    const node = list[i];
+
+    if (roleInfo.dataMark == "1") {
+      if (id) {
+        if (list[i].id != id) {
+          list[i].disabled = true;
+        } else {
+          deptIds.value.push(list[i].id);
+        }
+      } else {
+        list[i].disabled = false;
+      }
+    } else if (roleInfo.dataMark == "2") {
+      if (id) {
+        if (list[i].id != id && list[i].parentId != id) {
+          list[i].disabled = true;
+        } else {
+          list[i].disabled = false;
+          deptIds.value.push(list[i].id);
+        }
+        // if (list[i].disabled == false) {
+        //   deptIds.value.push(list[i].id);
+        // }
+      } else {
+        list[i].disabled = false;
+      }
+
+      //
+    } else {
+      list[i].disabled = false;
+    }
+    // console.log(list[i].disabled)
+
+    if (node.children && node.children.length > 0) {
+      disabledTree(node.children, id);
+    }
   }
 }
 
@@ -340,10 +494,22 @@ function getRoleList() {
       // roleId.value = res.data[0].id;
     });
 }
-onMounted(() => {
+onBeforeMount(() => {
   // 对 asyncRoutes 进行预处理并转换为树形结构
   const processedRoutes = preprocessRoutes(asyncRoutes);
-  treeData.value = convertToTreeData(processedRoutes);
+
+  treeData.value = convertToTreeData(0, processedRoutes);
+
+  api.roleApi.updateConfig({
+    sysConfig:JSON.stringify(treeData.value)
+  }).then(res=>{
+    console.log(res)
+  })
+
+});
+onMounted(() => {
+  // 对 asyncRoutes 进行预处理并转换为树形结构
+
   getRoleList();
   getInstitutionList();
 });