create-yoya-ui 0.2.1 → 0.2.3
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/README.md +11 -10
- package/bin/create-yoya-ui.js +1 -1
- package/package.json +1 -1
- package/templates/admin/README.md +59 -47
- package/templates/admin/RULES.md +105 -0
- package/templates/admin/src/features/dashboard/todos/pages/todo-approval-page.js +5 -0
- package/templates/admin/src/features/ops/deploys/pages/deploy-list-page.js +5 -0
- package/templates/admin/src/features/ops/services/pages/service-list-page.js +5 -0
- package/templates/admin/src/features/{dicts → system/dicts}/api/dict.mgr.d.ts +24 -17
- package/templates/admin/src/features/{dicts → system/dicts}/api/dict.mgr.js +24 -14
- package/templates/admin/src/features/{dicts → system/dicts}/api/dict.mock.js +22 -4
- package/templates/admin/src/features/{dicts → system/dicts}/api/dict.state.d.ts +5 -0
- package/templates/admin/src/features/{dicts → system/dicts}/api/dict.state.js +39 -8
- package/templates/admin/src/features/{dicts → system/dicts}/components/dict-editor-dialog.js +1 -1
- package/templates/admin/src/features/{dicts → system/dicts}/pages/dict-list-page.js +41 -21
- package/templates/admin/src/features/{members → system/members}/api/member.mgr.d.ts +10 -9
- package/templates/admin/src/features/{members → system/members}/api/member.mgr.js +8 -3
- package/templates/admin/src/features/{members → system/members}/api/member.mock.js +1 -1
- package/templates/admin/src/features/{members → system/members}/api/member.req.d.ts +1 -1
- package/templates/admin/src/features/{members → system/members}/api/member.req.js +3 -1
- package/templates/admin/src/features/{members → system/members}/api/member.state.js +4 -4
- package/templates/admin/src/features/{members → system/members}/components/member-table.js +1 -1
- package/templates/admin/src/features/{permissions → system/permissions}/api/permission.mgr.d.ts +11 -9
- package/templates/admin/src/features/{permissions → system/permissions}/api/permission.mgr.js +10 -5
- package/templates/admin/src/features/{permissions → system/permissions}/api/permission.mock.js +1 -1
- package/templates/admin/src/features/{permissions → system/permissions}/api/permission.state.js +4 -4
- package/templates/admin/src/features/{permissions → system/permissions}/pages/permission-list-page.js +1 -1
- package/templates/admin/src/features/{roles → system/roles}/api/role.mgr.d.ts +19 -6
- package/templates/admin/src/features/{roles → system/roles}/api/role.mgr.js +8 -3
- package/templates/admin/src/features/{roles → system/roles}/api/role.mock.js +1 -1
- package/templates/admin/src/features/{roles → system/roles}/api/role.state.js +4 -4
- package/templates/admin/src/features/{roles → system/roles}/components/role-table.js +1 -1
- package/templates/admin/src/main.js +16 -12
- package/templates/admin/src/{ui/row-action-button.js → shared/ui.buttons.js} +1 -0
- package/templates/admin/src/{ui/placeholder-page.js → shared/ui.pages.js} +1 -0
- package/templates/admin/src/shell/api/shell.mock.js +42 -0
- package/templates/admin/src/shell/api/shell.req.js +17 -0
- package/templates/admin/src/shell/api/shell.state.js +90 -0
- package/templates/admin/src/shell/api/shell.views.js +19 -0
- package/templates/admin/src/shell/components/admin-shell.js +42 -0
- package/templates/admin/src/{ui → shell/components}/app-navbar.js +11 -12
- package/templates/admin/src/shell/components/app-sidebar.js +44 -0
- package/templates/admin/src/{ui → shell/components}/sidebar-menu.js +3 -3
- package/templates/admin/src/shell/router.js +40 -0
- package/templates/admin/node_modules/.vite/deps/_metadata.json +0 -8
- package/templates/admin/node_modules/.vite/deps/package.json +0 -3
- package/templates/admin/src/app/admin-shell.js +0 -51
- package/templates/admin/src/app/modules.js +0 -37
- package/templates/admin/src/app/router.js +0 -20
- package/templates/admin/src/ui/app-sidebar.js +0 -27
- /package/templates/admin/src/features/dashboard/{components → overview/components}/dashboard-chart.js +0 -0
- /package/templates/admin/src/features/dashboard/{pages → overview/pages}/dashboard-overview-page.js +0 -0
- /package/templates/admin/src/features/{dicts → system/dicts}/api/dict.views.d.ts +0 -0
- /package/templates/admin/src/features/{dicts → system/dicts}/api/dict.views.js +0 -0
- /package/templates/admin/src/features/{dicts → system/dicts}/components/dict-item-form-dialog.js +0 -0
- /package/templates/admin/src/features/{dicts → system/dicts}/utils/options.js +0 -0
- /package/templates/admin/src/features/{members → system/members}/api/member.state.d.ts +0 -0
- /package/templates/admin/src/features/{members → system/members}/api/member.views.d.ts +0 -0
- /package/templates/admin/src/features/{members → system/members}/api/member.views.js +0 -0
- /package/templates/admin/src/features/{members → system/members}/components/member-form-dialog.js +0 -0
- /package/templates/admin/src/features/{members → system/members}/components/member-toolbar.js +0 -0
- /package/templates/admin/src/features/{members → system/members}/pages/member-list-page.js +0 -0
- /package/templates/admin/src/features/{members → system/members}/utils/options.d.ts +0 -0
- /package/templates/admin/src/features/{members → system/members}/utils/options.js +0 -0
- /package/templates/admin/src/features/{permissions → system/permissions}/api/permission.state.d.ts +0 -0
- /package/templates/admin/src/features/{permissions → system/permissions}/api/permission.views.d.ts +0 -0
- /package/templates/admin/src/features/{permissions → system/permissions}/api/permission.views.js +0 -0
- /package/templates/admin/src/features/{permissions → system/permissions}/components/permission-form-dialog.js +0 -0
- /package/templates/admin/src/features/{roles → system/roles}/api/role.state.d.ts +0 -0
- /package/templates/admin/src/features/{roles → system/roles}/api/role.views.d.ts +0 -0
- /package/templates/admin/src/features/{roles → system/roles}/api/role.views.js +0 -0
- /package/templates/admin/src/features/{roles → system/roles}/components/role-form-dialog.js +0 -0
- /package/templates/admin/src/features/{roles → system/roles}/components/role-toolbar.js +0 -0
- /package/templates/admin/src/features/{roles → system/roles}/pages/role-list-page.js +0 -0
- /package/templates/admin/src/features/{roles → system/roles}/utils/options.js +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// 演示用内存 mock(接入真实后端后删除本文件)。
|
|
2
|
+
import { mockRequest } from '../../api/domain.api.js';
|
|
3
|
+
|
|
4
|
+
const delay = (ms = 200) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
5
|
+
|
|
6
|
+
mockRequest('GET', '/menus', async () => {
|
|
7
|
+
await delay();
|
|
8
|
+
return {
|
|
9
|
+
ok: true,
|
|
10
|
+
data: [
|
|
11
|
+
{
|
|
12
|
+
key: 'dashboard',
|
|
13
|
+
label: '工作台',
|
|
14
|
+
icon: 'D',
|
|
15
|
+
routes: [
|
|
16
|
+
{ path: '/dashboard/overview', title: '数据概览', viewKey: 'dashboard-overview' },
|
|
17
|
+
{ path: '/dashboard/todos', title: '待办审批', viewKey: 'todo-approval' }
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
key: 'ops',
|
|
22
|
+
label: '运维',
|
|
23
|
+
icon: 'O',
|
|
24
|
+
routes: [
|
|
25
|
+
{ path: '/ops/services', title: '服务清单', viewKey: 'service-list' },
|
|
26
|
+
{ path: '/ops/deploys', title: '部署任务', viewKey: 'deploy-list' }
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
key: 'system',
|
|
31
|
+
label: '系统',
|
|
32
|
+
icon: 'S',
|
|
33
|
+
routes: [
|
|
34
|
+
{ path: '/system/members', title: '成员管理', viewKey: 'member-list' },
|
|
35
|
+
{ path: '/system/roles', title: '角色管理', viewKey: 'role-list' },
|
|
36
|
+
{ path: '/system/permissions', title: '权限管理', viewKey: 'permission-list' },
|
|
37
|
+
{ path: '/system/dicts', title: '字典管理', viewKey: 'dict-list' }
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// 外壳请求命令:其他模块(启动装配)调用本域能力的入口,方便后续替换为服务端接口(去掉 mock 即可)。
|
|
2
|
+
import { RequestBase } from '@yoyaflow/yoya-ui';
|
|
3
|
+
import Shell from './shell.views.js';
|
|
4
|
+
|
|
5
|
+
class QueryMenus extends RequestBase {
|
|
6
|
+
address() {
|
|
7
|
+
return '/menus';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
toItem(row) {
|
|
11
|
+
return new Shell.Module(row);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
QueryMenus: (init) => new QueryMenus(init)
|
|
17
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// 外壳状态类:菜单数据 + 导航状态(当前模块 / 当前路径)的唯一事实源,
|
|
2
|
+
// 加载时创建并持有路由,暴露导航动作(switchModule / navigate),由路由订阅驱动 syncFromPath。
|
|
3
|
+
import ShellReq from './shell.req.js';
|
|
4
|
+
import { createAppRouter } from '../router.js';
|
|
5
|
+
|
|
6
|
+
export default class ShellState {
|
|
7
|
+
constructor() {
|
|
8
|
+
this._menus = [];
|
|
9
|
+
this._router = null;
|
|
10
|
+
this._activeModuleKey = null;
|
|
11
|
+
this._activePath = null;
|
|
12
|
+
this._listeners = new Set();
|
|
13
|
+
this._unsubscribeRouter = null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
menus() {
|
|
17
|
+
return this._menus;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
router() {
|
|
21
|
+
return this._router;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
activeModuleKey() {
|
|
25
|
+
return this._activeModuleKey;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
activePath() {
|
|
29
|
+
return this._activePath;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
subscribe(listener) {
|
|
33
|
+
this._listeners.add(listener);
|
|
34
|
+
return () => this._listeners.delete(listener);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async load() {
|
|
38
|
+
const result = await ShellReq.QueryMenus().submit();
|
|
39
|
+
this._menus = result.data;
|
|
40
|
+
this._router = createAppRouter(this._menus);
|
|
41
|
+
this._unsubscribeRouter = this._router.subscribe((context) => this.syncFromPath(context.path));
|
|
42
|
+
this._emit();
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
start() {
|
|
47
|
+
this._router?.start();
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 顶栏切换模块:进入模块首个路由。
|
|
52
|
+
switchModule(module) {
|
|
53
|
+
const first = module?.routes?.[0];
|
|
54
|
+
if (first) {
|
|
55
|
+
this._router?.navigate(first.path);
|
|
56
|
+
}
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 侧栏 / 任意入口:打开指定路径。
|
|
61
|
+
navigate(path) {
|
|
62
|
+
this._router?.navigate(path);
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
syncFromPath(path) {
|
|
67
|
+
const module = this._menus.find((entry) =>
|
|
68
|
+
entry.routes.some((route) => route.path === path)
|
|
69
|
+
);
|
|
70
|
+
const changed =
|
|
71
|
+
this._activePath !== path || (module && this._activeModuleKey !== module.key);
|
|
72
|
+
this._activePath = path;
|
|
73
|
+
if (module) {
|
|
74
|
+
this._activeModuleKey = module.key;
|
|
75
|
+
}
|
|
76
|
+
if (changed) {
|
|
77
|
+
this._emit();
|
|
78
|
+
}
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
destroy() {
|
|
83
|
+
this._unsubscribeRouter?.();
|
|
84
|
+
this._listeners.clear();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
_emit() {
|
|
88
|
+
this._listeners.forEach((listener) => listener());
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// 外壳结果结构(纯数据):菜单模块与路由,服务端返回后由 toItem 映射。
|
|
2
|
+
class Route {
|
|
3
|
+
constructor({ path, title, viewKey }) {
|
|
4
|
+
this.path = path;
|
|
5
|
+
this.title = title;
|
|
6
|
+
this.viewKey = viewKey;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
class Module {
|
|
11
|
+
constructor({ key, label, icon, routes = [] }) {
|
|
12
|
+
this.key = key;
|
|
13
|
+
this.label = label;
|
|
14
|
+
this.icon = icon;
|
|
15
|
+
this.routes = routes.map((route) => new Route(route));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default { Module, Route };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { vBody, vRouterViews } from '@yoyaflow/yoya-ui';
|
|
2
|
+
import { AppNavbar } from './app-navbar.js';
|
|
3
|
+
import { AppSidebar } from './app-sidebar.js';
|
|
4
|
+
|
|
5
|
+
// 外壳装配:只做布局组装与状态接线。路由与导航动作都在 ShellState。
|
|
6
|
+
// URL 变化 → state.syncFromPath() → 状态通知 → 顶栏 / 侧栏从状态派生高亮。
|
|
7
|
+
export function AdminShell({ state }) {
|
|
8
|
+
const navbar = AppNavbar({ state });
|
|
9
|
+
const sidebar = AppSidebar({ state });
|
|
10
|
+
|
|
11
|
+
const unsubscribe = state.subscribe(() => {
|
|
12
|
+
navbar.applyState();
|
|
13
|
+
sidebar.applyState();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
render() {
|
|
18
|
+
return vBody((shell) => {
|
|
19
|
+
shell.gap(0);
|
|
20
|
+
shell.maxWidth('100%');
|
|
21
|
+
shell.padding(0);
|
|
22
|
+
shell.vContainer((frame) => {
|
|
23
|
+
frame.viewport(true);
|
|
24
|
+
frame.vHeader({ height: 56 }, (header) => {
|
|
25
|
+
header.style('padding', '0');
|
|
26
|
+
header.child(navbar);
|
|
27
|
+
});
|
|
28
|
+
frame.vContainer((body) => {
|
|
29
|
+
body.style({ flex: '1 1 auto', minHeight: '0' });
|
|
30
|
+
body.child(sidebar);
|
|
31
|
+
body.vMain((main) => {
|
|
32
|
+
main.child(vRouterViews(state.router(), { lockTitle: true, title: '内容区' }));
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
destroy() {
|
|
39
|
+
unsubscribe();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { vAvatar, vNavbar } from '@yoyaflow/yoya-ui';
|
|
2
2
|
|
|
3
|
-
export function AppNavbar({
|
|
3
|
+
export function AppNavbar({ state }) {
|
|
4
4
|
const items = new Map();
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
function applyState() {
|
|
7
|
+
const activeKey = state.activeModuleKey();
|
|
8
|
+
items.forEach((item, key) => {
|
|
9
|
+
item.active(key === activeKey);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
6
12
|
|
|
7
13
|
return {
|
|
8
14
|
render() {
|
|
@@ -39,11 +45,11 @@ export function AppNavbar({ modules, onModuleChange }) {
|
|
|
39
45
|
});
|
|
40
46
|
});
|
|
41
47
|
nav.menuContent((menu) => {
|
|
42
|
-
|
|
48
|
+
state.menus().forEach((module) => {
|
|
43
49
|
menu.vMenuItem((item) => {
|
|
44
50
|
item.text(module.label);
|
|
45
51
|
items.set(module.key, item);
|
|
46
|
-
item.on('click', () =>
|
|
52
|
+
item.on('click', () => state.switchModule(module));
|
|
47
53
|
});
|
|
48
54
|
});
|
|
49
55
|
});
|
|
@@ -55,13 +61,6 @@ export function AppNavbar({ modules, onModuleChange }) {
|
|
|
55
61
|
});
|
|
56
62
|
});
|
|
57
63
|
},
|
|
58
|
-
|
|
59
|
-
if (activeKey && activeKey !== key) {
|
|
60
|
-
items.get(activeKey)?.active(false);
|
|
61
|
-
}
|
|
62
|
-
activeKey = key;
|
|
63
|
-
items.get(key)?.active(true);
|
|
64
|
-
return this;
|
|
65
|
-
}
|
|
64
|
+
applyState
|
|
66
65
|
};
|
|
67
66
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { vSidebar } from '@yoyaflow/yoya-ui';
|
|
2
|
+
import { SidebarMenu } from './sidebar-menu.js';
|
|
3
|
+
|
|
4
|
+
export function AppSidebar({ state }) {
|
|
5
|
+
let sidebar = null;
|
|
6
|
+
|
|
7
|
+
function render() {
|
|
8
|
+
sidebar = vSidebar((side) => {
|
|
9
|
+
side.ariaLabel('左侧菜单');
|
|
10
|
+
side.title('导航');
|
|
11
|
+
side.collapsible(false);
|
|
12
|
+
side.style({
|
|
13
|
+
flex: '0 0 auto',
|
|
14
|
+
width: '220px',
|
|
15
|
+
gridTemplateRows: 'auto minmax(0, 1fr)'
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
return sidebar;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function applyState() {
|
|
22
|
+
if (!sidebar) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const module = state.menus().find((entry) => entry.key === state.activeModuleKey());
|
|
26
|
+
if (!module) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
sidebar.menuContent((menu) => {
|
|
30
|
+
menu.child(
|
|
31
|
+
SidebarMenu({
|
|
32
|
+
module,
|
|
33
|
+
activePath: state.activePath(),
|
|
34
|
+
onNavigate: (path) => state.navigate(path)
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
render,
|
|
42
|
+
applyState
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { vMenuGroup } from '@yoyaflow/yoya-ui';
|
|
2
2
|
|
|
3
|
-
export function SidebarMenu({ module,
|
|
3
|
+
export function SidebarMenu({ module, activePath, onNavigate }) {
|
|
4
4
|
return vMenuGroup((group) => {
|
|
5
5
|
group.label(module.label);
|
|
6
6
|
module.routes.forEach((route) => {
|
|
7
7
|
group.vMenuItem((item) => {
|
|
8
8
|
item.text(route.title);
|
|
9
|
-
item.active(route.path ===
|
|
10
|
-
item.on('click', () =>
|
|
9
|
+
item.active(route.path === activePath);
|
|
10
|
+
item.on('click', () => onNavigate(route.path));
|
|
11
11
|
});
|
|
12
12
|
});
|
|
13
13
|
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createRouter } from '@yoyaflow/yoya-ui';
|
|
2
|
+
import { PlaceholderPage } from '../shared/ui.pages.js';
|
|
3
|
+
import { DashboardOverviewPage } from '../features/dashboard/overview/pages/dashboard-overview-page.js';
|
|
4
|
+
import { TodoApprovalPage } from '../features/dashboard/todos/pages/todo-approval-page.js';
|
|
5
|
+
import { ServiceListPage } from '../features/ops/services/pages/service-list-page.js';
|
|
6
|
+
import { DeployListPage } from '../features/ops/deploys/pages/deploy-list-page.js';
|
|
7
|
+
import { MemberListPage } from '../features/system/members/pages/member-list-page.js';
|
|
8
|
+
import { RoleListPage } from '../features/system/roles/pages/role-list-page.js';
|
|
9
|
+
import { PermissionListPage } from '../features/system/permissions/pages/permission-list-page.js';
|
|
10
|
+
import { DictListPage } from '../features/system/dicts/pages/dict-list-page.js';
|
|
11
|
+
|
|
12
|
+
// 菜单视图注册表:服务端菜单只返回 viewKey,由这里映射到客户端页面组件。
|
|
13
|
+
const viewRegistry = {
|
|
14
|
+
'dashboard-overview': DashboardOverviewPage,
|
|
15
|
+
'todo-approval': TodoApprovalPage,
|
|
16
|
+
'service-list': ServiceListPage,
|
|
17
|
+
'deploy-list': DeployListPage,
|
|
18
|
+
'member-list': MemberListPage,
|
|
19
|
+
'role-list': RoleListPage,
|
|
20
|
+
'permission-list': PermissionListPage,
|
|
21
|
+
'dict-list': DictListPage
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function createAppRouter(menus) {
|
|
25
|
+
const router = createRouter((r) => {
|
|
26
|
+
menus.forEach((module) => {
|
|
27
|
+
module.routes.forEach((route) => {
|
|
28
|
+
const Page = viewRegistry[route.viewKey];
|
|
29
|
+
r.route(route.path, {
|
|
30
|
+
title: route.title,
|
|
31
|
+
view: () =>
|
|
32
|
+
Page ? Page() : PlaceholderPage({ title: route.title, text: '该页面待开发。' })
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
r.notFound(() => PlaceholderPage({ title: '未找到', text: '该页面不存在。' }));
|
|
37
|
+
});
|
|
38
|
+
router.default(menus[0].routes[0].path);
|
|
39
|
+
return router;
|
|
40
|
+
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { vBody, vRouterViews } from '@yoyaflow/yoya-ui';
|
|
2
|
-
import { AppNavbar } from '../ui/app-navbar.js';
|
|
3
|
-
import { AppSidebar } from '../ui/app-sidebar.js';
|
|
4
|
-
|
|
5
|
-
export function AdminShell({ router, modules }) {
|
|
6
|
-
const navbar = AppNavbar({ modules, onModuleChange: switchModule });
|
|
7
|
-
const sidebar = AppSidebar({ router });
|
|
8
|
-
|
|
9
|
-
function switchModule(module) {
|
|
10
|
-
navbar.activate(module.key);
|
|
11
|
-
router.navigate(module.routes[0].path);
|
|
12
|
-
sidebar.showModule(module);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function syncModuleFromUrl() {
|
|
16
|
-
const path = router.currentPath();
|
|
17
|
-
const module = modules.find((entry) => entry.routes.some((route) => route.path === path));
|
|
18
|
-
if (!module) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
navbar.activate(module.key);
|
|
22
|
-
sidebar.showModule(module);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return {
|
|
26
|
-
render() {
|
|
27
|
-
return vBody((shell) => {
|
|
28
|
-
shell.gap(0);
|
|
29
|
-
shell.maxWidth('100%');
|
|
30
|
-
shell.padding(0);
|
|
31
|
-
shell.vContainer((frame) => {
|
|
32
|
-
frame.viewport(true);
|
|
33
|
-
frame.vHeader({ height: 56 }, (header) => {
|
|
34
|
-
header.style('padding', '0');
|
|
35
|
-
header.child(navbar);
|
|
36
|
-
});
|
|
37
|
-
frame.vContainer((body) => {
|
|
38
|
-
body.style({ flex: '1 1 auto', minHeight: '0' });
|
|
39
|
-
body.child(sidebar);
|
|
40
|
-
body.vMain((main) => {
|
|
41
|
-
main.child(vRouterViews(router, { lockTitle: true, title: '内容区' }));
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
},
|
|
47
|
-
syncFromUrl() {
|
|
48
|
-
syncModuleFromUrl();
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { MemberListPage } from '../features/members/pages/member-list-page.js';
|
|
2
|
-
import { PermissionListPage } from '../features/permissions/pages/permission-list-page.js';
|
|
3
|
-
import { RoleListPage } from '../features/roles/pages/role-list-page.js';
|
|
4
|
-
import { DictListPage } from '../features/dicts/pages/dict-list-page.js';
|
|
5
|
-
import { DashboardOverviewPage } from '../features/dashboard/pages/dashboard-overview-page.js';
|
|
6
|
-
|
|
7
|
-
export const modules = [
|
|
8
|
-
{
|
|
9
|
-
key: 'dashboard',
|
|
10
|
-
label: '工作台',
|
|
11
|
-
icon: 'D',
|
|
12
|
-
routes: [
|
|
13
|
-
{ path: '/dashboard/overview', title: '数据概览', view: DashboardOverviewPage },
|
|
14
|
-
{ path: '/dashboard/todos', title: '待办审批', text: '待处理审批与任务。' }
|
|
15
|
-
]
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
key: 'ops',
|
|
19
|
-
label: '运维',
|
|
20
|
-
icon: 'O',
|
|
21
|
-
routes: [
|
|
22
|
-
{ path: '/ops/services', title: '服务清单', text: '服务列表与健康状态。' },
|
|
23
|
-
{ path: '/ops/deploys', title: '部署任务', text: '发布记录与执行状态。' }
|
|
24
|
-
]
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
key: 'system',
|
|
28
|
-
label: '系统',
|
|
29
|
-
icon: 'S',
|
|
30
|
-
routes: [
|
|
31
|
-
{ path: '/system/members', title: '成员管理', view: MemberListPage },
|
|
32
|
-
{ path: '/system/roles', title: '角色管理', view: RoleListPage },
|
|
33
|
-
{ path: '/system/permissions', title: '权限管理', view: PermissionListPage },
|
|
34
|
-
{ path: '/system/dicts', title: '字典管理', view: DictListPage }
|
|
35
|
-
]
|
|
36
|
-
}
|
|
37
|
-
];
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { createRouter } from '@yoyaflow/yoya-ui';
|
|
2
|
-
import { modules } from './modules.js';
|
|
3
|
-
import { PlaceholderPage } from '../ui/placeholder-page.js';
|
|
4
|
-
|
|
5
|
-
export function createAppRouter() {
|
|
6
|
-
const router = createRouter((r) => {
|
|
7
|
-
modules.forEach((module) => {
|
|
8
|
-
module.routes.forEach((route) => {
|
|
9
|
-
r.route(route.path, {
|
|
10
|
-
title: route.title,
|
|
11
|
-
view: () =>
|
|
12
|
-
route.view ? route.view() : PlaceholderPage({ title: route.title, text: route.text })
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
r.notFound(() => PlaceholderPage({ title: '未找到', text: '该页面不存在。' }));
|
|
17
|
-
});
|
|
18
|
-
router.default(modules[0].routes[0].path);
|
|
19
|
-
return router;
|
|
20
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { vSidebar } from '@yoyaflow/yoya-ui';
|
|
2
|
-
import { SidebarMenu } from './sidebar-menu.js';
|
|
3
|
-
|
|
4
|
-
export function AppSidebar({ router }) {
|
|
5
|
-
const sidebar = vSidebar((side) => {
|
|
6
|
-
side.ariaLabel('左侧菜单');
|
|
7
|
-
side.title('导航');
|
|
8
|
-
side.collapsible(false);
|
|
9
|
-
});
|
|
10
|
-
sidebar.style({
|
|
11
|
-
flex: '0 0 auto',
|
|
12
|
-
width: '220px',
|
|
13
|
-
gridTemplateRows: 'auto minmax(0, 1fr)'
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
return {
|
|
17
|
-
render() {
|
|
18
|
-
return sidebar;
|
|
19
|
-
},
|
|
20
|
-
showModule(module) {
|
|
21
|
-
sidebar.menuContent((menu) => {
|
|
22
|
-
menu.child(SidebarMenu({ module, router }));
|
|
23
|
-
});
|
|
24
|
-
return this;
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
}
|
|
File without changes
|
/package/templates/admin/src/features/dashboard/{pages → overview/pages}/dashboard-overview-page.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/admin/src/features/{dicts → system/dicts}/components/dict-item-form-dialog.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/admin/src/features/{members → system/members}/components/member-form-dialog.js
RENAMED
|
File without changes
|
/package/templates/admin/src/features/{members → system/members}/components/member-toolbar.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/admin/src/features/{permissions → system/permissions}/api/permission.state.d.ts
RENAMED
|
File without changes
|
/package/templates/admin/src/features/{permissions → system/permissions}/api/permission.views.d.ts
RENAMED
|
File without changes
|
/package/templates/admin/src/features/{permissions → system/permissions}/api/permission.views.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|