zouyu
2026-03-26 aae0b49229d8798a2cc31a8449092e2db62e2407
src/views/system/user/index.vue
@@ -8,8 +8,8 @@
            <div class="head-container addButton">
              <el-input v-model="deptName" placeholder="部门名称" clearable size="small" prefix-icon="el-icon-search"
                style="margin-bottom: 20px" />
              <el-button style="margin-left: 4px" type="primary" plain icon="el-icon-plus" size="mini" circle
                @click="addSchema"></el-button>
              <!-- <el-button style="margin-left: 4px" type="primary" plain icon="el-icon-plus" size="mini" circle
                @click="addSchema"></el-button> -->
            </div>
            <div class="head-container">
              <el-tree :data="deptOptions" :props="defaultProps" :expand-on-click-node="false"
@@ -28,14 +28,14 @@
                    @keyup.enter.native="handleQuery" />
                </el-form-item>
                <el-form-item label="状态" prop="status">
                  <el-select v-model="queryParams.status" placeholder="用户状态" clearable>
                  <el-select v-model="queryParams.status" placeholder="用户状态" clearable @change="handleQuery">
                    <el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label"
                      :value="dict.value" />
                  </el-select>
                </el-form-item>
                <el-form-item>
                  <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查 询</el-button>
                  <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重 置</el-button>
                  <el-button type="primary" size="mini" @click="handleQuery">查询</el-button>
                  <el-button size="mini" @click="resetQuery">重置</el-button>
                </el-form-item>
              </el-form>
            </div>
@@ -47,10 +47,11 @@
            </div>
          </div>
          <el-col>
            <el-table v-loading="loading" :data="userList">
            <el-table v-loading="loading" :data="userList" :header-cell-style="{ background: '#f8f8f9', color: '#515a6e' }" border>
              <el-table-column label="序号" align="center" type="index" />
              <el-table-column label="姓名" align="center" key="nickName" prop="nickName" :show-overflow-tooltip="true" />
              <el-table-column label="账号" align="center" key="userName" prop="userName" :show-overflow-tooltip="true" />
              <el-table-column label="角色" align="center" key="roleName" prop="roleName" :show-overflow-tooltip="true" />
              <el-table-column label="状态" align="center" key="status">
                <template slot-scope="scope">
                  <el-switch v-model="scope.row.status" active-value="0" inactive-value="1"
@@ -62,7 +63,7 @@
                <template slot-scope="scope">
                  <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
                    v-hasPermi="['system:user:edit']">修改</el-button>
                  <!--                  <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']">删除</el-button>-->
                  <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']">删除</el-button>
                  <!--                  <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">-->
                  <!--                    <el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>-->
                  <!--                    <el-dropdown-menu slot="dropdown">-->
@@ -113,42 +114,61 @@
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="岗位">
              <el-select style="width:100%" v-model="form.postIds" multiple placeholder="请选择">
                <el-option
                  v-for="item in postOptions"
                  :key="item.postId"
                  :label="item.postName"
                  :value="item.postId"
                  :disabled="item.status == 1"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="角色" prop="roleIds">
              <el-select v-model="form.roleIds" multiple placeholder="请选择角色" clearable>
              <el-select style="width:100%" v-model="form.roleIds" multiple placeholder="请选择角色" clearable>
                <el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId"
                  :disabled="item.status == 1"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="密码" prop="password">
              <el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="姓名EN" prop="nameEn">
              <el-input v-model="form.nameEn" placeholder="请输入姓名EN" maxlength="50" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="邮箱" prop="email">
              <el-input v-model="form.email" placeholder="请输入内容"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="单位" prop="company">
              <el-select v-model="form.company" placeholder="请选择单位" style="width: 100%" clearable>
                <el-option v-for="item in postOptions" :key="item.id" :label="item.company"
                <el-option v-for="item in companyOptions" :key="item.id" :label="item.company"
                  :value="item.id"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="归属部门" prop="deptId">
              <treeselect v-model="form.deptId" :options="enabledDeptOptions" :show-count="true"
                          placeholder="请选择归属部门" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="签名">
              <el-upload class="avatar-uploader" :action="uploadAction" :show-file-list="false"
