|
@@ -1,47 +1,710 @@
|
|
|
+<!-- 用户管理 -->
|
|
|
<template>
|
|
|
- <el-mention
|
|
|
- v-model="value1"
|
|
|
- whole
|
|
|
- :options="options1"
|
|
|
- style="width: 320px"
|
|
|
- placeholder="Please input"
|
|
|
- />
|
|
|
- <el-divider />
|
|
|
- <el-mention
|
|
|
- v-model="value2"
|
|
|
- :options="options2"
|
|
|
- :prefix="['@', '#']"
|
|
|
- whole
|
|
|
- :check-is-whole="checkIsWhole"
|
|
|
- style="width: 320px"
|
|
|
- placeholder="input @ to mention people, # to mention tag"
|
|
|
- @search="handleSearch"
|
|
|
- />
|
|
|
- <p style="color: red">{{ value1 }}||</p>
|
|
|
+ <div class="mainContentBox">
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <!-- 部门树 -->
|
|
|
+ <el-col :lg="4" :xs="24" class="mb-[12px]">
|
|
|
+ <DeptTree v-model="queryParams.deptId" @node-click="handleQuery" />
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 用户列表 -->
|
|
|
+ <el-col :lg="20" :xs="24">
|
|
|
+ <div class="search-container">
|
|
|
+ <el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
|
|
+ <el-form-item label="关键字" prop="keywords">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.keywords"
|
|
|
+ placeholder="用户名/昵称/手机号"
|
|
|
+ clearable
|
|
|
+ style="width: 200px"
|
|
|
+ @keyup.enter="handleQuery"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="状态" prop="state">
|
|
|
+ <el-select
|
|
|
+ v-model="queryParams.state"
|
|
|
+ placeholder="全部"
|
|
|
+ clearable
|
|
|
+ class="!w-[100px]"
|
|
|
+ >
|
|
|
+ <el-option label="启用" value="0" />
|
|
|
+ <el-option label="禁用" value="1" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="handleQuery"
|
|
|
+ ><i-ep-search />搜索</el-button
|
|
|
+ >
|
|
|
+ <el-button @click="resetQuery">
|
|
|
+ <i-ep-refresh />
|
|
|
+ 重置</el-button
|
|
|
+ >
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-card shadow="never" class="table-container">
|
|
|
+ <template #header>
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <div>
|
|
|
+ <el-button type="primary" @click="openDialog('user-form')"
|
|
|
+ ><i-ep-plus />新增</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="danger"
|
|
|
+ :disabled="removeIds.length === 0"
|
|
|
+ @click="handleDelete()"
|
|
|
+ ><i-ep-delete />删除</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <!-- <div>-->
|
|
|
+ <!-- <el-dropdown split-button>-->
|
|
|
+ <!-- 导入-->
|
|
|
+ <!-- <template #dropdown>-->
|
|
|
+ <!-- <el-dropdown-menu>-->
|
|
|
+ <!-- <el-dropdown-item @click="downloadTemplate">-->
|
|
|
+ <!-- <i-ep-download />下载模板</el-dropdown-item-->
|
|
|
+ <!-- >-->
|
|
|
+ <!-- <el-dropdown-item @click="openDialog('user-import')">-->
|
|
|
+ <!-- <i-ep-top />导入数据</el-dropdown-item-->
|
|
|
+ <!-- >-->
|
|
|
+ <!-- </el-dropdown-menu>-->
|
|
|
+ <!-- </template>-->
|
|
|
+ <!-- </el-dropdown>-->
|
|
|
+ <!-- <el-button class="ml-3" @click="handleExport"-->
|
|
|
+ <!-- ><template #icon><i-ep-download /></template>导出</el-button-->
|
|
|
+ <!-- >-->
|
|
|
+ <!-- </div>-->
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <el-table
|
|
|
+ v-loading="loading"
|
|
|
+ :data="pageData"
|
|
|
+ @selection-change="handleSelectionChange"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" width="50" align="center" />
|
|
|
+ <el-table-column
|
|
|
+ label="用户名"
|
|
|
+ width="120"
|
|
|
+ align="center"
|
|
|
+ prop="userName"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ label="姓名"
|
|
|
+ width="120"
|
|
|
+ align="center"
|
|
|
+ prop="nickName"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ key="employeeCode"
|
|
|
+ label="员工编号"
|
|
|
+ align="center"
|
|
|
+ prop="employeeCode"
|
|
|
+ />
|
|
|
+ <el-table-column label="性别" width="100" align="center" prop="sex">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag :type="scope.row.sex == 0 ? 'info' : 'success'">{{
|
|
|
+ scope.row.sex == 0 ? "未知" : scope.row.sex == 1 ? "男" : "女"
|
|
|
+ }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column
|
|
|
+ label="部门"
|
|
|
+ width="120"
|
|
|
+ align="center"
|
|
|
+ overHidden="true"
|
|
|
+ prop="deptNames"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ label="手机号码"
|
|
|
+ align="center"
|
|
|
+ prop="phone"
|
|
|
+ width="120"
|
|
|
+ />
|
|
|
+
|
|
|
+ <el-table-column label="状态" align="center" prop="state">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag :type="scope.row.state == 0 ? 'success' : 'info'">{{
|
|
|
+ scope.row.state == 0 ? "启用" : "禁用"
|
|
|
+ }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="创建时间"
|
|
|
+ align="center"
|
|
|
+ prop="created"
|
|
|
+ width="180"
|
|
|
+ />
|
|
|
+ <el-table-column label="操作" fixed="right" width="220">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ link
|
|
|
+ v-if="scope.row.id !== '1'"
|
|
|
+ @click="resetPassword(scope.row)"
|
|
|
+ ><i-ep-refresh-left />重置密码</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ link
|
|
|
+ size="small"
|
|
|
+ v-if="scope.row.id !== '1'"
|
|
|
+ @click="openDialog('user-form', scope.row)"
|
|
|
+ ><i-ep-edit />编辑</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ link
|
|
|
+ size="small"
|
|
|
+ v-if="scope.row.id !== '1'"
|
|
|
+ @click="handleDelete(scope.row.id)"
|
|
|
+ ><i-ep-delete />删除</el-button
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <pagination
|
|
|
+ v-if="total > 0"
|
|
|
+ v-model:total="total"
|
|
|
+ v-model:page="queryParams.pageNo"
|
|
|
+ v-model:limit="queryParams.pageSize"
|
|
|
+ @pagination="handleQuery"
|
|
|
+ />
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="dialog.visible"
|
|
|
+ :title="dialog.title"
|
|
|
+ :width="dialog.width"
|
|
|
+ append-to-body
|
|
|
+ @close="closeDialog"
|
|
|
+ >
|
|
|
+ <!-- 用户新增/编辑表单 -->
|
|
|
+ <el-form
|
|
|
+ v-if="dialog.type === 'user-form'"
|
|
|
+ ref="userFormRef"
|
|
|
+ :model="formData"
|
|
|
+ :rules="rules"
|
|
|
+ label-width="90px"
|
|
|
+ >
|
|
|
+ <el-row :gutter="22">
|
|
|
+ <el-col :span="11">
|
|
|
+ <el-form-item label="用户名称" prop="userName">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.userName"
|
|
|
+ :disabled="!!formData.id"
|
|
|
+ placeholder="请输入用户名称"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="11">
|
|
|
+ <el-form-item label="用户昵称" prop="nickName">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.nickName"
|
|
|
+ placeholder="请输入用户昵称"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row :gutter="22">
|
|
|
+ <el-col :span="11">
|
|
|
+ <el-form-item label="员工编号" prop="employeeCode">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.employeeCode"
|
|
|
+ placeholder="请输入员工编号"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="11">
|
|
|
+ <el-form-item label="性别" prop="sex">
|
|
|
+ <el-radio-group v-model="formData.sex">
|
|
|
+ <el-radio :value="0">未知</el-radio>
|
|
|
+ <el-radio :value="1">男</el-radio>
|
|
|
+ <el-radio :value="2">女</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="22">
|
|
|
+ <el-col :span="22">
|
|
|
+ <el-form-item label="所属部门" prop="deptIds">
|
|
|
+ <el-tree-select
|
|
|
+ v-model="formData.deptIds"
|
|
|
+ placeholder="请选择所属部门"
|
|
|
+ :data="deptList"
|
|
|
+ :multiple="true"
|
|
|
+ filterable
|
|
|
+ show-checkbox
|
|
|
+ load-key="deptName"
|
|
|
+ value-key="id"
|
|
|
+ :props="{
|
|
|
+ children: 'children',
|
|
|
+ label: 'deptName',
|
|
|
+ value: 'id',
|
|
|
+ disabled: '',
|
|
|
+ }"
|
|
|
+ check-strictly
|
|
|
+ :render-after-expand="false"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- <el-row :gutter="22">-->
|
|
|
+ <!-- <el-col :span="22">-->
|
|
|
+ <!-- <el-form-item label="角色" prop="roleIds">-->
|
|
|
+ <!-- <el-select-->
|
|
|
+ <!-- v-model="formData.roleIds"-->
|
|
|
+ <!-- multiple-->
|
|
|
+ <!-- placeholder="请选择"-->
|
|
|
+ <!-- >-->
|
|
|
+ <!-- <el-option-->
|
|
|
+ <!-- v-for="item in roleList"-->
|
|
|
+ <!-- :key="item.id"-->
|
|
|
+ <!-- :label="item.roleName"-->
|
|
|
+ <!-- :value="item.id"-->
|
|
|
+ <!-- />-->
|
|
|
+ <!-- </el-select>-->
|
|
|
+ <!-- </el-form-item>-->
|
|
|
+ <!-- </el-col>-->
|
|
|
+ <!-- </el-row>-->
|
|
|
+
|
|
|
+ <el-row :gutter="22">
|
|
|
+ <el-col :span="22">
|
|
|
+ <el-form-item label="岗位" prop="postIds">
|
|
|
+ <el-select
|
|
|
+ v-model="formData.postIds"
|
|
|
+ multiple
|
|
|
+ placeholder="请选择"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in postList"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.postName"
|
|
|
+ :value="item.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="22">
|
|
|
+ <el-col :span="11">
|
|
|
+ <el-form-item label="手机号码" prop="phone">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.phone"
|
|
|
+ placeholder="请输入手机号码"
|
|
|
+ maxlength="11"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="11">
|
|
|
+ <el-form-item label="邮箱" prop="email">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.email"
|
|
|
+ placeholder="请输入邮箱"
|
|
|
+ maxlength="50"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-form-item label="状态" prop="state">
|
|
|
+ <el-radio-group v-model="formData.state">
|
|
|
+ <el-radio :value="0">启用</el-radio>
|
|
|
+ <el-radio :value="1">禁用</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <!-- 用户导入表单 -->
|
|
|
+ <el-form
|
|
|
+ v-else-if="dialog.type === 'user-import'"
|
|
|
+ :model="importData"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-form-item label="部门">
|
|
|
+ <el-tree-select
|
|
|
+ v-model="importData.deptId"
|
|
|
+ placeholder="请选择部门"
|
|
|
+ :data="deptList"
|
|
|
+ load-key="deptName"
|
|
|
+ value-key="id"
|
|
|
+ :props="{
|
|
|
+ children: 'children',
|
|
|
+ label: 'deptName',
|
|
|
+ value: 'id',
|
|
|
+ disabled: '',
|
|
|
+ }"
|
|
|
+ filterable
|
|
|
+ check-strictly
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="Excel文件">
|
|
|
+ <el-upload
|
|
|
+ ref="uploadRef"
|
|
|
+ action=""
|
|
|
+ drag
|
|
|
+ accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
|
|
|
+ :limit="1"
|
|
|
+ :auto-upload="false"
|
|
|
+ :file-list="importData.fileList"
|
|
|
+ :on-change="handleFileChange"
|
|
|
+ :on-exceed="handleFileExceed"
|
|
|
+ >
|
|
|
+ <el-icon class="el-icon--upload">
|
|
|
+ <i-ep-upload-filled />
|
|
|
+ </el-icon>
|
|
|
+ <div class="el-upload__text">
|
|
|
+ 将文件拖到此处,或
|
|
|
+ <em>点击上传</em>
|
|
|
+ </div>
|
|
|
+ <template #tip>
|
|
|
+ <div>xls/xlsx files</div>
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <!-- 弹窗底部操作按钮 -->
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="handleSubmit">确 定</el-button>
|
|
|
+ <el-button @click="closeDialog">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
-<script setup lang="ts">
|
|
|
-import { ref } from "vue";
|
|
|
-import type { MentionOption } from "element-plus";
|
|
|
-
|
|
|
-const MOCK_DATA: Record<string, string[]> = {
|
|
|
- "@": ["Fuphoenixes", "kooriookami", "Jeremy", "btea"],
|
|
|
- "#": ["1.0", "2.0", "3.0"],
|
|
|
-};
|
|
|
-const value1 = ref("");
|
|
|
-const value2 = ref("");
|
|
|
-const options1 = ref<MentionOption[]>(
|
|
|
- MOCK_DATA["@"].map((value) => ({ value }))
|
|
|
-);
|
|
|
-const options2 = ref<MentionOption[]>([]);
|
|
|
-
|
|
|
-const handleSearch = (_: string, prefix: string) => {
|
|
|
- options2.value = (MOCK_DATA[prefix] || []).map((value) => ({
|
|
|
- value,
|
|
|
- }));
|
|
|
-};
|
|
|
-
|
|
|
-const checkIsWhole = (pattern: string, prefix: string) => {
|
|
|
- return (MOCK_DATA[prefix] || []).includes(pattern);
|
|
|
-};
|
|
|
+<script setup>
|
|
|
+defineOptions({
|
|
|
+ name: "User",
|
|
|
+ inheritAttrs: false,
|
|
|
+});
|
|
|
+
|
|
|
+import DeptTree from "./com/dept-tree.vue";
|
|
|
+import {
|
|
|
+ getUserPage,
|
|
|
+ deleteUsers,
|
|
|
+ addUser,
|
|
|
+ updateUser,
|
|
|
+ updateUserPassword,
|
|
|
+ downloadTemplateApi,
|
|
|
+ exportUser,
|
|
|
+ getPostOptions,
|
|
|
+ importUser,
|
|
|
+} from "@/api/system/user";
|
|
|
+import { treeList } from "@/api/system/dept";
|
|
|
+import { getRoleOptions } from "@/api/system/role";
|
|
|
+
|
|
|
+import { genFileId } from "element-plus";
|
|
|
+
|
|
|
+const queryFormRef = ref(ElForm); // 查询表单
|
|
|
+const userFormRef = ref(ElForm); // 用户表单
|
|
|
+const uploadRef = ref(); // 上传组件
|
|
|
+
|
|
|
+const loading = ref(false); // 加载状态
|
|
|
+const removeIds = ref([]); // 删除用户ID集合 用于批量删除
|
|
|
+const queryParams = reactive({
|
|
|
+ pageNo: 1,
|
|
|
+ pageSize: 10,
|
|
|
+});
|
|
|
+const dateTimeRange = ref("");
|
|
|
+const total = ref(0); // 数据总数
|
|
|
+const pageData = ref(); // 用户分页数据
|
|
|
+const deptList = ref(); // 部门下拉数据源
|
|
|
+const roleList = ref(); // 角色下拉数据源
|
|
|
+const postList = ref(); // 岗位下拉数据源
|
|
|
+
|
|
|
+// 弹窗对象
|
|
|
+const dialog = reactive({
|
|
|
+ visible: false,
|
|
|
+ type: "user-form",
|
|
|
+ width: 800,
|
|
|
+ title: "",
|
|
|
+});
|
|
|
+
|
|
|
+// 用户表单数据
|
|
|
+const formData = reactive({
|
|
|
+ state: 0,
|
|
|
+ sex: 0,
|
|
|
+ email: "",
|
|
|
+});
|
|
|
+
|
|
|
+// 用户导入数据
|
|
|
+const importData = reactive({
|
|
|
+ deptId: undefined,
|
|
|
+ file: undefined,
|
|
|
+ fileList: [],
|
|
|
+});
|
|
|
+
|
|
|
+// 校验规则
|
|
|
+const rules = reactive({
|
|
|
+ userName: [{ required: true, message: "用户名不能为空", trigger: "blur" }],
|
|
|
+ nickName: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
|
|
|
+ employeeCode: [
|
|
|
+ { required: true, message: "员工编号不能为空", trigger: "blur" },
|
|
|
+ ],
|
|
|
+ deptIds: [{ required: true, message: "所属部门不能为空", trigger: "blur" }],
|
|
|
+ // roleIds: [{ required: true, message: "用户角色不能为空", trigger: "blur" }],
|
|
|
+ postIds: [{ required: true, message: "用户岗位不能为空", trigger: "blur" }],
|
|
|
+ email: [
|
|
|
+ {
|
|
|
+ pattern: /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/,
|
|
|
+ message: "请输入正确的邮箱地址",
|
|
|
+ trigger: "blur",
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ phone: [
|
|
|
+ {
|
|
|
+ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
|
|
|
+ message: "请输入正确的手机号码",
|
|
|
+ trigger: "blur",
|
|
|
+ },
|
|
|
+ ],
|
|
|
+});
|
|
|
+
|
|
|
+/** 查询 */
|
|
|
+function handleQuery() {
|
|
|
+ loading.value = true;
|
|
|
+ queryParams.deptQuery = queryParams.deptId;
|
|
|
+ getUserPage(queryParams)
|
|
|
+ .then(({ data }) => {
|
|
|
+ pageData.value = data.records;
|
|
|
+ total.value = data.totalCount;
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ loading.value = false;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/** 重置查询 */
|
|
|
+function resetQuery() {
|
|
|
+ queryFormRef.value.resetFields();
|
|
|
+ dateTimeRange.value = "";
|
|
|
+ queryParams.pageNo = 1;
|
|
|
+ //queryParams.deptId = undefined;
|
|
|
+ queryParams.startTime = undefined;
|
|
|
+ queryParams.endTime = undefined;
|
|
|
+ handleQuery();
|
|
|
+}
|
|
|
+
|
|
|
+/** 行选中 */
|
|
|
+function handleSelectionChange(selection) {
|
|
|
+ removeIds.value = selection.map((item) => item.id);
|
|
|
+}
|
|
|
+
|
|
|
+/** 重置密码 */
|
|
|
+function resetPassword(row) {
|
|
|
+ ElMessageBox.confirm("确认重置用户密码吗?", "警告", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning",
|
|
|
+ }).then(function () {
|
|
|
+ updateUserPassword(row).then(() => {
|
|
|
+ ElMessage.success("密码重置成功,新密码为系统初始密码");
|
|
|
+ });
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/** 加载角色下拉数据源 */
|
|
|
+async function loadRoleOptions() {
|
|
|
+ getRoleOptions({}).then((response) => {
|
|
|
+ roleList.value = response.data;
|
|
|
+ });
|
|
|
+}
|
|
|
+/** 加载岗位下拉数据源 */
|
|
|
+async function loadPostOptions() {
|
|
|
+ getPostOptions({}).then((response) => {
|
|
|
+ postList.value = response.data;
|
|
|
+ });
|
|
|
+}
|
|
|
+/** 加载部门下拉数据源 */
|
|
|
+async function loadDeptOptions() {
|
|
|
+ treeList().then((response) => {
|
|
|
+ deptList.value = response.data;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 打开弹窗
|
|
|
+ *
|
|
|
+ * @param type 弹窗类型 用户表单:user-form | 用户导入:user-import
|
|
|
+ * @param id 用户ID
|
|
|
+ */
|
|
|
+async function openDialog(type, row) {
|
|
|
+ dialog.visible = true;
|
|
|
+ dialog.type = type;
|
|
|
+
|
|
|
+ if (dialog.type === "user-form") {
|
|
|
+ // 用户表单弹窗
|
|
|
+ await loadDeptOptions();
|
|
|
+ await loadPostOptions();
|
|
|
+ await loadRoleOptions();
|
|
|
+ if (row) {
|
|
|
+ dialog.title = "修改用户";
|
|
|
+ Object.assign(formData, row);
|
|
|
+ } else {
|
|
|
+ dialog.title = "新增用户";
|
|
|
+ }
|
|
|
+ } else if (dialog.type === "user-import") {
|
|
|
+ // 用户导入弹窗
|
|
|
+ dialog.title = "导入用户";
|
|
|
+ dialog.width = 600;
|
|
|
+ await loadDeptOptions();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 关闭弹窗
|
|
|
+ *
|
|
|
+ * @param type 弹窗类型 用户表单:user-form | 用户导入:user-import
|
|
|
+ */
|
|
|
+function closeDialog() {
|
|
|
+ dialog.visible = false;
|
|
|
+ if (dialog.type === "user-form") {
|
|
|
+ userFormRef.value.resetFields();
|
|
|
+ userFormRef.value.clearValidate();
|
|
|
+
|
|
|
+ formData.id = undefined;
|
|
|
+ formData.status = 1;
|
|
|
+ } else if (dialog.type === "user-import") {
|
|
|
+ importData.file = undefined;
|
|
|
+ importData.fileList = [];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/** 表单提交 */
|
|
|
+const handleSubmit = useThrottleFn(() => {
|
|
|
+ if (dialog.type === "user-form") {
|
|
|
+ userFormRef.value.validate((valid) => {
|
|
|
+ if (valid) {
|
|
|
+ const userId = formData.id;
|
|
|
+ loading.value = true;
|
|
|
+ if (userId) {
|
|
|
+ updateUser(userId, formData)
|
|
|
+ .then(() => {
|
|
|
+ ElMessage.success("修改用户成功");
|
|
|
+ closeDialog();
|
|
|
+ resetQuery();
|
|
|
+ })
|
|
|
+ .finally(() => (loading.value = false));
|
|
|
+ } else {
|
|
|
+ addUser(formData)
|
|
|
+ .then(() => {
|
|
|
+ ElMessage.success("新增用户成功");
|
|
|
+ closeDialog();
|
|
|
+ resetQuery();
|
|
|
+ })
|
|
|
+ .finally(() => (loading.value = false));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else if (dialog.type === "user-import") {
|
|
|
+ if (!importData?.deptId) {
|
|
|
+ ElMessage.warning("请选择部门");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!importData?.file) {
|
|
|
+ ElMessage.warning("上传Excel文件不能为空");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ importUser(importData?.deptId, importData?.file).then((response) => {
|
|
|
+ ElMessage.success(response.msg);
|
|
|
+ closeDialog();
|
|
|
+ resetQuery();
|
|
|
+ });
|
|
|
+ }
|
|
|
+}, 3000);
|
|
|
+
|
|
|
+/** 删除用户 */
|
|
|
+function handleDelete(id) {
|
|
|
+ ElMessageBox.confirm("确认删除用户?", "警告", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning",
|
|
|
+ }).then(function () {
|
|
|
+ deleteUsers(id).then(() => {
|
|
|
+ ElMessage.success("删除成功");
|
|
|
+ resetQuery();
|
|
|
+ });
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/** 下载导入模板 */
|
|
|
+function downloadTemplate() {
|
|
|
+ downloadTemplateApi().then((response) => {
|
|
|
+ const fileData = response.data;
|
|
|
+ const fileName = decodeURI(
|
|
|
+ response.headers["content-disposition"].split(";")[1].split("=")[1]
|
|
|
+ );
|
|
|
+ const fileType =
|
|
|
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
|
|
|
+
|
|
|
+ const blob = new Blob([fileData], { type: fileType });
|
|
|
+ const downloadUrl = window.URL.createObjectURL(blob);
|
|
|
+
|
|
|
+ const downloadLink = document.createElement("a");
|
|
|
+ downloadLink.href = downloadUrl;
|
|
|
+ downloadLink.download = fileName;
|
|
|
+
|
|
|
+ document.body.appendChild(downloadLink);
|
|
|
+ downloadLink.click();
|
|
|
+
|
|
|
+ document.body.removeChild(downloadLink);
|
|
|
+ window.URL.revokeObjectURL(downloadUrl);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/** Excel文件 Change */
|
|
|
+function handleFileChange(file) {
|
|
|
+ importData.file = file.raw;
|
|
|
+}
|
|
|
+
|
|
|
+/** Excel文件 Exceed */
|
|
|
+function handleFileExceed(files) {
|
|
|
+ uploadRef.value.clearFiles();
|
|
|
+ const file = files[0];
|
|
|
+ file.uid = genFileId();
|
|
|
+ uploadRef.value.handleStart(file);
|
|
|
+ importData.file = file;
|
|
|
+}
|
|
|
+
|
|
|
+/** 导出用户 */
|
|
|
+function handleExport() {
|
|
|
+ exportUser(queryParams).then((response) => {
|
|
|
+ const fileData = response.data;
|
|
|
+ const fileName = decodeURI(
|
|
|
+ response.headers["content-disposition"].split(";")[1].split("=")[1]
|
|
|
+ );
|
|
|
+ const fileType =
|
|
|
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
|
|
|
+
|
|
|
+ const blob = new Blob([fileData], { type: fileType });
|
|
|
+ const downloadUrl = window.URL.createObjectURL(blob);
|
|
|
+
|
|
|
+ const downloadLink = document.createElement("a");
|
|
|
+ downloadLink.href = downloadUrl;
|
|
|
+ downloadLink.download = fileName;
|
|
|
+
|
|
|
+ document.body.appendChild(downloadLink);
|
|
|
+ downloadLink.click();
|
|
|
+
|
|
|
+ document.body.removeChild(downloadLink);
|
|
|
+ window.URL.revokeObjectURL(downloadUrl);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+onMounted?.(() => {
|
|
|
+ handleQuery();
|
|
|
+});
|
|
|
</script>
|