vome-core 0.0.8 → 0.0.11

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 (198) hide show
  1. package/dist/admin/api/client.d.ts +32 -0
  2. package/dist/admin/api/client.js +1 -0
  3. package/dist/admin/config/plugin-dev.d.ts +30 -0
  4. package/dist/admin/config/plugin-dev.js +1 -0
  5. package/dist/admin/crud/config.d.ts +5 -0
  6. package/dist/admin/crud/config.js +1 -0
  7. package/dist/admin/crud/confirm.d.ts +11 -0
  8. package/dist/admin/crud/confirm.js +1 -0
  9. package/dist/admin/crud/dict.d.ts +3 -0
  10. package/dist/admin/crud/dict.js +1 -0
  11. package/dist/admin/crud/index.d.ts +40 -0
  12. package/dist/admin/crud/index.js +1 -0
  13. package/dist/admin/crud/key.d.ts +22 -0
  14. package/dist/admin/crud/key.js +1 -0
  15. package/dist/admin/crud/mitt.d.ts +10 -0
  16. package/dist/admin/crud/mitt.js +1 -0
  17. package/dist/admin/crud/plugins.d.ts +48 -0
  18. package/dist/admin/crud/plugins.js +1 -0
  19. package/dist/admin/crud/registry.d.ts +5 -0
  20. package/dist/admin/crud/registry.js +26 -0
  21. package/dist/admin/crud/span.d.ts +17 -0
  22. package/dist/admin/crud/span.js +1 -0
  23. package/dist/admin/crud/style.d.ts +36 -0
  24. package/dist/admin/crud/style.js +1 -0
  25. package/dist/admin/crud/useCrud.d.ts +18 -0
  26. package/dist/admin/crud/useCrud.js +1 -0
  27. package/dist/admin/crud/validate.d.ts +14 -0
  28. package/dist/admin/crud/validate.js +1 -0
  29. package/dist/admin/directives/perm.d.ts +3 -0
  30. package/dist/admin/directives/perm.js +1 -0
  31. package/dist/admin/hooks/useBrowser.d.ts +5 -0
  32. package/dist/admin/hooks/useBrowser.js +1 -0
  33. package/dist/admin/hooks/useUpload.d.ts +8 -0
  34. package/dist/admin/hooks/useUpload.js +1 -0
  35. package/dist/admin/hooks/useVome.d.ts +8 -0
  36. package/dist/admin/hooks/useVome.js +1 -0
  37. package/dist/admin/index.d.ts +26 -0
  38. package/dist/admin/index.js +1 -0
  39. package/dist/admin/lib/browser.d.ts +3 -0
  40. package/dist/admin/lib/browser.js +1 -0
  41. package/dist/admin/lib/cn.d.ts +2 -0
  42. package/dist/admin/lib/cn.js +1 -0
  43. package/dist/admin/lib/dialog-float.d.ts +4 -0
  44. package/dist/admin/lib/dialog-float.js +1 -0
  45. package/dist/admin/lib/eps.d.ts +11 -0
  46. package/dist/admin/lib/eps.js +1 -0
  47. package/dist/admin/lib/menu.d.ts +2 -0
  48. package/dist/admin/lib/menu.js +1 -0
  49. package/dist/admin/lib/module.d.ts +21 -0
  50. package/dist/admin/lib/module.js +1 -0
  51. package/dist/admin/lib/tree.d.ts +2 -0
  52. package/dist/admin/lib/tree.js +1 -0
  53. package/dist/admin/lib/upload.d.ts +13 -0
  54. package/dist/admin/lib/upload.js +1 -0
  55. package/dist/admin/router/index.d.ts +3 -0
  56. package/dist/admin/router/index.js +1 -0
  57. package/dist/admin/router/menu-routes.d.ts +7 -0
  58. package/dist/admin/router/menu-routes.js +1 -0
  59. package/dist/admin/service/base.d.ts +27 -0
  60. package/dist/admin/service/base.js +1 -0
  61. package/dist/admin/service/index.d.ts +15 -0
  62. package/dist/admin/service/index.js +1 -0
  63. package/dist/admin/stores/app.d.ts +1 -0
  64. package/dist/admin/stores/app.js +1 -0
  65. package/dist/admin/stores/tags.d.ts +1 -0
  66. package/dist/admin/stores/tags.js +1 -0
  67. package/dist/admin/stores/user.d.ts +1 -0
  68. package/dist/admin/stores/user.js +1 -0
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.js +1 -236
  71. package/dist/server/index.d.ts +1 -1
  72. package/dist/server/index.js +1 -3261
  73. package/dist/shared/index.js +1 -0
  74. package/dist/shared/tree.d.ts +18 -0
  75. package/dist/shared/tree.js +1 -0
  76. package/package.json +13 -10
  77. package/src/shared/tree.d.ts +18 -0
  78. package/typings/admin/base/auth.d.ts +20 -0
  79. package/typings/admin/base/permission.d.ts +19 -0
  80. package/typings/admin/comm/crud.d.ts +282 -0
  81. package/typings/admin/comm/request.d.ts +11 -0
  82. package/typings/admin/comm/service.d.ts +40 -0
  83. package/typings/admin/comm/upload.d.ts +26 -0
  84. package/typings/admin/vome/browser.d.ts +10 -0
  85. package/typings/admin/vome/module.d.ts +13 -0
  86. package/src/admin/api/client.ts +0 -184
  87. package/src/admin/config/plugin-dev.ts +0 -31
  88. package/src/admin/crud/config.ts +0 -38
  89. package/src/admin/crud/confirm.ts +0 -135
  90. package/src/admin/crud/dict.ts +0 -49
  91. package/src/admin/crud/index.ts +0 -79
  92. package/src/admin/crud/key.ts +0 -47
  93. package/src/admin/crud/mitt.ts +0 -27
  94. package/src/admin/crud/plugins.ts +0 -298
  95. package/src/admin/crud/registry.ts +0 -45
  96. package/src/admin/crud/span.ts +0 -48
  97. package/src/admin/crud/style.ts +0 -112
  98. package/src/admin/crud/useCrud.ts +0 -81
  99. package/src/admin/crud/validate.ts +0 -109
  100. package/src/admin/directives/perm.ts +0 -18
  101. package/src/admin/hooks/useBrowser.ts +0 -27
  102. package/src/admin/hooks/useUpload.ts +0 -82
  103. package/src/admin/hooks/useVome.ts +0 -13
  104. package/src/admin/index.ts +0 -59
  105. package/src/admin/lib/browser.ts +0 -28
  106. package/src/admin/lib/cn.ts +0 -7
  107. package/src/admin/lib/dialog-float.ts +0 -14
  108. package/src/admin/lib/eps.ts +0 -44
  109. package/src/admin/lib/menu.ts +0 -14
  110. package/src/admin/lib/module.ts +0 -112
  111. package/src/admin/lib/tree.ts +0 -2
  112. package/src/admin/lib/upload.ts +0 -102
  113. package/src/admin/router/index.ts +0 -68
  114. package/src/admin/router/menu-routes.ts +0 -126
  115. package/src/admin/service/base.ts +0 -96
  116. package/src/admin/service/index.ts +0 -378
  117. package/src/admin/stores/app.ts +0 -30
  118. package/src/admin/stores/tags.ts +0 -73
  119. package/src/admin/stores/user.ts +0 -52
  120. /package/{src → dist}/admin/components/vm-aside.vue +0 -0
  121. /package/{src → dist}/admin/components/vm-auto-perm-dialog.vue +0 -0
  122. /package/{src → dist}/admin/components/vm-check-tree.vue +0 -0
  123. /package/{src → dist}/admin/components/vm-dept-tree.vue +0 -0
  124. /package/{src → dist}/admin/components/vm-empty.vue +0 -0
  125. /package/{src → dist}/admin/components/vm-eps-perm-picker.vue +0 -0
  126. /package/{src → dist}/admin/components/vm-group-cascader.vue +0 -0
  127. /package/{src → dist}/admin/components/vm-icon-picker.vue +0 -0
  128. /package/{src → dist}/admin/components/vm-markdown.vue +0 -0
  129. /package/{src → dist}/admin/components/vm-ri-icon.vue +0 -0
  130. /package/{src → dist}/admin/components/vm-role-picker.vue +0 -0
  131. /package/{src → dist}/admin/components/vm-view-path-picker.vue +0 -0
  132. /package/{src → dist}/admin/crud/components/vm-column-custom.vue +0 -0
  133. /package/{src → dist}/admin/crud/components/vm-context-menu.vue +0 -0
  134. /package/{src → dist}/admin/crud/components/vm-date-picker.vue +0 -0
  135. /package/{src → dist}/admin/crud/components/vm-date-range.vue +0 -0
  136. /package/{src → dist}/admin/crud/components/vm-date-text.vue +0 -0
  137. /package/{src → dist}/admin/crud/components/vm-dict-tag.vue +0 -0
  138. /package/{src → dist}/admin/crud/components/vm-file-icon.vue +0 -0
  139. /package/{src → dist}/admin/crud/components/vm-multi-select.vue +0 -0
  140. /package/{src → dist}/admin/crud/components/vm-number-range.vue +0 -0
  141. /package/{src → dist}/admin/crud/components/vm-radio.vue +0 -0
  142. /package/{src → dist}/admin/crud/components/vm-select.vue +0 -0
  143. /package/{src → dist}/admin/crud/components/vm-switch.vue +0 -0
  144. /package/{src → dist}/admin/crud/components/vm-tree-select.vue +0 -0
  145. /package/{src → dist}/admin/crud/components/vm-upload-item.vue +0 -0
  146. /package/{src → dist}/admin/crud/components/vm-upload.vue +0 -0
  147. /package/{src → dist}/admin/crud/components/vm-user-select.vue +0 -0
  148. /package/{src → dist}/admin/crud/vm-add-btn.vue +0 -0
  149. /package/{src → dist}/admin/crud/vm-adv-search.vue +0 -0
  150. /package/{src → dist}/admin/crud/vm-crud.vue +0 -0
  151. /package/{src → dist}/admin/crud/vm-dialog.vue +0 -0
  152. /package/{src → dist}/admin/crud/vm-flex1.vue +0 -0
  153. /package/{src → dist}/admin/crud/vm-form.vue +0 -0
  154. /package/{src → dist}/admin/crud/vm-multi-delete-btn.vue +0 -0
  155. /package/{src → dist}/admin/crud/vm-pagination.vue +0 -0
  156. /package/{src → dist}/admin/crud/vm-refresh-btn.vue +0 -0
  157. /package/{src → dist}/admin/crud/vm-row.vue +0 -0
  158. /package/{src → dist}/admin/crud/vm-search-key.vue +0 -0
  159. /package/{src → dist}/admin/crud/vm-search.vue +0 -0
  160. /package/{src → dist}/admin/crud/vm-table.vue +0 -0
  161. /package/{src → dist}/admin/crud/vm-toolbar.vue +0 -0
  162. /package/{src → dist}/admin/crud/vm-upsert.vue +0 -0
  163. /package/{src → dist}/admin/data/remixicon-all.json +0 -0
  164. /package/{src → dist}/admin/env.d.ts +0 -0
  165. /package/{src → dist}/admin/static/fileicon/demo.css +0 -0
  166. /package/{src → dist}/admin/static/fileicon/demo_index.html +0 -0
  167. /package/{src → dist}/admin/static/fileicon/iconfont.css +0 -0
  168. /package/{src → dist}/admin/static/fileicon/iconfont.js +0 -0
  169. /package/{src → dist}/admin/static/fileicon/iconfont.json +0 -0
  170. /package/{src → dist}/admin/static/fileicon/iconfont.ttf +0 -0
  171. /package/{src → dist}/admin/static/fileicon/iconfont.woff +0 -0
  172. /package/{src → dist}/admin/static/fileicon/iconfont.woff2 +0 -0
  173. /package/{src → dist}/admin/static/scarce//344/270/213/350/275/275/345/244/261/350/264/245.svg" +0 -0
  174. /package/{src → dist}/admin/static/scarce//346/224/257/344/273/230/346/210/220/345/212/237.svg" +0 -0
  175. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/344/274/230/346/203/240/345/210/270.svg" +0 -0
  176. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/345/206/205/345/256/271.svg" +0 -0
  177. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/345/217/221/347/245/250.svg" +0 -0
  178. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/345/233/276/347/211/207.svg" +0 -0
  179. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/345/234/260/345/235/200.svg" +0 -0
  180. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/345/272/227/351/223/272.svg" +0 -0
  181. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/216/250/351/200/201.svg" +0 -0
  182. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/220/234/347/264/242/347/273/223/346/236/234.svg" +0 -0
  183. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/224/266/350/227/217.svg" +0 -0
  184. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/225/260/346/215/256.svg" +0 -0
  185. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/235/203/351/231/220.svg" +0 -0
  186. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/266/210/346/201/257.svg" +0 -0
  187. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/347/244/274/347/211/251.svg" +0 -0
  188. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/347/247/257/345/210/206.svg" +0 -0
  189. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/347/275/221/347/273/234.svg" +0 -0
  190. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/350/247/206/351/242/221.svg" +0 -0
  191. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/350/256/242/345/215/225.svg" +0 -0
  192. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/350/257/204/350/256/272.svg" +0 -0
  193. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/351/205/215/351/200/201.svg" +0 -0
  194. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/351/223/266/350/241/214/345/215/241.svg" +0 -0
  195. /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/351/237/263/344/271/220.svg" +0 -0
  196. /package/{src → dist}/admin/static/scarce//351/241/265/351/235/242/344/270/215/345/255/230/345/234/250.svg" +0 -0
  197. /package/{src → dist}/admin/styles/base.css +0 -0
  198. /package/{src → dist}/admin/tsconfig.json +0 -0