@@ -159,11 +179,13 @@
              </el-upload>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="个人照片">
              <el-upload class="avatar-uploader" :action="uploadAction" :show-file-list="false"
                :headers="upload.headers" accept=".png, .jpg, .jpeg, .gif" :on-error="handleUploadError1"
                :on-success="handleUploadSuccess1" :before-upload="handleBeforeUpload1">
                         :headers="upload.headers" accept=".png, .jpg, .jpeg, .gif" :on-error="handleUploadError1"
                         :on-success="handleUploadSuccess1" :before-upload="handleBeforeUpload1">
                <img v-if="form.pictureUrl" :src="javaApi + '/img/' + form.pictureUrl" class="avatar" alt="">
                <i v-else class="el-icon-plus avatar-uploader-icon"></i>
              </el-upload>
@@ -206,7 +228,7 @@
          <el-col :span="8" style="height: 70vh;overflow: hidden;" v-if="companiesList.length != 1">
            <el-input v-model="search2" placeholder="输入关键字搜索" clearable size="small" @clear="searchFilter2"
              @keyup.enter.native="searchFilter2" prefix-icon="el-icon-search" style="margin-bottom: 20px;width: 90%" />
            <el-tree :data="datathirdParty" node-key="companyId" :props="defaultProps" @node-click="nodeClick2"
            <el-tree :data="datathirdParty" node-key="companyId" :props="defaultProps1" @node-click="nodeClick2"
              style="height: calc(100% - 42px);" @node-expand="nodeOpen0" :filter-node-method="filterNode2" ref="tree2"
              highlight-current>
            </el-tree>
@@ -218,12 +240,13 @@
                style="width: 50%" @keyup.enter.native="searchPerson()"></el-input>
            </div>
            <el-table height="67vh" stripe :data="personList" v-loading="personLoad" ref="personTable"
                      :header-cell-style="{ background: '#f8f8f9', color: '#515a6e' }" border
              @selection-change="handleSelectionChange">
              <el-table-column type="selection" width="50">
              </el-table-column>
              <el-table-column prop="employeeID" label="员工号">
              </el-table-column>
              <el-table-column prop="nickName" label="员工姓名">
              <el-table-column prop="name" label="员工姓名">
              </el-table-column>
              <el-table-column prop="department" label="部门" min-width="200">
              </el-table-column>
