yh-pub 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.MD +19 -19
  2. package/layout/admin/adminIndex.vue +104 -104
  3. package/layout/admin/api/loginApi.js +24 -24
  4. package/layout/admin/api/routers.js +93 -93
  5. package/layout/admin/api/tenantApi.js +123 -123
  6. package/layout/admin/home/homeIndex.vue +25 -25
  7. package/layout/admin/login/login.vue +161 -161
  8. package/layout/admin/menu/MenuIndex.vue +648 -648
  9. package/layout/admin/menu/icon.vue +108 -108
  10. package/layout/admin/menu/iconList.js +934 -934
  11. package/layout/admin/saTenant/saTenant.vue +173 -173
  12. package/layout/admin/saTenant/saTenantForm.js +80 -80
  13. package/layout/admin/saTenant/saTenantForm.vue +61 -61
  14. package/layout/admin/saTenant/saTenantRoleManage.js +417 -417
  15. package/layout/admin/saTenant/saTenantRoleManage.vue +99 -99
  16. package/layout/admin/user/saUser.less +6 -6
  17. package/layout/admin/user/saUser.vue +72 -72
  18. package/layout/main/components/console/console.vue +205 -205
  19. package/layout/main/components/error-store/error-store.vue +72 -72
  20. package/layout/main/components/error-store/index.js +2 -2
  21. package/layout/main/components/fullscreen/fullscreen.vue +57 -57
  22. package/layout/main/components/fullscreen/index.js +2 -2
  23. package/layout/main/components/language/language.vue +71 -71
  24. package/layout/main/components/side-menu/side-menu.less +73 -73
  25. package/layout/main/components/side-menu/side-menu.vue +75 -75
  26. package/layout/main/components/tags-nav/tags-nav.less +44 -44
  27. package/layout/main/components/tags-nav/tags-nav.vue +144 -144
  28. package/layout/main/components/user/user.less +12 -12
  29. package/layout/main/components/user/user.vue +185 -185
  30. package/layout/main/home/home.vue +480 -480
  31. package/layout/main/home/index.js +2 -2
  32. package/layout/main/home/toDoList.vue +32 -32
  33. package/layout/main/login/login.less +93 -93
  34. package/layout/main/login/login.vue +151 -151
  35. package/layout/main/main.less +81 -81
  36. package/layout/main/main.vue +254 -202
  37. package/layout/main/system/dict.vue +64 -64
  38. package/layout/main/system/orgManage.vue +473 -473
  39. package/layout/main/system/roleManage.js +807 -755
  40. package/layout/main/system/roleManage.vue +424 -399
  41. package/package.json +11 -11
  42. package/view/basic/error-logger.vue +74 -74
  43. package/view/basic/error-page/401.vue +22 -22
  44. package/view/basic/error-page/404.vue +22 -22
  45. package/view/basic/error-page/500.vue +22 -22
  46. package/view/basic/error-page/back-btn-group.vue +48 -48
  47. package/view/basic/error-page/error-content.vue +28 -28
  48. package/view/basic/error-page/error.less +46 -46
  49. package/view/config/component/confFormItem.vue +49 -49
  50. package/view/config/config.scss +45 -45
  51. package/view/config/configIndex.vue +150 -150
  52. package/view/config/subPage/router-config.vue +4 -4
  53. package/view/config/subPage/sys-config.vue +249 -249
  54. package/view/window/IframeFReportView.vue +27 -27
  55. package/view/window/windowIndex.vue +22 -22
