Procházet zdrojové kódy

系统管理内部页面优化

sunxuewei před 2 roky
rodič
revize
37b99e1520

+ 5 - 5
src/api/index.ts

@@ -163,11 +163,11 @@ request.interceptors.response.use(
163 163
         return;
164 164
       }
165 165
     }
166
-    ElMessage({
167
-      message: message,
168
-      type: "error",
169
-      duration: 5 * 1000
170
-    });
166
+    // ElMessage({
167
+    //   message: message,
168
+    //   type: "error",
169
+    //   duration: 5 * 1000
170
+    // });
171 171
     return Promise.reject(error);
172 172
   }
173 173
 );

+ 13 - 0
src/utils/util.ts

@@ -183,3 +183,16 @@ export function getValueListLabel(arr: any, value: string[], valueName?: string,
183 183
   });
184 184
   return result.join("、");
185 185
 }
186
+
187
+// 级联字典获取对应value的label
188
+export function getLabelFromMutDict(arr: any, val: string, valueName?: string, labelName?: string): any {
189
+  const value = valueName ?? "value";
190
+  const label = labelName ?? "label";
191
+  for (const item of arr) {
192
+    if (item[value] === val) {
193
+      return item[label];
194
+    } else if (item.children?.length > 0) {
195
+      return getLabelFromMutDict(item.children, val, value, label);
196
+    }
197
+  }
198
+}

+ 7 - 1
src/views/admin/dept/index.vue

@@ -74,11 +74,16 @@
74 74
             </el-col>
75 75
           </el-row>
76 76
           <el-row>
77
-            <el-col :span="24">
77
+            <el-col :span="12">
78 78
               <el-form-item label="部门名称" prop="name">
79 79
                 <el-input v-model="form.name" placeholder="请输入部门名称" clearable />
80 80
               </el-form-item>
81 81
             </el-col>
82
+            <el-col :span="12">
83
+              <el-form-item label="部门简称" prop="abbreviationName">
84
+                <el-input v-model="form.abbreviationName" placeholder="请输入部门简称" clearable />
85
+              </el-form-item>
86
+            </el-col>
82 87
           </el-row>
83 88
           <el-row>
84 89
             <el-col :span="24">
