2 Commits 9672aba57e ... edd68d3495

Author SHA1 Message Date
  luoyb edd68d3495 Merge remote-tracking branch 'origin/master' 1 month ago
  luoyb 7f65129977 feature:系统管理->用户管理 1 month ago

+ 1 - 1
src/api/system/right/user/index.ts

@@ -1,4 +1,4 @@
1
-import { DeptVO } from './../dept/types';
1
+import { DeptVO } from '@/api/system/dept/types';
2
 import { RoleVO } from '@/api/system/role/types';
2
 import { RoleVO } from '@/api/system/role/types';
3
 import request from '@/utils/request';
3
 import request from '@/utils/request';
4
 import { AxiosPromise } from 'axios';
4
 import { AxiosPromise } from 'axios';

+ 8 - 3
src/views/system/right/user/UserDetailForm.vue

@@ -4,12 +4,12 @@
4
       <el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="auto" class="mt-3">
4
       <el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="auto" class="mt-3">
5
         <el-row>
5
         <el-row>
6
           <el-col :span="12">
6
           <el-col :span="12">
7
-            <el-form-item label="用户名" prop="userName">
7
+            <el-form-item v-if="formData.userId == undefined" label="用户名" prop="userName">
8
               <el-input v-model="formData.userName" placeholder="请输入用户名/登录账号" />
8
               <el-input v-model="formData.userName" placeholder="请输入用户名/登录账号" />
9
             </el-form-item>
9
             </el-form-item>
10
           </el-col>
10
           </el-col>
11
           <el-col :span="12">
11
           <el-col :span="12">
12
-            <el-form-item label="登录密码" prop="loginPwd">
12
+            <el-form-item v-if="formData.userId == undefined" label="登录密码" prop="loginPwd">
13
               <el-input v-model="formData.loginPwd" placeholder="请输入登录密码" type="password" maxlength="20" show-password />
13
               <el-input v-model="formData.loginPwd" placeholder="请输入登录密码" type="password" maxlength="20" show-password />
14
             </el-form-item>
14
             </el-form-item>
15
           </el-col>
15
           </el-col>
@@ -36,6 +36,7 @@
36
                 value-key="id"
36
                 value-key="id"
37
                 placeholder="请选择归属部门"
37
                 placeholder="请选择归属部门"
38
                 check-strictly
38
                 check-strictly
39
+                filterable
39
               />
40
               />
40
             </el-form-item>
41
             </el-form-item>
41
           </el-col>
42
           </el-col>
@@ -48,6 +49,7 @@
48
                   :label="item.postName"
49
                   :label="item.postName"
49
                   :value="item.postId"
50
                   :value="item.postId"
50
                   :disabled="item.status == '1'"
51
                   :disabled="item.status == '1'"
52
+                  filterable
51
                 ></el-option>
53
                 ></el-option>
52
               </el-select>
54
               </el-select>
53
             </el-form-item>
55
             </el-form-item>
@@ -136,6 +138,7 @@ import { PostVO } from '@/api/system/params/post/types';
136
 import { RoleVO } from '@/api/system/role/types';
138
 import { RoleVO } from '@/api/system/role/types';
137
 import { treeselect } from '@/api/system/dept';
139
 import { treeselect } from '@/api/system/dept';
138
 import { listUsePtCardType } from '@/api/basics/basicParameter/ptCardtype';
140
 import { listUsePtCardType } from '@/api/basics/basicParameter/ptCardtype';
141
+import { PtCardTypeVO } from '@/api/basics/basicParameter/ptCardtype/types';
139
 
142
 
140
 /** 当前组件属性 */
143
 /** 当前组件属性 */
141
 defineOptions({ name: 'RecompenseForm' });
144
 defineOptions({ name: 'RecompenseForm' });