@@ -270,8 +293,15 @@
  resetUserPwd,
  changeUserStatus,
  deptTreeSelect,
  selectCompaniesList, selectSimpleList, addPersonUser, uploadFile, selectRoleList, selectCustomEnum, addDepartment
  selectCompaniesList,
  selectSimpleList,
  addPersonUser,
  uploadFile,
  selectRoleList,
  selectCustomEnum,
  addDepartment
} from "@/api/system/user";
import {optionSelect} from '@/api/system/post'
import { getToken } from "@/utils/auth";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
@@ -286,6 +316,7 @@
    return {
      // 遮罩层
      loading: true,
      multipleSelection: [],
      // 选中数组
      ids: [],
      // 非单个禁用
@@ -314,6 +345,8 @@
      dateRange: [],
      // 岗位选项
      postOptions: [],
      //单位选项
      companyOptions:[],
      // 角色选项
      roleOptions: [],
      // 表单参数
@@ -321,6 +354,10 @@
      defaultProps: {
        children: "children",
        label: "label"
      },
      defaultProps1: {
        children: "children",
        label: "companyName"
      },
      // 用户导入参数
      upload: {
@@ -374,9 +411,35 @@
        roleIds: [
          { required: true, message: "请选择角色", trigger: "change" }
        ],
        // password: [
        //   { required: true, message: "密码不能为空", trigger: "blur" },
        // ],
        password: [
          { required: false, message: "密码不能为空", trigger: "blur" },
          { min: 8, max: 20, message: "密码长度必须在8-20个字符之间", trigger: "blur" },
          {
            validator: (rule, value, callback) => {
              if (!value) {
                callback();
                return;
              }
              // 检查是否包含大写字母
              const hasUpperCase = /[A-Z]/.test(value);
              // 检查是否包含小写字母
              const hasLowerCase = /[a-z]/.test(value);
              // 检查是否包含特殊符号
              const hasSpecialChar = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(value);
              if (!hasUpperCase) {
                callback(new Error('密码必须包含至少一个大写字母'));
              } else if (!hasLowerCase) {
                callback(new Error('密码必须包含至少一个小写字母'));
              } else if (!hasSpecialChar) {
                callback(new Error('密码必须包含至少一个特殊符号'));
              } else {
                callback();
              }
            },
            trigger: "blur"
          }
        ],
        phonenumber: [
          {
            required: true,
@@ -442,10 +505,6 @@
      }
      this.addLoad = true
      addDepartment(this.addOb).then(res => {
        if (res.code === 201) {
          this.addLoad = false
          return
        }
        this.$message.success('添加成功')
        this.addDia = false
        this.getList()
@@ -538,6 +597,7 @@
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.multipleSelection = selection;
      this.ids = selection.map(item => item.userId);
      this.single = selection.length != 1;
      this.multiple = !selection.length;
@@ -556,30 +616,31 @@
      }
    },
    // 获取三方人员
    openthirdParty() {
      this.addthirdParty = true;
      this.thirdPartyLoading = true;
      selectCompaniesList().then(res => {
        this.companiesList = this.HaveJson(res.data);
        if (this.companiesList.length == 1) {
          selectSimpleList({ companyId: this.companiesList[0].companyId }).then(res => {
            this.thirdPartyLoading = false;
            this.personListCopy = JSON.parse(JSON.stringify(res.data))
            this.personList = res.data
            this.$refs.personTable.doLayout()
          })
        } else {
          this.thirdPartyLoading = false;
    async openthirdParty() {
      try {
        this.addthirdParty = true;
        this.thirdPartyLoading = true;
        const companiesResponse = await selectCompaniesList();
        this.companiesList = this.HaveJson(companiesResponse.data);
        if (this.companiesList.length === 1) {
          const personResponse = await selectSimpleList({ companyId: this.companiesList[0].companyId });
          this.personListCopy = JSON.parse(JSON.stringify(personResponse.data));
          this.personList = personResponse.data;
          this.$refs.personTable.doLayout();
        }
        this.datathirdParty = this.tranListToTreeData(res.data, "ROOT");
      }).catch(() => {
        this.datathirdParty = this.tranListToTreeData(this.companiesList, "ROOT");
        console.log(' this.datathirdParty---',  this.datathirdParty)
      } catch (error) {
        console.error("Error fetching third party data:", error);
      } finally {
        this.thirdPartyLoading = false;
      })
      if (this.componentData.entity.roleId > 10000) this.$message.warning('由于未选中具体角色,新增用户将成为默认角色')
      }
    },
    tranListToTreeData(list, rootValue) {
      const arr = [];
      list.forEach((item) => {
      return list.reduce((arr, item) => {
        if (item.parentCompanyId === rootValue) {
          const children = this.tranListToTreeData(list, item.companyId);
          if (children.length) {
@@ -587,8 +648,8 @@
          }
          arr.push(item);
        }
      });
      return arr;
        return arr;
      }, []);
    },
    searchPerson() {
      let arr = JSON.parse(JSON.stringify(this.personListCopy))
@@ -620,7 +681,7 @@
      }
    },
    nodeOpen0(data, node, el) {
      this.currentCompaniesList[node.level - nodeOpen01] = data.id
      // this.currentCompaniesList[node.level - nodeOpen01] = data.id
    },
    filterNode2(value, data) {
      if (!value) return true;
@@ -648,16 +709,13 @@
      addPersonUser({
        company: arr,
        person: this.multipleSelection,
        roleId: this.componentData.entity.roleId
        // roleId: this.componentData.entity.roleId
      }).then(res => {
        if (res.code === 201) {
          this.addLoad = false
          return
        }
        this.$message.success('操作成功')
        this.multipleSelection = []
        this.$refs.personTable.clearSelection()
        this.addLoad = false
        this.addthirdParty = false
        this.userSearch2 = ''
        this.getList()
      }).catch(e => {
@@ -669,10 +727,11 @@
      this.reset();
      this.open = true;
      selectCustomEnum().then(res => {
        this.postOptions = res.data;
        this.companyOptions = res.data;
      })
      getUser().then(response => {
        this.roleOptions = response.roles;
        this.postOptions = response.posts
        this.title = "添加用户";
      });
    },
@@ -680,7 +739,7 @@
    handleUpdate(row) {
      this.reset();
      selectCustomEnum().then(res => {
        this.postOptions = res.data;
        this.companyOptions = res.data;
      })
      const userId = row.userId || this.ids;
      getUser(userId).then(response => {
@@ -688,6 +747,8 @@
        this.form.password = ''
        this.roleOptions = response.roles;
        this.$set(this.form, "roleIds", response.roleIds);
        this.postOptions = response.posts
        this.$set(this.form, "postIds", response.postIds);
        this.open = true;
        this.title = "修改用户";
      });