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
package/README.md
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
# create-yoya-ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
快速体验 [yoya-ui](https://github.com/yoyaflow/yoya-ui) 的脚手架。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g create-yoya-ui
|
|
9
|
+
```
|
|
4
10
|
|
|
5
11
|
## 用法
|
|
6
12
|
|
|
7
13
|
```bash
|
|
8
|
-
|
|
9
|
-
npx create-yoya-ui@latest my-app --template ssr # SSR 模板
|
|
10
|
-
npx create-yoya-ui@latest my-app --template admin # 后台管理模板
|
|
14
|
+
create-yoya-ui my-app --template admin
|
|
11
15
|
cd my-app
|
|
12
16
|
npm install
|
|
17
|
+
npm run dev
|
|
13
18
|
```
|
|
14
19
|
|
|
15
|
-
- **
|
|
16
|
-
- **ssr**:服务端渲染模板,`npm run build && npm start`(renderPage 整页渲染 + hydrateOrMount 客户端接入)
|
|
17
|
-
- **admin**:标准后台管理模板(顶部导航 + 可折叠侧栏 + RouterViews 内容区)
|
|
20
|
+
- **admin**:标准后台管理模板(顶部导航 + 左侧菜单 + RouterViews 内容区)
|
|
18
21
|
|
|
19
22
|
## 模板内容
|
|
20
23
|
|
|
21
|
-
- `templates/
|
|
22
|
-
- `templates/ssr`:home-page.js(页面组件 + 词典)、server.mjs(node:http + renderPage)、client.js(hydrateOrMount)
|
|
23
|
-
- `templates/admin`:标准后台管理模板(logo/系统名、顶部导航、用户头像、可折叠菜单、带标题内容区),内置数据概览看板与图表,以及成员 / 角色 / 权限 / 字典管理示例
|
|
24
|
+
- `templates/admin`:标准后台管理模板(logo/系统名、顶部导航、用户头像、左侧菜单、带标题内容区),内置数据概览看板与图表,以及成员 / 角色 / 权限 / 字典管理示例
|
package/bin/create-yoya-ui.js
CHANGED
|
@@ -41,7 +41,7 @@ if (templateName === 'ssr') {
|
|
|
41
41
|
} else {
|
|
42
42
|
console.log(' npm run dev');
|
|
43
43
|
console.log(
|
|
44
|
-
`\n${templateName === 'admin' ? '管理后台模板:顶部导航 +
|
|
44
|
+
`\n${templateName === 'admin' ? '管理后台模板:顶部导航 + 左侧菜单 + RouterViews 内容区。' : ''}更多:npm run build 构建,npm run preview 预览产物。\n`
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
47
|
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
- 左上角:logo + 系统名
|
|
6
6
|
- 中间:顶级导航
|
|
7
7
|
- 右上角:用户头像
|
|
8
|
-
-
|
|
8
|
+
- 下方:左侧菜单 + 右侧带标题的 RouterViews 内容区
|
|
9
9
|
- 点击顶级导航切换左侧菜单与内容路由
|
|
10
10
|
|
|
11
11
|
## 启动
|
|
@@ -23,55 +23,67 @@ npm run dev
|
|
|
23
23
|
|
|
24
24
|
```text
|
|
25
25
|
src/
|
|
26
|
-
main.js
|
|
26
|
+
main.js 入口:初始化主题、加载菜单状态、装配外壳并挂载
|
|
27
27
|
api/
|
|
28
28
|
fetch.api.js 原始传输层(fetch 实现,换请求库只改这里)
|
|
29
29
|
domain.api.js 领域请求入口:统一 Result 解析 + mock/真实切换
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
30
|
+
shared/ 跨模块共享(按类别集中管理)
|
|
31
|
+
ui.buttons.js 按钮类共享 UI(RowActionButton 行内操作按钮)
|
|
32
|
+
ui.pages.js 页面类共享 UI(PlaceholderPage 路由占位页)
|
|
33
|
+
shell/ 应用外壳(按 api / components 组织)
|
|
34
|
+
api/
|
|
35
|
+
shell.req.js 外壳请求命令:QueryMenus 获取菜单(可换服务端接口)
|
|
36
|
+
shell.mock.js 外壳 mock:模拟服务端返回(viewKey 由客户端映射页面)
|
|
37
|
+
shell.views.js 外壳结果结构(Module / Route)
|
|
38
|
+
shell.state.js 外壳状态类 ShellState:菜单 + 导航状态(当前模块/路径),加载时创建并持有路由,暴露导航动作(switchModule / navigate)
|
|
39
|
+
components/
|
|
40
|
+
admin-shell.js AdminShell 外壳装配(布局组装 + 顶栏/侧栏从状态派生)
|
|
41
|
+
app-navbar.js AppNavbar 顶部导航(logo + 顶级导航 + 主题/头像)
|
|
42
|
+
app-sidebar.js AppSidebar 左侧导航外壳
|
|
43
|
+
sidebar-menu.js SidebarMenu 模块菜单组件
|
|
44
|
+
router.js 路由组装:viewKey → 页面组件映射 + 404 占位页兜底
|
|
45
|
+
features/ 业务域 = 父模块节点(对应顶级菜单),下按菜单项分子模块
|
|
46
|
+
dashboard/ 工作台
|
|
47
|
+
overview/ 数据概览
|
|
48
|
+
pages/dashboard-overview-page.js 页面编排:核心指标看板 + 趋势卡 + 图表 + 资源使用
|
|
49
|
+
components/dashboard-chart.js vChart 内置 SVG 适配器(柱状图 / 折线图)
|
|
50
|
+
todos/ 待办审批(简单页示例)
|
|
51
|
+
pages/todo-approval-page.js
|
|
52
|
+
ops/ 运维
|
|
53
|
+
services/ 服务清单(简单页示例)
|
|
54
|
+
pages/service-list-page.js
|
|
55
|
+
deploys/ 部署任务(简单页示例)
|
|
56
|
+
pages/deploy-list-page.js
|
|
57
|
+
system/ 系统
|
|
58
|
+
members/ 成员管理业务域(CRUD 完整模块示例)
|
|
59
|
+
pages/member-list-page.js 页面编排:组合工具栏、表格、弹窗与分页
|
|
60
|
+
components/
|
|
61
|
+
member-toolbar.js MemberToolbar 搜索/新增工具栏
|
|
62
|
+
member-table.js MemberTable 成员表格
|
|
63
|
+
member-form-dialog.js MemberFormDialog 新增/编辑弹窗
|
|
64
|
+
api/
|
|
65
|
+
member.mgr.js 管理请求命令(增删改查等)
|
|
66
|
+
member.req.js 外部请求命令(其他模块调用本域能力)
|
|
67
|
+
member.views.js 领域结果结构(列表项 / 详情)
|
|
68
|
+
member.state.js 状态类 MembersPageState:持有数据与筛选,动作 submit 命令后驱动视图
|
|
69
|
+
member.mock.js 演示用内存 mock(接入真实后端后删除)
|
|
70
|
+
utils/options.js 领域常量(角色/状态选项与文案)
|
|
71
|
+
roles/ 角色管理业务域(分页 CRUD 示例)
|
|
72
|
+
pages/role-list-page.js 页面编排:搜索 + 表格 + 分页 + 表单弹窗
|
|
73
|
+
components/ RoleToolbar / RoleTable / RoleFormDialog
|
|
74
|
+
api/ 请求命令 / 状态类 / 结果结构 / mock
|
|
75
|
+
permissions/ 权限管理业务域(vTree 权限树示例)
|
|
76
|
+
pages/permission-list-page.js 页面编排:权限树 + 工具栏 + 表单弹窗 + 删除确认
|
|
77
|
+
components/ PermissionFormDialog
|
|
78
|
+
api/ 请求命令 / 状态类 / 结果结构 / mock
|
|
79
|
+
dicts/ 字典管理业务域(字典类型 + 字典项主从示例)
|
|
80
|
+
pages/dict-list-page.js 页面编排:字典类型表格 + 编辑弹窗(基本信息 + 字典值表格)
|
|
81
|
+
components/ DictEditorDialog / DictItemFormDialog
|
|
82
|
+
api/ 请求命令 / 状态类 / 结果结构 / mock
|
|
73
83
|
```
|
|
74
84
|
|
|
75
|
-
目录规则遵循 yoya-ui skill 的业务模块组织(feature 自包含、页面只编排、
|
|
85
|
+
目录规则遵循 yoya-ui skill 的业务模块组织(feature 自包含、页面只编排、api 管数据交互、state 管状态)。每个菜单项对应 `features/` 下的一个子模块目录;简单页只放 `pages/` 文件,有数据交互的页面展开 api / components / pages / utils。
|
|
76
86
|
|
|
77
|
-
扩展新模块:在 `
|
|
87
|
+
扩展新模块:在 `features/` 下建父模块目录(如 `features/orders/`),每个菜单项对应一个子目录;在 `shell/api/shell.mock.js` 模拟返回的菜单数据里加一组 `{ key, label, icon, routes }`(key 与父目录名一致),并把菜单项的 `viewKey` 注册到 `shell/router.js` 的视图注册表。接入真实后端时删除 `shell.mock.js`,由服务端返回同样的菜单结构即可。简单页只放 `pages/` 文件,有数据交互的页面参考 `features/system/members` 的 api / components / pages 分层。
|
|
88
|
+
|
|
89
|
+
完整开发规则见 [RULES.md](./RULES.md)(目录结构、命名、api 分层、请求命令范式、共享组件、导航状态等)。
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# yoya-ui admin 模板开发规则
|
|
2
|
+
|
|
3
|
+
本文件是 admin 模板的开发规则全集:目录结构、命名、api 分层、请求命令范式、共享组件、导航状态、页面与 mock 接入。以代码为准,新增/修改功能时先对照本文件。
|
|
4
|
+
|
|
5
|
+
## 1. 目录结构
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
src/
|
|
9
|
+
main.js 装配根:注册 mock → 加载状态 → 装配外壳 → 启动
|
|
10
|
+
api/ 全局传输层(fetch.api.js / domain.api.js)
|
|
11
|
+
shared/ 跨模块共享(按类别集中)
|
|
12
|
+
shell/ 应用外壳(也是模块,按 api / components 组织)
|
|
13
|
+
features/ 业务域 = 父模块节点(对应顶级菜单)
|
|
14
|
+
<父模块>/<菜单项>/ 每个菜单项一个子模块,自包含 api / components / pages / utils
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- **配置即目录**:菜单 `key` = features 父目录名 = 路由前缀(`system` ↔ `features/system/` ↔ `/system/members`)
|
|
18
|
+
- **模块自包含**:叶子模块只依赖自己的 api / components / pages / utils,不跨模块 import 内部实现
|
|
19
|
+
- **依赖方向**:跨模块唯一允许的引用是业务域 `req.js`(对外能力入口);`shared → features/<域>/api/req.js` 是允许的公开单向依赖
|
|
20
|
+
|
|
21
|
+
## 2. 文件命名
|
|
22
|
+
|
|
23
|
+
- api 层:`<域>.<层>.js`(`member.mgr.js`、`shell.req.js`、`ui.buttons.js`)
|
|
24
|
+
- 页面:`<名字>-page.js`(`member-list-page.js`、`todo-approval-page.js`)
|
|
25
|
+
- 组件:PascalCase(`AdminShell`、`MemberTable`)
|
|
26
|
+
- 共享 UI 类别文件:`ui.<类别>.js`(`ui.buttons.js`、`ui.pages.js`)
|
|
27
|
+
|
|
28
|
+
## 3. api 分层
|
|
29
|
+
|
|
30
|
+
每个业务域(含外壳)的 `api/` 按职责分文件:
|
|
31
|
+
|
|
32
|
+
- `mgr.js`:本域管理请求命令(增删改查等)
|
|
33
|
+
- `req.js`:对外能力入口(其他模块 / 共享组件调用本域时使用)
|
|
34
|
+
- `views.js`:领域结果结构(纯数据类),由命令的 `toItem / toDetail` 映射
|
|
35
|
+
- `state.js`:状态类,持有数据与筛选,`subscribe(listener)` 通知视图更新
|
|
36
|
+
- `mock.js`:演示用内存 mock(接入真实后端后删除)
|
|
37
|
+
|
|
38
|
+
判据:有管理动作用 `mgr.js`;只提供查询给外部用 `req.js`;两者可并存(如 `member.mgr.js` + `member.req.js`)。
|
|
39
|
+
|
|
40
|
+
## 4. 请求命令范式
|
|
41
|
+
|
|
42
|
+
- 构造器收**单一 `init` 对象**,`id` / `parentId` / `typeId` 等字段也放里面,不单独取参数
|
|
43
|
+
- 导出为工厂:`命令名: (init) => new 命令类(init)`
|
|
44
|
+
- 消费方:`Mgr.命令({ ... }).submit()`,不写 `new`
|
|
45
|
+
- 命令类继承 `RequestBase`,覆写 `address() / method() / params() / body() / toItem() / toDetail()`
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
export default {
|
|
49
|
+
Query: (init) => new Query(init),
|
|
50
|
+
Create: (init) => new Create(init),
|
|
51
|
+
Update: (init) => new Update(init),
|
|
52
|
+
Remove: (init) => new Remove(init)
|
|
53
|
+
};
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 5. 共享组件
|
|
57
|
+
|
|
58
|
+
- **通用 UI**(无业务语义):放 `shared/ui.<类别>.js`
|
|
59
|
+
- **业务共享组件**(带业务语义且多模块使用):放 `shared/<组件>/` 自包含子目录(组件 + 状态 + 文案),对外只暴露工厂
|
|
60
|
+
- **数据获取走 req.js**:共享组件需要业务数据时调用所属域 `api/<域>.req.js` 的公开能力(如 `MemberReq.QueryAvailable().submit()`),不自造数据请求、不注入数据源
|
|
61
|
+
- **不深层 import**:只允许跨模块引用 `req.js`,不 import 业务域的 pages / components / state 内部实现
|
|
62
|
+
- **自包含 UI 与状态**:弹窗、下拉、open/close 状态内聚在组件内,对外暴露工厂与必要方法(`open()/close()/value()`),不暴露内部状态实现
|
|
63
|
+
- **浮层自洽**:弹窗/下拉类共享组件自带 fixed 定位逻辑,不依赖使用方容器样式
|
|
64
|
+
|
|
65
|
+
## 6. 外壳与导航状态
|
|
66
|
+
|
|
67
|
+
- `ShellState` 是导航状态(当前模块 / 当前路径)的**唯一事实源**,持有 router,暴露 `switchModule(module)` / `navigate(path)`
|
|
68
|
+
- 路由订阅驱动同步:`router.subscribe → state.syncFromPath(path)`,状态变化时通知订阅者
|
|
69
|
+
- 顶栏 / 侧栏从状态**派生高亮**,组件不持有自己的激活状态
|
|
70
|
+
- `AdminShell` 只做装配:布局组装 + 状态接线,不直接操作 router
|
|
71
|
+
- 组件统一写法:节点在 `render()` 内声明式构建,内部引用(如 sidebar 实例、items Map)只用于动态更新
|
|
72
|
+
- 前进 / 后退、同模块内切换路由的高亮同步由状态管道自动完成,不需要手动调用
|
|
73
|
+
|
|
74
|
+
## 7. 页面规则
|
|
75
|
+
|
|
76
|
+
- **简单 / 占位页**:只放 `pages/<页面>-page.js`,可复用 `shared/ui.pages.js` 的 `PlaceholderPage`
|
|
77
|
+
- **有数据交互的页面**:展开完整模块(api / components / pages / utils)
|
|
78
|
+
- 页面只做编排:组合子组件、绑定事件、调用 state 动作,不写请求逻辑
|
|
79
|
+
|
|
80
|
+
## 8. mock 与数据接入
|
|
81
|
+
|
|
82
|
+
- 所有 mock 在 `main.js` 导入注册(副作用导入)
|
|
83
|
+
- mock 返回 `{ ok, data }` 结构,统一经 `Result.from` 解析
|
|
84
|
+
- 接入真实后端:删除对应 `mock.js`(或替换为真实接口),调用方零改动
|
|
85
|
+
|
|
86
|
+
## 9. 类型声明同步
|
|
87
|
+
|
|
88
|
+
- 改了 mgr / req / views / state 的 js 接口,必须同步对应 `d.ts`
|
|
89
|
+
- `d.ts` 与运行时一致:导出为工厂函数类型(如 `(init?) => Query`),不用 `typeof` 构造器类型
|
|
90
|
+
|
|
91
|
+
## 10. 新增菜单项 checklist(三处同步)
|
|
92
|
+
|
|
93
|
+
1. `features/` 建父模块目录与菜单项子目录、页面文件
|
|
94
|
+
2. `shell/api/shell.mock.js` 菜单数据加 `{ key, label, icon, routes: [{ path, title, viewKey }] }`,`key` 与目录名一致
|
|
95
|
+
3. `shell/router.js` 的 `viewRegistry` 注册 `viewKey → 页面组件`
|
|
96
|
+
|
|
97
|
+
## 11. 启动流程
|
|
98
|
+
|
|
99
|
+
`main.js` 固定顺序:
|
|
100
|
+
|
|
101
|
+
1. 导入并注册所有 mock(含 `shell.mock.js`)
|
|
102
|
+
2. `state.load()`:获取菜单 + 创建路由 + 订阅导航
|
|
103
|
+
3. `AdminShell({ state })` 装配外壳
|
|
104
|
+
4. `shell.render().bindTo('#app')`
|
|
105
|
+
5. `state.start()` 启动路由
|
|
@@ -6,7 +6,9 @@ type DictTypeInstance = InstanceType<typeof Dicts.DictTypeItem>;
|
|
|
6
6
|
type DictItemInstance = InstanceType<typeof Dicts.DictItem>;
|
|
7
7
|
|
|
8
8
|
declare class QueryTypes extends RequestBase {
|
|
9
|
+
constructor(init?: { page?: number; pageSize?: number });
|
|
9
10
|
address(): string;
|
|
11
|
+
params(): { page: number; pageSize: number };
|
|
10
12
|
toItem(row: Record<string, unknown>): DictTypeInstance;
|
|
11
13
|
}
|
|
12
14
|
|
|
@@ -19,8 +21,7 @@ declare class CreateType extends RequestBase {
|
|
|
19
21
|
|
|
20
22
|
declare class UpdateType extends RequestBase {
|
|
21
23
|
constructor(
|
|
22
|
-
id: number
|
|
23
|
-
init?: { name?: string; code?: string; status?: DictStatus; remark?: string }
|
|
24
|
+
init?: { id: number; name?: string; code?: string; status?: DictStatus; remark?: string }
|
|
24
25
|
);
|
|
25
26
|
method(): 'PUT';
|
|
26
27
|
address(): string;
|
|
@@ -28,21 +29,20 @@ declare class UpdateType extends RequestBase {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
declare class RemoveType extends RequestBase {
|
|
31
|
-
constructor(id: number);
|
|
32
|
+
constructor(init?: { id: number });
|
|
32
33
|
method(): 'DELETE';
|
|
33
34
|
address(): string;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
declare class QueryItems extends RequestBase {
|
|
37
|
-
constructor(typeId: number);
|
|
38
|
+
constructor(init?: { typeId: number });
|
|
38
39
|
address(): string;
|
|
39
40
|
toItem(row: Record<string, unknown>): DictItemInstance;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
declare class CreateItem extends RequestBase {
|
|
43
44
|
constructor(
|
|
44
|
-
typeId: number
|
|
45
|
-
init?: { label?: string; value?: string; sort?: number; status?: DictStatus }
|
|
45
|
+
init?: { typeId: number; label?: string; value?: string; sort?: number; status?: DictStatus }
|
|
46
46
|
);
|
|
47
47
|
method(): 'POST';
|
|
48
48
|
address(): string;
|
|
@@ -51,8 +51,7 @@ declare class CreateItem extends RequestBase {
|
|
|
51
51
|
|
|
52
52
|
declare class UpdateItem extends RequestBase {
|
|
53
53
|
constructor(
|
|
54
|
-
id: number
|
|
55
|
-
init?: { label?: string; value?: string; sort?: number; status?: DictStatus }
|
|
54
|
+
init?: { id: number; label?: string; value?: string; sort?: number; status?: DictStatus }
|
|
56
55
|
);
|
|
57
56
|
method(): 'PUT';
|
|
58
57
|
address(): string;
|
|
@@ -60,20 +59,28 @@ declare class UpdateItem extends RequestBase {
|
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
declare class RemoveItem extends RequestBase {
|
|
63
|
-
constructor(id: number);
|
|
62
|
+
constructor(init?: { id: number });
|
|
64
63
|
method(): 'DELETE';
|
|
65
64
|
address(): string;
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
declare const DictMgr: {
|
|
69
|
-
QueryTypes:
|
|
70
|
-
CreateType:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
QueryTypes: (init?: { page?: number; pageSize?: number }) => QueryTypes;
|
|
69
|
+
CreateType: (
|
|
70
|
+
init?: { name?: string; code?: string; status?: DictStatus; remark?: string }
|
|
71
|
+
) => CreateType;
|
|
72
|
+
UpdateType: (
|
|
73
|
+
init?: { id: number; name?: string; code?: string; status?: DictStatus; remark?: string }
|
|
74
|
+
) => UpdateType;
|
|
75
|
+
RemoveType: (init?: { id: number }) => RemoveType;
|
|
76
|
+
QueryItems: (init?: { typeId: number }) => QueryItems;
|
|
77
|
+
CreateItem: (
|
|
78
|
+
init?: { typeId: number; label?: string; value?: string; sort?: number; status?: DictStatus }
|
|
79
|
+
) => CreateItem;
|
|
80
|
+
UpdateItem: (
|
|
81
|
+
init?: { id: number; label?: string; value?: string; sort?: number; status?: DictStatus }
|
|
82
|
+
) => UpdateItem;
|
|
83
|
+
RemoveItem: (init?: { id: number }) => RemoveItem;
|
|
77
84
|
};
|
|
78
85
|
|
|
79
86
|
export default DictMgr;
|
|
@@ -3,10 +3,20 @@ import { RequestBase } from '@yoyaflow/yoya-ui';
|
|
|
3
3
|
import Dicts from './dict.views.js';
|
|
4
4
|
|
|
5
5
|
class QueryTypes extends RequestBase {
|
|
6
|
+
constructor({ page = 1, pageSize = 10 } = {}) {
|
|
7
|
+
super();
|
|
8
|
+
this.page = page;
|
|
9
|
+
this.pageSize = pageSize;
|
|
10
|
+
}
|
|
11
|
+
|
|
6
12
|
address() {
|
|
7
13
|
return '/dicts/types';
|
|
8
14
|
}
|
|
9
15
|
|
|
16
|
+
params() {
|
|
17
|
+
return { page: this.page, pageSize: this.pageSize };
|
|
18
|
+
}
|
|
19
|
+
|
|
10
20
|
toItem(row) {
|
|
11
21
|
return new Dicts.DictTypeItem(row);
|
|
12
22
|
}
|
|
@@ -35,7 +45,7 @@ class CreateType extends RequestBase {
|
|
|
35
45
|
}
|
|
36
46
|
|
|
37
47
|
class UpdateType extends RequestBase {
|
|
38
|
-
constructor(id,
|
|
48
|
+
constructor({ id, name = '', code = '', status = 'active', remark = '' } = {}) {
|
|
39
49
|
super();
|
|
40
50
|
this.id = id;
|
|
41
51
|
this.name = name;
|
|
@@ -58,7 +68,7 @@ class UpdateType extends RequestBase {
|
|
|
58
68
|
}
|
|
59
69
|
|
|
60
70
|
class RemoveType extends RequestBase {
|
|
61
|
-
constructor(id) {
|
|
71
|
+
constructor({ id } = {}) {
|
|
62
72
|
super();
|
|
63
73
|
this.id = id;
|
|
64
74
|
}
|
|
@@ -73,7 +83,7 @@ class RemoveType extends RequestBase {
|
|
|
73
83
|
}
|
|
74
84
|
|
|
75
85
|
class QueryItems extends RequestBase {
|
|
76
|
-
constructor(typeId) {
|
|
86
|
+
constructor({ typeId } = {}) {
|
|
77
87
|
super();
|
|
78
88
|
this.typeId = typeId;
|
|
79
89
|
}
|
|
@@ -88,7 +98,7 @@ class QueryItems extends RequestBase {
|
|
|
88
98
|
}
|
|
89
99
|
|
|
90
100
|
class CreateItem extends RequestBase {
|
|
91
|
-
constructor(typeId,
|
|
101
|
+
constructor({ typeId, label = '', value = '', sort = 0, status = 'active' } = {}) {
|
|
92
102
|
super();
|
|
93
103
|
this.typeId = typeId;
|
|
94
104
|
this.label = label;
|
|
@@ -111,7 +121,7 @@ class CreateItem extends RequestBase {
|
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
class UpdateItem extends RequestBase {
|
|
114
|
-
constructor(id,
|
|
124
|
+
constructor({ id, label = '', value = '', sort = 0, status = 'active' } = {}) {
|
|
115
125
|
super();
|
|
116
126
|
this.id = id;
|
|
117
127
|
this.label = label;
|
|
@@ -134,7 +144,7 @@ class UpdateItem extends RequestBase {
|
|
|
134
144
|
}
|
|
135
145
|
|
|
136
146
|
class RemoveItem extends RequestBase {
|
|
137
|
-
constructor(id) {
|
|
147
|
+
constructor({ id } = {}) {
|
|
138
148
|
super();
|
|
139
149
|
this.id = id;
|
|
140
150
|
}
|
|
@@ -149,12 +159,12 @@ class RemoveItem extends RequestBase {
|
|
|
149
159
|
}
|
|
150
160
|
|
|
151
161
|
export default {
|
|
152
|
-
QueryTypes,
|
|
153
|
-
CreateType,
|
|
154
|
-
UpdateType,
|
|
155
|
-
RemoveType,
|
|
156
|
-
QueryItems,
|
|
157
|
-
CreateItem,
|
|
158
|
-
UpdateItem,
|
|
159
|
-
RemoveItem
|
|
162
|
+
QueryTypes: (init) => new QueryTypes(init),
|
|
163
|
+
CreateType: (init) => new CreateType(init),
|
|
164
|
+
UpdateType: (init) => new UpdateType(init),
|
|
165
|
+
RemoveType: (init) => new RemoveType(init),
|
|
166
|
+
QueryItems: (init) => new QueryItems(init),
|
|
167
|
+
CreateItem: (init) => new CreateItem(init),
|
|
168
|
+
UpdateItem: (init) => new UpdateItem(init),
|
|
169
|
+
RemoveItem: (init) => new RemoveItem(init)
|
|
160
170
|
};
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
// 字典演示用内存 mock(接入真实后端后删除本文件)。
|
|
2
|
-
import { mockRequest } from '
|
|
2
|
+
import { mockRequest } from '../../../../api/domain.api.js';
|
|
3
3
|
|
|
4
4
|
let types = [
|
|
5
5
|
{ id: 1, name: '性别', code: 'gender', status: 'active', remark: '性别字典' },
|
|
6
6
|
{ id: 2, name: '通用状态', code: 'common_status', status: 'active', remark: '通用启停状态' },
|
|
7
|
-
{ id: 3, name: '通知类型', code: 'notice_type', status: 'active', remark: '消息通知类型' }
|
|
7
|
+
{ id: 3, name: '通知类型', code: 'notice_type', status: 'active', remark: '消息通知类型' },
|
|
8
|
+
{ id: 4, name: '优先级', code: 'priority', status: 'active', remark: '任务/工单优先级' },
|
|
9
|
+
{ id: 5, name: '审批状态', code: 'approval_status', status: 'active', remark: '审批流程状态' },
|
|
10
|
+
{ id: 6, name: '设备状态', code: 'device_status', status: 'active', remark: '设备在线/离线' },
|
|
11
|
+
{ id: 7, name: '客户等级', code: 'customer_level', status: 'active', remark: '客户分层等级' },
|
|
12
|
+
{ id: 8, name: '订单状态', code: 'order_status', status: 'active', remark: '订单流转状态' },
|
|
13
|
+
{ id: 9, name: '支付方式', code: 'payment_method', status: 'active', remark: '支付渠道' },
|
|
14
|
+
{ id: 10, name: '物流状态', code: 'logistics_status', status: 'active', remark: '物流轨迹状态' },
|
|
15
|
+
{ id: 11, name: '用户来源', code: 'user_source', status: 'active', remark: '注册/推广来源' },
|
|
16
|
+
{ id: 12, name: '语言', code: 'language', status: 'active', remark: '界面语言' }
|
|
8
17
|
];
|
|
9
18
|
|
|
10
19
|
let items = [
|
|
@@ -19,9 +28,18 @@ let items = [
|
|
|
19
28
|
|
|
20
29
|
const delay = (ms = 200) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
21
30
|
|
|
22
|
-
mockRequest('GET', '/dicts/types', async () => {
|
|
31
|
+
mockRequest('GET', '/dicts/types', async (req) => {
|
|
23
32
|
await delay();
|
|
24
|
-
|
|
33
|
+
const { page = 1, pageSize = 10 } = req.params();
|
|
34
|
+
const start = (page - 1) * pageSize;
|
|
35
|
+
return {
|
|
36
|
+
ok: true,
|
|
37
|
+
code: '0',
|
|
38
|
+
data: types.slice(start, start + pageSize),
|
|
39
|
+
pageNum: page,
|
|
40
|
+
pageSize,
|
|
41
|
+
total: types.length
|
|
42
|
+
};
|
|
25
43
|
});
|
|
26
44
|
|
|
27
45
|
mockRequest('POST', '/dicts/types', async (req) => {
|
|
@@ -10,6 +10,11 @@ export default class DictsPageState {
|
|
|
10
10
|
selectedTypeId(): number | null;
|
|
11
11
|
selectedType(): DictTypeInstance | null;
|
|
12
12
|
items(): DictItemInstance[];
|
|
13
|
+
page(): number;
|
|
14
|
+
pageSize(): number;
|
|
15
|
+
total(): number;
|
|
16
|
+
setPage(value: number): void;
|
|
17
|
+
setPageSize(value: number): void;
|
|
13
18
|
subscribe(listener: () => void): () => void;
|
|
14
19
|
loadTypes(): Promise<unknown>;
|
|
15
20
|
selectType(id: number): void;
|