@@ -1,648 +1,648 @@
1
- <template>
2
- <div class="search">
3
- <el-row class="operation">
4
- <div>
5
- <el-button @click="addNew">
6
- <i class="iconfont icon-plus"></i>
7
- 新增
8
- </el-button>
9
- <el-button @click="delAll">
10
- <i class="iconfont icon-delete"></i>
11
- 删除
12
- </el-button>
13
- <el-button @click="getAllList">
14
- <i class="iconfont icon-refresh"></i>
15
- 刷新
16
- </el-button>
17
- </div>
18
- </el-row>
19
- <el-row
20
- type="flex"
21
- justify="start"
22
- :gutter="16"
23
- v-show="showType === 'tree'">
24
- <el-col
25
- :sm="8"
26
- :md="8"
27
- :lg="8"
28
- :xl="6">
29
- <el-alert
30
- class="tree-tips"
31
- show-icon
32
- :closable="false"
33
- :title="`当前选择编辑:${editTitle}`"></el-alert>
34
- <a
35
- class="select-clear"
36
- v-show="form.adMenuId"
37
- @click="cancelEdit">
38
- 取消选择
39
- </a>
40
- <el-input
41
- v-model="searchKey"
42
- @change="search"
43
- placeholder="输入菜单名搜索"
44
- clearable>
45
- <template #prepend>
46
- <i class="iconfont icon-search"></i>
47
- </template>
48
- </el-input>
49
- <div v-loading="loading">
50
- <div
51
- class="tree-bar"
52
- :style="{ maxHeight: maxHeight }">
53
- <el-tree
54
- ref="tree"
55
- :data="data"
56
- :props="menuTreeProps"
57
- node-key="key"
58
- default-expand-all
59
- highlight-current
60
- :current-node-key="treeSelectedKeys"
61
- @current-change="selectTree"></el-tree>
62
- </div>
63
- </div>
64
- </el-col>
65
- <el-col
66
- :sm="16"
67
- :md="16"
68
- :lg="16"
69
- :xl="9">
70
- <el-form
71
- ref="form"
72
- class="menu-edit-form"
73
- :model="form"
74
- :rules="formValidate"
75
- label-width="90px">
76
- <el-form-item
77
- label="名称"
78
- prop="name">
79
- <el-input
80
- v-model="form.name"
81
- ref="orgNameRef" />
82
- </el-form-item>
83
- <el-form-item
84
- label="类型"
85
- prop="menuType">
86
- <el-select
87
- v-model="form.menuType"
88
- placeholder="请选择或输入搜索"
89
- filterable
90
- clearable>
91
- <el-option
92
- value="WINDOW"
93
- label="窗口"></el-option>
94
- <el-option
95
- value="LINK"
96
- label="访问链接"></el-option>
97
- <el-option
98
- value="SUBPAGE"
99
- label="子页面"></el-option>
100
- <el-option
101
- value="JOIN"
102
- label="关联弹窗"></el-option>
103
- <el-option
104
- value="GROUP"
105
- label="菜单分组"></el-option>
106
- <el-option
107
- value="APP"
108
- label="手机页面"></el-option>
109
- </el-select>
110
- </el-form-item>
111
- <el-form-item
112
- label="所属模块"
113
- prop="sysModuleId">
114
- <dict
115
- dict="sysModuleId"
116
- _select_id="59C1E77AE78D44DF8876688FE78DB53E"
117
- v-model="form.sysModuleId"
118
- placeholder="请选择或输入搜索"
119
- filterable
120
- clearable />
121
- </el-form-item>
122
- <el-form-item
123
- label="请求地址"
124
- prop="url"
125
- v-show="['LINK', 'SUBPAGE'].includes(form.menuType)">
126
- <el-input v-model="form.url" />
127
- </el-form-item>
128
- <el-form-item
129
- label="访问窗口"
130
- prop="sysWindowId"
131
- v-show="['WINDOW', 'JOIN'].includes(form.menuType)">
132
- <dict
133
- dict="sysWindowId"
134
- _select_id="F56B868C8FF44053926920588FB3C76C"
135
- v-model="form.sysWindowId"
136
- placeholder="请选择或输入搜索"
137
- filterable
138
- clearable />
139
- </el-form-item>
140
- <el-form-item
141
- label="App页面"
142
- prop="sysAppDesignId"
143
- v-show="form.menuType === 'APP'">
144
- <dict
145
- dict="sysAppDesignId"
146
- _select_id="1352728B367842EDAFF195BF073DD817"
147
- v-model="form.sysAppDesignId"
148
- placeholder="请选择或输入搜索"
149
- filterable
150
- clearable />
151
- </el-form-item>
152
- <el-form-item
153
- label="上级菜单"
154
- prop="parentId">
155
- <el-select
156
- v-model="form.parentId"
157
- placeholder="请选择或输入搜索"
158
- filterable
159
- clearable>
160
- <el-option
161
- v-for="m in menuListOptions"
162
- :value="m.adMenuId"
163
- :label="m.name"
164
- :key="m.adMenuId"></el-option>
165
- </el-select>
166
- </el-form-item>
167
- <el-form-item
168
- label="显示模式"
169
- prop="showMode">
170
- <el-select
171
- v-model="form.showMode"
172
- placeholder="请选择或输入搜索"
173
- filterable
174
- clearable>
175
- <el-option
176
- value="P"
177
- label="电脑端"></el-option>
178
- <el-option
179
- value="M"
180
- label="手机端"></el-option>
181
- <el-option
182
- value="PM"
183
- label="电脑+手机"></el-option>
184
- </el-select>
185
- </el-form-item>
186
- <el-form-item
187
- label="排序"
188
- prop="seq">
189
- <el-input
190
- type="number"
191
- v-model="form.seq" />
192
- </el-form-item>
193
- <el-form-item
194
- label="图标地址"
195
- prop="iconPath"
196
- class="icon-select-form-item">
197
- <el-button
198
- type="info"
199
- @click="getIcon()">
200
- 图标选择
201
- </el-button>
202
- <el-input v-model="form.iconPath" />
203
- <span class="icon-preview">
204
- <i :class="form.iconPath"></i>
205
- </span>
206
- </el-form-item>
207
- <el-form-item
208
- label="备注"
209
- prop="description">
210
- <el-input
211
- v-model="form.description"
212
- type="textarea" />
213
- </el-form-item>
214
- <el-form-item label="是否有效">
215
- <el-switch
216
- v-model="form.active"
217
- active-value="Y"
218
- inactive-value="N" />
219
- </el-form-item>
220
- <el-form-item>
221
- <el-button
222
- style="margin-right: 5px"
223
- @click="submitEdit"
224
- :loading="submitLoading"
225
- :disabled="form.adMenuId != ''"
226
- type="primary">
227
- <i class="iconfont icon-plus"></i>
228
- 保存新增
229
- </el-button>
230
- <el-button
231
- style="margin-right: 5px"
232
- @click="submitEdit"
233
- :loading="submitLoading"
234
- :disabled="form.adMenuId === ''"
235
- type="primary">
236
- <i class="iconfont icon-save"></i>
237
- 保存修改
238
- </el-button>
239
- <el-button @click="handleReset">重置</el-button>
240
- </el-form-item>
241
- </el-form>
242
- </el-col>
243
- </el-row>
244
- <icon
245
- :actionData="toIconData"
246
- @clickSure="iconSure"></icon>
247
- </div>
248
- </template>
249
-
250
- <script>
251
- import dict from "yh-pub/layout/main/system/dict.vue";
252
- import icon from "./icon.vue";
253
- import { deepClone } from "@/libs/util.js";
254
-
255
- export default {
256
- name: "menu-manage",
257
- components: {
258
- dict,
259
- icon,
260
- },
261
- data() {
262
- return {
263
- showType: "tree",
264
- loading: true,
265
- strict: false,
266
- maxHeight: "500px",
267
- expandLevel: 1,
268
- menuModalVisible: false,
269
- iconModalVisible: false,
270
- selectList: [],
271
- showParent: false,
272
- searchKey: "",
273
- parentTitle: "",
274
- editTitle: "",
275
- modalTitle: "",
276
- treeExpandKeys: [],
277
- menuTreeProps: {
278
- label: "title",
279
- },
280
- form: {
281
- name: "",
282
- menuType: "",
283
- sysModuleId: "",
284
- sysWindowId: "",
285
- sysAppDesignId: "",
286
- url: "",
287
- parentId: "",
288
- showMode: null,
289
- seq: null,
290
- iconPath: "",
291
- description: "",
292
- adMenuId: "",
293
- active: "Y",
294
- },
295
- formAdd: {},
296
- formValidate: {
297
- name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
298
- menuType: [{ required: true, message: "菜单类型不能为空", trigger: "blur" }],
299
- sysModuleId: [{ required: true, message: "所属模块不能为空", trigger: "blur" }],
300
- // parentId: [{ required: false, message: '上级菜单不能为空', trigger: 'blur' }],
301
- showMode: [{ required: true, message: "显示模式不能为空", trigger: "blur" }],
302
- seq: [
303
- {
304
- required: true,
305
- message: "排序值不能为空",
306
- trigger: "blur",
307
- },
308
- ],
309
- },
310
- submitLoading: false,
311
- data: [],
312
- allMenu: [],
313
- menuList: [],
314
- toIconData: {},
315
- dictPermissions: [],
316
- selectedNodes: [],
317
- treeSelectedKeys: [],
318
- };
319
- },
320
- computed: {
321
- menuListOptions() {
322
- return this.menuList.filter((menu) => {
323
- return this.form.menuType == "JOIN" || (menu.menuType == "GROUP" && this.form.menuType != "JOIN");
324
- });
325
- },
326
- },
327
- methods: {
328
- init() {
329
- this.getAllList();
330
- },
331
- loadData(item, callback) {},
332
- renderContent(h, { root, node, data }) {
333
- let icon = "";
334
- if (data.level === 0) {
335
- icon = "ios-navigate";
336
- } else if (data.level === 1) {
337
- icon = "md-list-box";
338
- } else if (data.level === 2) {
339
- icon = "md-list";
340
- } else if (data.level === 3) {
341
- icon = "md-radio-button-on";
342
- } else {
343
- icon = "md-radio-button-off";
344
- }
345
- return h("span", [
346
- h("span", [
347
- h("Icon", {
348
- props: {
349
- type: icon,
350
- size: "16",
351
- },
352
- style: {
353
- "margin-right": "8px",
354
- "margin-bottom": "3px",
355
- },
356
- }),
357
- h("span", data.title),
358
- ]),
359
- ]);
360
- },
361
- getMenuKeys(level) {
362
- let keys = [];
363
- let cLevel = 1;
364
- function getKeys(menus, cl) {
365
- if (cl <= level && level > 0) {
366
- menus.forEach((item) => {
367
- if (item._childs) {
368
- getKeys(item._childs, cl + 1);
369
- }
370
- keys.push(item.adMenuId);
371
- });
372
- }
373
- }
374
- getKeys(this.allMenu, cLevel);
375
- return keys;
376
- },
377
- handleDropdown(name) {
378
- if (name === "expandOne") {
379
- this.expandLevel = 1;
380
- } else if (name === "expandTwo") {
381
- this.expandLevel = 2;
382
- } else if (name === "expandThree") {
383
- this.expandLevel = 3;
384
- } else if (name === "expandAll") {
385
- this.expandLevel = 0;
386
- }
387
- let keys = this.getMenuKeys(this.expandLevel + 1);
388
- this.treeExpandKeys = keys;
389
- },
390
- getAllList() {
391
- this.loading = true;
392
- this.axios.post("/menuController/getMenuData", this.$qs.stringify({})).then((response) => {
393
- if (response.data.result) {
394
- this.menuList = [];
395
- this.allMenu = response.data.menuList;
396
- let newTreeData = this.parseTreeData(this.allMenu, 0);
397
- this.data = newTreeData;
398
- }
399
- this.loading = false;
400
- });
401
- this.$emit("on-query-change");
402
- },
403
- search() {
404
- this.loading = true;
405
- let newTreeData = this.parseTreeData(this.allMenu, 0, this.searchKey);
406
- this.data = newTreeData;
407
- this.loading = false;
408
- },
409
- parseTreeData(menus, curLevel, search) {
410
- let data = [];
411
- menus.forEach((menu) => {
412
- let newLevelData = {
413
- data: menu,
414
- };
415
- if (menu["_childs"] && menu["_childs"].length > 0) {
416
- newLevelData.children = this.parseTreeData(menu["_childs"], curLevel + 1, search);
417
- }
418
- if (
419
- search != undefined &&
420
- (newLevelData.children == undefined || newLevelData.children.length == 0) &&
421
- menu.name.indexOf(search) == -1
422
- ) {
423
- return;
424
- } else if (search == undefined) {
425
- this.menuList.push(menu);
426
- }
427
-
428
- newLevelData["key"] = menu.adMenuId;
429
- newLevelData["title"] = menu.name;
430
- newLevelData["level"] = curLevel;
431
- data.push(newLevelData);
432
- });
433
- return data;
434
- },
435
- selectTree(data, node) {
436
- if (data) {
437
- let form = data.data;
438
- this.form = form;
439
- this.editTitle = form.name;
440
- this.selectedNodes = node;
441
- this.treeSelectedKeys = data.data.adMenuId;
442
- } else {
443
- this.cancelEdit();
444
- }
445
- },
446
- addNew() {
447
- this.cancelEdit();
448
- this.$nextTick(() => {
449
- this.$refs.orgNameRef.focus();
450
- });
451
- },
452
- cancelEdit() {
453
- this.$refs.tree.setCurrentKey(null);
454
- this.$nextTick(() => {
455
- this.treeSelectedKeys = null;
456
- this.handleReset();
457
- });
458
- },
459
- handleReset() {
460
- this.form.adMenuId = "";
461
- this.editTitle = "";
462
- this.$refs.form.resetFields();
463
- },
464
- submitEdit() {
465
- let that = this;
466
- if (this.form.adMenuId && this.form.parentId === this.form.adMenuId) {
467
- this.$message.error("父级菜单不能为自身!");
468
- return false;
469
- }
470
- this.$refs.form.validate((valid) => {
471
- if (valid) {
472
- this.submitLoading = true;
473
- let curForm = deepClone({}, this.form);
474
- curForm.created = undefined;
475
- curForm.updated = undefined;
476
- curForm._childs = undefined;
477
- this.axios
478
- .post("/menuController/submitMenu", this.$qs.stringify(curForm))
479
- .then((response) => {
480
- if (response.data.result) {
481
- that.$message.success((that.form.adMenuId !== "" ? "修改" : "新增") + "成功");
482
- that.getAllList();
483
- that.handleReset();
484
- } else {
485
- that.$message.error(response.data.msg);
486
- }
487
- that.submitLoading = false;
488
- })
489
- .catch((response) => {
490
- that.submitLoading = false;
491
- });
492
- }
493
- });
494
- },
495
- add() {
496
- if (!this.form.id) {
497
- this.$message.warning("请先点击选择一个菜单权限节点");
498
- return;
499
- }
500
- this.parentTitle = this.form.title;
501
- this.modalTitle = "添加子节点(可拖动)";
502
- this.showParent = true;
503
- let type = 0;
504
- if (this.form.level === 1) {
505
- type = 0;
506
- } else if (this.form.level === 2) {
507
- type = 1;
508
- } else if (this.form.level === 3) {
509
- this.$warning({
510
- title: "抱歉,不能添加啦",
511
- content: "左侧仅支持2级菜单目录",
512
- });
513
- return;
514
- } else {
515
- type = 0;
516
- }
517
- if (!this.form.children) {
518
- this.form.children = [];
519
- }
520
- this.formAdd = {
521
- icon: "",
522
- type: type,
523
- parentId: this.form.id,
524
- level: Number(this.form.level) + 1,
525
- sortOrder: this.form.children.length + 1,
526
- buttonType: "",
527
- status: 0,
528
- showAlways: true,
529
- };
530
- if (this.form.level === 0) {
531
- this.formAdd.path = "/";
532
- this.formAdd.component = "Main";
533
- }
534
- this.menuModalVisible = true;
535
- },
536
- changeSelect(v) {
537
- this.selectList = v;
538
- },
539
- clearSelectAll() {
540
- this.$refs.table.selectAll(false);
541
- },
542
- remove(v) {
543
- this.selectList = [];
544
- this.selectList.push(v);
545
- this.delAll();
546
- },
547
- delAll() {
548
- if (!this.selectedNodes) {
549
- this.$message.warning("您还未勾选要删除的数据");
550
- return;
551
- }
552
- this.$confirm("您确认要删除所选的数据?", "确认删除", {
553
- type: "warning",
554
- }).then(() => {
555
- let ids = this.selectedNodes.data.key;
556
- this.axios.post("/menuController/delMenuByIds", this.$qs.stringify({ ids: ids })).then((response) => {
557
- if (response.data.result) {
558
- this.$message.success("删除成功");
559
- this.selectList = [];
560
- this.getAllList();
561
- this.handleReset();
562
- } else {
563
- this.$message.error(response.data.msg);
564
- }
565
- this.submitLoading = false;
566
- });
567
- });
568
- },
569
- getIcon() {
570
- this.toIconData = {
571
- type: "select",
572
- };
573
- },
574
- dealInput(toIcon) {
575
- this.form.iconPath = toIcon;
576
- },
577
- iconSure(iconPath) {
578
- this.form.iconPath = iconPath;
579
- },
580
- },
581
- activated() {
582
- // 计算高度
583
- let height = document.documentElement.clientHeight;
584
- this.maxHeight = Number(height - 287) + "px";
585
- this.init();
586
- },
587
- };
588
- </script>
589
- <style lang="scss">
590
- .search {
591
- padding: 10px 0;
592
- .operation {
593
- margin-bottom: 2vh;
594
- .more-btn {
595
- margin-left: 10px;
596
- }
597
- }
598
-
599
- .select-clear,
600
- .tree-tips {
601
- margin-bottom: 10px;
602
- }
603
-
604
- .select-title {
605
- font-weight: 600;
606
- color: #40a9ff;
607
- }
608
-
609
- .tree-bar {
610
- overflow: auto;
611
- margin-top: 5px;
612
- position: relative;
613
- min-height: 80px;
614
- &::-webkit-scrollbar {
615
- width: 6px;
616
- height: 6px;
617
- }
618
-
619
- &::-webkit-scrollbar-thumb {
620
- border-radius: 4px;
621
- box-shadow: inset 0 0 2px #d1d1d1;
622
- background: #e4e4e4;
623
- }
624
- }
625
-
626
- .menu-edit-form {
627
- .el-form-item__content {
628
- display: flex;
629
- .el-input,
630
- .el-select {
631
- flex: 1;
632
- }
633
- }
634
- .icon-select-form-item {
635
- .el-input {
636
- margin: 0 10px;
637
- }
638
- .icon-preview {
639
- padding: 0 10px 0 0;
640
- .iconfont {
641
- font-size: 24px;
642
- }
643
- }
644
- }
645
- }
646
- }
647
- </style>
648
- @/libs/util.js
1
+ <template>
2
+ <div class="search">
3
+ <el-row class="operation">
4
+ <div>
5
+ <el-button @click="addNew">
6
+ <i class="iconfont icon-plus"></i>
7
+ 新增
8
+ </el-button>
9
+ <el-button @click="delAll">
10
+ <i class="iconfont icon-delete"></i>
11
+ 删除
12
+ </el-button>
13
+ <el-button @click="getAllList">
14
+ <i class="iconfont icon-refresh"></i>
15
+ 刷新
16
+ </el-button>
17
+ </div>
18
+ </el-row>
19
+ <el-row
20
+ type="flex"
21
+ justify="start"
22
+ :gutter="16"
23
+ v-show="showType === 'tree'">
24
+ <el-col
25
+ :sm="8"
26
+ :md="8"
27
+ :lg="8"
28
+ :xl="6">
29
+ <el-alert
30
+ class="tree-tips"
31
+ show-icon
32
+ :closable="false"
33
+ :title="`当前选择编辑:${editTitle}`"></el-alert>
34
+ <a
35
+ class="select-clear"
36
+ v-show="form.adMenuId"
37
+ @click="cancelEdit">
38
+ 取消选择
39
+ </a>
40
+ <el-input
41
+ v-model="searchKey"
42
+ @change="search"
43
+ placeholder="输入菜单名搜索"
44
+ clearable>
45
+ <template #prepend>
46
+ <i class="iconfont icon-search"></i>
47
+ </template>
48
+ </el-input>
49
+ <div v-loading="loading">
50
+ <div
51
+ class="tree-bar"
52
+ :style="{ maxHeight: maxHeight }">
53
+ <el-tree
54
+ ref="tree"
55
+ :data="data"
56
+ :props="menuTreeProps"
57
+ node-key="key"
58
+ default-expand-all
59
+ highlight-current
60
+ :current-node-key="treeSelectedKeys"
61
+ @current-change="selectTree"></el-tree>
62
+ </div>
63
+ </div>
64
+ </el-col>
65
+ <el-col
66
+ :sm="16"
67
+ :md="16"
68
+ :lg="16"
69
+ :xl="9">
70
+ <el-form
71
+ ref="form"
72
+ class="menu-edit-form"
73
+ :model="form"
74
+ :rules="formValidate"
75
+ label-width="90px">
76
+ <el-form-item
77
+ label="名称"
78
+ prop="name">
79
+ <el-input
80
+ v-model="form.name"
81
+ ref="orgNameRef" />
82
+ </el-form-item>
83
+ <el-form-item
84
+ label="类型"
85
+ prop="menuType">
86
+ <el-select
87
+ v-model="form.menuType"
88
+ placeholder="请选择或输入搜索"
89
+ filterable
90
+ clearable>
91
+ <el-option
92
+ value="WINDOW"
93
+ label="窗口"></el-option>
94
+ <el-option
95
+ value="LINK"
96
+ label="访问链接"></el-option>
97
+ <el-option
98
+ value="SUBPAGE"
99
+ label="子页面"></el-option>
100
+ <el-option
101
+ value="JOIN"
102
+ label="关联弹窗"></el-option>
103
+ <el-option
104
+ value="GROUP"
105
+ label="菜单分组"></el-option>
106
+ <el-option
107
+ value="APP"
108
+ label="手机页面"></el-option>
109
+ </el-select>
110
+ </el-form-item>
111
+ <el-form-item
112
+ label="所属模块"
113
+ prop="sysModuleId">
114
+ <dict
115
+ dict="sysModuleId"
116
+ _select_id="59C1E77AE78D44DF8876688FE78DB53E"
117
+ v-model="form.sysModuleId"
118
+ placeholder="请选择或输入搜索"
119
+ filterable
120
+ clearable />
121
+ </el-form-item>
122
+ <el-form-item
123
+ label="请求地址"
124
+ prop="url"
125
+ v-show="['LINK', 'SUBPAGE'].includes(form.menuType)">
126
+ <el-input v-model="form.url" />
127
+ </el-form-item>
128
+ <el-form-item
129
+ label="访问窗口"
130
+ prop="sysWindowId"
131
+ v-show="['WINDOW', 'JOIN'].includes(form.menuType)">
132
+ <dict
133
+ dict="sysWindowId"
134
+ _select_id="F56B868C8FF44053926920588FB3C76C"
135
+ v-model="form.sysWindowId"
136
+ placeholder="请选择或输入搜索"
137
+ filterable
138
+ clearable />
139
+ </el-form-item>
140
+ <el-form-item
141
+ label="App页面"
142
+ prop="sysAppDesignId"
143
+ v-show="form.menuType === 'APP'">
144
+ <dict
145
+ dict="sysAppDesignId"
146
+ _select_id="1352728B367842EDAFF195BF073DD817"
147
+ v-model="form.sysAppDesignId"
148
+ placeholder="请选择或输入搜索"
149
+ filterable
150
+ clearable />
151
+ </el-form-item>
152
+ <el-form-item
153
+ label="上级菜单"
154
+ prop="parentId">
155
+ <el-select
156
+ v-model="form.parentId"
157
+ placeholder="请选择或输入搜索"
158
+ filterable
159
+ clearable>
160
+ <el-option
161
+ v-for="m in menuListOptions"
162
+ :value="m.adMenuId"
163
+ :label="m.name"
164
+ :key="m.adMenuId"></el-option>
165
+ </el-select>
166
+ </el-form-item>
167
+ <el-form-item
168
+ label="显示模式"
169
+ prop="showMode">
170
+ <el-select
171
+ v-model="form.showMode"
172
+ placeholder="请选择或输入搜索"
173
+ filterable
174
+ clearable>
175
+ <el-option
176
+ value="P"
177
+ label="电脑端"></el-option>
178
+ <el-option
179
+ value="M"
180
+ label="手机端"></el-option>
181
+ <el-option
182
+ value="PM"
183
+ label="电脑+手机"></el-option>
184
+ </el-select>
185
+ </el-form-item>
186
+ <el-form-item
187
+ label="排序"
188
+ prop="seq">
189
+ <el-input
190
+ type="number"
191
+ v-model="form.seq" />
192
+ </el-form-item>
193
+ <el-form-item
194
+ label="图标地址"
195
+ prop="iconPath"
196
+ class="icon-select-form-item">
197
+ <el-button
198
+ type="info"
199
+ @click="getIcon()">
200
+ 图标选择
201
+ </el-button>
202
+ <el-input v-model="form.iconPath" />
203
+ <span class="icon-preview">
204
+ <i :class="form.iconPath"></i>
205
+ </span>
206
+ </el-form-item>
207
+ <el-form-item
208
+ label="备注"
209
+ prop="description">
210
+ <el-input
211
+ v-model="form.description"
212
+ type="textarea" />
213
+ </el-form-item>
214
+ <el-form-item label="是否有效">
215
+ <el-switch
216
+ v-model="form.active"
217
+ active-value="Y"
218
+ inactive-value="N" />
219
+ </el-form-item>
220
+ <el-form-item>
221
+ <el-button
222
+ style="margin-right: 5px"
223
+ @click="submitEdit"
224
+ :loading="submitLoading"
225
+ :disabled="form.adMenuId != ''"
226
+ type="primary">
227
+ <i class="iconfont icon-plus"></i>
228
+ 保存新增
229
+ </el-button>
230
+ <el-button
231
+ style="margin-right: 5px"
232
+ @click="submitEdit"
233
+ :loading="submitLoading"
234
+ :disabled="form.adMenuId === ''"
235
+ type="primary">
236
+ <i class="iconfont icon-save"></i>
237
+ 保存修改
238
+ </el-button>
239
+ <el-button @click="handleReset">重置</el-button>
240
+ </el-form-item>
241
+ </el-form>
242
+ </el-col>
243
+ </el-row>
244
+ <icon
245
+ :actionData="toIconData"
246
+ @clickSure="iconSure"></icon>
247
+ </div>
248
+ </template>
249
+
250
+ <script>
251
+ import dict from "yh-pub/layout/main/system/dict.vue";
252
+ import icon from "./icon.vue";
253
+ import { deepClone } from "@/libs/util.js";
254
+
255
+ export default {
256
+ name: "menu-manage",
257
+ components: {
258
+ dict,
259
+ icon,
260
+ },
261
+ data() {
262
+ return {
263
+ showType: "tree",
264
+ loading: true,
265
+ strict: false,
266
+ maxHeight: "500px",
267
+ expandLevel: 1,
268
+ menuModalVisible: false,
269
+ iconModalVisible: false,
270
+ selectList: [],
271
+ showParent: false,
272
+ searchKey: "",
273
+ parentTitle: "",
274
+ editTitle: "",
275
+ modalTitle: "",
276
+ treeExpandKeys: [],
277
+ menuTreeProps: {
278
+ label: "title",
279
+ },
280
+ form: {
281
+ name: "",
282
+ menuType: "",
283
+ sysModuleId: "",
284
+ sysWindowId: "",
285
+ sysAppDesignId: "",
286
+ url: "",
287
+ parentId: "",
288
+ showMode: null,
289
+ seq: null,
290
+ iconPath: "",
291
+ description: "",
292
+ adMenuId: "",
293
+ active: "Y",
294
+ },
295
+ formAdd: {},
296
+ formValidate: {
297
+ name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
298
+ menuType: [{ required: true, message: "菜单类型不能为空", trigger: "blur" }],
299
+ sysModuleId: [{ required: true, message: "所属模块不能为空", trigger: "blur" }],
300
+ // parentId: [{ required: false, message: '上级菜单不能为空', trigger: 'blur' }],
301
+ showMode: [{ required: true, message: "显示模式不能为空", trigger: "blur" }],
302
+ seq: [
303
+ {
304
+ required: true,
305
+ message: "排序值不能为空",
306
+ trigger: "blur",
307
+ },
308
+ ],
309
+ },
310
+ submitLoading: false,
311
+ data: [],
312
+ allMenu: [],
313
+ menuList: [],
314
+ toIconData: {},
315
+ dictPermissions: [],
316
+ selectedNodes: [],
317
+ treeSelectedKeys: [],
318
+ };
319
+ },
320
+ computed: {
321
+ menuListOptions() {
322
+ return this.menuList.filter((menu) => {
323
+ return this.form.menuType == "JOIN" || (menu.menuType == "GROUP" && this.form.menuType != "JOIN");
324
+ });
325
+ },
326
+ },
327
+ methods: {
328
+ init() {
329
+ this.getAllList();
330
+ },
331
+ loadData(item, callback) {},
332
+ renderContent(h, { root, node, data }) {
333
+ let icon = "";
334
+ if (data.level === 0) {
335
+ icon = "ios-navigate";
336
+ } else if (data.level === 1) {
337
+ icon = "md-list-box";
338
+ } else if (data.level === 2) {
339
+ icon = "md-list";
340
+ } else if (data.level === 3) {
341
+ icon = "md-radio-button-on";
342
+ } else {
343
+ icon = "md-radio-button-off";
344
+ }
345
+ return h("span", [
346
+ h("span", [
347
+ h("Icon", {
348
+ props: {
349
+ type: icon,
350
+ size: "16",
351
+ },
352
+ style: {
353
+ "margin-right": "8px",
354
+ "margin-bottom": "3px",
355
+ },
356
+ }),
357
+ h("span", data.title),
358
+ ]),
359
+ ]);
360
+ },
361
+ getMenuKeys(level) {
362
+ let keys = [];
363
+ let cLevel = 1;
364
+ function getKeys(menus, cl) {
365
+ if (cl <= level && level > 0) {
366
+ menus.forEach((item) => {
367
+ if (item._childs) {
368
+ getKeys(item._childs, cl + 1);
369
+ }
370
+ keys.push(item.adMenuId);
371
+ });
372
+ }
373
+ }
374
+ getKeys(this.allMenu, cLevel);
375
+ return keys;
376
+ },
377
+ handleDropdown(name) {
378
+ if (name === "expandOne") {
379
+ this.expandLevel = 1;
380
+ } else if (name === "expandTwo") {
381
+ this.expandLevel = 2;
382
+ } else if (name === "expandThree") {
383
+ this.expandLevel = 3;
384
+ } else if (name === "expandAll") {
385
+ this.expandLevel = 0;
386
+ }
387
+ let keys = this.getMenuKeys(this.expandLevel + 1);
388
+ this.treeExpandKeys = keys;
389
+ },
390
+ getAllList() {
391
+ this.loading = true;
392
+ this.axios.post("/menuController/getMenuData", this.$qs.stringify({})).then((response) => {
393
+ if (response.data.result) {
394
+ this.menuList = [];
395
+ this.allMenu = response.data.menuList;
396
+ let newTreeData = this.parseTreeData(this.allMenu, 0);
397
+ this.data = newTreeData;
398
+ }
399
+ this.loading = false;
400
+ });
401
+ this.$emit("on-query-change");
402
+ },
403
+ search() {
404
+ this.loading = true;
405
+ let newTreeData = this.parseTreeData(this.allMenu, 0, this.searchKey);
406
+ this.data = newTreeData;
407
+ this.loading = false;
408
+ },
409
+ parseTreeData(menus, curLevel, search) {
410
+ let data = [];
411
+ menus.forEach((menu) => {
412
+ let newLevelData = {
413
+ data: menu,
414
+ };
415
+ if (menu["_childs"] && menu["_childs"].length > 0) {
416
+ newLevelData.children = this.parseTreeData(menu["_childs"], curLevel + 1, search);
417
+ }
418
+ if (
419
+ search != undefined &&
420
+ (newLevelData.children == undefined || newLevelData.children.length == 0) &&
421
+ menu.name.indexOf(search) == -1
422
+ ) {
423
+ return;
424
+ } else if (search == undefined) {
425
+ this.menuList.push(menu);
426
+ }
427
+
428
+ newLevelData["key"] = menu.adMenuId;
429
+ newLevelData["title"] = menu.name;
430
+ newLevelData["level"] = curLevel;
431
+ data.push(newLevelData);
432
+ });
433
+ return data;
434
+ },
435
+ selectTree(data, node) {
436
+ if (data) {
437
+ let form = data.data;
438
+ this.form = form;
439
+ this.editTitle = form.name;
440
+ this.selectedNodes = node;
441
+ this.treeSelectedKeys = data.data.adMenuId;
442
+ } else {
443
+ this.cancelEdit();
444
+ }
445
+ },
446
+ addNew() {
447
+ this.cancelEdit();
448
+ this.$nextTick(() => {
449
+ this.$refs.orgNameRef.focus();
450
+ });
451
+ },
452
+ cancelEdit() {
453
+ this.$refs.tree.setCurrentKey(null);
454
+ this.$nextTick(() => {
455
+ this.treeSelectedKeys = null;
456
+ this.handleReset();
457
+ });
458
+ },
459
+ handleReset() {
460
+ this.form.adMenuId = "";
461
+ this.editTitle = "";
462
+ this.$refs.form.resetFields();
463
+ },
464
+ submitEdit() {
465
+ let that = this;
466
+ if (this.form.adMenuId && this.form.parentId === this.form.adMenuId) {
467
+ this.$message.error("父级菜单不能为自身!");
468
+ return false;
469
+ }
470
+ this.$refs.form.validate((valid) => {
471
+ if (valid) {
472
+ this.submitLoading = true;
473
+ let curForm = deepClone({}, this.form);
474
+ curForm.created = undefined;
475
+ curForm.updated = undefined;
476
+ curForm._childs = undefined;
477
+ this.axios
478
+ .post("/menuController/submitMenu", this.$qs.stringify(curForm))
479
+ .then((response) => {
480
+ if (response.data.result) {
481
+ that.$message.success((that.form.adMenuId !== "" ? "修改" : "新增") + "成功");
482
+ that.getAllList();
483
+ that.handleReset();
484
+ } else {
485
+ that.$message.error(response.data.msg);
486
+ }
487
+ that.submitLoading = false;
488
+ })
489
+ .catch((response) => {
490
+ that.submitLoading = false;
491
+ });
492
+ }
493
+ });
494
+ },
495
+ add() {
496
+ if (!this.form.id) {
497
+ this.$message.warning("请先点击选择一个菜单权限节点");
498
+ return;
499
+ }
500
+ this.parentTitle = this.form.title;
501
+ this.modalTitle = "添加子节点(可拖动)";
502
+ this.showParent = true;
503
+ let type = 0;
504
+ if (this.form.level === 1) {
505
+ type = 0;
506
+ } else if (this.form.level === 2) {
507
+ type = 1;
508
+ } else if (this.form.level === 3) {
509
+ this.$warning({
510
+ title: "抱歉,不能添加啦",
511
+ content: "左侧仅支持2级菜单目录",
512
+ });
513
+ return;
514
+ } else {
515
+ type = 0;
516
+ }
517
+ if (!this.form.children) {
518
+ this.form.children = [];
519
+ }
520
+ this.formAdd = {
521
+ icon: "",
522
+ type: type,
523
+ parentId: this.form.id,
524
+ level: Number(this.form.level) + 1,
525
+ sortOrder: this.form.children.length + 1,
526
+ buttonType: "",
527
+ status: 0,
528
+ showAlways: true,
529
+ };
530
+ if (this.form.level === 0) {
531
+ this.formAdd.path = "/";
532
+ this.formAdd.component = "Main";
533
+ }
534
+ this.menuModalVisible = true;
535
+ },
536
+ changeSelect(v) {
537
+ this.selectList = v;
538
+ },
539
+ clearSelectAll() {
540
+ this.$refs.table.selectAll(false);
541
+ },
542
+ remove(v) {
543
+ this.selectList = [];
544
+ this.selectList.push(v);
545
+ this.delAll();
546
+ },
547
+ delAll() {
548
+ if (!this.selectedNodes) {
549
+ this.$message.warning("您还未勾选要删除的数据");
550
+ return;
551
+ }
552
+ this.$confirm("您确认要删除所选的数据?", "确认删除", {
553
+ type: "warning",
554
+ }).then(() => {
555
+ let ids = this.selectedNodes.data.key;
556
+ this.axios.post("/menuController/delMenuByIds", this.$qs.stringify({ ids: ids })).then((response) => {
557
+ if (response.data.result) {
558
+ this.$message.success("删除成功");
559
+ this.selectList = [];
560
+ this.getAllList();
561
+ this.handleReset();
562
+ } else {
563
+ this.$message.error(response.data.msg);
564
+ }
565
+ this.submitLoading = false;
566
+ });
567
+ });
568
+ },
569
+ getIcon() {
570
+ this.toIconData = {
571
+ type: "select",
572
+ };
573
+ },
574
+ dealInput(toIcon) {
575
+ this.form.iconPath = toIcon;
576
+ },
577
+ iconSure(iconPath) {
578
+ this.form.iconPath = iconPath;
579
+ },
580
+ },
581
+ activated() {
582
+ // 计算高度
583
+ let height = document.documentElement.clientHeight;
584
+ this.maxHeight = Number(height - 287) + "px";
585
+ this.init();
586
+ },
587
+ };
588
+ </script>
589
+ <style lang="scss">
590
+ .search {
591
+ padding: 10px 0;
592
+ .operation {
593
+ margin-bottom: 2vh;
594
+ .more-btn {
595
+ margin-left: 10px;
596
+ }
597
+ }
598
+
599
+ .select-clear,
600
+ .tree-tips {
601
+ margin-bottom: 10px;
602
+ }
603
+
604
+ .select-title {
605
+ font-weight: 600;
606
+ color: #40a9ff;
607
+ }
608
+
609
+ .tree-bar {
610
+ overflow: auto;
611
+ margin-top: 5px;
612
+ position: relative;
613
+ min-height: 80px;
614
+ &::-webkit-scrollbar {
615
+ width: 6px;
616
+ height: 6px;
617
+ }
618
+
619
+ &::-webkit-scrollbar-thumb {
620
+ border-radius: 4px;
621
+ box-shadow: inset 0 0 2px #d1d1d1;
622
+ background: #e4e4e4;
623
+ }
624
+ }
625
+
626
+ .menu-edit-form {
627
+ .el-form-item__content {
628
+ display: flex;
629
+ .el-input,
630
+ .el-select {
631
+ flex: 1;
632
+ }
633
+ }
634
+ .icon-select-form-item {
635
+ .el-input {
636
+ margin: 0 10px;
637
+ }
638
+ .icon-preview {
639
+ padding: 0 10px 0 0;
640
+ .iconfont {
641
+ font-size: 24px;
642
+ }
643
+ }
644
+ }
645
+ }
646
+ }
647
+ </style>
648
+ @/libs/util.js