Selaa lähdekoodia

feat: 账号管理添加用户新增接口获取

qindao 1 vuosi sitten
vanhempi
commit
57c7dc589b

+ 62 - 58
src/api/system/user-operate.ts

@@ -31,54 +31,53 @@ interface AdminUserType {
   tenantId: number;
 }
 
-
 export interface DeptListItem {
-  children: [],
-  createdAt: string,
-  createdBy: string,
-  deptName: string,
-  id: number,
-  isDeleted: number,
-  isDisabled: number,
-  orderNum: number,
-  parentId: string,
-  tenantId: number,
-  updatedAt: string,
-  updatedBy: string
+  children: [];
+  createdAt: string;
+  createdBy: string;
+  deptName: string;
+  id: number;
+  isDeleted: number;
+  isDisabled: number;
+  orderNum: number;
+  parentId: string;
+  tenantId: number;
+  updatedAt: string;
+  updatedBy: string;
 }
 
 export interface RoleListItem {
-  createdAt: string,
-  createdBy: number,
-  id: number,
-  isDeleted: number,
-  roleName: string,
-  tenantId: number,
-  updatedAt: string,
-  updatedBy: null
+  createdAt: string;
+  createdBy: number;
+  id: number;
+  isDeleted: number;
+  roleName: string;
+  tenantId: number;
+  updatedAt: string;
+  updatedBy: null;
 }
 export interface UserLisItem {
-  avatar: string,
-  createdAt: string,
-  createdBy: null,
-  deptId: number,
-  deptList: DeptListItem[],
-  email: null,
-  gender: null,
-  id: number,
-  isDeleted: number,
-  isDisabled: number,
-  mobile: null,
-  password: string,
-  realname: string,
-  remark: null,
-  roleList: RoleListItem[],
-  roleType: number,
-  staffNo: string,
-  tenantId: number,
-  updatedAt: string,
-  updatedBy: null,
-  username: string
+  avatar: string;
+  createdAt: string;
+  createdBy: null;
+  deptId: number;
+  deptList: DeptListItem[];
+  email: null;
+  gender: null;
+  id: number;
+  isDeleted: number;
+  isDisabled: number;
+  mobile: null;
+  password: string;
+  realname: string;
+  remark: null;
+  roleList: RoleListItem[];
+  roleType: number;
+  staffNo: string;
+  tenantId: number;
+  updatedAt: string;
+  updatedBy: null;
+  username: string;
 }
 
 /** root用户给某个租户添加管理员 */
@@ -135,7 +134,7 @@ export interface UserTypeDel {
 }
 
 export interface UserProps {
-  userId: number
+  userId: number;
 }
 //删除用户
 export function delUser(params: UserProps) {
@@ -193,17 +192,17 @@ export interface QueryUser {
 }
 
 export interface UserPramas {
-  realname?: string, // 用户姓名
-  mobile?: string, // 手机号
-  staffNo?: string, // 工号
-  deptId?: number, // 部门
+  realname?: string; // 用户姓名
+  mobile?: string; // 手机号
+  staffNo?: string; // 工号
+  deptId?: number; // 部门
   roleId?: number; // 角色id
 }
 
 export interface QueryUserPramas {
   pageNumber: number; //当前页数
   pageSize: number; //每页个数
-  queryParam: UserPramas
+  queryParam: UserPramas;
 }
 
 //获取单个用户信息
@@ -229,7 +228,7 @@ export function resetCode(data: ResetCodeType) {
     data,
   });
 }
- 
+
 export interface AddTenantAdminProps {
   username: string;
   realname: string;
@@ -238,6 +237,8 @@ export interface AddTenantAdminProps {
   password: string;
   userId?: number;
   passwordRe?: string;
+  deptId?: number | null;
+  staffNo: string;
 }
 
 // V4: 添加租户管理员
@@ -245,16 +246,19 @@ export function addTenantAdmin(data: AddTenantAdminProps) {
   return http.request({
     url: 'admin/user/saveTenantAdmin',
     method: 'POST',
-    data
-  })
+    data,
+  });
 }
 
 // V4: 删除用户
 export function deleteUser(params: UserProps) {
-  return http.request({
-    url: `admin/user/deleteUser?userId=${params.userId}`,
-    method: 'DELETE',
-  }, {
-    isTransformResponse: false
-  })
-}
+  return http.request(
+    {
+      url: `admin/user/deleteUser?userId=${params.userId}`,
+      method: 'DELETE',
+    },
+    {
+      isTransformResponse: false,
+    },
+  );
+}

+ 14 - 1
src/api/system/user.ts

@@ -1,5 +1,7 @@
 import { http } from '@/utils/http/axios';
 import { UserProps } from './user-operate';
