@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.
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <TDialog v-model:visible="$Data.visible" :header="$Prop.actionType === 'upd' ? '更新角色' : '添加角色'" width="600px" :append-to-body="true" :show-footer="true" :esc-closable="false" top="10vh" @close="$Method.onClose">
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
- <template #footer>
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
- const $Method = {
101
- async initData() {
102
- if ($Prop.actionType === "upd" && $Prop.rowData.id) {
103
- $Data.formData = Object.assign({}, $Prop.rowData);
104
- }
105
- $Method.onShow();
106
- },
107
- onShow() {
108
- setTimeout(() => {
109
- $Data.visible = $Prop.modelValue;
110
- }, 100);
111
- },
112
- // 关闭抽屉事件
113
- onClose() {
114
- $Data.visible = false;
115
- setTimeout(() => {
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
- $Data.submitting = true;
125
- const formData = $Prop.actionType === "add" ? fieldClear($Data.formData, { omitKeys: ["id", "state"] }) : $Data.formData;
126
- const res = await $Http.post($Prop.actionType === "upd" ? "/addon/admin/role/upd" : "/addon/admin/role/ins", formData);
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
- MessagePlugin.success(res.msg);
129
- $Emit("success");
130
- $Method.onClose();
131
- } catch (error) {
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
- $Method.initData();
134
+ initData();
140
135
  </script>
@@ -1,9 +1,9 @@
1
1
  <template>
2
- <TDialog v-model:visible="$Data.visible" title="菜单权限" width="900px" :append-to-body="true" :show-footer="true" top="5vh" @close="$Method.onClose">
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="$Method.onSearch">
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
- <template #footer>
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 { Dialog as TDialog, CheckboxGroup as TCheckboxGroup, Checkbox as TCheckbox, Button as TButton, Input as TInput, MessagePlugin } from "tdesign-vue-next";
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
- const $Method = {
76
- async initData() {
77
- await Promise.all([$Method.apiMenuAll(), $Method.apiRoleMenuDetail()]);
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
- async apiMenuAll() {
97
- try {
98
- const res = await $Http.post(
99
- "/addon/admin/menu/all",
100
- {},
101
- {
102
- dropValues: [""]
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
- const children = Array.isArray(node?.children) ? node.children : [];
131
- for (const child of children) {
132
- walk(child, depth + 1);
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
- walk(root, 0);
126
+ walk(root as Record<string, unknown>, 0);
137
127
 
138
- const groupTitle = rootName.length > 0 ? rootName : rootPath;
139
- groups.push({
140
- name: rootPath.length > 0 ? rootPath : groupTitle,
141
- title: groupTitle.length > 0 ? groupTitle : "未命名菜单",
142
- menus: menus
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
- async apiRoleMenuDetail() {
154
- if (!$Prop.rowData.id) return;
155
-
156
- try {
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
- // menus 返回的 data 直接就是菜单 path 数组
168
- $Data.checkedMenuPaths = Array.isArray(res.data) ? res.data : [];
169
- } catch (error) {
170
- MessagePlugin.error("加载数据失败");
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
- onSearch() {
176
- const kw = typeof $Data.searchText === "string" ? $Data.searchText.trim().toLowerCase() : "";
177
- if (kw.length === 0) {
178
- $Data.filteredMenuGroups = $Data.menuGroups;
179
- return;
180
- }
156
+ $Data.checkedMenuPaths = Array.isArray(res.data) ? res.data : [];
157
+ } catch (error) {
158
+ MessagePlugin.error("加载数据失败");
159
+ }
160
+ }
181
161
 
182
- $Data.filteredMenuGroups = $Data.menuGroups
183
- .map((group) => {
184
- const menus = Array.isArray(group?.menus)
185
- ? group.menus.filter((menu) => {
186
- const label = typeof menu?.label === "string" ? menu.label : "";
187
- return label.toLowerCase().includes(kw);
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
- async onSubmit() {
202
- try {
203
- $Data.submitting = true;
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 res = await $Http.post("/addon/admin/role/menuSave", {
206
- roleCode: $Prop.rowData.code,
207
- menuPaths: $Data.checkedMenuPaths
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
- if (res.code === 0) {
211
- MessagePlugin.success("保存成功");
212
- $Data.visible = false;
213
- $Emit("success");
214
- } else {
215
- MessagePlugin.error(res.msg || "保存失败");
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
- } catch (error) {
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
- $Method.initData();
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(--bg-color-hover);
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: 8px;
262
- height: 8px;
250
+ width: 12px;
251
+ height: 12px;
263
252
  border-radius: 50%;
264
253
  background-color: var(--primary-color);
265
- opacity: 0.3;
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
- <PagedTableDetailPage class="page-role page-table" :columns="$Data.columns" :endpoints="$Data.endpoints" :table-slot-names="['state', 'menuCount', 'apiCount']">
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="$Method.onAdd">
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="$Method.onReload(scope.reload)">
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
- {{ $Method.getPathCount(row.menus) }}
26
+ {{ getPathCount(row.menus) }}
27
27
  </template>
28
28
 
29
29
  <template #apiCount="{ row }">
30
- {{ $Method.getPathCount(row.apis) }}
30
+ {{ getPathCount(row.apis) }}
31
31
  </template>
32
32
 
33
33
  <template #operation="{ row, deleteRow }">
34
- <TDropdown trigger="click" placement="bottom-right" @click="$Method.onDropdownAction($event, row, deleteRow)">
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="$Method.onDialogSuccess(scope.reload)" />
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="$Method.onDialogSuccess(scope.reload)" />
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="$Method.onDialogSuccess(scope.reload)" />
68
+ <ApiDialog v-if="$Data.apiVisible" v-model="$Data.apiVisible" :row-data="$Data.rowData" @success="onDialogSuccess(scope.reload)" />
69
69
  </template>
70
- </PagedTableDetailPage>
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 PagedTableDetailPage from "@/components/PagedTableDetailPage.vue";
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
- const $Method = {
127
- onAdd() {
128
- $Method.onAction("add", {});
129
- },
125
+ function onAdd(): void {
126
+ onAction("add", {});
127
+ }
130
128
 
131
- onReload(reload) {
132
- reload({ keepSelection: true });
133
- },
129
+ function onReload(reload: (options: { keepSelection?: boolean }) => void): void {
130
+ reload({ keepSelection: true });
131
+ }
134
132
 
135
- onDialogSuccess(reload) {
136
- reload({ keepSelection: true });
137
- },
133
+ function onDialogSuccess(reload: (options: { keepSelection?: boolean }) => void): void {
134
+ reload({ keepSelection: true });
135
+ }
138
136
 
139
- getPathCount(value) {
140
- if (!Array.isArray(value)) return 0;
141
- return value.filter((p) => typeof p === "string" && p.trim().length > 0).length;
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
- if (command === "add") {
147
- $Data.rowData = {};
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
- if (command === "add" || command === "upd") {
153
- $Data.editVisible = true;
154
- return;
155
- }
145
+ if (command === "add") {
146
+ $Data.rowData = {};
147
+ } else {
148
+ $Data.rowData = Object.assign({}, rowData);
149
+ }
156
150
 
157
- if (command === "menu") {
158
- $Data.menuVisible = true;
159
- return;
160
- }
151
+ if (command === "add" || command === "upd") {
152
+ $Data.editVisible = true;
153
+ return;
154
+ }
161
155
 
162
- if (command === "api") {
163
- $Data.apiVisible = true;
164
- }
165
- },
156
+ if (command === "menu") {
157
+ $Data.menuVisible = true;
158
+ return;
159
+ }
166
160
 
167
- onDropdownAction(data, rowData, deleteRow) {
168
- const cmd = data && data.value ? String(data.value) : "";
169
- if (cmd === "del") {
170
- deleteRow(rowData);
171
- return;
172
- }
173
- $Method.onAction(cmd, rowData);
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
+ }