@@ -203,7 +206,9 @@ const formRules = reactive({
203
   postId: [{ required: true, message: '工作岗位不能为空', trigger: 'blur' }],
206
   postId: [{ required: true, message: '工作岗位不能为空', trigger: 'blur' }],
204
   category: [{ required: true, message: '用户身份不能为空', trigger: 'blur' }],
207
   category: [{ required: true, message: '用户身份不能为空', trigger: 'blur' }],
205
   phone: [{ required: true, message: '电话号码不能为空', trigger: 'blur' }],
208
   phone: [{ required: true, message: '电话号码不能为空', trigger: 'blur' }],
206
-  roleIds: [{ required: true, message: '用户角色不能为空', trigger: 'blur' }]
209
+  roleIds: [{ required: true, message: '用户角色不能为空', trigger: 'blur' }],
210
+  cardType: [{ required: true, message: '账户卡类不能为空', trigger: 'blur' }],
211
+  lifespan: [{ required: true, message: '账户有效期不能为空', trigger: 'blur' }]
207
 });
212
 });
208
 /** 当前组件方法 */
213
 /** 当前组件方法 */
209
 const open = async (cmd: string, id?: string | number) => {
214
 const open = async (cmd: string, id?: string | number) => {

+ 50 - 181
src/views/system/right/user/index.vue

@@ -54,27 +54,27 @@
54
                   删除
54
                   删除
55
                 </el-button>
55
                 </el-button>
56
               </el-col>
56
               </el-col>
57
-              <el-col :span="1.5">
58
-                <el-dropdown class="mt-[1px]">
59
-                  <el-button plain type="info">
60
-                    更多
61
-                    <el-icon class="el-icon--right">
62
-                      <arrow-down />
63
-                    </el-icon>
64
-                  </el-button>
65
-                  <template #dropdown>
66
-                    <el-dropdown-menu>
67
-                      <el-dropdown-item icon="Download" @click="importTemplate">下载模板</el-dropdown-item>
68
-                      <el-dropdown-item icon="Top" @click="handleImport"> 导入数据</el-dropdown-item>
69
-                      <el-dropdown-item icon="Download" @click="handleExport"> 导出数据</el-dropdown-item>
70
-                    </el-dropdown-menu>
71
-                  </template>
72
-                </el-dropdown>
73
-              </el-col>
57
+<!--              <el-col :span="1.5">-->
58
+<!--                <el-dropdown class="mt-[1px]">-->
59
+<!--                  <el-button plain type="info">-->
60
+<!--                    更多-->
61
+<!--                    <el-icon class="el-icon&#45;&#45;right">-->
62
+<!--                      <arrow-down />-->
63
+<!--                    </el-icon>-->
64
+<!--                  </el-button>-->
65
+<!--                  <template #dropdown>-->
66
+<!--                    <el-dropdown-menu>-->
67
+<!--                      <el-dropdown-item icon="Download" @click="importTemplate">下载模板</el-dropdown-item>-->
68
+<!--                      <el-dropdown-item icon="Top" @click="handleImport"> 导入数据</el-dropdown-item>-->
69
+<!--                      <el-dropdown-item icon="Download" @click="handleExport"> 导出数据</el-dropdown-item>-->
70
+<!--                    </el-dropdown-menu>-->
71
+<!--                  </template>-->
72
+<!--                </el-dropdown>-->
73
+<!--              </el-col>-->
74
               <right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @query-table="getList"></right-toolbar>
74
               <right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @query-table="getList"></right-toolbar>
75
             </el-row>
75
             </el-row>
76
           </template>
76
           </template>
77
-          <el-table v-loading="loading" :data="userList" height="calc(100vh - 22rem)" @selection-change="handleSelectionChange" highlight-current-row>
77
+          <el-table v-loading="loading" :data="userList" height="calc(100vh - 22rem)" highlight-current-row @selection-change="handleSelectionChange">
78
             <el-table-column type="selection" width="50" align="center" />
78
             <el-table-column type="selection" width="50" align="center" />
79
             <el-table-column
79
             <el-table-column
80
               v-if="columns[0].visible"
80
               v-if="columns[0].visible"
@@ -103,14 +103,7 @@
103
               width="160"
103
               width="160"
104
               :show-overflow-tooltip="true"
104
               :show-overflow-tooltip="true"
105
             />
105
             />
106
-            <el-table-column
107
-              v-if="columns[3].visible"
108
-              key="deptName"
109
-              label="部门"
110
-              align="center"
111
-              prop="deptName"
112
-              :show-overflow-tooltip="true"
113
-            />
106
+            <el-table-column v-if="columns[3].visible" key="deptName" label="部门" align="center" prop="deptName" :show-overflow-tooltip="true" />
114
             <el-table-column
107
             <el-table-column
115
               v-if="columns[4].visible"
108
               v-if="columns[4].visible"
116
               key="phone"
109
               key="phone"
@@ -138,10 +131,16 @@
138
                 <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
131
                 <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
139
               </template>
132
               </template>
140
             </el-table-column>
133
             </el-table-column>
141
-            <el-table-column label="操作" fixed="right"  class-name="small-padding fixed-width">
134
+            <el-table-column label="操作" fixed="right" class-name="small-padding fixed-width">
142
               <template #default="scope">
135
               <template #default="scope">
143
                 <el-tooltip v-if="scope.row.userId !== 1" content="修改" placement="top">
136
                 <el-tooltip v-if="scope.row.userId !== 1" content="修改" placement="top">
144
-                  <el-button v-hasPermi="['system:user:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
137
+                  <el-button
138
+                    v-hasPermi="['system:user:edit']"
139
+                    link
140
+                    type="primary"
141
+                    icon="Edit"
142
+                    @click="handleOpenDetail('edit', scope.row)"
143
+                  ></el-button>
145
                 </el-tooltip>
144
                 </el-tooltip>
146
                 <el-tooltip v-if="scope.row.userId !== 1" content="删除" placement="top">
145
                 <el-tooltip v-if="scope.row.userId !== 1" content="删除" placement="top">
147
                   <el-button v-hasPermi="['system:user:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
146
                   <el-button v-hasPermi="['system:user:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
@@ -210,17 +209,16 @@
210
 
209
 
211
 <script setup name="User" lang="ts">
210
 <script setup name="User" lang="ts">
212
 import api from '@/api/system/right/user';
211
 import api from '@/api/system/right/user';
213
-import { UserForm, UserQuery, UserVO } from '@/api/system/right/user/types';
212
+import { UserQuery, UserVO } from '@/api/system/right/user/types';
214
 import { DeptVO } from '@/api/system/dept/types';
213
 import { DeptVO } from '@/api/system/dept/types';
215
-import { PostVO } from '@/api/system/params/post/types';
216
-import { treeselect } from '@/api/system/dept';
217
 import { globalHeaders } from '@/utils/request';
214
 import { globalHeaders } from '@/utils/request';
218
 import { to } from 'await-to-js';
215
 import { to } from 'await-to-js';
219
 import UserDetailForm from '@/views/system/right/user/UserDetailForm.vue';
216
 import UserDetailForm from '@/views/system/right/user/UserDetailForm.vue';
217
+import { ArrowDown } from '@element-plus/icons-vue';
220
 
218
 
221
 const router = useRouter();
219
 const router = useRouter();
222
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
220
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
223
-const { sys_normal_disable, sys_user_sex,CATEGORY } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_user_sex','CATEGORY'));
221
+const { CATEGORY } = toRefs<any>(proxy?.useDict('CATEGORY'));
224
 const userList = ref<UserVO[]>();
222
 const userList = ref<UserVO[]>();
225
 const loading = ref(true);
223
 const loading = ref(true);
226
 const showSearch = ref(true);
224
 const showSearch = ref(true);
@@ -232,7 +230,6 @@ const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
232
 const deptName = ref('');
230
 const deptName = ref('');
233
 const deptOptions = ref<DeptVO[]>([]);
231
 const deptOptions = ref<DeptVO[]>([]);
234
 const initPassword = ref<string>('');
232
 const initPassword = ref<string>('');
235
-const postOptions = ref<PostVO[]>([]);
236
 
233
 
237
 /*** 用户导入参数 */
234
 /*** 用户导入参数 */
238
 const upload = reactive<ImportOption>({
235
 const upload = reactive<ImportOption>({
@@ -259,87 +256,19 @@ const columns = ref<FieldOption[]>([
259
   { key: 5, label: `状态`, visible: true, children: [] },
256
   { key: 5, label: `状态`, visible: true, children: [] },
260
   { key: 6, label: `创建时间`, visible: true, children: [] }
257
   { key: 6, label: `创建时间`, visible: true, children: [] }
261
 ]);
258
 ]);
259
+const queryParams = reactive<UserQuery>({
260
+  pageNum: 1,
261
+  pageSize: 10,
262
+  userName: '',
263
+  phone: '',
264
+  status: '',
265
+  deptId: '',
266
+  roleId: ''
267
+});
262
 const deptTreeRef = ref<ElTreeInstance>();
268
 const deptTreeRef = ref<ElTreeInstance>();
263
 // 查询客体ref
269
 // 查询客体ref
264
 const queryFormRef = ref<ElFormInstance>();
270
 const queryFormRef = ref<ElFormInstance>();
265
-const userFormRef = ref<ElFormInstance>();
266
 const uploadRef = ref<ElUploadInstance>();
271
 const uploadRef = ref<ElUploadInstance>();
267
-const formDialogRef = ref<ElDialogInstance>();
268
-
269
-const dialog = reactive<DialogOption>({
270
-  visible: false,
271
-  title: ''
272
-});
273
-
274
-const initFormData: UserForm = {
275
-  userId: undefined,
276
-  deptId: undefined,
277
-  userName: '',
278
-  nickName: undefined,
279
-  password: '',
280
-  phonenumber: undefined,
281
-  email: undefined,
282
-  sex: undefined,
283
-  status: '0',
284
-  remark: '',
285
-  postIds: [],
286
-  roleIds: []
287
-};
288
-
289
-const initData: PageData<UserForm, UserQuery> = {
290
-  form: { ...initFormData },
291
-  queryParams: {
292
-    pageNum: 1,
293
-    pageSize: 10,
294
-    userName: '',
295
-    realName: '',
296
-    phone: '',
297
-    status: '',
298
-    deptId: '',
299
-    roleId: ''
300
-  },
301
-  rules: {
302
-    userName: [
303
-      { required: true, message: '用户名称不能为空', trigger: 'blur' },
304
-      {
305
-        min: 2,
306
-        max: 20,
307
-        message: '用户名称长度必须介于 2 和 20 之间',
308
-        trigger: 'blur'
309
-      }
310
-    ],
311
-    nickName: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }],
312
-    password: [
313
-      { required: true, message: '用户密码不能为空', trigger: 'blur' },
314
-      {
315
-        min: 5,
316
-        max: 20,
317
-        message: '用户密码长度必须介于 5 和 20 之间',
318
-        trigger: 'blur'
319
-      },
320
-      { pattern: /^[^<>"'|\\]+$/, message: '不能包含非法字符:< > " \' \\\ |', trigger: 'blur' }
321
-    ],
322
-    email: [
323
-      {
324
-        type: 'email',
325
-        message: '请输入正确的邮箱地址',
326
-        trigger: ['blur', 'change']
327
-      }
328
-    ],
329
-    phonenumber: [
330
-      {
331
-        pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
332
-        message: '请输入正确的手机号码',
333
-        trigger: 'blur'
334
-      }
335
-    ],
336
-    roleIds: [{ required: true, message: '用户角色不能为空', trigger: 'blur' }]
337
-  }
338
-};
339
-const data = reactive<PageData<UserForm, UserQuery>>(initData);
340
-
341
-const { queryParams, form, rules } = toRefs<PageData<UserForm, UserQuery>>(data);
342
-
343
 /** 通过条件过滤节点  */
272
 /** 通过条件过滤节点  */
344
 const filterNode = (value: string, data: any) => {
273
 const filterNode = (value: string, data: any) => {
345
   if (!value) return true;
274
   if (!value) return true;
@@ -364,7 +293,7 @@ const getTreeSelect = async () => {
364
 /** 查询用户列表 */
293
 /** 查询用户列表 */
365
 const getList = async () => {
294
 const getList = async () => {
366
   loading.value = true;
295
   loading.value = true;
367
-  const res = await api.listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
296
+  const res = await api.listUser(proxy?.addDateRange(queryParams, dateRange.value));
368
   loading.value = false;
297
   loading.value = false;
369
   userList.value = res.rows;
298
   userList.value = res.rows;
370
   total.value = res.total;
299
   total.value = res.total;
@@ -372,21 +301,21 @@ const getList = async () => {
372
 
301
 
373
 /** 节点单击事件 */
302
 /** 节点单击事件 */
374
 const handleNodeClick = (data: DeptVO) => {
303
 const handleNodeClick = (data: DeptVO) => {
375
-  queryParams.value.deptId = data.id;
304
+  queryParams.deptId = data.id;
376
   handleQuery();
305
   handleQuery();
377
 };
306
 };
378
 
307
 
379
 /** 搜索按钮操作 */
308
 /** 搜索按钮操作 */
380
 const handleQuery = () => {
309
 const handleQuery = () => {
381
-  queryParams.value.pageNum = 1;
310
+  queryParams.pageNum = 1;
382
   getList();
311
   getList();
383
 };
312
 };
384
 /** 重置按钮操作 */
313
 /** 重置按钮操作 */
385
 const resetQuery = () => {
314
 const resetQuery = () => {
386
   dateRange.value = ['', ''];
315
   dateRange.value = ['', ''];
387
   queryFormRef.value?.resetFields();
316
   queryFormRef.value?.resetFields();
388
-  queryParams.value.pageNum = 1;
389
-  queryParams.value.deptId = undefined;
317
+  queryParams.pageNum = 1;
318
+  queryParams.deptId = undefined;
390
   deptTreeRef.value?.setCurrentKey(undefined);
319
   deptTreeRef.value?.setCurrentKey(undefined);
391
   handleQuery();
320
   handleQuery();
392
 };
321
 };
@@ -394,14 +323,11 @@ const resetQuery = () => {
394
 /** 删除按钮操作 */
323
 /** 删除按钮操作 */
395
 const handleDelete = async (row?: UserVO) => {
324
 const handleDelete = async (row?: UserVO) => {
396
   const userIds = row?.userId || ids.value;
325
   const userIds = row?.userId || ids.value;
397
-  const [err] = await to(proxy?.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?') as any);
398
-  if (!err) {
399
-    await api.delUser(userIds);
400
-    await getList();
401
-    proxy?.$modal.msgSuccess('删除成功');
402
-  }
326
+  await proxy?.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?');
327
+  await api.delUser(userIds);
328
+  await getList();
329
+  proxy?.$modal.msgSuccess('删除成功');
403
 };
330
 };
404
-
405
 /** 用户状态修改  */
331
 /** 用户状态修改  */
406
 const handleStatusChange = async (row: UserVO) => {
332
 const handleStatusChange = async (row: UserVO) => {
407
   let text = row.status === '0' ? '启用' : '停用';
333
   let text = row.status === '0' ? '启用' : '停用';
@@ -429,7 +355,7 @@ const handleResetPwd = async (row: UserVO) => {
429
       inputPattern: /^.{5,20}$/,
355
       inputPattern: /^.{5,20}$/,
430
       inputErrorMessage: '用户密码长度必须介于 5 和 20 之间',
356
       inputErrorMessage: '用户密码长度必须介于 5 和 20 之间',
431
       inputValidator: (value) => {
357
       inputValidator: (value) => {
432
-        if (/<|>|"|'|\||\\/.test(value)) {
358
+        if (/[<>"'|\\]/.test(value)) {
433
           return '不能包含非法字符:< > " \' \\\ |';
359
           return '不能包含非法字符:< > " \' \\\ |';
434
         }
360
         }
435
       }
361
       }
@@ -458,7 +384,7 @@ const handleExport = () => {
458
   proxy?.download(
384
   proxy?.download(
459
     'system/user/export',
385
     'system/user/export',
460
     {
386
     {
461
-      ...queryParams.value
387
+      ...queryParams
462
     },
388
     },
463
     `user_${new Date().getTime()}.xlsx`
389
     `user_${new Date().getTime()}.xlsx`
464
   );
390
   );
@@ -488,26 +414,6 @@ function submitFileForm() {
488
   uploadRef.value?.submit();
414
   uploadRef.value?.submit();
489
 }
415
 }
490
 
416
 
491
-/** 初始化部门数据 */
492
-const initTreeData = async () => {
493
-  // 判断部门的数据是否存在,存在不获取,不存在则获取
494
-  if (deptOptions.value === undefined) {
495
-    const { data } = await treeselect();
496
-    deptOptions.value = data;
497
-  }
498
-};
499
-
500
-/** 重置操作表单 */
501
-const reset = () => {
502
-  form.value = { ...initFormData };
503
-  userFormRef.value?.resetFields();
504
-};
505
-/** 取消按钮 */
506
-const cancel = () => {
507
-  dialog.visible = false;
508
-  reset();
509
-};
510
-
511
 /** 增加/修改按钮操作 */
417
 /** 增加/修改按钮操作 */
512
 const userDetailFormRef = ref();
418
 const userDetailFormRef = ref();
513
 const handleOpenDetail = async (cmd: string, row?: UserVO) => {
419
 const handleOpenDetail = async (cmd: string, row?: UserVO) => {
@@ -517,37 +423,6 @@ const handleOpenDetail = async (cmd: string, row?: UserVO) => {
517
   }
423
   }
518
   userDetailFormRef?.value.open(cmd, userId);
424
   userDetailFormRef?.value.open(cmd, userId);
519
 };
425
 };
520
-
521
-/** 提交按钮 */
522
-const submitForm = () => {
523
-  userFormRef.value?.validate(async (valid: boolean) => {
524
-    if (valid) {
525
-      form.value.userId ? await api.updateUser(form.value) : await api.addUser(form.value);
526
-      proxy?.$modal.msgSuccess('操作成功');
527
-      dialog.visible = false;
528
-      await getList();
529
-    }
530
-  });
531
-};
532
-
533
-/**
534
- * 关闭用户弹窗
535
- */
536
-const closeDialog = () => {
537
-  dialog.visible = false;
538
-  resetForm();
539
-};
540
-
541
-/**
542
- * 重置表单
543
- */
544
-const resetForm = () => {
545
-  userFormRef.value?.resetFields();
546
-  userFormRef.value?.clearValidate();
547
-
548
-  form.value.id = undefined;
549
-  form.value.status = '1';
550
-};
551
 onMounted(() => {
426
 onMounted(() => {
552
   getTreeSelect(); // 初始化部门数据
427
   getTreeSelect(); // 初始化部门数据
553
   getList(); // 初始化列表数据
428
   getList(); // 初始化列表数据
@@ -555,12 +430,6 @@ onMounted(() => {
555
     initPassword.value = response.data;
430
     initPassword.value = response.data;
556
   });
431
   });
557
 });
432
 });
558
-
559
-async function handleDeptChange(value: number | string) {
560
-  const response = await optionselect(value);
561
-  postOptions.value = response.data;
562
-  form.value.postIds = [];
563
-}
564
 </script>
433
 </script>
565
 
434
 
566
 <style lang="scss" scoped>
435
 <style lang="scss" scoped>