@befly-addon/admin 1.1.35 → 1.2.0

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 (46) hide show
  1. package/apis/admin/cacheRefresh.ts +2 -2
  2. package/apis/menu/all.ts +8 -9
  3. package/apis/menu/list.ts +1 -2
  4. package/apis/role/apiSave.ts +3 -3
  5. package/apis/role/apis.ts +3 -3
  6. package/apis/role/menuSave.ts +2 -2
  7. package/apis/role/menus.ts +3 -3
  8. package/package.json +21 -21
  9. package/plugins/email.ts +3 -8
  10. package/tables/api.json +1 -20
  11. package/tables/menu.json +6 -11
  12. package/tables/role.json +4 -4
  13. package/views/403_1/index.vue +0 -75
  14. package/views/config/dict/components/edit.vue +0 -109
  15. package/views/config/dict/index.vue +0 -266
  16. package/views/config/dictType/components/edit.vue +0 -100
  17. package/views/config/dictType/index.vue +0 -244
  18. package/views/config/index.vue +0 -12
  19. package/views/config/system/components/edit.vue +0 -171
  20. package/views/config/system/index.vue +0 -286
  21. package/views/index/components/addonList.vue +0 -132
  22. package/views/index/components/environmentInfo.vue +0 -100
  23. package/views/index/components/operationLogs.vue +0 -112
  24. package/views/index/components/performanceMetrics.vue +0 -145
  25. package/views/index/components/quickActions.vue +0 -30
  26. package/views/index/components/serviceStatus.vue +0 -192
  27. package/views/index/components/systemNotifications.vue +0 -137
  28. package/views/index/components/systemOverview.vue +0 -190
  29. package/views/index/components/systemResources.vue +0 -111
  30. package/views/index/components/userInfo.vue +0 -204
  31. package/views/index/index.vue +0 -74
  32. package/views/log/email/index.vue +0 -292
  33. package/views/log/index.vue +0 -12
  34. package/views/log/login/index.vue +0 -187
  35. package/views/log/operate/index.vue +0 -249
  36. package/views/login_1/index.vue +0 -415
  37. package/views/people/admin/components/edit.vue +0 -168
  38. package/views/people/admin/index.vue +0 -240
  39. package/views/people/index.vue +0 -12
  40. package/views/permission/api/index.vue +0 -149
  41. package/views/permission/index.vue +0 -12
  42. package/views/permission/menu/index.vue +0 -128
  43. package/views/permission/role/components/api.vue +0 -261
  44. package/views/permission/role/components/edit.vue +0 -142
  45. package/views/permission/role/components/menu.vue +0 -116
  46. package/views/permission/role/index.vue +0 -263