+import { OrganizationUserTree } from '@/views/system/user/types';
+import { LargeNumberLike } from 'crypto';
 export interface BasicResponseModel<T = any> {
   code: number;
   msg: string;
@@ -48,7 +50,7 @@ export function editUsur(params) {
 /**
  * @description: 用户信息
  */
-export function userInfo(params:UserProps) {
+export function userInfo(params: UserProps) {
   return http.request({
     url: '/admin/user/queryUserInfo',
     method: 'GET',
@@ -148,3 +150,14 @@ export function onlineLogOut(params?) {
     params,
   });
 }
+
+/**
+ * @description: V4: 根据工号模糊查询组织人员树
+ */
+export function queryOrganizationUserTree(workNo: number) {
+  return http.request<OrganizationUserTree[]>({
+    url: '/admin/hrdatasync/queryOrganizationUserTreeDataByWorkNo',
+    method: 'POST',
+    data: { workNo },
+  });
+}

+ 42 - 0
src/directives/debounceTreeSelect.ts

@@ -0,0 +1,42 @@
+import { ObjectDirective } from 'vue';
+
+// 防抖函数
+function debounce<T extends (...args: any[]) => any>(func: T, delay: number) {
+  let timer: ReturnType<typeof setTimeout> | null = null;
+  return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
+    if (timer) {
+      clearTimeout(timer);
+    }
+    timer = setTimeout(() => {
+      func.apply(this, args);
+    }, delay);
+  };
+}
+
+// 自定义防抖指令
+const vDebounceTreeSelect: ObjectDirective = {
+  mounted(el: HTMLElement, binding) {
+    const inputElement = el.querySelector('input') as HTMLInputElement;
+    if (inputElement) {
+      const originalRemoteMethod = binding.value;
+      const debouncedRemoteMethod = debounce(originalRemoteMethod, 1000);
+      inputElement.addEventListener('input', (event) => {
+        const query = (event.target as HTMLInputElement).value;
+        debouncedRemoteMethod(query);
+      });
+    }
+  },
+  unmounted(el: HTMLElement, binding) {
+    const inputElement = el.querySelector('input') as HTMLInputElement;
+    if (inputElement) {
+      const originalRemoteMethod = binding.value;
+      const debouncedRemoteMethod = debounce(originalRemoteMethod, 1000);
+      inputElement.removeEventListener('input', (event) => {
+        const query = (event.target as HTMLInputElement).value;
+        debouncedRemoteMethod(query);
+      });
+    }
+  },
+};
+
+export default vDebounceTreeSelect;

+ 115 - 0
src/utils/findUserByWorkNo.ts

@@ -0,0 +1,115 @@
+interface TreeNode {
+  children?: TreeNode[];
+  users?: {
+    idtUserWorkNo: string;
+    // 其他用户属性
+  }[];
+}
+
+/**
+ * 从树形结构数据中查找 idtUserWorkNo 相等的用户项
+ * @param nodes 树形结构数据
+ * @param workNo 要查找的工号
+ * @returns 找到的用户项,如果未找到则返回 undefined
+ */
+export function findUserByWorkNo(nodes: TreeNode[], workNo: string) {
+  for (const node of nodes) {
+    if (node.users) {
+      const foundUser = node.users.find((user) => user.idtUserWorkNo === workNo);
+      if (foundUser) {
+        return foundUser;
+      }
+    }
+    if (node.children) {
+      const result = findUserByWorkNo(node.children, workNo);
+      if (result) {
+        return result;
+      }
+    }
+  }
+  return undefined;
+}
+
+interface TreeNode {
+  children?: TreeNode[];
+  idtOrgId?: string;
+  users?: {
+    idtUserWorkNo: string;
+  }[];
+}
+
+/**
+ * 从树形结构数据中查找 idtUserWorkNo 相等的用户项,并返回其同级别的 idtOrgOrgCode
+ * @param nodes 树形结构数据
+ * @param workNo 要查找的工号
+ * @returns 找到的 idtOrgId undefined
+ */
+export function findOrgCodeByWorkNo(nodes: TreeNode[], workNo: string): string | undefined {
+  for (const node of nodes) {
+    if (node.users) {
+      const foundUser = node.users.find((user) => user.idtUserWorkNo === workNo);
+      if (foundUser) {
+        return node.idtOrgId;
+      }
+    }
+    if (node.children) {
+      const result = findOrgCodeByWorkNo(node.children, workNo);
+      if (result) {
+        return result;
+      }
+    }
+  }
+  return undefined;
+}
+
+interface TreeNode {
+  children?: TreeNode[];
+  idtOrgId?: string;
+  idtOrgName?: string;
+  users?: {
+    appAccountAccountName: string;
+    idtUserWorkNo: string;
+  }[];
+}
+
+export interface TransformedTreeNode {
+  label: string;
+  value: string;
+  children?: TransformedTreeNode[];
+}
+
+/**
+ * 将原始树形结构数据转换为指定格式的树形结构
+ * @param nodes 原始树形结构数据
+ * @returns 转换后的树形结构数据
+ */
+export const transformTreeData = (nodes: TreeNode[], isNeedUser = false): TransformedTreeNode[] => {
+  return nodes.map((node) => {
+    const { children, idtOrgId, idtOrgName, users } = node;
+    const result: TransformedTreeNode = {
+      label: idtOrgName || '',
+      value: idtOrgId || '',
+    };
+
+    if (children && children.length > 0) {
+      result.children = transformTreeData(children, isNeedUser);
+    }
+
+    if (isNeedUser && users && users.length > 0) {
+      result.children = users.map((user) => ({
+        label: `${user.idtUserWorkNo}(${user.appAccountAccountName})`,
+        value: user.idtUserWorkNo,
+      }));
+    }
+    return result;
+  });
+};
+
+/**
+ * 去除字符串中的括号及其内部内容
+ * @param str 要处理的字符串
+ * @returns 处理后的字符串
+ */
+export function removeParentheses(str: string) {
+  return str.replace(/\(.*?\)/g, '');
+}

+ 3 - 15
src/views/message/reportmessage/CustomReport.vue

@@ -5,9 +5,7 @@
         <el-icon
           class="cardIcon"
           color="rgb(216,216,216)"
-          v-if="
-            prop.form.customPushConfigList.filter((custom) => custom.isDeleted === 0).length > 1
-          "
+          v-if="prop.form.customPushConfigList.filter((custom) => custom.isDeleted === 0).length > 1"
           @click="deleteReportCard(index)"
         >
           <CircleCloseFilled />
@@ -103,12 +101,7 @@
             style="width: 326px; padding-bottom: 0px"
             :disabled="disableType.contentDisable"
           >
-            <el-option
-              v-for="item in options"
-              :key="item.userGroupId"
-              :label="item.name"
-              :value="item.userGroupId"
-            />
+            <el-option v-for="item in options" :key="item.userGroupId" :label="item.name" :value="item.userGroupId" />
           </el-select>
         </el-col>
       </el-form-item>
@@ -138,12 +131,7 @@
       </el-form-item>
     </div>
   </div>
-  <el-button
-    type="primary"
-    :icon="Plus"
-    @click="addCustom"
-    class="addButton"
-    :disabled="disableType.contentDisable"
+  <el-button type="primary" :icon="Plus" @click="addCustom" class="addButton" :disabled="disableType.contentDisable"
     >新建自定义</el-button
   >
 </template>

+ 269 - 155
src/views/system/user/CreateAdminDrawer.vue

@@ -1,23 +1,64 @@
 <template>
   <el-drawer v-model="isDrawer" :size="width" :title="props.title" @close="handleReset">
     <el-form :model="formParams" :rules="rules" ref="formRef" label-placement="left" :label-width="80">
-      <el-form-item label="登录账号" prop="username">
-        <el-input placeholder="请输入登录账号" v-model="formParams.username" :disabled="!isAddUser" />
+      <el-form-item label="工号" prop="staffNo">
+        <el-input placeholder="请输入工号" v-model="formParams.staffNo" v-if="staffNoHtmlType === 'INPUT'" />
+        <el-tree-select
+          v-model="formParams.staffNo"
+          v-debounce-tree-select="remoteMethod"
+          check-strictly
+          placeholder="请选择工号"
+          class="protocal-select"
+          filterable
+          remote
+          reserve-keyword
+          clearable
+          :loading="loading"
+          :data="staffNoOptions"
+          :render-after-expand="false"
+          :default-expand-all="true"
+          @clear="handleClear"
+          @change="handleChange"
+          v-else
+        />
+
+        <el-text class="mx-1 text-mode" type="primary" @click="handleChangeStaff">{{
+          `工号${staffNoHtmlType === 'INPUT' ? '选择' : '输入'}方式`
+        }}</el-text>
       </el-form-item>
       <el-form-item label="姓名" prop="realname">
         <el-input placeholder="请输入姓名" v-model="formParams.realname" />
       </el-form-item>
+      <el-form-item label="所属部门" prop="deptId">
+        <el-tree-select
+          v-model="formParams.deptId"
+          :data="departmentArr"
+          :render-after-expand="false"
+          :default-expand-all="true"
+          check-strictly
+          placeholder="请选择所属组织"
+          class="protocal-select"
+        />
+      </el-form-item>
       <el-form-item label="角色" prop="roleIdList">
         <el-select clearable v-model="formParams.roleIdList" multiple v-if="isCanAddTenant && isSysTenant">
           <el-option v-for="item in roleData" :key="item.value" :label="item.label" :value="item.value" />
         </el-select>
         <el-input v-else placeholder="租户管理员默认拥有全部角色权限" disabled />
       </el-form-item>
+      <el-form-item label="登录账号" prop="username">
+        <el-input placeholder="请输入登录账号" v-model="formParams.username" :disabled="!isAddUser" />
+      </el-form-item>
       <el-form-item v-if="isAddUser" label="密码" prop="password">
         <el-input type="password" show-password-on="mousedown" placeholder="请输入密码" v-model="formParams.password" />
       </el-form-item>
       <el-form-item v-if="isAddUser" label="确认密码" :prop="!formParams.username ? 'passwordRe' : ''">
-        <el-input type="password" show-password-on="mousedown" placeholder="请输入密码" v-model="formParams.passwordRe" />
+        <el-input
+          type="password"
+          show-password-on="mousedown"
+          placeholder="请输入密码"
+          v-model="formParams.passwordRe"
+        />
       </el-form-item>
       <el-form-item label="是否启用" prop="isDisabled">
         <el-switch v-model="formParams.isDisabled" />
@@ -33,115 +74,200 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, computed, watch } from 'vue';
-import { FormRules, ElMessage } from 'element-plus';
-import { userInfo } from '@/api/system/user';
-import { cloneDeep } from 'lodash-es';
-import {
-  addTenantAdmin,
-  AddTenantAdminProps,
-  updateUser,
-  addSingleUser,
-} from '@/api/system/user-operate';
-import { EditType, OptionsProps, DisabledEnum } from './types';
-import { useTargetTenantIdSetting } from '@/utils/useTargetTenantIdSetting';
-import { ResultEnum } from '@/enums/httpEnum';
-
-const { isSysTenant } = useTargetTenantIdSetting();
-let rules: FormRules = {
-  username: {
-    required: true,
-    message: '登录账号不能为空',
-    trigger: 'blur',
-  },
-  realname: {
-    required: true,
-    message: '姓名不能为空',
-    trigger: 'blur',
-  },
-  roleIdList: {
-    required: true,
-    message: '请选择角色',
-    trigger: 'change',
-  },
-  password: {
-    required: true,
-    message: '密码不能为空',
-    trigger: 'blur',
-  },
-  passwordRe: {
-    required: true,
-    message: '密码不能为空',
-    trigger: 'blur',
-  },
-};
-
-const emit = defineEmits(['change']);
-const props = withDefaults(
-  defineProps<{ title: string; width: number; editType: EditType; roleData: OptionsProps[], isCanAddTenant: boolean, isSysTenant: boolean }>(),
-  {
-    title: '添加用户',
-    width: 450,
-  },
-);
-
-const defaultValueRef = () => ({
-  username: '',
-  isDisabled: true,
-  realname: '',
-  roleIdList: [],
-  password: '',
-  passwordRe: '',
-});
-
-const message = ElMessage;
-const formRef: any = ref(null);
-const isDrawer = ref(false);
-const subLoading = ref(false);
-const formParams = ref<AddTenantAdminProps>(defaultValueRef());
-
-async function openDrawer(userId?) {
-  if (userId) {
-    formParams.value.userId = userId;
-    getInfo();
-    return;
-  }
-  isDrawer.value = true;
-}
+  import { ref, computed, watch } from 'vue';
+  import { FormRules, ElMessage } from 'element-plus';
+  import { userInfo, queryOrganizationUserTree } from '@/api/system/user';
+  import { cloneDeep } from 'lodash-es';
+  import { addTenantAdmin, AddTenantAdminProps, updateUser, addSingleUser } from '@/api/system/user-operate';
+  import { EditType, OptionsProps, DisabledEnum, OrganizationUserTree } from './types';
+  import { useTargetTenantIdSetting } from '@/utils/useTargetTenantIdSetting';
+  import { ResultEnum } from '@/enums/httpEnum';
+  import vDebounceTreeSelect from '@/directives/debounceTreeSelect';
+  import {
+    findUserByWorkNo,
+    findOrgCodeByWorkNo,
+    transformTreeData,
+    TransformedTreeNode,
+    removeParentheses,
+  } from '@/utils/findUserByWorkNo';
 
-const isAddUser = computed(() => {
-  return props.editType === EditType.create;
-});
+  const { isSysTenant } = useTargetTenantIdSetting();
+  let rules: FormRules = {
+    staffNo: {
+      required: true,
+      message: '工号不能为空',
+      trigger: 'blur',
+    },
+    username: {
+      required: true,
+      message: '登录账号不能为空',
+      trigger: 'blur',
+    },
+    realname: {
+      required: true,
+      message: '姓名不能为空',
+      trigger: 'blur',
+    },
+    deptId: {
+      required: true,
+      message: '部门不能为空',
+      trigger: 'blur',
+    },
 
-function closeDrawer() {
-  isDrawer.value = false;
-}
+    roleIdList: {
+      required: true,
+      message: '请选择角色',
+      trigger: 'change',
+    },
+    password: {
+      required: true,
+      message: '密码不能为空',
+      trigger: 'blur',
+    },
+    passwordRe: {
+      required: true,
+      message: '密码不能为空',
+      trigger: 'blur',
+    },
+  };
 
-function formSubmit() {
-  formRef.value.validate((valid) => {
-    if (!valid) {
-      message.error('请填写完整信息');
-      return;
+  const emit = defineEmits(['change']);
+  const props = withDefaults(
+    defineProps<{
+      title: string;
+      width: number;
+      editType: EditType;
+      roleData: OptionsProps[];
+      isCanAddTenant: boolean;
+      isSysTenant: boolean;
+      departmentList: OptionsProps[];
+    }>(),
+    {
+      title: '添加用户',
+      width: 450,
+    },
+  );
+
+  const defaultValueRef = () => ({
+    username: '',
+    isDisabled: true,
+    realname: '',
+    roleIdList: [],
+    password: '',
+    passwordRe: '',
+    deptId: null,
+    staffNo: '',
+  });
+  const message = ElMessage;
+  const formRef: any = ref(null);
+  const isDrawer = ref(false);
+  const subLoading = ref(false);
+  const formParams = ref<AddTenantAdminProps>(defaultValueRef());
+  const loading = ref(false);
+  const staffNoOptions = ref<TransformedTreeNode[]>([]);
+  const OrganizationSourceData = ref<OrganizationUserTree[]>([]);
+  const departmentArr = ref<OptionsProps[]>([]);
+
+  const remoteMethod = (query: string) => {
+    if (query) {
+      loading.value = true;
+      queryOrganizationUserTree(Number(query)).then((res) => {
+        if (res) {
+          loading.value = false;
+          staffNoOptions.value = transformTreeData(res, true);
+        }
+        /* 保存原始数据,用于选中后将数据返显到表单 */
+        OrganizationSourceData.value = res;
+      });
+    } else {
+      staffNoOptions.value = [];
+    }
+  };
+
+  type STAFFNO_HTML_TYPE = 'INPUT' | 'SELECT';
+  const staffNoHtmlType = ref<STAFFNO_HTML_TYPE>('SELECT');
+  const handleChangeStaff = () => {
+    staffNoHtmlType.value = staffNoHtmlType.value === 'INPUT' ? 'SELECT' : 'INPUT';
+  };
+
+  const handleClear = () => {
+    formRef.value.resetFields();
+    formParams.value = Object.assign(formParams.value, defaultValueRef());
+  };
+
+  const handleChange = (value) => {
+    /* 将选中的数据返显到表单 */
+    const findUser = findUserByWorkNo(OrganizationSourceData.value, value);
+    if (findUser) {
+      formParams.value.realname = findUser.appAccountAccountName;
+      formParams.value.staffNo = findUser.idtUserWorkNo;
+      formParams.value.username = findUser.idtUserWorkNo;
+      formParams.value.roleIdList = JSON.parse(findUser.useTypes);
+
+      /* 选中数据后将部门设置为当前数据的部门 */
+      departmentArr.value = transformTreeData(OrganizationSourceData.value, false);
+      formParams.value.deptId = findOrgCodeByWorkNo(OrganizationSourceData.value, value);
+      console.log(departmentArr.value);
     }
+  };
 
-    // 克隆
-    const params = cloneDeep(formParams.value);
-    if (params.password != params.passwordRe) {
-      return message.error('两次密码不一致');
+  async function openDrawer(userId?) {
+    if (userId) {
+      formParams.value.userId = userId;
+      getInfo();
+      return;
     }
-    if (isAddUser.value) {
-      formParams.value.isDisabled
-        ? (params.isDisabled = DisabledEnum.NO)
-        : (params.isDisabled = DisabledEnum.YES);
-      if (!isSysTenant) {
-        addTenantAdmin(params).then((res) => {
-          message.success('添加管理员账户成功');
-          emit('change');
-          handleReset();
-          closeDrawer();
-        });
+    isDrawer.value = true;
+  }
+
+  const isAddUser = computed(() => {
+    return props.editType === EditType.create;
+  });
+
+  function closeDrawer() {
+    isDrawer.value = false;
+  }
+
+  function formSubmit() {
+    formRef.value.validate((valid) => {
+      if (!valid) {
+        message.error('请填写完整信息');
+        return;
+      }
+
+      // 克隆
+      const params = cloneDeep(formParams.value);
+      if (params.password != params.passwordRe) {
+        return message.error('两次密码不一致');
+      }
+      params.staffNo = removeParentheses(params.staffNo);
+      if (isAddUser.value) {
+        formParams.value.isDisabled ? (params.isDisabled = DisabledEnum.NO) : (params.isDisabled = DisabledEnum.YES);
+        if (!isSysTenant) {
+          addTenantAdmin(params).then((res) => {
+            message.success('添加管理员账户成功');
+            emit('change');
+            handleReset();
+            closeDrawer();
+          });
+        } else {
+          addSingleUser(params)
+            .then((res) => {
+              if (res.code !== ResultEnum.SUCCESS) {
+                return Promise.reject(res.msg);
+              }
+              emit('change');
+              handleReset();
+              closeDrawer();
+              ElMessage.success('添加成功');
+            })
+            .catch((error) => {
+              ElMessage.error(error);
+            });
+        }
       } else {
-        addSingleUser(params)
+        formParams.value.isDisabled ? (params.isDisabled = DisabledEnum.NO) : (params.isDisabled = DisabledEnum.YES);
+        updateUser(params)
           .then((res) => {
             if (res.code !== ResultEnum.SUCCESS) {
               return Promise.reject(res.msg);
@@ -149,64 +275,52 @@ function formSubmit() {
             emit('change');
             handleReset();
             closeDrawer();
-            ElMessage.success('添加成功');
+            ElMessage.success('修改成功');
           })
           .catch((error) => {
             ElMessage.error(error);
           });
       }
-    } else {
-      formParams.value.isDisabled
-        ? (params.isDisabled = DisabledEnum.NO)
-        : (params.isDisabled = DisabledEnum.YES);
-      updateUser(params)
-        .then((res) => {
-          if (res.code !== ResultEnum.SUCCESS) {
-            return Promise.reject(res.msg);
-          }
-          emit('change');
-          handleReset();
-          closeDrawer();
-          ElMessage.success('修改成功');
-        })
-        .catch((error) => {
-          ElMessage.error(error);
-        });
-    }
-  });
-}
+    });
+  }
 
-function handleReset() {
-  formRef.value.resetFields();
-  formParams.value = Object.assign(formParams.value, defaultValueRef());
-}
+  function handleReset() {
+    formRef.value.resetFields();
+    formParams.value = Object.assign(formParams.value, defaultValueRef());
+  }
 
-function getInfo() {
-  userInfo({ userId: Number(formParams.value.userId) }).then((res) => {
-    Object.entries(res).forEach(([key, value]) => {
-      formParams.value[key] = value;
+  function getInfo() {
+    userInfo({ userId: Number(formParams.value.userId) }).then((res) => {
+      Object.entries(res).forEach(([key, value]) => {
+        formParams.value[key] = value;
+      });
+      formParams.value.roleIdList = res.roleIds;
+      formParams.value.passwordRe = res.password;
+      formParams.value.isDisabled = res.isDisabled === DisabledEnum.NO ? true : false;
+      isDrawer.value = true;
     });
-    formParams.value.roleIdList = res.roleIds;
-    formParams.value.passwordRe = res.password;
-    formParams.value.isDisabled = res.isDisabled === DisabledEnum.NO ? true : false;
-    isDrawer.value = true;
-  });
-}
-
-watch(
-  () => props,
-  () => {
-    if (props.isCanAddTenant && !props.isSysTenant) {
-      rules!.roleIdList!.required = false
-    }
-  },
-  {
-    immediate: true
   }
-)
 
-defineExpose({
-  openDrawer,
-  closeDrawer,
-});
+  watch(
+    () => props,
+    () => {
+      if (props.isCanAddTenant && !props.isSysTenant) {
+        rules!.roleIdList!.required = false;
+      }
+      departmentArr.value = props.departmentList;
+    },
+    {
+      immediate: true,
+    },
+  );
+
+  defineExpose({
+    openDrawer,
+    closeDrawer,
+  });
 </script>
+<style scoped>
+  .text-mode {
+    cursor: pointer;
+  }
+</style>

+ 39 - 10
src/views/system/user/types/index.ts

@@ -1,4 +1,4 @@
-import { PaginationRequest } from "@/types/common/type";
+import { PaginationRequest } from '@/types/common/type';
 export interface formParamsType {
   userId?: number | null;
   roleIds?: number[];
@@ -24,21 +24,50 @@ export enum EditType {
 export const ROOT_USER = 'root';
 
 export interface OptionsProps {
-  value: string | number,
-  label: string
+  value: string | number;
+  label: string;
 }
 
 export interface QueryParamas {
-  realname?: string, // 用户姓名
-  mobile?: string, // 手机号
-  staffNo?: string, // 工号
-  deptId?: number, // 部门
+  realname?: string; // 用户姓名
+  mobile?: string; // 手机号
+  staffNo?: string; // 工号
+  deptId?: number; // 部门
   roleId?: number; // 角色id
 }
-export type SearchParamsProps = PaginationRequest & {queryParam: QueryParamas}
+export type SearchParamsProps = PaginationRequest & { queryParam: QueryParamas };
 
 /* 状态: 0-启用, 1-禁用 */
 export enum DisabledEnum {
   NO = 0,
-  YES = 1
-}
+  YES = 1,
+}
+
+/* 工号模糊查询组织人员树 用户信息 */
+export interface UserItem {
+  id: number;
+  appAccountId: string;
+  appAccountAccountNo: string;
+  appAccountAccountName: string;
+  idtUserEmail: string;
+  idtUserUserEmail: string;
+  idtUserMobile: string;
+  idtUserWorkNo: string;
+  idtUserPinyin: string;
+  useTypes: string;
+  requestLogActionFlag: number;
+  requestLogActionDesc: string;
+  createdAt: string;
+  updatedTime: string;
+  isDeleted: number;
+}
+
+/* 组织人员树 */
+export interface OrganizationUserTree {
+  idtOrgId: string;
+  idtOrgName: string;
+  idtOrgParentId: string;
+  idtOrgOrgCode: string;
+  users: UserItem[];
+  children: OrganizationUserTree[];
+}

+ 82 - 48
src/views/system/user/user.vue

@@ -1,11 +1,12 @@
 <template>
   <div class="user-page">
-    <SearchForm ref="searchFormRef" 
-      :departmentList="departmentList" 
+    <SearchForm
+      ref="searchFormRef"
+      :departmentList="departmentList"
       :roleData="roleData"
-      @get-table-data="onSearchCommit" 
-      @reset-form="onResetForm" 
-      />
+      @get-table-data="onSearchCommit"
+      @reset-form="onResetForm"
+    />
     <el-card>
       <template #header>
         <el-space align="center">
@@ -36,10 +37,7 @@
         </el-space>
       </template>
 
-      <el-table height="calc(100vh - 340px)" 
-        :data="userList"  
-        row-key="id" 
-        >
+      <el-table height="calc(100vh - 340px)" :data="userList" row-key="id">
         <el-table-column label="工号" prop="staffNo">
           <template #default="scope">
             <div>
@@ -50,18 +48,18 @@
         <el-table-column label="登录账号" prop="username" width="150">
           <template #default="scope">
             <div class="account">
-            {{ scope.row.username }}
-             <el-tooltip
-              class="box-item"
-              effect="dark"
-              content="租户管理员账号,自动拥有全部相机查看权限及功能权限"
-              placement="top-start"
-              v-if="scope.row.roleType === RoleTypeEnum.TENANT_ADMIN"
-            >
-              <el-icon color="#409efc">
-                <Stamp />
-              </el-icon>
-            </el-tooltip>
+              {{ scope.row.username }}
+              <el-tooltip
+                class="box-item"
+                effect="dark"
+                content="租户管理员账号,自动拥有全部相机查看权限及功能权限"
+                placement="top-start"
+                v-if="scope.row.roleType === RoleTypeEnum.TENANT_ADMIN"
+              >
+                <el-icon color="#409efc">
+                  <Stamp />
+                </el-icon>
+              </el-tooltip>
             </div>
           </template>
         </el-table-column>
@@ -69,9 +67,10 @@
         <el-table-column label="手机" prop="mobile" />
         <el-table-column label="状态" prop="isDisabled">
           <template #default="scope">
-            <div >
+            <div>
               <el-tag :type="!scope.row.isDisabled ? 'success' : 'danger'">
-                {{ !scope.row.isDisabled ? '正常' : '锁定' }}</el-tag>
+                {{ !scope.row.isDisabled ? '正常' : '锁定' }}</el-tag
+              >
             </div>
           </template>
         </el-table-column>
@@ -84,7 +83,7 @@
         </el-table-column>
         <el-table-column label="组织" prop="deptList">
           <template #default="scope">
-            <div >
+            <div>
               {{ tranformDeptList(scope.row.deptList) }}
             </div>
           </template>
@@ -95,13 +94,25 @@
           <template #default="scope">
             <el-space v-if="scope.row.roleType !== RoleTypeEnum.SUPER_ADMIN">
               <div class="el-space el-space--horizontal">
-                <div class="el-space__item"  @click="handleEdit(scope.row)"  v-permission="{ action: [PERM_USER.ACCOUNT_EDIT] }">
-                  <div><img :src="editIcon" class="el-tooltip__trigger" ></div>
+                <div
+                  class="el-space__item"
+                  @click="handleEdit(scope.row)"
+                  v-permission="{ action: [PERM_USER.ACCOUNT_EDIT] }"
+                >
+                  <div><img :src="editIcon" class="el-tooltip__trigger" /></div>
                 </div>
-                <div class="el-space__item" @click="handleDelete(scope.row)"  v-permission="{ action: [PERM_USER.ACCOUNT_DELETE] }">
-                  <div><img :src="deleteIcon" class="el-tooltip__trigger"></div>
+                <div
+                  class="el-space__item"
+                  @click="handleDelete(scope.row)"
+                  v-permission="{ action: [PERM_USER.ACCOUNT_DELETE] }"
+                >
+                  <div><img :src="deleteIcon" class="el-tooltip__trigger" /></div>
                 </div>
-                <div class="el-space__item" v-if="visibleRestPassBtn(scope.row.roleType) && hasResetPasswordPermission()" @click="handleResetCode(scope.row)" >
+                <div
+                  class="el-space__item"
+                  v-if="visibleRestPassBtn(scope.row.roleType) && hasResetPasswordPermission()"
+                  @click="handleResetCode(scope.row)"
+                >
                   <div class="tooltip__password">重置密码</div>
                 </div>
               </div>
@@ -111,17 +122,44 @@
       </el-table>
 
       <section class="mt-4 flex justify-end">
-        <el-pagination background layout="total, sizes, prev, pager, next" :page-sizes="[10, 30, 50]" :total="total"
-          v-model:page-size="params.pageSize" v-model:current-page="params.pageNumber" @change="loadPageData" />
+        <el-pagination
+          background
+          layout="total, sizes, prev, pager, next"
+          :page-sizes="[10, 30, 50]"
+          :total="total"
+          v-model:page-size="params.pageSize"
+          v-model:current-page="params.pageNumber"
+          @change="loadPageData"
+        />
       </section>
     </el-card>
-    <CreateDrawer ref="createDrawerRef" :title="drawerTitle" @change="reloadTable" :departmentList="departmentList"
-      :roleData="roleData" :width="450" />
+    <CreateDrawer
+      ref="createDrawerRef"
+      :title="drawerTitle"
+      @change="reloadTable"
+      :departmentList="departmentList"
+      :roleData="roleData"
+      :width="450"
+    />
     <ResetCodeDrawer ref="ResetCodeDrawerRef" :title="drawerTitle" @change="reloadTable" />
-    <CreateAdminDrawer ref="createAdminDrawerRef" :title="createAdminTitle" @change="reloadTable"
-      :editType="createAdminType" :roleData="roleData" :width="450" :isCanAddTenant="isCanAddTenant" :isSysTenant="isSysTenant"/>
-    <AddUser v-if="showAddPopover" :colseAddUser="setShowAddPopoverFalse" v-model="showAddPopover" class="add-popover"
-      @change="reloadTable" />
+    <CreateAdminDrawer
+      ref="createAdminDrawerRef"
+      :title="createAdminTitle"
+      @change="reloadTable"
+      :editType="createAdminType"
+      :roleData="roleData"
+      :width="450"
+      :isCanAddTenant="isCanAddTenant"
+      :isSysTenant="isSysTenant"
+      :departmentList="departmentList"
+    />
+    <AddUser
+      v-if="showAddPopover"
+      :colseAddUser="setShowAddPopoverFalse"
+      v-model="showAddPopover"
+      class="add-popover"
+      @change="reloadTable"
+    />
   </div>
 </template>
 
@@ -166,7 +204,7 @@
   const departmentList = ref<OptionsProps[]>([]);
   const createAdminType = ref(EditType.create);
   const { isSysTenant } = useTargetTenantIdSetting();
-  
+
   function reloadTable() {
     loadPageData();
   }
@@ -255,11 +293,7 @@
   onMounted(async () => {
     loadPageData();
     getAllDepartments().then((res) => {
-      departmentList.value = calculateTreeData(
-        res,
-        { level: 3, valueKey: 'id', labelKey: 'deptName' },
-        1,
-      );
+      departmentList.value = calculateTreeData(res, { level: 3, valueKey: 'id', labelKey: 'deptName' }, 1);
     });
     const res = (await getRoles()) || [];
     roleData.value = res.map((item: any) => {
@@ -282,8 +316,8 @@
   const loadPageData = () => {
     const searchFormData = searchFormRef.value?.getSearchFromData();
     if (searchFormData) {
-      const { queryType, queryTypeContent} = searchFormData;
-      Object.entries(searchFormData).forEach(([key, value]) => { 
+      const { queryType, queryTypeContent } = searchFormData;
+      Object.entries(searchFormData).forEach(([key, value]) => {
         if (value) {
           if (['deptId', 'roleId'].includes(key)) {
             params.queryParam[key] = value;
@@ -293,7 +327,7 @@
           }
         }
       });
-      
+
       // 删除多余参数
       delteExtraParams(queryType);
       getUserList(params).then((res) => {
@@ -360,7 +394,7 @@
   }
 
   .el-space--horizontal {
-    align-items: center; 
+    align-items: center;
     gap: 0px 20px;
   }
 
@@ -372,7 +406,7 @@
     color: var(--el-color-primary);
   }
 
-  .box-item{
+  .box-item {
     position: absolute;
     top: 0;
     left: 0;