中国算力平台算力登记系统2.0
yanzhaofeige
2024-09-30 0f03e47899d7fd52ab5c7ad11a3bc5d4eec413cb
commit | author | age
43dc29 1 <template>
Y 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"
71               type="daterange"
72               range-separator="-"
73               start-placeholder="开始日期"
74               end-placeholder="结束日期"
75             ></el-date-picker>
76           </el-form-item>
77           <el-form-item>
78             <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
79             <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
80           </el-form-item>
81         </el-form>
82
83         <el-row :gutter="10" class="mb8">
84           <el-col :span="1.5">
85             <el-button
86               type="primary"
87               plain
88               icon="el-icon-plus"
89               size="mini"
90               @click="handleAdd"
91               v-hasPermi="['system:user:add']"
92             >新增</el-button>
93           </el-col>
94           <el-col :span="1.5">
95             <el-button
96               type="success"
97               plain
98               icon="el-icon-edit"
99               size="mini"
100               :disabled="single"
101               @click="handleUpdate"
102               v-hasPermi="['system:user:edit']"
103             >修改</el-button>
104           </el-col>
105           <el-col :span="1.5">
106             <el-button
107               type="danger"
108               plain
109               icon="el-icon-delete"
110               size="mini"
111               :disabled="multiple"
112               @click="handleDelete"
113               v-hasPermi="['system:user:remove']"
114             >删除</el-button>
115           </el-col>
116           <el-col :span="1.5">
117             <el-button
118               type="info"
119               plain
120               icon="el-icon-upload2"
121               size="mini"
122               @click="handleImport"
123               v-hasPermi="['system:user:import']"
124             >导入</el-button>
125           </el-col>
126           <el-col :span="1.5">
127             <el-button
128               type="warning"
129               plain
130               icon="el-icon-download"
131               size="mini"
132               @click="handleExport"
133               v-hasPermi="['system:user:export']"
134             >导出</el-button>
135           </el-col>
136           <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
137         </el-row>
138
139         <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
140           <el-table-column type="selection" width="50" align="center" />
141           <el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
142           <el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
143           <el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
144           <el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
145           <el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
146           <el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
147             <template slot-scope="scope">
148               <el-switch
149                 v-model="scope.row.status"
150                 active-value="0"
151                 inactive-value="1"
152                 @change="handleStatusChange(scope.row)"
153               ></el-switch>
154             </template>
155           </el-table-column>
156           <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
157             <template slot-scope="scope">
158               <span>{{ parseTime(scope.row.createTime) }}</span>
159             </template>
160           </el-table-column>
161           <el-table-column
162             label="操作"
163             align="center"
164             width="160"
165             class-name="small-padding fixed-width"
166           >
167             <template slot-scope="scope" v-if="scope.row.userId !== 1">
168               <el-button
169                 size="mini"
170                 type="text"
171                 icon="el-icon-edit"
172                 @click="handleUpdate(scope.row)"
173                 v-hasPermi="['system:user:edit']"
174               >修改</el-button>
175               <el-button
176                 size="mini"
177                 type="text"
178                 icon="el-icon-delete"
179                 @click="handleDelete(scope.row)"
180                 v-hasPermi="['system:user:remove']"
181               >删除</el-button>
182               <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
183                 <el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
184                 <el-dropdown-menu slot="dropdown">
185                   <el-dropdown-item command="handleResetPwd" icon="el-icon-key"
186                     v-hasPermi="['system:user:resetPwd']">重置密码</el-dropdown-item>
187                   <el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check"
188                     v-hasPermi="['system:user:edit']">分配角色</el-dropdown-item>
189                 </el-dropdown-menu>
190               </el-dropdown>
191             </template>
192           </el-table-column>
193         </el-table>
194
195         <pagination
196           v-show="total>0"
197           :total="total"
198           :page.sync="queryParams.pageNum"
199           :limit.sync="queryParams.pageSize"
200           @pagination="getList"
201         />
202       </el-col>
203     </el-row>
204
205     <!-- 添加或修改用户配置对话框 -->
206     <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
207       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
208         <el-row>
209           <el-col :span="12">
210             <el-form-item label="用户昵称" prop="nickName">
211               <el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
212             </el-form-item>
213           </el-col>
214           <el-col :span="12">
215             <el-form-item label="归属部门" prop="deptId">
216               <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
217             </el-form-item>
218           </el-col>
219         </el-row>
220         <el-row>
221           <el-col :span="12">
222             <el-form-item label="手机号码" prop="phonenumber">
223               <el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
224             </el-form-item>
225           </el-col>
226           <el-col :span="12">
227             <el-form-item label="邮箱" prop="email">
228               <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
229             </el-form-item>
230           </el-col>
231         </el-row>
232         <el-row>
233           <el-col :span="12">
234             <el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
235               <el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30" />
236             </el-form-item>
237           </el-col>
238           <el-col :span="12">
239             <el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
240               <el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password/>
241             </el-form-item>
242           </el-col>
243         </el-row>
244         <el-row>
245           <el-col :span="12">
246             <el-form-item label="用户性别">
247               <el-select v-model="form.sex" placeholder="请选择性别">
248                 <el-option
249                   v-for="dict in dict.type.sys_user_sex"
250                   :key="dict.value"
251                   :label="dict.label"
252                   :value="dict.value"
253                 ></el-option>
254               </el-select>
255             </el-form-item>
256           </el-col>
257           <el-col :span="12">
258             <el-form-item label="状态">
259               <el-radio-group v-model="form.status">
260                 <el-radio
261                   v-for="dict in dict.type.sys_normal_disable"
262                   :key="dict.value"
263                   :label="dict.value"
264                 >{{dict.label}}</el-radio>
265               </el-radio-group>
266             </el-form-item>
267           </el-col>
268         </el-row>
269         <el-row>
270           <el-col :span="12">
271             <el-form-item label="岗位">
272               <el-select v-model="form.postIds" multiple placeholder="请选择岗位">
273                 <el-option
274                   v-for="item in postOptions"
275                   :key="item.postId"
276                   :label="item.postName"
277                   :value="item.postId"
278                   :disabled="item.status == 1"
279                 ></el-option>
280               </el-select>
281             </el-form-item>
282           </el-col>
283           <el-col :span="12">
284             <el-form-item label="角色">
285               <el-select v-model="form.roleIds" multiple placeholder="请选择角色">
286                 <el-option
287                   v-for="item in roleOptions"
288                   :key="item.roleId"
289                   :label="item.roleName"
290                   :value="item.roleId"
291                   :disabled="item.status == 1"
292                 ></el-option>
293               </el-select>
294             </el-form-item>
295           </el-col>
296         </el-row>
297         <el-row>
298           <el-col :span="24">
299             <el-form-item label="备注">
300               <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
301             </el-form-item>
302           </el-col>
303         </el-row>
304       </el-form>
305       <div slot="footer" class="dialog-footer">
306         <el-button type="primary" @click="submitForm">确 定</el-button>
307         <el-button @click="cancel">取 消</el-button>
308       </div>
309     </el-dialog>
310
311     <!-- 用户导入对话框 -->
312     <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
313       <el-upload
314         ref="upload"
315         :limit="1"
316         accept=".xlsx, .xls"
317         :headers="upload.headers"
318         :action="upload.url + '?updateSupport=' + upload.updateSupport"
319         :disabled="upload.isUploading"
320         :on-progress="handleFileUploadProgress"
321         :on-success="handleFileSuccess"
322         :auto-upload="false"
323         drag
324       >
325         <i class="el-icon-upload"></i>
326         <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
327         <div class="el-upload__tip text-center" slot="tip">
328           <div class="el-upload__tip" slot="tip">
329             <el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的用户数据
330           </div>
331           <span>仅允许导入xls、xlsx格式文件。</span>
332           <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
333         </div>
334       </el-upload>
335       <div slot="footer" class="dialog-footer">
336         <el-button type="primary" @click="submitFileForm">确 定</el-button>
337         <el-button @click="upload.open = false">取 消</el-button>
338       </div>
339     </el-dialog>
340   </div>
341 </template>
342
343 <script>
344 import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user";
345 import { getToken } from "@/utils/auth";
346 import Treeselect from "@riophae/vue-treeselect";
347 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
348
349 export default {
350   name: "User",
351   dicts: ['sys_normal_disable', 'sys_user_sex'],
352   components: { Treeselect },
353   data() {
354     return {
355       // 遮罩层
356       loading: true,
357       // 选中数组
358       ids: [],
359       // 非单个禁用
360       single: true,
361       // 非多个禁用
362       multiple: true,
363       // 显示搜索条件
364       showSearch: true,
365       // 总条数
366       total: 0,
367       // 用户表格数据
368       userList: null,
369       // 弹出层标题
370       title: "",
371       // 部门树选项
372       deptOptions: undefined,
373       // 是否显示弹出层
374       open: false,
375       // 部门名称
376       deptName: undefined,
377       // 默认密码
378       initPassword: undefined,
379       // 日期范围
380       dateRange: [],
381       // 岗位选项
382       postOptions: [],
383       // 角色选项
384       roleOptions: [],
385       // 表单参数
386       form: {},
387       defaultProps: {
388         children: "children",
389         label: "label"
390       },
391       // 用户导入参数
392       upload: {
393         // 是否显示弹出层(用户导入)
394         open: false,
395         // 弹出层标题(用户导入)
396         title: "",
397         // 是否禁用上传
398         isUploading: false,
399         // 是否更新已经存在的用户数据
400         updateSupport: 0,
401         // 设置上传的请求头部
402         headers: { Authorization: "Bearer " + getToken() },
403         // 上传的地址
404         url: process.env.VUE_APP_BASE_API + "/system/user/importData"
405       },
406       // 查询参数
407       queryParams: {
408         pageNum: 1,
409         pageSize: 10,
410         userName: undefined,
411         phonenumber: undefined,
412         status: undefined,
413         deptId: undefined
414       },
415       // 列信息
416       columns: [
417         { key: 0, label: `用户编号`, visible: true },
418         { key: 1, label: `用户名称`, visible: true },
419         { key: 2, label: `用户昵称`, visible: true },
420         { key: 3, label: `部门`, visible: true },
421         { key: 4, label: `手机号码`, visible: true },
422         { key: 5, label: `状态`, visible: true },
423         { key: 6, label: `创建时间`, visible: true }
424       ],
425       // 表单校验
426       rules: {
427         userName: [
428           { required: true, message: "用户名称不能为空", trigger: "blur" },
429           { min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }
430         ],
431         nickName: [
432           { required: true, message: "用户昵称不能为空", trigger: "blur" }
433         ],
434         password: [
435           { required: true, message: "用户密码不能为空", trigger: "blur" },
436           { min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
437           { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", 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.posts;
567         this.roleOptions = response.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;
579         this.postOptions = response.posts;
580         this.roleOptions = response.roles;
581         this.$set(this.form, "postIds", response.postIds);
582         this.$set(this.form, "roleIds", response.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         inputValidator: (value) => {
597           if (/<|>|"|'|\||\\/.test(value)) {
598             return "不能包含非法字符:< > \" ' \\\ |"
599           }
600         },
601       }).then(({ value }) => {
602           resetUserPwd(row.userId, value).then(response => {
603             this.$modal.msgSuccess("修改成功,新密码是:" + value);
604           });
605         }).catch(() => {});
606     },
607     /** 分配角色操作 */
608     handleAuthRole: function(row) {
609       const userId = row.userId;
610       this.$router.push("/system/user-auth/role/" + userId);
611     },
612     /** 提交按钮 */
613     submitForm: function() {
614       this.$refs["form"].validate(valid => {
615         if (valid) {
616           if (this.form.userId != undefined) {
617             updateUser(this.form).then(response => {
618               this.$modal.msgSuccess("修改成功");
619               this.open = false;
620               this.getList();
621             });
622           } else {
623             addUser(this.form).then(response => {
624               this.$modal.msgSuccess("新增成功");
625               this.open = false;
626               this.getList();
627             });
628           }
629         }
630       });
631     },
632     /** 删除按钮操作 */
633     handleDelete(row) {
634       const userIds = row.userId || this.ids;
635       this.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?').then(function() {
636         return delUser(userIds);
637       }).then(() => {
638         this.getList();
639         this.$modal.msgSuccess("删除成功");
640       }).catch(() => {});
641     },
642     /** 导出按钮操作 */
643     handleExport() {
644       this.download('system/user/export', {
645         ...this.queryParams
646       }, `user_${new Date().getTime()}.xlsx`)
647     },
648     /** 导入按钮操作 */
649     handleImport() {
650       this.upload.title = "用户导入";
651       this.upload.open = true;
652     },
653     /** 下载模板操作 */
654     importTemplate() {
655       this.download('system/user/importTemplate', {
656       }, `user_template_${new Date().getTime()}.xlsx`)
657     },
658     // 文件上传中处理
659     handleFileUploadProgress(event, file, fileList) {
660       this.upload.isUploading = true;
661     },
662     // 文件上传成功处理
663     handleFileSuccess(response, file, fileList) {
664       this.upload.open = false;
665       this.upload.isUploading = false;
666       this.$refs.upload.clearFiles();
667       this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
668       this.getList();
669     },
670     // 提交上传文件
671     submitFileForm() {
672       this.$refs.upload.submit();
673     }
674   }
675 };
676 </script>