vome-core 0.0.9 → 0.0.12
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/dist/admin/api/client.d.ts +32 -0
- package/dist/admin/api/client.js +1 -0
- package/dist/admin/config/plugin-dev.d.ts +30 -0
- package/dist/admin/config/plugin-dev.js +1 -0
- package/dist/admin/crud/config.d.ts +5 -0
- package/dist/admin/crud/config.js +1 -0
- package/dist/admin/crud/confirm.d.ts +11 -0
- package/dist/admin/crud/confirm.js +1 -0
- package/dist/admin/crud/dict.d.ts +3 -0
- package/dist/admin/crud/dict.js +1 -0
- package/dist/admin/crud/index.d.ts +40 -0
- package/dist/admin/crud/index.js +1 -0
- package/dist/admin/crud/key.d.ts +22 -0
- package/dist/admin/crud/key.js +1 -0
- package/dist/admin/crud/mitt.d.ts +10 -0
- package/dist/admin/crud/mitt.js +1 -0
- package/dist/admin/crud/plugins.d.ts +48 -0
- package/dist/admin/crud/plugins.js +1 -0
- package/dist/admin/crud/registry.d.ts +5 -0
- package/dist/admin/crud/registry.js +26 -0
- package/dist/admin/crud/span.d.ts +17 -0
- package/dist/admin/crud/span.js +1 -0
- package/dist/admin/crud/style.d.ts +36 -0
- package/dist/admin/crud/style.js +1 -0
- package/dist/admin/crud/useCrud.d.ts +18 -0
- package/dist/admin/crud/useCrud.js +1 -0
- package/dist/admin/crud/validate.d.ts +14 -0
- package/dist/admin/crud/validate.js +1 -0
- package/dist/admin/directives/perm.d.ts +3 -0
- package/dist/admin/directives/perm.js +1 -0
- package/dist/admin/hooks/useBrowser.d.ts +5 -0
- package/dist/admin/hooks/useBrowser.js +1 -0
- package/dist/admin/hooks/useUpload.d.ts +8 -0
- package/dist/admin/hooks/useUpload.js +1 -0
- package/dist/admin/hooks/useVome.d.ts +8 -0
- package/dist/admin/hooks/useVome.js +1 -0
- package/dist/admin/index.d.ts +26 -0
- package/dist/admin/index.js +1 -0
- package/dist/admin/lib/browser.d.ts +3 -0
- package/dist/admin/lib/browser.js +1 -0
- package/dist/admin/lib/cn.d.ts +2 -0
- package/dist/admin/lib/cn.js +1 -0
- package/dist/admin/lib/dialog-float.d.ts +4 -0
- package/dist/admin/lib/dialog-float.js +1 -0
- package/dist/admin/lib/eps.d.ts +11 -0
- package/dist/admin/lib/eps.js +1 -0
- package/dist/admin/lib/menu.d.ts +2 -0
- package/dist/admin/lib/menu.js +1 -0
- package/dist/admin/lib/module.d.ts +21 -0
- package/dist/admin/lib/module.js +1 -0
- package/dist/admin/lib/tree.d.ts +2 -0
- package/dist/admin/lib/tree.js +1 -0
- package/dist/admin/lib/upload.d.ts +13 -0
- package/dist/admin/lib/upload.js +1 -0
- package/dist/admin/router/index.d.ts +3 -0
- package/dist/admin/router/index.js +1 -0
- package/dist/admin/router/menu-routes.d.ts +7 -0
- package/dist/admin/router/menu-routes.js +1 -0
- package/dist/admin/service/base.d.ts +27 -0
- package/dist/admin/service/base.js +1 -0
- package/dist/admin/service/index.d.ts +15 -0
- package/dist/admin/service/index.js +1 -0
- package/dist/admin/stores/app.d.ts +1 -0
- package/dist/admin/stores/app.js +1 -0
- package/dist/admin/stores/tags.d.ts +1 -0
- package/dist/admin/stores/tags.js +1 -0
- package/dist/admin/stores/user.d.ts +1 -0
- package/dist/admin/stores/user.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -236
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -3261
- package/dist/shared/index.js +1 -0
- package/dist/shared/tree.d.ts +18 -0
- package/dist/shared/tree.js +1 -0
- package/package.json +12 -10
- package/src/shared/tree.d.ts +18 -0
- package/typings/admin/base/auth.d.ts +20 -0
- package/typings/admin/base/permission.d.ts +19 -0
- package/typings/admin/comm/crud.d.ts +282 -0
- package/typings/admin/comm/request.d.ts +11 -0
- package/typings/admin/comm/service.d.ts +40 -0
- package/typings/admin/comm/upload.d.ts +26 -0
- package/typings/admin/vome/browser.d.ts +10 -0
- package/typings/admin/vome/module.d.ts +13 -0
- package/src/admin/api/client.ts +0 -184
- package/src/admin/config/plugin-dev.ts +0 -31
- package/src/admin/crud/config.ts +0 -38
- package/src/admin/crud/confirm.ts +0 -135
- package/src/admin/crud/dict.ts +0 -49
- package/src/admin/crud/index.ts +0 -79
- package/src/admin/crud/key.ts +0 -47
- package/src/admin/crud/mitt.ts +0 -27
- package/src/admin/crud/plugins.ts +0 -298
- package/src/admin/crud/registry.ts +0 -45
- package/src/admin/crud/span.ts +0 -48
- package/src/admin/crud/style.ts +0 -112
- package/src/admin/crud/useCrud.ts +0 -81
- package/src/admin/crud/validate.ts +0 -109
- package/src/admin/directives/perm.ts +0 -18
- package/src/admin/hooks/useBrowser.ts +0 -27
- package/src/admin/hooks/useUpload.ts +0 -82
- package/src/admin/hooks/useVome.ts +0 -13
- package/src/admin/index.ts +0 -59
- package/src/admin/lib/browser.ts +0 -28
- package/src/admin/lib/cn.ts +0 -7
- package/src/admin/lib/dialog-float.ts +0 -14
- package/src/admin/lib/eps.ts +0 -44
- package/src/admin/lib/menu.ts +0 -14
- package/src/admin/lib/module.ts +0 -112
- package/src/admin/lib/tree.ts +0 -2
- package/src/admin/lib/upload.ts +0 -102
- package/src/admin/router/index.ts +0 -68
- package/src/admin/router/menu-routes.ts +0 -126
- package/src/admin/service/base.ts +0 -96
- package/src/admin/service/index.ts +0 -413
- package/src/admin/stores/app.ts +0 -30
- package/src/admin/stores/tags.ts +0 -73
- package/src/admin/stores/user.ts +0 -52
- /package/{src → dist}/admin/components/vm-aside.vue +0 -0
- /package/{src → dist}/admin/components/vm-auto-perm-dialog.vue +0 -0
- /package/{src → dist}/admin/components/vm-check-tree.vue +0 -0
- /package/{src → dist}/admin/components/vm-dept-tree.vue +0 -0
- /package/{src → dist}/admin/components/vm-empty.vue +0 -0
- /package/{src → dist}/admin/components/vm-eps-perm-picker.vue +0 -0
- /package/{src → dist}/admin/components/vm-group-cascader.vue +0 -0
- /package/{src → dist}/admin/components/vm-icon-picker.vue +0 -0
- /package/{src → dist}/admin/components/vm-markdown.vue +0 -0
- /package/{src → dist}/admin/components/vm-ri-icon.vue +0 -0
- /package/{src → dist}/admin/components/vm-role-picker.vue +0 -0
- /package/{src → dist}/admin/components/vm-view-path-picker.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-column-custom.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-context-menu.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-date-picker.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-date-range.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-date-text.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-dict-tag.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-file-icon.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-multi-select.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-number-range.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-radio.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-select.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-switch.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-tree-select.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-upload-item.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-upload.vue +0 -0
- /package/{src → dist}/admin/crud/components/vm-user-select.vue +0 -0
- /package/{src → dist}/admin/crud/vm-add-btn.vue +0 -0
- /package/{src → dist}/admin/crud/vm-adv-search.vue +0 -0
- /package/{src → dist}/admin/crud/vm-crud.vue +0 -0
- /package/{src → dist}/admin/crud/vm-dialog.vue +0 -0
- /package/{src → dist}/admin/crud/vm-flex1.vue +0 -0
- /package/{src → dist}/admin/crud/vm-form.vue +0 -0
- /package/{src → dist}/admin/crud/vm-multi-delete-btn.vue +0 -0
- /package/{src → dist}/admin/crud/vm-pagination.vue +0 -0
- /package/{src → dist}/admin/crud/vm-refresh-btn.vue +0 -0
- /package/{src → dist}/admin/crud/vm-row.vue +0 -0
- /package/{src → dist}/admin/crud/vm-search-key.vue +0 -0
- /package/{src → dist}/admin/crud/vm-search.vue +0 -0
- /package/{src → dist}/admin/crud/vm-table.vue +0 -0
- /package/{src → dist}/admin/crud/vm-toolbar.vue +0 -0
- /package/{src → dist}/admin/crud/vm-upsert.vue +0 -0
- /package/{src → dist}/admin/data/remixicon-all.json +0 -0
- /package/{src → dist}/admin/env.d.ts +0 -0
- /package/{src → dist}/admin/static/fileicon/demo.css +0 -0
- /package/{src → dist}/admin/static/fileicon/demo_index.html +0 -0
- /package/{src → dist}/admin/static/fileicon/iconfont.css +0 -0
- /package/{src → dist}/admin/static/fileicon/iconfont.js +0 -0
- /package/{src → dist}/admin/static/fileicon/iconfont.json +0 -0
- /package/{src → dist}/admin/static/fileicon/iconfont.ttf +0 -0
- /package/{src → dist}/admin/static/fileicon/iconfont.woff +0 -0
- /package/{src → dist}/admin/static/fileicon/iconfont.woff2 +0 -0
- /package/{src → dist}/admin/static/scarce//344/270/213/350/275/275/345/244/261/350/264/245.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/224/257/344/273/230/346/210/220/345/212/237.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/344/274/230/346/203/240/345/210/270.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/345/206/205/345/256/271.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/345/217/221/347/245/250.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/345/233/276/347/211/207.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/345/234/260/345/235/200.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/345/272/227/351/223/272.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/216/250/351/200/201.svg" +0 -0
- /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
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/224/266/350/227/217.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/225/260/346/215/256.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/235/203/351/231/220.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/346/266/210/346/201/257.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/347/244/274/347/211/251.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/347/247/257/345/210/206.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/347/275/221/347/273/234.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/350/247/206/351/242/221.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/350/256/242/345/215/225.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/350/257/204/350/256/272.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/351/205/215/351/200/201.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/351/223/266/350/241/214/345/215/241.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//346/232/202/346/227/240/351/237/263/344/271/220.svg" +0 -0
- /package/{src → dist}/admin/static/scarce//351/241/265/351/235/242/344/270/215/345/255/230/345/234/250.svg" +0 -0
- /package/{src → dist}/admin/styles/base.css +0 -0
- /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,413 +0,0 @@
|
|
|
1
|
-
import { loadEps } from '../lib/eps'
|
|
2
|
-
import { BaseService } from './base'
|
|
3
|
-
|
|
4
|
-
const SIDE_ID = 'admin'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* 每次发版递增。globalThis 单例若跨 HMR/旧包残留,靠此戳强制换新根对象并重建。
|
|
8
|
-
* 根因:旧 singleton 只有 CRUD、无 tree/roleMap,且 plugin-info 错名导致 base.plugin 缺失。
|
|
9
|
-
*/
|
|
10
|
-
const SERVICE_BUILD = 9
|
|
11
|
-
|
|
12
|
-
/** 标准 CRUD 之外的常用接口(不依赖 EPS 是否已返回) */
|
|
13
|
-
const FALLBACK_EXTRA_APIS: Record<
|
|
14
|
-
string,
|
|
15
|
-
Array<{ method: string; path: string; perms?: string[] }>
|
|
16
|
-
> = {
|
|
17
|
-
'/admin/base/department': [{ method: 'get', path: '/tree' }],
|
|
18
|
-
'/admin/base/menu': [{ method: 'get', path: '/tree' }],
|
|
19
|
-
'/admin/base/role': [
|
|
20
|
-
{ method: 'get', path: '/menus' },
|
|
21
|
-
{ method: 'post', path: '/setMenus' },
|
|
22
|
-
{ method: 'get', path: '/departments' },
|
|
23
|
-
{ method: 'post', path: '/setDepartments' },
|
|
24
|
-
],
|
|
25
|
-
'/admin/base/user': [
|
|
26
|
-
{ method: 'get', path: '/roles' },
|
|
27
|
-
{ method: 'get', path: '/roleMap' },
|
|
28
|
-
{ method: 'post', path: '/setRoles' },
|
|
29
|
-
{ method: 'post', path: '/transferSuper' },
|
|
30
|
-
{ method: 'post', path: '/moveDepartment' },
|
|
31
|
-
],
|
|
32
|
-
'/admin/base/task': [
|
|
33
|
-
{ method: 'post', path: '/start' },
|
|
34
|
-
{ method: 'post', path: '/stop' },
|
|
35
|
-
{ method: 'post', path: '/once' },
|
|
36
|
-
{ method: 'get', path: '/log' },
|
|
37
|
-
],
|
|
38
|
-
'/admin/base/log': [
|
|
39
|
-
{ method: 'post', path: '/clear' },
|
|
40
|
-
{ method: 'post', path: '/setKeep' },
|
|
41
|
-
{ method: 'post', path: '/getKeep' },
|
|
42
|
-
],
|
|
43
|
-
'/admin/base/dict/info': [
|
|
44
|
-
{ method: 'get', path: '/types' },
|
|
45
|
-
{ method: 'post', path: '/data' },
|
|
46
|
-
{ method: 'post', path: '/get' },
|
|
47
|
-
{ method: 'post', path: '/find' },
|
|
48
|
-
{ method: 'post', path: '/getValues' },
|
|
49
|
-
{ method: 'post', path: '/pathValue' },
|
|
50
|
-
{ method: 'post', path: '/childValue' },
|
|
51
|
-
],
|
|
52
|
-
'/admin/base/module': [{ method: 'post', path: '/install' }],
|
|
53
|
-
'/admin/base/comm': [{ method: 'post', path: '/upload' }],
|
|
54
|
-
'/admin/user/info': [
|
|
55
|
-
{ method: 'get', path: '/roles' },
|
|
56
|
-
{ method: 'get', path: '/roleMap' },
|
|
57
|
-
{ method: 'post', path: '/setRoles' },
|
|
58
|
-
],
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const FALLBACK_PREFIXES = [
|
|
62
|
-
'/admin/base/menu',
|
|
63
|
-
'/admin/base/user',
|
|
64
|
-
'/admin/base/role',
|
|
65
|
-
'/admin/base/department',
|
|
66
|
-
'/admin/base/tenant',
|
|
67
|
-
'/admin/base/task',
|
|
68
|
-
'/admin/base/log',
|
|
69
|
-
'/admin/base/plugin',
|
|
70
|
-
'/admin/base/dict/info',
|
|
71
|
-
'/admin/base/dict/type',
|
|
72
|
-
'/admin/base/module',
|
|
73
|
-
'/admin/base/comm',
|
|
74
|
-
'/admin/user/info',
|
|
75
|
-
'/admin/user/role',
|
|
76
|
-
]
|
|
77
|
-
|
|
78
|
-
function toCamel(str: string) {
|
|
79
|
-
return str.replace(/([^-])(?:-+([^-]))/g, (_m, a, b) => a + String(b).toUpperCase())
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function methodName(path: string) {
|
|
83
|
-
return path.replace(/^\//, '').replace(/[:,\s/-]/g, '')
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function isValidName(name: string) {
|
|
87
|
-
return Boolean(name) && !['{', '}', ':'].some((c) => name.includes(c))
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function resolvePermCode(prefix: string, action: string) {
|
|
91
|
-
const parts = prefix.replace(/^\//, '').split('/').filter(Boolean)
|
|
92
|
-
const module = parts[1] || parts[0] || 'base'
|
|
93
|
-
let resource = parts.slice(2).join(':')
|
|
94
|
-
if (resource === module) {
|
|
95
|
-
resource = module
|
|
96
|
-
} else if (resource.startsWith(`${module}:`)) {
|
|
97
|
-
resource = resource.slice(module.length + 1)
|
|
98
|
-
}
|
|
99
|
-
const head = `${module}-`
|
|
100
|
-
if (resource.startsWith(head)) resource = resource.slice(head.length)
|
|
101
|
-
resource = resource.replace(/-/g, ':')
|
|
102
|
-
if (!resource) resource = module
|
|
103
|
-
return `${module}:${resource}:${action}`
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function prefixToParts(prefix: string) {
|
|
107
|
-
const raw = prefix.replace(/^\//, '')
|
|
108
|
-
return raw
|
|
109
|
-
.replace(new RegExp(`^${SIDE_ID}/?`), '')
|
|
110
|
-
.split('/')
|
|
111
|
-
.filter(Boolean)
|
|
112
|
-
.map(toCamel)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function bindCrud(leaf: ServiceLeaf, base: BaseService) {
|
|
116
|
-
const proto = BaseService.prototype as unknown as Record<string, unknown>
|
|
117
|
-
for (const name of [
|
|
118
|
-
'request',
|
|
119
|
-
'page',
|
|
120
|
-
'list',
|
|
121
|
-
'info',
|
|
122
|
-
'add',
|
|
123
|
-
'update',
|
|
124
|
-
'delete',
|
|
125
|
-
'restore',
|
|
126
|
-
]) {
|
|
127
|
-
const fn = proto[name]
|
|
128
|
-
if (typeof fn === 'function') {
|
|
129
|
-
;(leaf as Record<string, unknown>)[name] = (
|
|
130
|
-
fn as (...a: unknown[]) => unknown
|
|
131
|
-
).bind(base)
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function bindApis(leaf: ServiceLeaf, base: BaseService, apis: EpsApiItem[]) {
|
|
137
|
-
leaf.permission ||= {}
|
|
138
|
-
for (const api of apis) {
|
|
139
|
-
const name = methodName(api.path)
|
|
140
|
-
if (!isValidName(name) || /[-:]/g.test(name)) continue
|
|
141
|
-
const method = (api.method || 'get').toLowerCase()
|
|
142
|
-
;(leaf as Record<string, unknown>)[name] = function (
|
|
143
|
-
this: BaseService,
|
|
144
|
-
data?: unknown,
|
|
145
|
-
) {
|
|
146
|
-
return this.request({
|
|
147
|
-
url: api.path.startsWith('/') ? api.path : `/${api.path}`,
|
|
148
|
-
method,
|
|
149
|
-
[method === 'post' ? 'data' : 'params']: data,
|
|
150
|
-
})
|
|
151
|
-
}.bind(base)
|
|
152
|
-
leaf.permission[name] =
|
|
153
|
-
api.perms?.[0] || resolvePermCode(`/${leaf.namespace}`, name)
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/** 原地重挂方法,保持叶子对象引用不变(避免页面 const log = service.base.log 失效) */
|
|
158
|
-
function remountLeaf(leaf: ServiceLeaf, namespace: string, apis: EpsApiItem[]) {
|
|
159
|
-
const ns = namespace.replace(/^\//, '')
|
|
160
|
-
const base = new BaseService(ns)
|
|
161
|
-
leaf.namespace = ns
|
|
162
|
-
leaf.permission = {}
|
|
163
|
-
leaf._permission = leaf._permission || {}
|
|
164
|
-
|
|
165
|
-
// 清掉旧方法再绑,避免残留错误实现
|
|
166
|
-
for (const key of Object.keys(leaf as object)) {
|
|
167
|
-
if (
|
|
168
|
-
key === 'namespace' ||
|
|
169
|
-
key === 'permission' ||
|
|
170
|
-
key === '_permission' ||
|
|
171
|
-
key === 'search'
|
|
172
|
-
) {
|
|
173
|
-
continue
|
|
174
|
-
}
|
|
175
|
-
delete (leaf as Record<string, unknown>)[key]
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
bindCrud(leaf, base)
|
|
179
|
-
bindApis(leaf, base, apis)
|
|
180
|
-
|
|
181
|
-
for (const name of Object.keys(leaf.permission)) {
|
|
182
|
-
if (leaf._permission[name] == null) leaf._permission[name] = false
|
|
183
|
-
}
|
|
184
|
-
return leaf
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function createLeaf(namespace: string, apis: EpsApiItem[] = []): ServiceLeaf {
|
|
188
|
-
const ns = namespace.replace(/^\//, '')
|
|
189
|
-
const base = new BaseService(ns)
|
|
190
|
-
const leaf = base as unknown as ServiceLeaf
|
|
191
|
-
leaf.namespace = ns
|
|
192
|
-
leaf.permission = {}
|
|
193
|
-
leaf._permission = {}
|
|
194
|
-
bindCrud(leaf, base)
|
|
195
|
-
bindApis(leaf, base, apis)
|
|
196
|
-
return leaf
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function attachLeaf(
|
|
200
|
-
tree: ServiceTree | Eps.Service,
|
|
201
|
-
prefix: string,
|
|
202
|
-
apis: EpsApiItem[] = [],
|
|
203
|
-
) {
|
|
204
|
-
const raw = prefix.replace(/^\//, '')
|
|
205
|
-
const arr = prefixToParts(prefix)
|
|
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
|
-
const cur = node[key] as ServiceLeaf | Record<string, unknown> | undefined
|
|
214
|
-
// 中间节点若被误建成叶子,换成容器(否则 dict/info 挂不上)
|
|
215
|
-
if (!cur || typeof cur !== 'object' || 'namespace' in cur) {
|
|
216
|
-
node[key] = {}
|
|
217
|
-
}
|
|
218
|
-
node = node[key] as Record<string, unknown>
|
|
219
|
-
continue
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const existing = node[key] as ServiceLeaf | undefined
|
|
223
|
-
if (existing && typeof existing === 'object' && existing.namespace) {
|
|
224
|
-
return remountLeaf(existing, raw, apis)
|
|
225
|
-
}
|
|
226
|
-
const leaf = createLeaf(raw, apis)
|
|
227
|
-
node[key] = leaf
|
|
228
|
-
return leaf
|
|
229
|
-
}
|
|
230
|
-
return undefined
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function buildFromEps(map: EpsModuleMap) {
|
|
234
|
-
const list = Object.values(map).flat() as EpsEntity[]
|
|
235
|
-
for (const e of list) {
|
|
236
|
-
if (!e.prefix) continue
|
|
237
|
-
const leaf = attachLeaf(service, e.prefix, e.api || [])
|
|
238
|
-
if (leaf) {
|
|
239
|
-
const op = (e as { pageQueryOp?: Record<string, unknown> }).pageQueryOp
|
|
240
|
-
if (op) {
|
|
241
|
-
;(leaf as ServiceLeaf & { search?: unknown }).search = {
|
|
242
|
-
fieldEq: op.fieldEq,
|
|
243
|
-
fieldLike: op.fieldLike,
|
|
244
|
-
fieldArray: op.fieldArray,
|
|
245
|
-
fieldRange: op.fieldRange,
|
|
246
|
-
keyWordLikeFields: op.keyWordLikeFields,
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function extraApisOf(prefix: string): EpsApiItem[] {
|
|
254
|
-
return (FALLBACK_EXTRA_APIS[prefix] || []).map(
|
|
255
|
-
(a) =>
|
|
256
|
-
({
|
|
257
|
-
method: a.method,
|
|
258
|
-
path: a.path,
|
|
259
|
-
perms: a.perms,
|
|
260
|
-
}) as EpsApiItem,
|
|
261
|
-
)
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* 用 fallback 补全:已有叶子则合并补方法(不整棵删,避免打断引用)。
|
|
266
|
-
* 对 fallback 前缀:若 EPS 已挂过,只补缺失的 extra;attachLeaf/remount 会重绑整叶。
|
|
267
|
-
*/
|
|
268
|
-
function buildFallback() {
|
|
269
|
-
for (const prefix of FALLBACK_PREFIXES) {
|
|
270
|
-
const parts = prefixToParts(prefix)
|
|
271
|
-
let node: Record<string, unknown> = service as unknown as Record<string, unknown>
|
|
272
|
-
let missing = false
|
|
273
|
-
for (let i = 0; i < parts.length; i++) {
|
|
274
|
-
const key = parts[i]!
|
|
275
|
-
if (!node[key]) {
|
|
276
|
-
missing = true
|
|
277
|
-
break
|
|
278
|
-
}
|
|
279
|
-
if (i < parts.length - 1) {
|
|
280
|
-
node = node[key] as Record<string, unknown>
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
const leaf = missing
|
|
284
|
-
? undefined
|
|
285
|
-
: (node[parts[parts.length - 1]!] as ServiceLeaf | undefined)
|
|
286
|
-
|
|
287
|
-
if (leaf?.namespace) {
|
|
288
|
-
// 只补 extra 里还没有的方法,保留 EPS 已绑方法
|
|
289
|
-
const extras = extraApisOf(prefix).filter((api) => {
|
|
290
|
-
const name = methodName(api.path)
|
|
291
|
-
return typeof (leaf as Record<string, unknown>)[name] !== 'function'
|
|
292
|
-
})
|
|
293
|
-
if (extras.length) {
|
|
294
|
-
const base = new BaseService(leaf.namespace)
|
|
295
|
-
bindApis(leaf, base, extras)
|
|
296
|
-
}
|
|
297
|
-
continue
|
|
298
|
-
}
|
|
299
|
-
attachLeaf(service, prefix, extraApisOf(prefix))
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
type ServiceRoot = Eps.Service & { request: BaseService['request'] }
|
|
304
|
-
|
|
305
|
-
const g = globalThis as typeof globalThis & {
|
|
306
|
-
__vome_admin_service__?: ServiceRoot
|
|
307
|
-
__vome_admin_service_build__?: number
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
function createServiceRoot(): ServiceRoot {
|
|
311
|
-
const root = new BaseService()
|
|
312
|
-
return {
|
|
313
|
-
request: root.request.bind(root),
|
|
314
|
-
} as ServiceRoot
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function getOrCreateRoot(): ServiceRoot {
|
|
318
|
-
if (
|
|
319
|
-
!g.__vome_admin_service__ ||
|
|
320
|
-
g.__vome_admin_service_build__ !== SERVICE_BUILD
|
|
321
|
-
) {
|
|
322
|
-
g.__vome_admin_service__ = createServiceRoot()
|
|
323
|
-
g.__vome_admin_service_build__ = SERVICE_BUILD
|
|
324
|
-
}
|
|
325
|
-
return g.__vome_admin_service__
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/** 全局链式 service(service.base.user.page()) */
|
|
329
|
-
export const service: ServiceRoot = getOrCreateRoot()
|
|
330
|
-
|
|
331
|
-
buildFallback()
|
|
332
|
-
|
|
333
|
-
/** 从 EPS 构建/刷新;再 fallback 补自定义方法 */
|
|
334
|
-
export async function createEps(force = false) {
|
|
335
|
-
try {
|
|
336
|
-
const map = (await loadEps(force)) || {}
|
|
337
|
-
if (Object.keys(map).length) buildFromEps(map)
|
|
338
|
-
} catch (e) {
|
|
339
|
-
console.warn('[vome-eps] load failed', e)
|
|
340
|
-
}
|
|
341
|
-
buildFallback()
|
|
342
|
-
return service
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
if (import.meta.hot) {
|
|
346
|
-
import.meta.hot.on('eps-update', () => {
|
|
347
|
-
void createEps(true).then(() => {
|
|
348
|
-
if (import.meta.env.DEV) console.log('[vome-eps] service hot updated')
|
|
349
|
-
})
|
|
350
|
-
})
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
export function setServicePerms(perms: string[], isSuper = false) {
|
|
354
|
-
const list = perms || []
|
|
355
|
-
|
|
356
|
-
function deep(d: unknown) {
|
|
357
|
-
if (!d || typeof d !== 'object') return
|
|
358
|
-
const obj = d as ServiceLeaf & Record<string, unknown>
|
|
359
|
-
if (obj.permission && obj.namespace) {
|
|
360
|
-
obj._permission = {}
|
|
361
|
-
for (const key of Object.keys(obj.permission)) {
|
|
362
|
-
if (isSuper) {
|
|
363
|
-
obj._permission[key] = true
|
|
364
|
-
continue
|
|
365
|
-
}
|
|
366
|
-
const code = obj.permission[key]
|
|
367
|
-
obj._permission[key] =
|
|
368
|
-
list.includes(code) ||
|
|
369
|
-
list.some((p) =>
|
|
370
|
-
p
|
|
371
|
-
.replace(/:/g, '/')
|
|
372
|
-
.includes(`${obj.namespace.replace(/^admin\//, '')}/${key}`),
|
|
373
|
-
)
|
|
374
|
-
}
|
|
375
|
-
return
|
|
376
|
-
}
|
|
377
|
-
for (const k of Object.keys(obj)) {
|
|
378
|
-
if (k === 'request') continue
|
|
379
|
-
deep(obj[k])
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
deep(service)
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
export function resolveService(path: string): ServiceLeaf | undefined {
|
|
387
|
-
const parts = path.replace(/^\//, '').split('.').filter(Boolean)
|
|
388
|
-
let cur: unknown = service
|
|
389
|
-
for (const p of parts) {
|
|
390
|
-
if (!cur || typeof cur !== 'object') return undefined
|
|
391
|
-
cur = (cur as Record<string, unknown>)[p]
|
|
392
|
-
}
|
|
393
|
-
if (cur && typeof cur === 'object' && 'namespace' in (cur as object)) {
|
|
394
|
-
return cur as ServiceLeaf
|
|
395
|
-
}
|
|
396
|
-
return undefined
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
export function serviceOf(prefix: string): ServiceLeaf {
|
|
400
|
-
const raw = prefix.replace(/\/$/, '')
|
|
401
|
-
const path = prefixToParts(raw).join('.')
|
|
402
|
-
const hit = resolveService(path)
|
|
403
|
-
if (hit) return hit
|
|
404
|
-
return attachLeaf(service, raw, extraApisOf(raw.startsWith('/') ? raw : `/${raw}`)) as ServiceLeaf
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/** @deprecated 请用 service.base.xxx */
|
|
408
|
-
export function createEpsService(prefix: string) {
|
|
409
|
-
return serviceOf(prefix)
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
export { BaseService }
|
|
413
|
-
export type { ServiceLeaf, ServiceTree } from '../../../typings/admin/comm/service'
|
package/src/admin/stores/app.ts
DELETED
|
@@ -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
|
-
})
|