@@ -46,8 +46,8 @@ export default {
46
46
 
47
47
  await befly.redis.setObject(CacheKeys.menusAll(), menus.lists);
48
48
 
49
- const parentCount = menus.lists.filter((m: any) => m.pid === 0).length;
50
- const childCount = menus.lists.filter((m: any) => m.pid !== 0).length;
49
+ const parentCount = menus.lists.filter((m: any) => typeof m.parentPath !== "string" || m.parentPath.length === 0).length;
50
+ const childCount = menus.lists.filter((m: any) => typeof m.parentPath === "string" && m.parentPath.length > 0).length;
51
51
 
52
52
  results.menus = {
53
53
  success: true,
package/apis/menu/all.ts CHANGED
@@ -21,11 +21,11 @@ export default {
21
21
  return befly.tool.No("角色不存在", { lists: [] });
22
22
  }
23
23
 
24
- // 3. 解析菜单ID列表(数组,数据库字段已改为 array 存储)
25
- const rawMenuIds = Array.isArray(role.menus) ? role.menus : [];
26
- const menuIds = rawMenuIds.map((id: any) => Number(id)).filter((id: number) => Number.isFinite(id));
24
+ // 3. 解析菜单路径列表(menu.path 数组,array_text)
25
+ const rawMenuPaths = Array.isArray(role.menus) ? role.menus : [];
26
+ const menuPaths = rawMenuPaths.map((p: any) => (typeof p === "string" ? p.trim() : "")).filter((p: string) => p.length > 0);
27
27
 
28
- if (menuIds.length === 0) {
28
+ if (menuPaths.length === 0) {
29
29
  return befly.tool.Yes("菜单为空", { lists: [] });
30
30
  }
31
31
 
@@ -35,8 +35,7 @@ export default {
35
35
  // 如果缓存不存在,从数据库查询
36
36
  if (allMenus.length === 0) {
37
37
  const result = await befly.db.getAll({
38
- table: "addon_admin_menu",
39
- orderBy: ["sort#ASC", "id#ASC"]
38
+ table: "addon_admin_menu"
40
39
  });
41
40
  allMenus = result.lists;
42
41
  }
@@ -45,9 +44,9 @@ export default {
45
44
  return befly.tool.Yes("菜单为空", { lists: [] });
46
45
  }
47
46
 
48
- // 5. 根据角色权限过滤菜单
49
- const menuIdSet = new Set<number>(menuIds);
50
- const authorizedMenus = allMenus.filter((menu: any) => menuIdSet.has(Number(menu.id)));
47
+ // 5. 根据角色权限过滤菜单(按 menu.path)
48
+ const menuPathSet = new Set<string>(menuPaths);
49
+ const authorizedMenus = allMenus.filter((menu: any) => typeof menu?.path === "string" && menuPathSet.has(String(menu.path)));
51
50
 
52
51
  // 6. 返回一维数组(由前端构建树形结构)
53
52
  return befly.tool.Yes("获取菜单成功", { lists: authorizedMenus });
package/apis/menu/list.ts CHANGED
@@ -9,8 +9,7 @@ export default {
9
9
  handler: async (befly) => {
10
10
  try {
11
11
  const menus = await befly.db.getAll({
12
- table: "addon_admin_menu",
13
- orderBy: ["sort#ASC", "id#ASC"]
12
+ table: "addon_admin_menu"
14
13
  });
15
14
 
16
15
  return befly.tool.Yes("操作成功", { lists: menus.lists });
@@ -4,7 +4,7 @@ export default {
4
4
  name: "保存角色接口权限",
5
5
  fields: {
6
6
  roleCode: adminRoleTable.code,
7
- apiIds: adminRoleTable.apis
7
+ apiPaths: adminRoleTable.apis
8
8
  },
9
9
  handler: async (befly, ctx) => {
10
10
  // 查询角色是否存在
@@ -22,12 +22,12 @@ export default {
22
22
  table: "addon_admin_role",
23
23
  where: { code: ctx.body.roleCode },
24
24
  data: {
25
- apis: ctx.body.apiIds
25
+ apis: ctx.body.apiPaths
26
26
  }
27
27
  });
28
28
 
29
29
  // 增量刷新 Redis 权限缓存
30
- await befly.cache.refreshRoleApiPermissions(role.code, ctx.body.apiIds || []);
30
+ await befly.cache.refreshRoleApiPermissions(role.code, ctx.body.apiPaths || []);
31
31
 
32
32
  return befly.tool.Yes("操作成功");
33
33
  }
package/apis/role/apis.ts CHANGED
@@ -16,9 +16,9 @@ export default {
16
16
  return befly.tool.No("角色不存在");
17
17
  }
18
18
 
19
- // 数据库自动将 array_number_string 转换为数组
20
- const apiIds = role.apis || [];
19
+ // 数据库自动将 array_text 转换为数组
20
+ const apiPaths = role.apis || [];
21
21
 
22
- return befly.tool.Yes("操作成功", { apiIds });
22
+ return befly.tool.Yes("操作成功", { apiPaths: apiPaths });
23
23
  }
24
24
  };
@@ -4,7 +4,7 @@ export default {
4
4
  name: "保存角色菜单权限",
5
5
  fields: {
6
6
  roleCode: adminRoleTable.code,
7
- menuIds: adminRoleTable.menus
7
+ menuPaths: adminRoleTable.menus
8
8
  },
9
9
  handler: async (befly, ctx) => {
10
10
  // 查询角色是否存在
@@ -22,7 +22,7 @@ export default {
22
22
  table: "addon_admin_role",
23
23
  where: { code: ctx.body.roleCode },
24
24
  data: {
25
- menus: ctx.body.menuIds
25
+ menus: ctx.body.menuPaths
26
26
  }
27
27
  });
28
28
 
@@ -16,9 +16,9 @@ export default {
16
16
  return befly.tool.No("角色不存在");
17
17
  }
18
18
 
19
- // 数据库自动将 array_number_string 转换为数组
20
- const menuIds = role.menus || [];
19
+ // 数据库自动将 array_text 转换为数组
20
+ const menuPaths = role.menus || [];
21
21
 
22
- return befly.tool.Yes("操作成功", menuIds);
22
+ return befly.tool.Yes("操作成功", menuPaths);
23
23
  }
24
24
  };
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@befly-addon/admin",
3
- "version": "1.1.35",
3
+ "version": "1.2.0",
4
+ "gitHead": "faa8189c7d23cf45885c03d1425cba8f5bf45df9",
4
5
  "private": false,
5
6
  "description": "Befly - 管理后台功能组件",
6
7
  "keywords": [
@@ -11,42 +12,46 @@
11
12
  "rbac",
12
13
  "typescript"
13
14
  ],
15
+ "license": "Apache-2.0",
16
+ "author": "chenbimo",
14
17
  "repository": {
15
18
  "type": "git",
16
19
  "url": "https://github.com/chenbimo/befly.git",
17
20
  "directory": "packages/addon-admin"
18
21
  },
19
- "author": "chenbimo",
20
- "license": "Apache-2.0",
21
- "type": "module",
22
- "main": "package.json",
23
- "exports": {
24
- ".": "./package.json",
25
- "./styles/*": "./styles/*"
26
- },
27
22
  "files": [
28
- "README.md",
29
23
  "apis",
30
24
  "libs",
31
25
  "package.json",
32
26
  "plugins",
27
+ "README.md",
33
28
  "styles",
34
29
  "tables",
35
30
  "views"
36
31
  ],
32
+ "type": "module",
33
+ "main": "package.json",
34
+ "exports": {
35
+ ".": "./package.json",
36
+ "./styles/*": "./styles/*"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public",
40
+ "registry": "https://registry.npmjs.org"
41
+ },
37
42
  "scripts": {
38
43
  "dev": "vite",
39
44
  "build": "vite build",
40
45
  "preview": "vite preview"
41
46
  },
42
47
  "dependencies": {
43
- "befly": "^3.9.40",
44
- "befly-vite": "^1.1.13",
45
- "nodemailer": "^7.0.11",
48
+ "befly": "^3.10.0",
49
+ "befly-vite": "^1.2.0",
50
+ "nodemailer": "^7.0.12",
46
51
  "ua-parser-js": "^2.0.7"
47
52
  },
48
53
  "devDependencies": {
49
- "@iconify-json/lucide": "^1.2.80",
54
+ "@iconify-json/lucide": "^1.2.82",
50
55
  "@types/nodemailer": "^7.0.4",
51
56
  "@types/ua-parser-js": "^0.7.39",
52
57
  "pinia": "^3.0.4",
@@ -55,16 +60,11 @@
55
60
  "vue-router": "^4.6.4"
56
61
  },
57
62
  "peerDependencies": {
58
- "@iconify-json/lucide": "^1.2.80",
63
+ "@iconify-json/lucide": "^1.2.82",
59
64
  "pinia": "^3.0.4",
60
65
  "tdesign-vue-next": "^1.17.7",
61
66
  "vue": "^3.5.26",
62
67
  "vue-router": "^4.6.4"
63
68
  },
64
- "publishConfig": {
65
- "access": "public",
66
- "registry": "https://registry.npmjs.org"
67
- },
68
- "gitHead": "3a0df4a847cf3da97bb2d09455fabba62027e6c0",
69
- "title": "管理后台"
69
+ "addonName": "管理后台"
70
70
  }
package/plugins/email.ts CHANGED
@@ -19,11 +19,8 @@ const defaultConfig: EmailConfig = {
19
19
  fromName: "Befly System"
20
20
  };
21
21
 
22
- /**
23
- * 邮件插件
24
- */
25
- const emailPlugin: Plugin = {
26
- after: ["db", "logger", "config"],
22
+ export default {
23
+ deps: ["db", "logger", "config"],
27
24
  async handler(befly: BeflyContext): Promise<EmailHelper> {
28
25
  // 从 befly.config.addons.admin.email 获取配置
29
26
  const addonEmailConfig = befly.config?.addons?.admin?.email || {};
@@ -34,6 +31,4 @@ const emailPlugin: Plugin = {
34
31
 
35
32
  return new EmailHelper(befly, emailConfig);
36
33
  }
37
- };
38
-
39
- export default emailPlugin;
34
+ } satisfies Plugin;
package/tables/api.json CHANGED
@@ -6,35 +6,16 @@
6
6
  "max": 100,
7
7
  "index": true
8
8
  },
9
- "path": {
9
+ "routePath": {
10
10
  "name": "接口路径",
11
11
  "type": "string",
12
12
  "min": 1,
13
13
  "max": 200,
14
14
  "index": true
15
15
  },
16
- "method": {
17
- "name": "请求方法",
18
- "type": "string",
19
- "min": 3,
20
- "max": 10,
21
- "default": "POST",
22
- "index": true,
23
- "regexp": "^(GET|POST|PUT|DELETE|PATCH)$"
24
- },
25
- "description": {
26
- "name": "接口描述",
27
- "type": "string",
28
- "max": 500
29
- },
30
16
  "addonName": {
31
17
  "name": "所属插件",
32
18
  "type": "string",
33
19
  "max": 50
34
- },
35
- "addonTitle": {
36
- "name": "插件标题",
37
- "type": "string",
38
- "max": 100
39
20
  }
40
21
  }
package/tables/menu.json CHANGED
@@ -11,12 +11,7 @@
11
11
  "type": "string",
12
12
  "min": 1,
13
13
  "max": 200,
14
- "index": true
15
- },
16
- "icon": {
17
- "name": "图标名称",
18
- "type": "string",
19
- "max": 50
14
+ "unique": true
20
15
  },
21
16
  "sort": {
22
17
  "name": "排序",
@@ -25,11 +20,11 @@
25
20
  "max": 9999,
26
21
  "default": 0
27
22
  },
28
- "pid": {
29
- "name": "父级ID",
30
- "type": "number",
31
- "min": 0,
32
- "default": 0,
23
+ "parentPath": {
24
+ "name": "父级路径",
25
+ "type": "string",
26
+ "max": 200,
27
+ "default": "",
33
28
  "index": true
34
29
  }
35
30
  }
package/tables/role.json CHANGED
@@ -21,13 +21,13 @@
21
21
  },
22
22
  "menus": {
23
23
  "name": "菜单权限",
24
- "type": "array_number_text",
25
- "detail": "菜单ID数组,如 [1,2,3]"
24
+ "type": "array_text",
25
+ "detail": "菜单路径数组(menu.path),如 [\"/permission/role\",\"/dashboard\"]"
26
26
  },
27
27
  "apis": {
28
28
  "name": "接口权限",
29
- "type": "array_number_text",
30
- "detail": "接口ID数组,如 [1,2,3]"
29
+ "type": "array_text",
30
+ "detail": "接口路径数组(url.pathname),如 [\"/api/addon/addonAdmin/auth/login\"]"
31
31
  },
32
32
  "sort": {
33
33
  "name": "排序",
@@ -1,75 +0,0 @@
1
- <template>
2
- <div class="error-page">
3
- <div class="error-content">
4
- <div class="error-code">403</div>
5
- <h1 class="error-title">无权限访问</h1>
6
- <p class="error-description">抱歉,您没有访问该页面的权限</p>
7
- <div class="error-actions">
8
- <TButton theme="primary" @click="$Method.goHome">返回首页</TButton>
9
- <TButton @click="$Method.goBack">返回上一页</TButton>
10
- </div>
11
- </div>
12
- </div>
13
- </template>
14
-
15
- <script setup>
16
- import { useRouter } from "vue-router";
17
- import { Button as TButton } from "tdesign-vue-next";
18
-
19
- definePage({
20
- meta: {
21
- title: "403",
22
- order: 101
23
- }
24
- });
25
-
26
- const router = useRouter();
27
-
28
- const $Method = {
29
- goHome() {
30
- router.push("/");
31
- },
32
- goBack() {
33
- router.back();
34
- }
35
- };
36
- </script>
37
-
38
- <style scoped lang="scss">
39
- .error-page {
40
- display: flex;
41
- flex-direction: column;
42
- align-items: center;
43
- justify-content: center;
44
- min-height: 100vh;
45
- background: var(--bg-color-page);
46
-
47
- .error-code {
48
- font-size: 120px;
49
- font-weight: 700;
50
- background: linear-gradient(135deg, var(--primary-color) 0%, #764ba2 100%);
51
- -webkit-background-clip: text;
52
- -webkit-text-fill-color: transparent;
53
- background-clip: text;
54
- margin: 0;
55
- }
56
-
57
- .error-message {
58
- font-size: 24px;
59
- color: var(--text-primary);
60
- margin: 20px 0;
61
- }
62
-
63
- .error-description {
64
- font-size: 16px;
65
- color: var(--text-secondary);
66
- margin: 8px 0 24px;
67
- }
68
-
69
- .error-actions {
70
- display: flex;
71
- gap: 12px;
72
- justify-content: center;
73
- }
74
- }
75
- </style>
@@ -1,109 +0,0 @@
1
- <template>
2
- <TDialog v-model:visible="visible" :header="actionType === 'add' ? '添加字典项' : '编辑字典项'" width="600px" @confirm="$Method.handleSubmit" @close="$Method.handleClose">
3
- <TForm ref="formRef" :data="$Data.formData" :rules="$Data.rules" label-width="100px">
4
- <TFormItem label="字典类型" name="typeCode">
5
- <TSelect v-model="$Data.formData.typeCode" placeholder="请选择字典类型" filterable>
6
- <TOption v-for="item in typeList" :key="item.code" :value="item.code" :label="item.name" />
7
- </TSelect>
8
- </TFormItem>
9
- <TFormItem label="键值" name="key">
10
- <TInput v-model="$Data.formData.key" placeholder="请输入键名(英文/数字/下划线)" />
11
- </TFormItem>
12
- <TFormItem label="标签" name="label">
13
- <TInput v-model="$Data.formData.label" placeholder="请输入标签(显示名称)" />
14
- </TFormItem>
15
- <TFormItem label="排序" name="sort">
16
- <TInputNumber v-model="$Data.formData.sort" :min="0" placeholder="请输入排序值" />
17
- </TFormItem>
18
- <TFormItem label="备注" name="remark">
19
- <TTextarea v-model="$Data.formData.remark" placeholder="请输入备注信息" :autosize="{ minRows: 3, maxRows: 6 }" />
20
- </TFormItem>
21
- </TForm>
22
- </TDialog>
23
- </template>
24
-
25
- <script setup>
26
- import { computed } from "vue";
27
-
28
- import { Dialog as TDialog, Form as TForm, FormItem as TFormItem, Input as TInput, Select as TSelect, Option as TOption, Textarea as TTextarea, InputNumber as TInputNumber, MessagePlugin } from "tdesign-vue-next";
29
- import { $Http } from "@/plugins/http";
30
-
31
- const props = defineProps({
32
- modelValue: Boolean,
33
- actionType: String,
34
- rowData: Object,
35
- typeList: Array
36
- });
37
-
38
- const emit = defineEmits(["update:modelValue", "success"]);
39
-
40
- const visible = computed({
41
- get: () => props.modelValue,
42
- set: (val) => emit("update:modelValue", val)
43
- });
44
-
45
- const formRef = $ref(null);
46
-
47
- const $Data = $ref({
48
- formData: {
49
- typeCode: "",
50
- key: "",
51
- label: "",
52
- sort: 0,
53
- remark: ""
54
- },
55
- rules: {
56
- typeCode: [{ required: true, message: "请选择字典类型" }],
57
- key: [{ required: true, message: "请输入键值" }],
58
- label: [{ required: true, message: "请输入标签" }]
59
- }
60
- });
61
-
62
- const $Method = {
63
- async handleSubmit() {
64
- try {
65
- const valid = await formRef.validate();
66
- const apiUrl = props.actionType === "add" ? "/addon/admin/dict/ins" : "/addon/admin/dict/upd";
67
- const params = {
68
- typeCode: $Data.formData.typeCode,
69
- key: $Data.formData.key,
70
- label: $Data.formData.label,
71
- sort: $Data.formData.sort,
72
- remark: $Data.formData.remark
73
- };
74
- if (props.actionType === "upd") {
75
- params.id = props.rowData.id;
76
- }
77
-
78
- const res = await $Http(apiUrl, params);
79
- if (res.code === 0) {
80
- MessagePlugin.success(props.actionType === "add" ? "添加成功" : "更新成功");
81
- visible.value = false;
82
- emit("success");
83
- } else {
84
- MessagePlugin.error(res.msg || "操作失败");
85
- }
86
- } catch (error) {
87
- MessagePlugin.error("操作失败");
88
- }
89
- },
90
- handleClose() {
91
- visible.value = false;
92
- }
93
- };
94
-
95
- // 该组件由父组件 v-if 控制挂载/卸载,因此无需 watch:创建时初始化一次即可
96
- if (props.actionType === "upd" && props.rowData) {
97
- $Data.formData.typeCode = props.rowData.typeCode || "";
98
- $Data.formData.key = props.rowData.key || "";
99
- $Data.formData.label = props.rowData.label || "";
100
- $Data.formData.sort = props.rowData.sort || 0;
101
- $Data.formData.remark = props.rowData.remark || "";
102
- } else {
103
- $Data.formData.typeCode = "";
104
- $Data.formData.key = "";
105
- $Data.formData.label = "";
106
- $Data.formData.sort = 0;
107
- $Data.formData.remark = "";
108
- }
109
- </script>