@@ -1,126 +0,0 @@
1
- import type { Router, RouteRecordRaw } from 'vue-router'
2
- import { defineComponent, h } from 'vue'
3
- import { resolveView, viewPathToName } from '../lib/module'
4
- import MissingView from '#vome-host/pages/missing/index.vue'
5
- import MicroAppView from '#vome-host/pages/micro/index.vue'
6
-
7
- /** 已挂载的动态菜单路由名 menu-${id} */
8
- const addedNames = new Set<string>()
9
-
10
- function isMicroMenu(m: MenuTreeNode) {
11
- return Boolean(m.appKey && m.router)
12
- }
13
-
14
- function walk(nodes: MenuTreeNode[], out: MenuTreeNode[]) {
15
- for (const n of nodes) {
16
- if (Number(n.type) === 1 && n.router) out.push(n)
17
- if (n.children?.length) walk(n.children, out)
18
- }
19
- }
20
-
21
- function missingView(viewPath: string) {
22
- return defineComponent({
23
- name: 'MissingViewPage',
24
- setup() {
25
- return () => h(MissingView, { path: viewPath })
26
- },
27
- })
28
- }
29
-
30
- function routeNameOf(id: number | string) {
31
- return `menu-${id}`
32
- }
33
-
34
- function buildRoute(item: MenuTreeNode): RouteRecordRaw {
35
- const full = item.router!
36
- const childPath = full.replace(/^\//, '')
37
- let component: RouteRecordRaw['component']
38
- const componentName = viewPathToName(item.viewPath)
39
- const meta: Record<string, unknown> = {
40
- title: item.name,
41
- keepAlive: item.keepAlive !== false,
42
- viewPath: item.viewPath,
43
- perms: item.perms,
44
- componentName,
45
- }
46
-
47
- if (isMicroMenu(item)) {
48
- component = MicroAppView
49
- meta.appKey = item.appKey
50
- meta.componentName = `micro-${item.appKey}`
51
- meta.keepAlive = false
52
- } else if (item.viewPath) {
53
- const loader = resolveView(item.viewPath)
54
- component = loader || missingView(item.viewPath)
55
- } else {
56
- component = missingView(full)
57
- }
58
-
59
- return {
60
- path: childPath,
61
- name: routeNameOf(item.id),
62
- component,
63
- meta,
64
- }
65
- }
66
-
67
- /** 根据权限菜单动态挂载:viewPath 本地模块 / appKey 微应用(仅补新增) */
68
- export async function ensureMenuRoutes(router: Router, menus: MenuTreeNode[]) {
69
- const items: MenuTreeNode[] = []
70
- walk(menus, items)
71
-
72
- for (const item of items) {
73
- const name = routeNameOf(item.id)
74
- if (addedNames.has(name)) continue
75
- addedNames.add(name)
76
- router.addRoute('layout', buildRoute(item))
77
- }
78
- }
79
-
80
- /** 全量同步:删旧补新,菜单改名/改路由/显隐后侧栏与路由一致 */
81
- export async function syncMenuRoutes(router: Router, menus: MenuTreeNode[]) {
82
- const items: MenuTreeNode[] = []
83
- walk(menus, items)
84
- const nextNames = new Set(items.map((i) => routeNameOf(i.id)))
85
-
86
- for (const name of [...addedNames]) {
87
- if (!nextNames.has(name)) {
88
- if (router.hasRoute(name)) router.removeRoute(name)
89
- addedNames.delete(name)
90
- }
91
- }
92
-
93
- for (const item of items) {
94
- const name = routeNameOf(item.id)
95
- const childPath = item.router!.replace(/^\//, '')
96
- if (addedNames.has(name) && router.hasRoute(name)) {
97
- const existing = router.getRoutes().find((r) => r.name === name)
98
- if (existing && existing.path.replace(/^\//, '') !== childPath) {
99
- router.removeRoute(name)
100
- addedNames.delete(name)
101
- } else if (existing?.meta) {
102
- existing.meta.title = item.name
103
- existing.meta.keepAlive = item.keepAlive !== false
104
- existing.meta.viewPath = item.viewPath
105
- existing.meta.perms = item.perms
106
- if (item.appKey) existing.meta.appKey = item.appKey
107
- continue
108
- }
109
- }
110
- if (!addedNames.has(name)) {
111
- addedNames.add(name)
112
- router.addRoute('layout', buildRoute(item))
113
- }
114
- }
115
- }
116
-
117
- export function clearMenuRoutesFlag() {
118
- addedNames.clear()
119
- }
120
-
121
- export function removeAllMenuRoutes(router: Router) {
122
- for (const name of [...addedNames]) {
123
- if (router.hasRoute(name)) router.removeRoute(name)
124
- }
125
- addedNames.clear()
126
- }
@@ -1,96 +0,0 @@
1
- import { request } from '../api/client'
2
- /** 系统时间由后端维护;所有方法请求体都不传 */
3
- function stripTimeMeta(data: unknown): unknown {
4
- if (Array.isArray(data)) return data.map((item) => stripTimeMeta(item))
5
- if (data && typeof data === 'object') {
6
- const out = { ...(data as Record<string, unknown>) }
7
- delete out.createTime
8
- delete out.updateTime
9
- return out
10
- }
11
- return data
12
- }
13
-
14
- /** BaseService:namespace + request + 标准 CRUD */
15
- export class BaseService {
16
- namespace?: string
17
-
18
- constructor(namespace?: string) {
19
- if (namespace) this.namespace = namespace.replace(/^\//, '')
20
- }
21
-
22
- async request(options: ServiceRequestOptions = {}) {
23
- let url = options.url || ''
24
-
25
- if (url && !/^https?:\/\//.test(url)) {
26
- if (this.namespace) {
27
- const ns = this.namespace.startsWith('/')
28
- ? this.namespace
29
- : `/${this.namespace}`
30
- url = url.startsWith('/') ? `${ns}${url}` : `${ns}/${url}`
31
- }
32
- if (!url.startsWith('/')) url = `/${url}`
33
- }
34
-
35
- const method = (options.method || 'GET').toUpperCase()
36
- if (method === 'GET') {
37
- const params = options.params || {}
38
- const q = new URLSearchParams()
39
- for (const [k, v] of Object.entries(params)) {
40
- if (v == null) continue
41
- q.set(k, String(v))
42
- }
43
- const qs = q.toString()
44
- return request(qs ? `${url}?${qs}` : url)
45
- }
46
-
47
- return request(url, {
48
- method,
49
- body: JSON.stringify(stripTimeMeta(options.data ?? {})),
50
- })
51
- }
52
-
53
- page(data: Record<string, unknown> = {}) {
54
- return this.request({ url: '/page', method: 'POST', data }) as Promise<{
55
- list: Record<string, unknown>[]
56
- pagination: { page: number; size: number; total: number }
57
- }>
58
- }
59
-
60
- list(data: Record<string, unknown> = {}) {
61
- return this.request({
62
- url: '/list',
63
- method: 'POST',
64
- data,
65
- }) as Promise<Record<string, unknown>[]>
66
- }
67
-
68
- info(params: { id: number | string }) {
69
- return this.request({
70
- url: '/info',
71
- method: 'GET',
72
- params: params as Record<string, unknown>,
73
- }) as Promise<Record<string, unknown>>
74
- }
75
-
76
- add(data: Record<string, unknown> | Record<string, unknown>[]) {
77
- return this.request({ url: '/add', method: 'POST', data })
78
- }
79
-
80
- update(data: Record<string, unknown> | Record<string, unknown>[]) {
81
- return this.request({ url: '/update', method: 'POST', data })
82
- }
83
-
84
- delete(
85
- data:
86
- | { ids: Array<number | string>; force?: boolean }
87
- | Array<number | string>
88
- | Array<Record<string, unknown>>,
89
- ) {
90
- return this.request({ url: '/delete', method: 'POST', data })
91
- }
92
-
93
- restore(data: { ids: Array<number | string> }) {
94
- return this.request({ url: '/restore', method: 'POST', data })
95
- }
96
- }
@@ -1,378 +0,0 @@
1
- import { loadEps } from '../lib/eps'
2
- import { BaseService } from './base'
3
-
4
- const SIDE_ID = 'admin'
5
-
6
- /** 标准 CRUD 之外的常用接口(EPS 未就绪时也可用) */
7
- const FALLBACK_EXTRA_APIS: Record<
8
- string,
9
- Array<{ method: string; path: string; perms?: string[] }>
10
- > = {
11
- '/admin/base/department': [{ method: 'get', path: '/tree' }],
12
- '/admin/base/menu': [{ method: 'get', path: '/tree' }],
13
- '/admin/base/role': [
14
- { method: 'get', path: '/menus' },
15
- { method: 'post', path: '/setMenus' },
16
- { method: 'get', path: '/departments' },
17
- { method: 'post', path: '/setDepartments' },
18
- ],
19
- '/admin/base/user': [
20
- { method: 'get', path: '/roles' },
21
- { method: 'get', path: '/roleMap' },
22
- { method: 'post', path: '/setRoles' },
23
- { method: 'post', path: '/transferSuper' },
24
- { method: 'post', path: '/moveDepartment' },
25
- ],
26
- '/admin/base/task': [
27
- { method: 'post', path: '/start' },
28
- { method: 'post', path: '/stop' },
29
- { method: 'post', path: '/once' },
30
- { method: 'get', path: '/log' },
31
- ],
32
- '/admin/base/log': [
33
- { method: 'post', path: '/clear' },
34
- { method: 'post', path: '/setKeep' },
35
- { method: 'post', path: '/getKeep' },
36
- ],
37
- '/admin/base/dict/info': [
38
- { method: 'get', path: '/types' },
39
- { method: 'post', path: '/data' },
40
- { method: 'post', path: '/get' },
41
- { method: 'post', path: '/find' },
42
- { method: 'post', path: '/getValues' },
43
- { method: 'post', path: '/pathValue' },
44
- { method: 'post', path: '/childValue' },
45
- ],
46
- '/admin/base/module': [{ method: 'post', path: '/install' }],
47
- '/admin/base/comm': [{ method: 'post', path: '/upload' }],
48
- '/admin/user/info': [
49
- { method: 'get', path: '/roles' },
50
- { method: 'get', path: '/roleMap' },
51
- { method: 'post', path: '/setRoles' },
52
- ],
53
- }
54
-
55
- /** EPS 不可用时仍保证业务页链式可调 */
56
- const FALLBACK_PREFIXES = [
57
- '/admin/base/menu',
58
- '/admin/base/user',
59
- '/admin/base/role',
60
- '/admin/base/department',
61
- '/admin/base/tenant',
62
- '/admin/base/task',
63
- '/admin/base/log',
64
- '/admin/base/plugin',
65
- '/admin/base/dict/info',
66
- '/admin/base/dict/type',
67
- '/admin/base/module',
68
- '/admin/base/comm',
69
- '/admin/user/info',
70
- '/admin/user/role',
71
- ]
72
-
73
- function toCamel(str: string) {
74
- return str.replace(/([^-])(?:-+([^-]))/g, (_m, a, b) => a + String(b).toUpperCase())
75
- }
76
-
77
- function methodName(path: string) {
78
- return path.replace(/^\//, '').replace(/[:,\s/-]/g, '')
79
- }
80
-
81
- function isValidName(name: string) {
82
- return Boolean(name) && !['{', '}', ':'].some((c) => name.includes(c))
83
- }
84
-
85
- /** 无 EPS perms 时生成权限码 */
86
- function resolvePermCode(prefix: string, action: string) {
87
- const parts = prefix.replace(/^\//, '').split('/').filter(Boolean)
88
- const module = parts[1] || parts[0] || 'base'
89
- let resource = parts.slice(2).join(':')
90
- if (resource === module) {
91
- resource = module
92
- } else if (resource.startsWith(`${module}:`)) {
93
- resource = resource.slice(module.length + 1)
94
- }
95
- const head = `${module}-`
96
- if (resource.startsWith(head)) resource = resource.slice(head.length)
97
- resource = resource.replace(/-/g, ':')
98
- if (!resource) resource = module
99
- return `${module}:${resource}:${action}`
100
- }
101
-
102
- function getMethodKeys(leaf: Record<string, unknown>) {
103
- return Object.keys(leaf).filter(
104
- (k) => !['namespace', 'permission', '_permission', 'request', 'search'].includes(k),
105
- )
106
- }
107
-
108
- function bindCrud(leaf: ServiceLeaf, base: BaseService) {
109
- const proto = BaseService.prototype as unknown as Record<string, unknown>
110
- for (const name of [
111
- 'request',
112
- 'page',
113
- 'list',
114
- 'info',
115
- 'add',
116
- 'update',
117
- 'delete',
118
- 'restore',
119
- ]) {
120
- const fn = proto[name]
121
- if (typeof fn === 'function') {
122
- ;(leaf as Record<string, unknown>)[name] = (
123
- fn as (...a: unknown[]) => unknown
124
- ).bind(base)
125
- }
126
- }
127
- }
128
-
129
- function bindApis(leaf: ServiceLeaf, base: BaseService, apis: EpsApiItem[]) {
130
- leaf.permission ||= {}
131
- for (const api of apis) {
132
- const name = methodName(api.path)
133
- if (!isValidName(name) || /[-:]/g.test(name)) continue
134
- const method = (api.method || 'get').toLowerCase()
135
- // 已有同名方法则保留(避免 fallback 覆盖 EPS 绑定)
136
- if (typeof (leaf as Record<string, unknown>)[name] === 'function') {
137
- if (!leaf.permission[name]) {
138
- leaf.permission[name] =
139
- api.perms?.[0] || resolvePermCode(`/${leaf.namespace}`, name)
140
- }
141
- continue
142
- }
143
- ;(leaf as Record<string, unknown>)[name] = function (
144
- this: BaseService,
145
- data?: unknown,
146
- ) {
147
- return this.request({
148
- url: api.path.startsWith('/') ? api.path : `/${api.path}`,
149
- method,
150
- [method === 'post' ? 'data' : 'params']: data,
151
- })
152
- }.bind(base)
153
- leaf.permission[name] =
154
- api.perms?.[0] || resolvePermCode(`/${leaf.namespace}`, name)
155
- }
156
- }
157
-
158
- function createLeaf(namespace: string, apis: EpsApiItem[] = []): ServiceLeaf {
159
- const base = new BaseService(namespace)
160
- const leaf = base as unknown as ServiceLeaf
161
- leaf.namespace = namespace.replace(/^\//, '')
162
- leaf.permission = {}
163
- leaf._permission = {}
164
-
165
- bindCrud(leaf, base)
166
- bindApis(leaf, base, apis)
167
-
168
- for (const name of getMethodKeys(leaf as unknown as Record<string, unknown>)) {
169
- if (!leaf.permission[name]) {
170
- leaf.permission[name] = resolvePermCode(`/${leaf.namespace}`, name)
171
- }
172
- }
173
-
174
- return leaf
175
- }
176
-
177
- /** 合并到已有叶子:补方法,不抹掉已有自定义 API */
178
- function mergeLeaf(existing: ServiceLeaf, namespace: string, apis: EpsApiItem[]) {
179
- const base = new BaseService(namespace)
180
- // 确保 CRUD 在实例上(兼容旧 fallback)
181
- bindCrud(existing, base)
182
- bindApis(existing, base, apis)
183
- existing.namespace = namespace.replace(/^\//, '')
184
- existing.permission ||= {}
185
- existing._permission ||= {}
186
- for (const name of getMethodKeys(existing as unknown as Record<string, unknown>)) {
187
- if (!existing.permission[name]) {
188
- existing.permission[name] = resolvePermCode(`/${existing.namespace}`, name)
189
- }
190
- }
191
- return existing
192
- }
193
-
194
- function attachLeaf(
195
- tree: ServiceTree | Eps.Service,
196
- prefix: string,
197
- apis: EpsApiItem[] = [],
198
- ) {
199
- const raw = prefix.replace(/^\//, '')
200
- const arr = raw
201
- .replace(new RegExp(`^${SIDE_ID}/?`), '')
202
- .split('/')
203
- .filter(Boolean)
204
- .map(toCamel)
205
-
206
- if (!arr.length) return undefined
207
-
208
- let node: Record<string, unknown> = tree as unknown as Record<string, unknown>
209
- for (let i = 0; i < arr.length; i++) {
210
- const key = arr[i]!
211
- const isLast = i === arr.length - 1
212
- if (!isLast) {
213
- if (!node[key] || typeof node[key] !== 'object') node[key] = {}
214
- node = node[key] as Record<string, unknown>
215
- continue
216
- }
217
- const existing = node[key] as ServiceLeaf | undefined
218
- if (existing?.namespace) {
219
- return mergeLeaf(existing, raw, apis)
220
- }
221
- const leaf = createLeaf(raw, apis)
222
- node[key] = leaf
223
- return leaf
224
- }
225
- return undefined
226
- }
227
-
228
- function buildFromEps(map: EpsModuleMap) {
229
- const list = Object.values(map).flat() as EpsEntity[]
230
- for (const e of list) {
231
- if (!e.prefix) continue
232
- const leaf = attachLeaf(service, e.prefix, e.api || [])
233
- if (leaf) {
234
- const op = (e as { pageQueryOp?: Record<string, unknown> }).pageQueryOp
235
- if (op) {
236
- ;(leaf as ServiceLeaf & { search?: unknown }).search = {
237
- fieldEq: op.fieldEq,
238
- fieldLike: op.fieldLike,
239
- fieldArray: op.fieldArray,
240
- fieldRange: op.fieldRange,
241
- keyWordLikeFields: op.keyWordLikeFields,
242
- }
243
- }
244
- }
245
- }
246
- }
247
-
248
- function buildFallback() {
249
- for (const prefix of FALLBACK_PREFIXES) {
250
- const extra = FALLBACK_EXTRA_APIS[prefix] || []
251
- const apis = extra.map(
252
- (a) =>
253
- ({
254
- method: a.method,
255
- path: a.path,
256
- perms: a.perms,
257
- }) as EpsApiItem,
258
- )
259
- attachLeaf(service, prefix, apis)
260
- }
261
- }
262
-
263
- type ServiceRoot = Eps.Service & { request: BaseService['request'] }
264
-
265
- /**
266
- * 全局单例:npm 包经多路径解析时避免出现两份 service(一份有 tree、一份没有)。
267
- */
268
- const g = globalThis as typeof globalThis & { __vome_admin_service__?: ServiceRoot }
269
-
270
- function createServiceRoot(): ServiceRoot {
271
- const root = new BaseService()
272
- return {
273
- request: root.request.bind(root),
274
- } as ServiceRoot
275
- }
276
-
277
- /** 全局链式 service(service.base.user.page()) */
278
- export const service: ServiceRoot =
279
- g.__vome_admin_service__ ?? (g.__vome_admin_service__ = createServiceRoot())
280
-
281
- // 同步兜底(含 tree / menus 等),页面 import 时即可调用
282
- buildFallback()
283
-
284
- /** 从 EPS 构建/刷新 service 树;失败时用兜底 prefix + 自定义 API */
285
- export async function createEps(force = false) {
286
- try {
287
- const map = (await loadEps(force)) || {}
288
- if (Object.keys(map).length) buildFromEps(map)
289
- } catch (e) {
290
- console.warn('[vome-eps] load failed', e)
291
- }
292
- buildFallback()
293
- return service
294
- }
295
-
296
- if (import.meta.hot) {
297
- import.meta.hot.on('eps-update', () => {
298
- void createEps(true).then(() => {
299
- if (import.meta.env.DEV) console.log('[vome-eps] service hot updated')
300
- })
301
- })
302
- }
303
-
304
- /** 登录后写入 _permission,供 CRUD / 按钮显隐 */
305
- export function setServicePerms(perms: string[], isSuper = false) {
306
- const list = perms || []
307
-
308
- function deep(d: unknown) {
309
- if (!d || typeof d !== 'object') return
310
- const obj = d as ServiceLeaf & Record<string, unknown>
311
- if (obj.permission && obj.namespace) {
312
- obj._permission = {}
313
- for (const key of Object.keys(obj.permission)) {
314
- if (isSuper) {
315
- obj._permission[key] = true
316
- continue
317
- }
318
- const code = obj.permission[key]
319
- obj._permission[key] =
320
- list.includes(code) ||
321
- list.some((p) =>
322
- p
323
- .replace(/:/g, '/')
324
- .includes(`${obj.namespace.replace(/^admin\//, '')}/${key}`),
325
- )
326
- }
327
- return
328
- }
329
- for (const k of Object.keys(obj)) {
330
- if (k === 'request') continue
331
- deep(obj[k])
332
- }
333
- }
334
-
335
- deep(service)
336
- }
337
-
338
- /** 解析 service.base.user 或 'base.user' */
339
- export function resolveService(path: string): ServiceLeaf | undefined {
340
- const parts = path.replace(/^\//, '').split('.').filter(Boolean)
341
- let cur: unknown = service
342
- for (const p of parts) {
343
- if (!cur || typeof cur !== 'object') return undefined
344
- cur = (cur as Record<string, unknown>)[p]
345
- }
346
- if (cur && typeof cur === 'object' && 'namespace' in (cur as object)) {
347
- return cur as ServiceLeaf
348
- }
349
- return undefined
350
- }
351
-
352
- /** 按 prefix 取或创建 service 叶子 */
353
- export function serviceOf(prefix: string): ServiceLeaf {
354
- const raw = prefix.replace(/\/$/, '')
355
- const path = raw
356
- .replace(/^\//, '')
357
- .replace(new RegExp(`^${SIDE_ID}/?`), '')
358
- .split('/')
359
- .filter(Boolean)
360
- .map(toCamel)
361
- .join('.')
362
- const hit = resolveService(path)
363
- if (hit) return hit
364
- const extra = FALLBACK_EXTRA_APIS[raw.startsWith('/') ? raw : `/${raw}`] || []
365
- return attachLeaf(
366
- service,
367
- raw,
368
- extra.map((a) => ({ method: a.method, path: a.path, perms: a.perms }) as EpsApiItem),
369
- ) as ServiceLeaf
370
- }
371
-
372
- /** @deprecated 请用 service.base.xxx */
373
- export function createEpsService(prefix: string) {
374
- return serviceOf(prefix)
375
- }
376
-
377
- export { BaseService }
378
- export type { ServiceLeaf, ServiceTree } from '../../../typings/admin/comm/service'
@@ -1,30 +0,0 @@
1
- import { defineStore } from 'pinia'
2
- import { nextTick } from 'vue'
3
-
4
- const FOLD_KEY = 'vome_admin_sidebar_fold'
5
-
6
- export const useAppStore = defineStore('app', {
7
- state: () => ({
8
- /** 桌面端手动折叠侧栏 */
9
- sidebarFold: localStorage.getItem(FOLD_KEY) === '1',
10
- /** 移动端抽屉开合 */
11
- mobileOpen: false,
12
- /** 为 false 时卸掉 RouterView,用于「刷新当前页」 */
13
- viewAlive: true,
14
- }),
15
- actions: {
16
- toggleSidebarFold() {
17
- this.sidebarFold = !this.sidebarFold
18
- localStorage.setItem(FOLD_KEY, this.sidebarFold ? '1' : '0')
19
- },
20
- setMobileOpen(open: boolean) {
21
- this.mobileOpen = open
22
- },
23
- /** 重挂载当前视图(非浏览器整页刷新) */
24
- async reloadView() {
25
- this.viewAlive = false
26
- await nextTick()
27
- this.viewAlive = true
28
- },
29
- },
30
- })
@@ -1,73 +0,0 @@
1
- import { defineStore } from 'pinia'
2
- import type { RouteLocationNormalized } from 'vue-router'
3
- export const useTagsStore = defineStore('tags', {
4
- state: () => ({
5
- list: [] as TagItem[],
6
- /** KeepAlive :include,值为页面组件 name(如 base-role) */
7
- caches: [] as string[],
8
- }),
9
- actions: {
10
- add(route: RouteLocationNormalized) {
11
- if (route.meta.public || route.path === '/login') return
12
- const title = String(route.meta.title || route.name || route.path)
13
- const componentName =
14
- typeof route.meta.componentName === 'string'
15
- ? route.meta.componentName
16
- : undefined
17
- const keepAlive = route.meta.keepAlive !== false
18
-
19
- if (componentName && keepAlive) {
20
- this.addCache(componentName)
21
- }
22
-
23
- const exists = this.list.find((t) => t.path === route.path)
24
- if (exists) {
25
- exists.fullPath = route.fullPath
26
- exists.title = title
27
- exists.componentName = componentName
28
- exists.keepAlive = keepAlive
29
- return
30
- }
31
- this.list.push({
32
- path: route.path,
33
- fullPath: route.fullPath,
34
- title,
35
- name: route.name,
36
- componentName,
37
- keepAlive,
38
- })
39
- },
40
- addCache(name: string) {
41
- if (!name || this.caches.includes(name)) return
42
- this.caches.push(name)
43
- },
44
- removeCache(name?: string) {
45
- if (!name) return
46
- this.caches = this.caches.filter((c) => c !== name)
47
- },
48
- remove(path: string) {
49
- const i = this.list.findIndex((t) => t.path === path)
50
- if (i < 0) return
51
- const [tag] = this.list.splice(i, 1)
52
- // 无其它 tab 引用同一组件名时才踢出缓存
53
- const still =
54
- tag?.componentName &&
55
- this.list.some((t) => t.componentName === tag.componentName)
56
- if (tag?.componentName && !still) {
57
- this.removeCache(tag.componentName)
58
- }
59
- },
60
- closeOthers(path: string) {
61
- const keep = this.list.filter((t) => t.path === path || t.path === '/')
62
- this.list = keep
63
- this.caches = keep
64
- .filter((t) => t.keepAlive && t.componentName)
65
- .map((t) => t.componentName!)
66
- .filter((n, i, arr) => arr.indexOf(n) === i)
67
- },
68
- clear() {
69
- this.list = this.list.filter((t) => t.path === '/')
70
- this.caches = []
71
- },
72
- },
73
- })