wyg
2024-06-14 a57dc2fae73d6e0dd315a120ca43ee685a6c7b7c
提交 | 用户 | 时间
a57dc2 1 <template>
W 2   <div class="app-container">
3     <el-row :gutter="20">
4       <!--部门数据-->
5       <el-col :span="4" :xs="24">
6         <div class="head-container">
7           <el-input
8             v-model="deptName"
9             placeholder="请输入部门名称"
10             clearable
11             size="small"
12             prefix-icon="el-icon-search"
13             style="margin-bottom: 20px"
14           />
15         </div>
16         <div class="head-container">
17           <el-tree
18             :data="deptOptions"
19             :props="defaultProps"
20             :expand-on-click-node="false"
21             :filter-node-method="filterNode"
22             ref="tree"
23             node-key="id"
24             default-expand-all
25             highlight-current
26             @node-click="handleNodeClick"
27           />
28         </div>
29       </el-col>
30       <!--用户数据-->
31       <el-col :span="20" :xs="24">
32         <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
33           <el-form-item label="用户名称" prop="userName">
34             <el-input
35               v-model="queryParams.userName"
36               placeholder="请输入用户名称"
37               clearable
38               style="width: 240px"
39               @keyup.enter.native="handleQuery"
40             />
41           </el-form-item>
42           <el-form-item label="手机号码" prop="phonenumber">
43             <el-input
44               v-model="queryParams.phonenumber"
45               placeholder="请输入手机号码"
46               clearable
47               style="width: 240px"
48               @keyup.enter.native="handleQuery"
49             />
50           </el-form-item>
51           <el-form-item label="状态" prop="status">
52             <el-select
53               v-model="queryParams.status"
54               placeholder="用户状态"
55               clearable
56               style="width: 240px"
57             >
58               <el-option
59                 v-for="dict in dict.type.sys_normal_disable"
60                 :key="dict.value"
61                 :label="dict.label"
62                 :value="dict.value"
63               />
64             </el-select>
65           </el-form-item>
66           <el-form-item label="创建时间">
67             <el-date-picker
68               v-model="dateRange"
69               style="width: 240px"
70               value-format="yyyy-MM-dd HH:mm:ss"
71               type="daterange"
72               range-separator="-"
73               start-placeholder="开始日期"
74               end-placeholder="结束日期"
75               :default-time="['00:00:00', '23:59:59']"
76             ></el-date-picker>
77           </el-form-item>
78           <el-form-item>
79             <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
80             <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
81           </el-form-item>
82         </el-form>
83
84         <el-row :gutter="10" class="mb8">
85           <el-col :span="1.5">
86             <el-button
87               type="primary"
88               plain
89               icon="el-icon-plus"
90               size="mini"
91               @click="handleAdd"
92               v-hasPermi="['system:user:add']"
93             >新增</el-button>
94           </el-col>
95           <el-col :span="1.5">
96             <el-button
97               type="success"
98               plain
99               icon="el-icon-edit"
100               size="mini"
101               :disabled="single"
102               @click="handleUpdate"
103               v-hasPermi="['system:user:edit']"
104             >修改</el-button>
105           </el-col>
106           <el-col :span="1.5">
107             <el-button
108               type="danger"
109               plain
110               icon="el-icon-delete"
111               size="mini"
112               :disabled="multiple"
113               @click="handleDelete"
114               v-hasPermi="['system:user:remove']"
115             >删除</el-button>
116           </el-col>
117           <el-col :span="1.5">
118             <el-button
119               type="info"
120               plain
121               icon="el-icon-upload2"
122               size="mini"
123               @click="handleImport"
124               v-hasPermi="['system:user:import']"
125             >导入</el-button>
126           </el-col>
127           <el-col :span="1.5">
128             <el-button
129               type="warning"
130               plain
131               icon="el-icon-download"
132               size="mini"
133               @click="handleExport"
134               v-hasPermi="['system:user:export']"
135             >导出</el-button>
136           </el-col>
137           <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
138         </el-row>
139
140         <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
141           <el-table-column type="selection" width="50" align="center" />
142           <el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
143           <el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
144           <el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
145           <el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
146           <el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
147           <el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
148             <template slot-scope="scope">
149               <el-switch
150                 v-model="scope.row.status"
151                 active-value="0"
152                 inactive-value="1"
153                 @change="handleStatusChange(scope.row)"
154               ></el-switch>
155             </template>
156           </el-table-column>
157           <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
158             <template slot-scope="scope">
159               <span>{{ parseTime(scope.row.createTime) }}</span>
160             </template>
161           </el-table-column>
162           <el-table-column
163             label="操作"
164             align="center"
165             width="160"
166             class-name="small-padding fixed-width"
167           >
168             <template slot-scope="scope" v-if="scope.row.userId !== 1">
169               <el-button
170                 size="mini"
171                 type="text"
172                 icon="el-icon-edit"
173                 @click="handleUpdate(scope.row)"
174                 v-hasPermi="['system:user:edit']"
175               >修改</el-button>
176               <el-button
177                 size="mini"
178                 type="text"
179                 icon="el-icon-delete"
180                 @click="handleDelete(scope.row)"
181                 v-hasPermi="['system:user:remove']"
182               >删除</el-button>
183               <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
184                 <el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
185                 <el-dropdown-menu slot="dropdown">
186                   <el-dropdown-item command="handleResetPwd" icon="el-icon-key"
187                     v-hasPermi="['system:user:resetPwd']">重置密码</el-dropdown-item>
188                   <el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check"
189                     v-hasPermi="['system:user:edit']">分配角色</el-dropdown-item>
190                 </el-dropdown-menu>
191               </el-dropdown>
192             </template>
193           </el-table-column>
194         </el-table>
195
196         <pagination
197           v-show="total>0"
198           :total="total"
199           :page.sync="queryParams.pageNum"
200           :limit.sync="queryParams.pageSize"
201           @pagination="getList"
202         />
203       </el-col>
204     </el-row>
205
206     <!-- 添加或修改用户配置对话框 -->
207     <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
208       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
209         <el-row>
210           <el-col :span="12">
211             <el-form-item label="用户昵称" prop="nickName">
212               <el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
213             </el-form-item>
214           </el-col>
215           <el-col :span="12">
216             <el-form-item label="归属部门" prop="deptId">
217               <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
218             </el-form-item>
219           </el-col>
220         </el-row>
221         <el-row>
222           <el-col :span="12">
223             <el-form-item label="手机号码" prop="phonenumber">
224               <el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
225             </el-form-item>
226           </el-col>
227           <el-col :span="12">
228             <el-form-item label="邮箱" prop="email">
229               <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
230             </el-form-item>
231           </el-col>
232         </el-row>
233         <el-row>
234           <el-col :span="12">
235             <el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
236               <el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30" />
237             </el-form-item>
238           </el-col>
239           <el-col :span="12">
240             <el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
241               <el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password/>
242             </el-form-item>
243           </el-col>
244         </el-row>
245         <el-row>
246           <el-col :span="12">
247             <el-form-item label="用户性别">
248               <el-select v-model="form.sex" placeholder="请选择性别">
249                 <el-option
250                   v-for="dict in dict.type.sys_user_sex"
251                   :key="dict.value"
252                   :label="dict.label"
253                   :value="dict.value"
254                 ></el-option>
255               </el-select>
256             </el-form-item>
257           </el-col>
258           <el-col :span="12">
259             <el-form-item label="状态">
260               <el-radio-group v-model="form.status">
261                 <el-radio
262                   v-for="dict in dict.type.sys_normal_disable"
263                   :key="dict.value"
264                   :label="dict.value"
265                 >{{dict.label}}</el-radio>
266               </el-radio-group>
267             </el-form-item>
268           </el-col>
269         </el-row>
270         <el-row>
271           <el-col :span="12">
272             <el-form-item label="岗位">
273               <el-select v-model="form.postIds" multiple placeholder="请选择岗位">
274                 <el-option
275                   v-for="item in postOptions"
276                   :key="item.postId"
277                   :label="item.postName"
278                   :value="item.postId"
279                   :disabled="item.status == 1"
280                 ></el-option>
281               </el-select>
282             </el-form-item>
283           </el-col>
284           <el-col :span="12">
285             <el-form-item label="角色">
286               <el-select v-model="form.roleIds" multiple placeholder="请选择角色">
287                 <el-option
288                   v-for="item in roleOptions"
289                   :key="item.roleId"
290                   :label="item.roleName"
291                   :value="item.roleId"
292                   :disabled="item.status == 1"
293                 ></el-option>
294               </el-select>
295             </el-form-item>
296           </el-col>
297         </el-row>
298         <el-row>
299           <el-col :span="24">
300             <el-form-item label="备注">
301               <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
302             </el-form-item>
303           </el-col>
304         </el-row>
305       </el-form>
306       <div slot="footer" class="dialog-footer">
307         <el-button type="primary" @click="submitForm">确 定</el-button>
308         <el-button @click="cancel">取 消</el-button>
309       </div>
310     </el-dialog>
311
312     <!-- 用户导入对话框 -->
313     <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
314       <el-upload
315         ref="upload"
316         :limit="1"
317         accept=".xlsx, .xls"
318         :headers="upload.headers"
319         :action="upload.url + '?updateSupport=' + upload.updateSupport"
320         :disabled="upload.isUploading"
321         :on-progress="handleFileUploadProgress"
322         :on-success="handleFileSuccess"
323         :auto-upload="false"
324         drag
325       >
326         <i class="el-icon-upload"></i>
327         <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
328         <div class="el-upload__tip text-center" slot="tip">
329           <div class="el-upload__tip" slot="tip">
330             <el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的用户数据
331           </div>
332           <span>仅允许导入xls、xlsx格式文件。</span>
333           <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
334         </div>
335       </el-upload>
336       <div slot="footer" class="dialog-footer">
337         <el-button type="primary" @click="submitFileForm">确 定</el-button>
338         <el-button @click="upload.open = false">取 消</el-button>
339       </div>
340     </el-dialog>
341   </div>
342 </template>
343
344 <script>
345 import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user";
346 import { getToken } from "@/utils/auth";
347 import Treeselect from "@riophae/vue-treeselect";
348 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
349
350 export default {
351   name: "User",
352   dicts: ['sys_normal_disable', 'sys_user_sex'],
353   components: { Treeselect },
354   data() {
355     return {
356       // 遮罩层
357       loading: true,
358       // 选中数组
359       ids: [],
360       // 非单个禁用
361       single: true,
362       // 非多个禁用
363       multiple: true,
364       // 显示搜索条件
365       showSearch: true,
366       // 总条数
367       total: 0,
368       // 用户表格数据
369       userList: null,
370       // 弹出层标题
371       title: "",
372       // 部门树选项
373       deptOptions: undefined,
374       // 是否显示弹出层
375       open: false,
376       // 部门名称
377       deptName: undefined,
378       // 默认密码
379       initPassword: undefined,
380       // 日期范围
381       dateRange: [],
382       // 岗位选项
383       postOptions: [],
384       // 角色选项
385       roleOptions: [],
386       // 表单参数
387       form: {},
388       defaultProps: {
389         children: "children",
390         label: "label"
391       },
392       // 用户导入参数
393       upload: {
394         // 是否显示弹出层(用户导入)
395         open: false,
396         // 弹出层标题(用户导入)
397         title: "",
398         // 是否禁用上传
399         isUploading: false,
400         // 是否更新已经存在的用户数据
401         updateSupport: 0,
402         // 设置上传的请求头部
403         headers: { Authorization: "Bearer " + getToken() },
404         // 上传的地址
405         url: process.env.VUE_APP_BASE_API + "/system/user/importData"
406       },
407       // 查询参数
408       queryParams: {
409         pageNum: 1,
410         pageSize: 10,
411         userName: undefined,
412         phonenumber: undefined,
413         status: undefined,
414         deptId: undefined
415       },
416       // 列信息
417       columns: [
418         { key: 0, label: `用户编号`, visible: true },
419         { key: 1, label: `用户名称`, visible: true },
420         { key: 2, label: `用户昵称`, visible: true },
421         { key: 3, label: `部门`, visible: true },
422         { key: 4, label: `手机号码`, visible: true },
423         { key: 5, label: `状态`, visible: true },
424         { key: 6, label: `创建时间`, visible: true }
425       ],
426       // 表单校验
427       rules: {
428         userName: [
429           { required: true, message: "用户名称不能为空", trigger: "blur" },
430           { min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }
431         ],
432         nickName: [
433           { required: true, message: "用户昵称不能为空", trigger: "blur" }
434         ],
435         password: [
436           { required: true, message: "用户密码不能为空", trigger: "blur" },
437           { min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' }
438         ],
439         email: [
440           {
441             type: "email",
442             message: "请输入正确的邮箱地址",
443             trigger: ["blur", "change"]
444           }
445         ],
446         phonenumber: [
447           {
448             pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
449             message: "请输入正确的手机号码",
450             trigger: "blur"
451           }
452         ]
453       }
454     };
455   },
456   watch: {
457     // 根据名称筛选部门树
458     deptName(val) {
459       this.$refs.tree.filter(val);
460     }
461   },
462   created() {
463     this.getList();
464     this.getDeptTree();
465     this.getConfigKey("sys.user.initPassword").then(response => {
466       this.initPassword = response.msg;
467     });
468   },
469   methods: {
470     /** 查询用户列表 */
471     getList() {
472       this.loading = true;
473       listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
474           this.userList = response.rows;
475           this.total = response.total;
476           this.loading = false;
477         }
478       );
479     },
480     /** 查询部门下拉树结构 */
481     getDeptTree() {
482       deptTreeSelect().then(response => {
483         this.deptOptions = response.data;
484       });
485     },
486     // 筛选节点
487     filterNode(value, data) {
488       if (!value) return true;
489       return data.label.indexOf(value) !== -1;
490     },
491     // 节点单击事件
492     handleNodeClick(data) {
493       this.queryParams.deptId = data.id;
494       this.handleQuery();
495     },
496     // 用户状态修改
497     handleStatusChange(row) {
498       let text = row.status === "0" ? "启用" : "停用";
499       this.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?').then(function() {
500         return changeUserStatus(row.userId, row.status);
501       }).then(() => {
502         this.$modal.msgSuccess(text + "成功");
503       }).catch(function() {
504         row.status = row.status === "0" ? "1" : "0";
505       });
506     },
507     // 取消按钮
508     cancel() {
509       this.open = false;
510       this.reset();
511     },
512     // 表单重置
513     reset() {
514       this.form = {
515         userId: undefined,
516         deptId: undefined,
517         userName: undefined,
518         nickName: undefined,
519         password: undefined,
520         phonenumber: undefined,
521         email: undefined,
522         sex: undefined,
523         status: "0",
524         remark: undefined,
525         postIds: [],
526         roleIds: []
527       };
528       this.resetForm("form");
529     },
530     /** 搜索按钮操作 */
531     handleQuery() {
532       this.queryParams.pageNum = 1;
533       this.getList();
534     },
535     /** 重置按钮操作 */
536     resetQuery() {
537       this.dateRange = [];
538       this.resetForm("queryForm");
539       this.queryParams.deptId = undefined;
540       this.$refs.tree.setCurrentKey(null);
541       this.handleQuery();
542     },
543     // 多选框选中数据
544     handleSelectionChange(selection) {
545       this.ids = selection.map(item => item.userId);
546       this.single = selection.length != 1;
547       this.multiple = !selection.length;
548     },
549     // 更多操作触发
550     handleCommand(command, row) {
551       switch (command) {
552         case "handleResetPwd":
553           this.handleResetPwd(row);
554           break;
555         case "handleAuthRole":
556           this.handleAuthRole(row);
557           break;
558         default:
559           break;
560       }
561     },
562     /** 新增按钮操作 */
563     handleAdd() {
564       this.reset();
565       getUser().then(response => {
566         this.postOptions = response.data.posts;
567         this.roleOptions = response.data.roles;
568         this.open = true;
569         this.title = "添加用户";
570         this.form.password = this.initPassword;
571       });
572     },
573     /** 修改按钮操作 */
574     handleUpdate(row) {
575       this.reset();
576       const userId = row.userId || this.ids;
577       getUser(userId).then(response => {
578         this.form = response.data.user;
579         this.postOptions = response.data.posts;
580         this.roleOptions = response.data.roles;
581         this.$set(this.form, "postIds", response.data.postIds);
582         this.$set(this.form, "roleIds", response.data.roleIds);
583         this.open = true;
584         this.title = "修改用户";
585         this.form.password = "";
586       });
587     },
588     /** 重置密码按钮操作 */
589     handleResetPwd(row) {
590       this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
591         confirmButtonText: "确定",
592         cancelButtonText: "取消",
593         closeOnClickModal: false,
594         inputPattern: /^.{5,20}$/,
595         inputErrorMessage: "用户密码长度必须介于 5 和 20 之间"
596       }).then(({ value }) => {
597           resetUserPwd(row.userId, value).then(response => {
598             this.$modal.msgSuccess("修改成功,新密码是:" + value);
599           });
600         }).catch(() => {});
601     },
602     /** 分配角色操作 */
603     handleAuthRole: function(row) {
604       const userId = row.userId;
605       this.$router.push("/system/user-auth/role/" + userId);
606     },
607     /** 提交按钮 */
608     submitForm: function() {
609       this.$refs["form"].validate(valid => {
610         if (valid) {
611           if (this.form.userId != undefined) {
612             updateUser(this.form).then(response => {
613               this.$modal.msgSuccess("修改成功");
614               this.open = false;
615               this.getList();
616             });
617           } else {
618             addUser(this.form).then(response => {
619               this.$modal.msgSuccess("新增成功");
620               this.open = false;
621               this.getList();
622             });
623           }
624         }
625       });
626     },
627     /** 删除按钮操作 */
628     handleDelete(row) {
629       const userIds = row.userId || this.ids;
630       this.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?').then(function() {
631         return delUser(userIds);
632       }).then(() => {
633         this.getList();
634         this.$modal.msgSuccess("删除成功");
635       }).catch(() => {});
636     },
637     /** 导出按钮操作 */
638     handleExport() {
639       this.download('system/user/export', {
640         ...this.queryParams
641       }, `user_${new Date().getTime()}.xlsx`)
642     },
643     /** 导入按钮操作 */
644     handleImport() {
645       this.upload.title = "用户导入";
646       this.upload.open = true;
647     },
648     /** 下载模板操作 */
649     importTemplate() {
650       this.download('system/user/importTemplate', {
651       }, `user_template_${new Date().getTime()}.xlsx`)
652     },
653     // 文件上传中处理
654     handleFileUploadProgress(event, file, fileList) {
655       this.upload.isUploading = true;
656     },
657     // 文件上传成功处理
658     handleFileSuccess(response, file, fileList) {
659       this.upload.open = false;
660       this.upload.isUploading = false;
661       this.$refs.upload.clearFiles();
662       this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
663       this.getList();
664     },
665     // 提交上传文件
666     submitFileForm() {
667       this.$refs.upload.submit();
668     }
669   }
670 };
671 </script>