@@ -189,6 +194,7 @@ const title = ref(""); // 新增/修改/查看 弹窗标题
189 194
 const form = ref<any>({
190 195
   parentId: "",
191 196
   name: "",
197
+  abbreviationName: "",
192 198
   sortOrder: "",
193 199
   deptType: "",
194 200
   longitude: "",

+ 39 - 38
src/views/admin/user/index.vue

@@ -12,7 +12,17 @@
12 12
             default-expand-all
13 13
             :expand-on-click-node="false"
14 14
             @node-click="handleNodeClick"
15
-          />
15
+          >
16
+            <template #default="{ node, data }">
17
+              <el-tooltip v-if="!data.isLock" class="item" effect="dark" content="无数据权限" placement="right-start">
18
+                <span>
19
+                  {{ data.name }}
20
+                  <el-icon><Lock /> </el-icon>
21
+                </span>
22
+              </el-tooltip>
23
+              <span v-else>{{ data.name }}</span>
24
+            </template>
25
+          </el-tree>
16 26
         </div>
17 27
       </div>
18 28
       <div class="user__main">
@@ -57,9 +67,17 @@
57 67
         <el-table v-loading="tableLoading" border :data="tableData" row-key="id">
58 68
           <el-table-column type="index" label="排序" width="60" align="center" />
59 69
           <el-table-column prop="username" label="用户名称" align="center" />
60
-          <el-table-column prop="deptId" label="部门" align="center" />
70
+          <el-table-column prop="deptId" label="部门" align="center">
71
+            <template #default="{ row }">
72
+              {{ getLabelFromMutDict(deptData, row.deptId, "id", "name") }}
73
+            </template>
74
+          </el-table-column>
61 75
           <el-table-column prop="phone" label="手机号码" align="center" />
62
-          <el-table-column prop="lockFlag" label="状态" align="center" />
76
+          <el-table-column prop="lockFlag" label="状态" align="center">
77
+            <template #default="{ row }">
78
+              {{ getValueLabel(del_type, row.lockFlag) }}
79
+            </template>
80
+          </el-table-column>
63 81
           <el-table-column prop="createTime" label="创建时间" align="center" />
64 82
           <el-table-column label="操作" width="220" align="center" class-name="small-padding fixed-width">
65 83
             <template #default="{ row }">
@@ -126,12 +144,13 @@
126 144
             </el-form-item>
127 145
           </el-col>
128 146
           <el-col :span="12">
129
-            <el-form-item label="岗位">
147
+            <el-form-item label="岗位" prop="deptId">
130 148
               <el-tree-select
131 149
                 placeholder="请选择岗位"
132 150
                 v-model="dialogForm.deptId"
133 151
                 :data="deptOptions"
134 152
                 check-strictly
153
+                clearable
135 154
                 :render-after-expand="false"
136 155
               />
137 156
             </el-form-item>
@@ -178,10 +197,11 @@
178 197
 import { ref } from "vue";
179 198
 import { ElMessage, ElMessageBox } from "element-plus";
180 199
 import type { FormInstance, FormRules } from "element-plus";
181
-import { Search, Refresh, Plus } from "@element-plus/icons-vue";
200
+import { Search, Refresh, Plus, Lock } from "@element-plus/icons-vue";
182 201
 
183 202
 import { ITablePage } from "@/const/interface_type";
184
-import { deepClone } from "@/utils/util";
203
+import { useDict } from "@/hooks/dict";
204
+import { deepClone, getValueLabel, getLabelFromMutDict } from "@/utils/util";
185 205
 import { getDeptList, getUserList, getDetails, getRoleList, addUserObj, putUserObj, delUserObj } from "@/api/admin";
186 206
 
187 207
 const validateUsername = (rule: any, value: any, callback: any) => {
@@ -227,6 +247,7 @@ const tablePage = ref<ITablePage>({
227 247
   total: 0
228 248
 });
229 249
 
250
+const { del_type } = useDict("del_type");
230 251
 const dialogVisible = ref(false); // 弹窗显隐
231 252
 const title = ref(""); // 弹窗标题
232 253
 const dialogForm = ref<any>({
@@ -241,40 +262,15 @@ const dialogForm = ref<any>({
241 262
 });
242 263
 const dialogFormRef = ref<FormInstance>();
243 264
 const dialogFormRules = ref<FormRules>({
244
-  username: [],
245
-  name: [
246
-    {
247
-      min: 2,
248
-      max: 64,
249
-      required: true,
250
-      message: "请输入姓名",
251
-      trigger: "blur"
252
-    }
253
-  ],
265
+  username: [{ min: 2, max: 64, required: true, message: "请输入用户昵称", trigger: "blur" }],
266
+  name: [{ min: 2, max: 64, required: true, message: "请输入姓名", trigger: "blur" }],
254 267
   password: [
255
-    {
256
-      min: 6,
257
-      max: 20,
258
-      required: true,
259
-      message: "长度在 6 到 20 个字符",
260
-      trigger: "blur"
261
-    }
262
-    // { required: true, validator: validatePass1, trigger: "blur" }
268
+    { min: 6, max: 20, required: true, message: "长度在 6 到 20 个字符", trigger: "blur" },
269
+    { required: true, validator: validatePass1, trigger: "blur" }
263 270
   ],
264
-  lockFlag: [
265
-    {
266
-      required: true,
267
-      message: "请选择状态",
268
-      trigger: "change"
269
-    }
270
-  ],
271
-  role: [
272
-    {
273
-      required: true,
274
-      message: "请选择角色",
275
-      trigger: "change"
276
-    }
277
-  ]
271
+  deptId: [{ required: true, message: "请选择岗位", trigger: "change" }],
272
+  lockFlag: [{ required: true, message: "请选择状态", trigger: "change" }],
273
+  role: [{ required: true, message: "请选择角色", trigger: "change" }]
278 274
 });
279 275
 const deptOptions = ref<any>([]); // 部门数据
280 276
 const roleList = ref<any>([]);
@@ -286,7 +282,12 @@ getRoleList().then((res: any) => {
286 282
 });
287 283
 
288 284
 const handleNodeClick = (data: any) => {
285
+  if (!data.isLock) {
286
+    ElMessage.warning("暂无权限查看该数据");
287
+    return;
288
+  }
289 289
   searchForm.value.deptId = data.id;
290
+  dialogForm.value.deptId = data.id;
290 291
   getList();
291 292
 };
292 293
 

+ 312 - 0
src/views/orderType/administration/index.vue

@@ -0,0 +1,312 @@
1
+<template>
2
+  <basic-container class="mti-container">
3
+    <div class="mti-flex">
4
+      <div class="mti-tree">
5
+        <el-tree
6
+          :data="treeData"
7
+          node-key="id"
8
+          highlight-current
9
+          :props="{ children: 'children', label: 'name' }"
10
+          :filter-node-method="filterNode"
11
+          :render-after-expand="true"
12
+          @node-click="getNodeData"
13
+        />
14
+      </div>
15
+      <div class="mti-form">
16
+        <div class="filter-container">
17
+          <el-button size="mini" :icon="Plus" type="primary" round @click="handlerAdd">添加</el-button>
18
+          <el-button size="mini" :icon="Edit" round @click="handlerEdit">编辑</el-button>
19
+          <el-button size="mini" :icon="Delete" round @click="handleDelete">删除</el-button>
20
+        </div>
21
+        <div class="box-card">
22
+          <el-form
23
+            ref="form"
24
+            label-position="right"
25
+            label-width="100px"
26
+            :rules="formRules"
27
+            :model="formData"
28
+            :disabled="formEdit"
29
+            size="small"
30
+          >
31
+            <el-form-item label="父级节点" prop="parentId">
32
+              <el-input v-model="formData.parentId" disabled />
33
+            </el-form-item>
34
+            <el-form-item label="分类名称" prop="name">
35
+              <el-input v-model="formData.name" placeholder="请输入分类名称" />
36
+            </el-form-item>
37
+            <el-form-item label="节点内容" prop="content">
38
+              <el-input v-model="formData.content" placeholder="请输入节点内容" />
39
+            </el-form-item>
40
+            <el-form-item label="是否有效" prop="delFlag">
41
+              <el-select v-model="formData.delFlag" clearable>
42
+                <el-option v-for="item in del_type" :key="item.value" :label="item.label" :value="item.value" />
43
+              </el-select>
44
+            </el-form-item>
45
+            <!-- <el-form-item label="物资类型" prop="difference">
46
+              <el-select v-model="formData.difference" clearable>
47
+                <el-option v-for="item in material_type" :key="item.value" :label="item.label" :value="item.value" />
48
+              </el-select>
49
+            </el-form-item> -->
50
+            <el-form-item label="父级行政编码" prop="parentCode">
51
+              <el-input v-model="formData.parentCode" disabled />
52
+            </el-form-item>
53
+            <el-form-item label="行政编码" prop="code">
54
+              <el-input v-model="formData.code" placeholder="请输入行政编码" />
55
+            </el-form-item>
56
+            <el-form-item label="排序" prop="sort">
57
+              <el-input v-model="formData.sort" type="number" placeholder="请输入排序" />
58
+            </el-form-item>
59
+            <el-form-item v-if="formStatus == 'update'">
60
+              <el-button type="primary" round size="mini" @click="update">更新</el-button>
61
+              <el-button size="mini" class="mti-cancle-btn" round @click="onCancel('update')">取消</el-button>
62
+            </el-form-item>
63
+            <el-form-item v-if="formStatus == 'create'" size="mini">
64
+              <el-button type="primary" round @click="create">保存</el-button>
65
+              <el-button size="mini" class="mti-cancle-btn" round @click="onCancel('create')">取消</el-button>
66
+            </el-form-item>
67
+          </el-form>
68
+        </div>
69
+      </div>
70
+    </div>
71
+  </basic-container>
72
+</template>
73
+
74
+<script setup lang="ts">
75
+import { ref } from "vue";
76
+import { ElMessage, ElMessageBox } from "element-plus";
77
+import type { FormInstance, FormRules } from "element-plus";
78
+import { Plus, Edit, Delete } from "@element-plus/icons-vue";
79
+
80
+import { deepClone } from "@/utils/util";
81
+import { useDict } from "@/hooks/dict";
82
+import { dictTree, getObj, delObj, putDict, addDict } from "@/api/orderType";
83
+
84
+interface IFormData {
85
+  type?: number;
86
+  parentId?: number;
87
+  delFlag?: string;
88
+  id?: string;
89
+  name?: string;
90
+  content?: string;
91
+  sort?: number;
92
+  difference?: string;
93
+  parentCode?: string | number;
94
+  code?: string;
95
+}
96
+
97
+const treeData = ref([]);
98
+const form = ref<FormInstance>();
99
+const formRules = ref<FormRules>({
100
+  id: [{ required: true, message: "请输入节点编号", trigger: "blur" }],
101
+  name: [{ required: true, message: "请输入分类名称", trigger: "blur" }],
102
+  delFlag: [{ required: true, message: "请选择是否有效", trigger: "change" }],
103
+  sort: [
104
+    { required: true, message: "请输入排序字段", trigger: "blur" },
105
+    { max: 5, message: "长度在 0 到 5 个数字", trigger: "blur" }
106
+  ]
107
+});
108
+const formData = ref<IFormData>({});
109
+const tmpForm = ref<IFormData>({
110
+  type: 2
111
+});
112
+const currentItem = ref({
113
+  id: 0,
114
+  code: 0
115
+});
116
+const formEdit = ref(true);
117
+const formStatus = ref("");
118
+
119
+const { del_type } = useDict("del_type");
120
+
121
+const getList = () => {
122
+  dictTree(2).then((res: any) => {
123
+    treeData.value = res.data == null ? [] : res.data;
124
+  });
125
+};
126
+
127
+getList();
128
+
129
+const filterNode = (value: any, data: any) => {
130
+  if (!value) return true;
131
+  return data.label.indexOf(value) !== -1;
132
+};
133
+
134
+// 点击时获取对应节点数据
135
+const getNodeData = (data: any) => {
136
+  form.value?.clearValidate();
137
+  formEdit.value = true;
138
+  getObj(data.id).then((res: any) => {
139
+    formData.value = res.data;
140
+    tmpForm.value = deepClone(res.data);
141
+    currentItem.value.id = data.id;
142
+    currentItem.value.code = data.code;
143
+  });
144
+};
145
+
146
+// 添加节点
147
+const handlerAdd = () => {
148
+  resetForm();
149
+  formEdit.value = false;
150
+  formStatus.value = "create";
151
+};
152
+
153
+// 编辑节点
154
+const handlerEdit = () => {
155
+  form.value?.clearValidate();
156
+  formEdit.value = false;
157
+  formStatus.value = "update";
158
+};
159
+
160
+// 删除节点
161
+const handleDelete = () => {
162
+  if (currentItem.value.id !== 0) {
163
+    ElMessageBox.confirm(`此操作将永久删除改父节点及其下的所有子节点, 是否继续?`, "提示", {
164
+      confirmButtonText: "确定",
165
+      cancelButtonText: "取消",
166
+      type: "warning"
167
+    }).then(() => {
168
+      delObj(currentItem.value.id).then((res: any) => {
169
+        currentItem.value.id = 0;
170
+        onCancel();
171
+        getList();
172
+        if (res.code === 0) {
173
+          ElMessage.success(`删除成功`);
174
+        } else {
175
+          ElMessage.error(`失败`);
176
+        }
177
+      });
178
+    });
179
+  } else {
180
+    ElMessage.warning(`请选择需要删除的数据`);
181
+  }
182
+};
183
+
184
+// 更新节点
185
+const update = () => {
186
+  form.value?.validate((valid: boolean) => {
187
+    if (!valid) return;
188
+    putDict({ ...formData.value }).then(() => {
189
+      ElMessage.success(`更新成功`);
190
+      formEdit.value = true;
191
+    });
192
+  });
193
+};
194
+
195
+// 创建节点
196
+const create = () => {
197
+  form.value?.validate((valid: boolean) => {
198
+    if (!valid) return;
199
+    addDict({ ...formData.value }).then(() => {
200
+      getList();
201
+      onCancel();
202
+      formStatus.value = "";
203
+      ElMessage.success(`创建成功`);
204
+    });
205
+  });
206
+};
207
+
208
+// 编辑时初始化表单
209
+const resetForm = () => {
210
+  formData.value = {
211
+    parentId: currentItem.value.id,
212
+    parentCode: currentItem.value.code,
213
+    difference: "",
214
+    type: 2,
215
+    id: "",
216
+    code: "",
217
+    delFlag: "0",
218
+    name: "",
219
+    content: "",
220
+    sort: 1
221
+  };
222
+};
223
+
224
+// 取消修改时处理数据
225
+const onCancel = (val?: string) => {
226
+  form.value?.clearValidate();
227
+  if (val === "update") {
228
+    formData.value = JSON.parse(JSON.stringify(tmpForm.value));
229
+  } else {
230
+    formData.value = {};
231
+  }
232
+  formEdit.value = true;
233
+  formStatus.value = "";
234
+};
235
+</script>
236
+
237
+<style lang="scss" scoped>
238
+.mti-container {
239
+  .mti-flex {
240
+    display: flex;
241
+    .mti-tree {
242
+      width: 250px;
243
+      overflow-y: auto;
244
+      margin-bottom: 0;
245
+      .el-tree {
246
+        padding: 10px;
247
+        background-color: #e2f1fe !important;
248
+        color: #606266;
249
+        border: 1px solid #d9ebf8;
250
+        &.el-tree--highlight-current {
251
+          .el-tree-node.is-current {
252
+            > .el-tree-node__content {
253
+              background-color: #ffffff;
254
+            }
255
+          }
256
+        }
257
+        .el-tree-node__content {
258
+          height: 30px;
259
+          &:hover {
260
+            background-color: #fff;
261
+          }
262
+        }
263
+      }
264
+      .filter-tree.avue-tree {
265
+        .el-tree-node {
266
+          &:focus {
267
+            > .el-tree-node__content {
268
+              background-color: #ffffff !important;
269
+            }
270
+          }
271
+        }
272
+        position: relative;
273
+        padding-top: 10px;
274
+        background-color: #e2f1fe;
275
+        color: #606266;
276
+        border: 1px solid #d9ebf8;
277
+        height: 100%;
278
+        .avue-tree__filter {
279
+          margin-bottom: 5px;
280
+          padding: 0 12px;
281
+        }
282
+        .el-tree {
283
+          padding-top: 0;
284
+          border-style: none;
285
+        }
286
+      }
287
+    }
288
+    .mti-form {
289
+      flex-grow: 1;
290
+      position: relative;
291
+      padding: 10px 20px;
292
+
293
+      .filter-container {
294
+        margin-bottom: 20px;
295
+      }
296
+      .box-card {
297
+        border: 1px solid #d9ebf8;
298
+        padding: 30px 32px;
299
+
300
+        .el-button.mti-cancle-btn {
301
+          background-color: #fd5f43;
302
+          color: #fff;
303
+
304
+          &:hover {
305
+            background-color: #e26f5a;
306
+          }
307
+        }
308
+      }
309
+    }
310
+  }
311
+}
312
+</style>