@befly-addon/admin 1.8.4 → 1.8.6
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.
- package/adminViews/403_1/index.vue +9 -10
- package/adminViews/config/dict/components/edit.vue +30 -33
- package/adminViews/config/dict/index.vue +64 -63
- package/adminViews/config/dictType/components/edit.vue +29 -32
- package/adminViews/config/dictType/index.vue +43 -43
- package/adminViews/config/system/components/edit.vue +69 -67
- package/adminViews/config/system/index.vue +44 -54
- package/adminViews/index/components/userInfo.vue +67 -77
- package/adminViews/log/email/index.vue +92 -103
- package/adminViews/log/login/index.vue +31 -45
- package/adminViews/log/operate/index.vue +44 -59
- package/adminViews/login_1/index.vue +24 -31
- package/adminViews/people/admin/components/edit.vue +57 -69
- package/adminViews/people/admin/index.vue +32 -33
- package/adminViews/permission/api/index.vue +52 -62
- package/adminViews/permission/menu/index.vue +43 -53
- package/adminViews/permission/role/components/api.vue +164 -168
- package/adminViews/permission/role/components/edit.vue +39 -44
- package/adminViews/permission/role/components/menu.vue +139 -150
- package/adminViews/permission/role/index.vue +53 -53
- package/adminViews/tsconfig.json +14 -0
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<PageDialog v-model="dialogVisible" :title="$Prop.actionType === 'upd' ? '更新角色' : '添加角色'" :confirm-loading="$Data.submitting" @confirm="onSubmit">
|
|
3
3
|
<div class="comp-role-edit">
|
|
4
4
|
<TForm :model="$Data.formData" label-width="120px" label-position="left" :rules="$Data2.formRules" :ref="(el) => ($From.form = el)">
|
|
5
5
|
<TFormItem label="角色名称" prop="name">
|
|
@@ -22,17 +22,14 @@
|
|
|
22
22
|
</TFormItem>
|
|
23
23
|
</TForm>
|
|
24
24
|
</div>
|
|
25
|
-
|
|
26
|
-
<TButton @click="$Method.onClose">取消</TButton>
|
|
27
|
-
<TButton theme="primary" :loading="$Data.submitting" @click="$Method.onSubmit">确定</TButton>
|
|
28
|
-
</template>
|
|
29
|
-
</TDialog>
|
|
25
|
+
</PageDialog>
|
|
30
26
|
</template>
|
|
31
27
|
|
|
32
28
|
<script setup lang="ts">
|
|
29
|
+
import { computed } from "vue";
|
|
30
|
+
|
|
33
31
|
import {
|
|
34
32
|
//
|
|
35
|
-
Dialog as TDialog,
|
|
36
33
|
Form as TForm,
|
|
37
34
|
FormItem as TFormItem,
|
|
38
35
|
Input as TInput,
|
|
@@ -42,6 +39,7 @@ import {
|
|
|
42
39
|
Button as TButton,
|
|
43
40
|
MessagePlugin
|
|
44
41
|
} from "tdesign-vue-next";
|
|
42
|
+
import PageDialog from "@/components/pageDialog.vue";
|
|
45
43
|
import { $Http } from "@/plugins/http";
|
|
46
44
|
import { fieldClear } from "befly-shared/utils/fieldClear";
|
|
47
45
|
|
|
@@ -65,6 +63,10 @@ const $Emit = defineEmits<{
|
|
|
65
63
|
(e: "success"): void;
|
|
66
64
|
}>();
|
|
67
65
|
|
|
66
|
+
type PageDialogEventContext = {
|
|
67
|
+
close: () => void;
|
|
68
|
+
};
|
|
69
|
+
|
|
68
70
|
// 表单引用
|
|
69
71
|
const $From = $shallowRef({
|
|
70
72
|
form: null
|
|
@@ -73,7 +75,6 @@ const $From = $shallowRef({
|
|
|
73
75
|
const $Computed = {};
|
|
74
76
|
|
|
75
77
|
const $Data = $ref({
|
|
76
|
-
visible: false,
|
|
77
78
|
submitting: false,
|
|
78
79
|
formData: {
|
|
79
80
|
id: 0,
|
|
@@ -96,45 +97,39 @@ const $Data2 = $shallowRef({
|
|
|
96
97
|
}
|
|
97
98
|
});
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
$Emit("update:modelValue", false);
|
|
117
|
-
}, 300);
|
|
118
|
-
},
|
|
119
|
-
async onSubmit() {
|
|
120
|
-
try {
|
|
121
|
-
const valid = await $From.form.validate();
|
|
122
|
-
if (!valid) return;
|
|
100
|
+
async function initData(): Promise<void> {
|
|
101
|
+
if ($Prop.actionType === "upd" && $Prop.rowData.id) {
|
|
102
|
+
$Data.formData = Object.assign({}, $Prop.rowData);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const dialogVisible = computed({
|
|
107
|
+
get: () => $Prop.modelValue,
|
|
108
|
+
set: (value) => {
|
|
109
|
+
$Emit("update:modelValue", value);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
async function onSubmit(context?: PageDialogEventContext): Promise<void> {
|
|
114
|
+
try {
|
|
115
|
+
const valid = await $From.form.validate();
|
|
116
|
+
if (!valid) return;
|
|
123
117
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
118
|
+
$Data.submitting = true;
|
|
119
|
+
const formData = $Prop.actionType === "add" ? fieldClear($Data.formData, { omitKeys: ["id", "state"] }) : $Data.formData;
|
|
120
|
+
const res = await $Http.post($Prop.actionType === "upd" ? "/addon/admin/role/upd" : "/addon/admin/role/ins", formData);
|
|
127
121
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
MessagePlugin.error(error.msg || "提交失败");
|
|
133
|
-
} finally {
|
|
134
|
-
$Data.submitting = false;
|
|
122
|
+
MessagePlugin.success(res.msg);
|
|
123
|
+
$Emit("success");
|
|
124
|
+
if (context && typeof context.close === "function") {
|
|
125
|
+
context.close();
|
|
135
126
|
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
MessagePlugin.error((error as { msg?: string }).msg || "提交失败");
|
|
129
|
+
} finally {
|
|
130
|
+
$Data.submitting = false;
|
|
136
131
|
}
|
|
137
|
-
}
|
|
132
|
+
}
|
|
138
133
|
|
|
139
|
-
|
|
134
|
+
initData();
|
|
140
135
|
</script>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<PageDialog v-model="dialogVisible" title="菜单权限" width="900px" :confirm-loading="$Data.submitting" @confirm="onSubmit">
|
|
3
3
|
<div class="comp-role-menu">
|
|
4
4
|
<!-- 搜索框 -->
|
|
5
5
|
<div class="search-box">
|
|
6
|
-
<TInput v-model="$Data.searchText" placeholder="搜索菜单名称或路径" clearable @change="
|
|
6
|
+
<TInput v-model="$Data.searchText" placeholder="搜索菜单名称或路径" clearable @change="onSearch">
|
|
7
7
|
<template #prefix-icon>
|
|
8
8
|
<ILucideSearch />
|
|
9
9
|
</template>
|
|
@@ -29,20 +29,15 @@
|
|
|
29
29
|
</div>
|
|
30
30
|
</div>
|
|
31
31
|
</div>
|
|
32
|
-
|
|
33
|
-
<div class="dialog-footer">
|
|
34
|
-
<t-space>
|
|
35
|
-
<TButton theme="default" @click="$Method.onClose">取消</TButton>
|
|
36
|
-
<TButton theme="primary" :loading="$Data.submitting" @click="$Method.onSubmit">保存</TButton>
|
|
37
|
-
</t-space>
|
|
38
|
-
</div>
|
|
39
|
-
</template>
|
|
40
|
-
</TDialog>
|
|
32
|
+
</PageDialog>
|
|
41
33
|
</template>
|
|
42
34
|
|
|
43
35
|
<script setup lang="ts">
|
|
44
|
-
import {
|
|
36
|
+
import { computed } from "vue";
|
|
37
|
+
|
|
38
|
+
import { CheckboxGroup as TCheckboxGroup, Checkbox as TCheckbox, Input as TInput, MessagePlugin } from "tdesign-vue-next";
|
|
45
39
|
import ILucideSearch from "~icons/lucide/search";
|
|
40
|
+
import PageDialog from "@/components/pageDialog.vue";
|
|
46
41
|
import { $Http } from "@/plugins/http";
|
|
47
42
|
import { arrayToTree } from "befly-shared/utils/arrayToTree";
|
|
48
43
|
|
|
@@ -62,8 +57,18 @@ const $Emit = defineEmits<{
|
|
|
62
57
|
(e: "success"): void;
|
|
63
58
|
}>();
|
|
64
59
|
|
|
60
|
+
type PageDialogEventContext = {
|
|
61
|
+
close: () => void;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const dialogVisible = computed({
|
|
65
|
+
get: () => $Prop.modelValue,
|
|
66
|
+
set: (value) => {
|
|
67
|
+
$Emit("update:modelValue", value);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
65
71
|
const $Data = $ref({
|
|
66
|
-
visible: false,
|
|
67
72
|
submitting: false,
|
|
68
73
|
searchText: "",
|
|
69
74
|
menuGroups: [],
|
|
@@ -71,158 +76,142 @@ const $Data = $ref({
|
|
|
71
76
|
checkedMenuPaths: []
|
|
72
77
|
});
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
$Data.filteredMenuGroups = $Data.menuGroups;
|
|
79
|
-
$Method.onShow();
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
onShow() {
|
|
83
|
-
setTimeout(() => {
|
|
84
|
-
$Data.visible = $Prop.modelValue;
|
|
85
|
-
}, 100);
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
onClose() {
|
|
89
|
-
$Data.visible = false;
|
|
90
|
-
setTimeout(() => {
|
|
91
|
-
$Emit("update:modelValue", false);
|
|
92
|
-
}, 300);
|
|
93
|
-
},
|
|
79
|
+
async function initData(): Promise<void> {
|
|
80
|
+
await Promise.all([apiMenuAll(), apiRoleMenuDetail()]);
|
|
81
|
+
$Data.filteredMenuGroups = $Data.menuGroups;
|
|
82
|
+
}
|
|
94
83
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
84
|
+
async function apiMenuAll(): Promise<void> {
|
|
85
|
+
try {
|
|
86
|
+
const res = await $Http.post(
|
|
87
|
+
"/addon/admin/menu/all",
|
|
88
|
+
{},
|
|
89
|
+
{
|
|
90
|
+
dropValues: [""]
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
const lists = Array.isArray(res?.data?.lists) ? res.data.lists : [];
|
|
94
|
+
|
|
95
|
+
const treeResult = arrayToTree(lists, "path", "parentPath", "children", "sort");
|
|
96
|
+
const roots = Array.isArray(treeResult?.tree) ? treeResult.tree : [];
|
|
97
|
+
|
|
98
|
+
const groups: Array<{ name: string; title: string; menus: unknown[] }> = [];
|
|
99
|
+
for (const root of roots) {
|
|
100
|
+
const rootPath = typeof root?.path === "string" ? root.path : "";
|
|
101
|
+
const rootName = typeof root?.name === "string" ? root.name : "";
|
|
102
|
+
|
|
103
|
+
const menus: unknown[] = [];
|
|
104
|
+
|
|
105
|
+
const walk = (node: Record<string, unknown>, depth: number): void => {
|
|
106
|
+
const name = typeof node["name"] === "string" ? String(node["name"]) : "";
|
|
107
|
+
const path = typeof node["path"] === "string" ? String(node["path"]) : "";
|
|
108
|
+
if (path.length > 0) {
|
|
109
|
+
menus.push({
|
|
110
|
+
value: path,
|
|
111
|
+
name: name,
|
|
112
|
+
path: path,
|
|
113
|
+
depth: depth,
|
|
114
|
+
label: `${name} ${path}`.trim()
|
|
115
|
+
});
|
|
103
116
|
}
|
|
104
|
-
);
|
|
105
|
-
const lists = Array.isArray(res?.data?.lists) ? res.data.lists : [];
|
|
106
|
-
|
|
107
|
-
const treeResult = arrayToTree(lists, "path", "parentPath", "children", "sort");
|
|
108
|
-
const roots = Array.isArray(treeResult?.tree) ? treeResult.tree : [];
|
|
109
|
-
|
|
110
|
-
const groups = [];
|
|
111
|
-
for (const root of roots) {
|
|
112
|
-
const rootPath = typeof root?.path === "string" ? root.path : "";
|
|
113
|
-
const rootName = typeof root?.name === "string" ? root.name : "";
|
|
114
|
-
|
|
115
|
-
const menus = [];
|
|
116
|
-
|
|
117
|
-
const walk = (node, depth) => {
|
|
118
|
-
const name = typeof node?.name === "string" ? node.name : "";
|
|
119
|
-
const path = typeof node?.path === "string" ? node.path : "";
|
|
120
|
-
if (path.length > 0) {
|
|
121
|
-
menus.push({
|
|
122
|
-
value: path,
|
|
123
|
-
name: name,
|
|
124
|
-
path: path,
|
|
125
|
-
depth: depth,
|
|
126
|
-
label: `${name} ${path}`.trim()
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
117
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
118
|
+
const children = Array.isArray(node["children"]) ? (node["children"] as unknown[]) : [];
|
|
119
|
+
for (const child of children) {
|
|
120
|
+
if (child && typeof child === "object") {
|
|
121
|
+
walk(child as Record<string, unknown>, depth + 1);
|
|
133
122
|
}
|
|
134
|
-
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
135
125
|
|
|
136
|
-
|
|
126
|
+
walk(root as Record<string, unknown>, 0);
|
|
137
127
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
$Data.menuGroups = groups;
|
|
147
|
-
} catch (error) {
|
|
148
|
-
MessagePlugin.error("加载菜单失败");
|
|
128
|
+
const groupTitle = rootName.length > 0 ? rootName : rootPath;
|
|
129
|
+
groups.push({
|
|
130
|
+
name: rootPath.length > 0 ? rootPath : groupTitle,
|
|
131
|
+
title: groupTitle.length > 0 ? groupTitle : "未命名菜单",
|
|
132
|
+
menus: menus
|
|
133
|
+
});
|
|
149
134
|
}
|
|
150
|
-
},
|
|
151
135
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const res = await $Http.post(
|
|
158
|
-
"/addon/admin/role/menus",
|
|
159
|
-
{
|
|
160
|
-
roleCode: $Prop.rowData.code
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
dropValues: [""]
|
|
164
|
-
}
|
|
165
|
-
);
|
|
136
|
+
$Data.menuGroups = groups as never;
|
|
137
|
+
} catch (error) {
|
|
138
|
+
MessagePlugin.error("加载菜单失败");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
166
141
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
142
|
+
async function apiRoleMenuDetail(): Promise<void> {
|
|
143
|
+
if (!$Prop.rowData.id) return;
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
const res = await $Http.post(
|
|
147
|
+
"/addon/admin/role/menus",
|
|
148
|
+
{
|
|
149
|
+
roleCode: $Prop.rowData.code
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
dropValues: [""]
|
|
153
|
+
}
|
|
154
|
+
);
|
|
173
155
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
156
|
+
$Data.checkedMenuPaths = Array.isArray(res.data) ? res.data : [];
|
|
157
|
+
} catch (error) {
|
|
158
|
+
MessagePlugin.error("加载数据失败");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
181
161
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
})
|
|
189
|
-
: [];
|
|
190
|
-
|
|
191
|
-
return {
|
|
192
|
-
name: group.name,
|
|
193
|
-
title: group.title,
|
|
194
|
-
menus: menus
|
|
195
|
-
};
|
|
196
|
-
})
|
|
197
|
-
.filter((group) => Array.isArray(group.menus) && group.menus.length > 0);
|
|
198
|
-
},
|
|
162
|
+
function onSearch(): void {
|
|
163
|
+
const kw = typeof $Data.searchText === "string" ? $Data.searchText.trim().toLowerCase() : "";
|
|
164
|
+
if (kw.length === 0) {
|
|
165
|
+
$Data.filteredMenuGroups = $Data.menuGroups;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
199
168
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
169
|
+
$Data.filteredMenuGroups = ($Data.menuGroups as unknown[])
|
|
170
|
+
.map((group) => {
|
|
171
|
+
const groupRecord = group && typeof group === "object" ? (group as Record<string, unknown>) : null;
|
|
172
|
+
const groupMenus = groupRecord && Array.isArray(groupRecord["menus"]) ? (groupRecord["menus"] as unknown[]) : [];
|
|
204
173
|
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
174
|
+
const menus = groupMenus.filter((menu) => {
|
|
175
|
+
const menuRecord = menu && typeof menu === "object" ? (menu as Record<string, unknown>) : null;
|
|
176
|
+
const label = menuRecord && typeof menuRecord["label"] === "string" ? String(menuRecord["label"]) : "";
|
|
177
|
+
return label.toLowerCase().includes(kw);
|
|
208
178
|
});
|
|
209
179
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
180
|
+
return {
|
|
181
|
+
name: groupRecord && typeof groupRecord["name"] === "string" ? String(groupRecord["name"]) : "",
|
|
182
|
+
title: groupRecord && typeof groupRecord["title"] === "string" ? String(groupRecord["title"]) : "",
|
|
183
|
+
menus: menus
|
|
184
|
+
};
|
|
185
|
+
})
|
|
186
|
+
.filter((group) => group.menus.length > 0) as never;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function onSubmit(context?: PageDialogEventContext): Promise<void> {
|
|
190
|
+
try {
|
|
191
|
+
$Data.submitting = true;
|
|
192
|
+
|
|
193
|
+
const res = await $Http.post("/addon/admin/role/menuSave", {
|
|
194
|
+
roleCode: $Prop.rowData.code,
|
|
195
|
+
menuPaths: $Data.checkedMenuPaths
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
if (res.code === 0) {
|
|
199
|
+
MessagePlugin.success("保存成功");
|
|
200
|
+
$Emit("success");
|
|
201
|
+
if (context && typeof context.close === "function") {
|
|
202
|
+
context.close();
|
|
216
203
|
}
|
|
217
|
-
}
|
|
218
|
-
MessagePlugin.error("保存失败");
|
|
219
|
-
} finally {
|
|
220
|
-
$Data.submitting = false;
|
|
204
|
+
} else {
|
|
205
|
+
MessagePlugin.error(res.msg || "保存失败");
|
|
221
206
|
}
|
|
207
|
+
} catch (error) {
|
|
208
|
+
MessagePlugin.error("保存失败");
|
|
209
|
+
} finally {
|
|
210
|
+
$Data.submitting = false;
|
|
222
211
|
}
|
|
223
|
-
}
|
|
212
|
+
}
|
|
224
213
|
|
|
225
|
-
|
|
214
|
+
initData();
|
|
226
215
|
</script>
|
|
227
216
|
|
|
228
217
|
<style scoped lang="scss">
|
|
@@ -248,7 +237,7 @@ $Method.initData();
|
|
|
248
237
|
|
|
249
238
|
.group-header {
|
|
250
239
|
padding: 12px 16px;
|
|
251
|
-
background-color: var(--
|
|
240
|
+
background-color: var(--primary-color-light);
|
|
252
241
|
font-weight: 500;
|
|
253
242
|
font-size: var(--font-size-sm);
|
|
254
243
|
color: var(--text-primary);
|
|
@@ -258,11 +247,11 @@ $Method.initData();
|
|
|
258
247
|
|
|
259
248
|
&::before {
|
|
260
249
|
content: "";
|
|
261
|
-
width:
|
|
262
|
-
height:
|
|
250
|
+
width: 12px;
|
|
251
|
+
height: 12px;
|
|
263
252
|
border-radius: 50%;
|
|
264
253
|
background-color: var(--primary-color);
|
|
265
|
-
|
|
254
|
+
box-shadow: 0 0 0 2px var(--bg-color-container);
|
|
266
255
|
flex-shrink: 0;
|
|
267
256
|
}
|
|
268
257
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<PagedTableDetail class="page-role page-table" :columns="$Data.columns" :endpoints="$Data.endpoints" :table-slot-names="['state', 'menuCount', 'apiCount']">
|
|
3
3
|
<template #toolLeft>
|
|
4
|
-
<TButton theme="primary" @click="
|
|
4
|
+
<TButton theme="primary" @click="onAdd">
|
|
5
5
|
<template #icon>
|
|
6
6
|
<ILucidePlus />
|
|
7
7
|
</template>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</template>
|
|
10
10
|
|
|
11
11
|
<template #toolRight="scope">
|
|
12
|
-
<TButton shape="circle" @click="
|
|
12
|
+
<TButton shape="circle" @click="onReload(scope.reload)">
|
|
13
13
|
<template #icon>
|
|
14
14
|
<ILucideRotateCw />
|
|
15
15
|
</template>
|
|
@@ -23,15 +23,15 @@
|
|
|
23
23
|
</template>
|
|
24
24
|
|
|
25
25
|
<template #menuCount="{ row }">
|
|
26
|
-
{{
|
|
26
|
+
{{ getPathCount(row.menus) }}
|
|
27
27
|
</template>
|
|
28
28
|
|
|
29
29
|
<template #apiCount="{ row }">
|
|
30
|
-
{{
|
|
30
|
+
{{ getPathCount(row.apis) }}
|
|
31
31
|
</template>
|
|
32
32
|
|
|
33
33
|
<template #operation="{ row, deleteRow }">
|
|
34
|
-
<TDropdown trigger="click" placement="bottom-right" @click="
|
|
34
|
+
<TDropdown trigger="click" placement="bottom-right" @click="onDropdownAction($event, row, deleteRow)">
|
|
35
35
|
<TButton theme="primary" size="small">
|
|
36
36
|
操作
|
|
37
37
|
<template #suffix> <ILucideChevronDown /></template>
|
|
@@ -59,15 +59,15 @@
|
|
|
59
59
|
|
|
60
60
|
<template #dialogs="scope">
|
|
61
61
|
<!-- 编辑对话框组件 -->
|
|
62
|
-
<EditDialog v-if="$Data.editVisible" v-model="$Data.editVisible" :action-type="$Data.actionType" :row-data="$Data.rowData" @success="
|
|
62
|
+
<EditDialog v-if="$Data.editVisible" v-model="$Data.editVisible" :action-type="$Data.actionType" :row-data="$Data.rowData" @success="onDialogSuccess(scope.reload)" />
|
|
63
63
|
|
|
64
64
|
<!-- 菜单权限对话框组件 -->
|
|
65
|
-
<MenuDialog v-if="$Data.menuVisible" v-model="$Data.menuVisible" :row-data="$Data.rowData" @success="
|
|
65
|
+
<MenuDialog v-if="$Data.menuVisible" v-model="$Data.menuVisible" :row-data="$Data.rowData" @success="onDialogSuccess(scope.reload)" />
|
|
66
66
|
|
|
67
67
|
<!-- 接口权限对话框组件 -->
|
|
68
|
-
<ApiDialog v-if="$Data.apiVisible" v-model="$Data.apiVisible" :row-data="$Data.rowData" @success="
|
|
68
|
+
<ApiDialog v-if="$Data.apiVisible" v-model="$Data.apiVisible" :row-data="$Data.rowData" @success="onDialogSuccess(scope.reload)" />
|
|
69
69
|
</template>
|
|
70
|
-
</
|
|
70
|
+
</PagedTableDetail>
|
|
71
71
|
</template>
|
|
72
72
|
|
|
73
73
|
<script setup lang="ts">
|
|
@@ -82,7 +82,7 @@ import ILucideChevronDown from "~icons/lucide/chevron-down";
|
|
|
82
82
|
import EditDialog from "./components/edit.vue";
|
|
83
83
|
import MenuDialog from "./components/menu.vue";
|
|
84
84
|
import ApiDialog from "./components/api.vue";
|
|
85
|
-
import
|
|
85
|
+
import PagedTableDetail from "@/components/pagedTableDetail.vue";
|
|
86
86
|
import { withDefaultColumns } from "befly-shared/utils/withDefaultColumns";
|
|
87
87
|
|
|
88
88
|
// 响应式数据
|
|
@@ -122,57 +122,57 @@ const $Data = $ref({
|
|
|
122
122
|
rowData: {}
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
$Method.onAction("add", {});
|
|
129
|
-
},
|
|
125
|
+
function onAdd(): void {
|
|
126
|
+
onAction("add", {});
|
|
127
|
+
}
|
|
130
128
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
function onReload(reload: (options: { keepSelection?: boolean }) => void): void {
|
|
130
|
+
reload({ keepSelection: true });
|
|
131
|
+
}
|
|
134
132
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
function onDialogSuccess(reload: (options: { keepSelection?: boolean }) => void): void {
|
|
134
|
+
reload({ keepSelection: true });
|
|
135
|
+
}
|
|
138
136
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
onAction(command, rowData) {
|
|
144
|
-
$Data.actionType = command;
|
|
137
|
+
function getPathCount(value: unknown): number {
|
|
138
|
+
if (!Array.isArray(value)) return 0;
|
|
139
|
+
return value.filter((p) => typeof p === "string" && p.trim().length > 0).length;
|
|
140
|
+
}
|
|
145
141
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
} else {
|
|
149
|
-
$Data.rowData = Object.assign({}, rowData);
|
|
150
|
-
}
|
|
142
|
+
function onAction(command: string, rowData: Record<string, unknown>): void {
|
|
143
|
+
$Data.actionType = command;
|
|
151
144
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
145
|
+
if (command === "add") {
|
|
146
|
+
$Data.rowData = {};
|
|
147
|
+
} else {
|
|
148
|
+
$Data.rowData = Object.assign({}, rowData);
|
|
149
|
+
}
|
|
156
150
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
151
|
+
if (command === "add" || command === "upd") {
|
|
152
|
+
$Data.editVisible = true;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
161
155
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
156
|
+
if (command === "menu") {
|
|
157
|
+
$Data.menuVisible = true;
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
166
160
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
161
|
+
if (command === "api") {
|
|
162
|
+
$Data.apiVisible = true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function onDropdownAction(data: unknown, rowData: Record<string, unknown>, deleteRow: (row: Record<string, unknown>) => void): void {
|
|
167
|
+
const record = data as Record<string, unknown>;
|
|
168
|
+
const rawValue = record && record["value"] ? record["value"] : "";
|
|
169
|
+
const cmd = rawValue ? String(rawValue) : "";
|
|
170
|
+
if (cmd === "del") {
|
|
171
|
+
deleteRow(rowData);
|
|
172
|
+
return;
|
|
174
173
|
}
|
|
175
|
-
|
|
174
|
+
onAction(cmd, rowData);
|
|
175
|
+
}
|
|
176
176
|
</script>
|
|
177
177
|
|
|
178
178
|
<style scoped lang="scss">
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"noEmit": true,
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"types": ["vite/client", "unplugin-icons/types/vue"],
|
|
7
|
+
"baseUrl": ".",
|
|
8
|
+
"paths": {
|
|
9
|
+
"@/*": ["../../admin/src/*"]
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"include": ["**/*.vue", "**/*.ts", "**/*.d.ts"],
|
|
13
|
+
"exclude": ["node_modules", "dist", "logs", "temp"]
|
|
14
|
+
}
|