create-pactor-app 1.22.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/next-app/README.md +2 -0
- package/templates/next-app/app/api/users/route.ts +57 -0
- package/templates/next-app/app/layout.tsx +2 -4
- package/templates/next-app/app/theme.css +111 -0
- package/templates/next-app/next.config.js +32 -0
- package/templates/next-app/package.json +10 -7
- package/templates/next-app/scripts/build.mjs +35 -0
- package/templates/next-app/src/pactor/config.ts +8 -2
- package/templates/next-app/src/server/accounts.ts +1 -1
- package/templates/next-app/src/server/sitemap.ts +113 -517
- package/templates/next-app/src/server/yaml/pages/home.page.yaml +23 -0
- package/templates/next-app/src/server/yaml/pages/login.page.yaml +69 -0
- package/templates/next-app/src/server/yaml/pages/monthly-detail.page.yaml +23 -0
- package/templates/next-app/src/server/yaml/pages/monthly.page.yaml +41 -0
- package/templates/next-app/src/server/yaml/pages/register.page.yaml +23 -0
- package/templates/next-app/src/server/yaml/pages/users.page.yaml +85 -0
- package/templates/next-app/src/server/yaml/sitemap.yaml +148 -0
- package/templates/spa/package.json +4 -4
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# 登录页 DSL:内联在 sitemap 中下发(public 页,匿名可见)。
|
|
2
|
+
# 登录 / 登出是普通 HTTP 调用,用内置 request 动作表达;
|
|
3
|
+
# 登录成功整页重载,sitemap 端点按已登录会话重新裁剪内容。
|
|
4
|
+
dsl: "1.0"
|
|
5
|
+
page:
|
|
6
|
+
id: login
|
|
7
|
+
title: 登录
|
|
8
|
+
|
|
9
|
+
state:
|
|
10
|
+
submitting: false
|
|
11
|
+
|
|
12
|
+
body:
|
|
13
|
+
type: Form
|
|
14
|
+
events:
|
|
15
|
+
onSubmit:
|
|
16
|
+
- action: setState
|
|
17
|
+
params: { submitting: true }
|
|
18
|
+
- id: loginResult
|
|
19
|
+
action: request
|
|
20
|
+
params:
|
|
21
|
+
method: POST
|
|
22
|
+
url: http://localhost:9011/api/auth/login
|
|
23
|
+
body:
|
|
24
|
+
username: ${event.username}
|
|
25
|
+
password: ${event.password}
|
|
26
|
+
- action: setState
|
|
27
|
+
params: { submitting: false }
|
|
28
|
+
- action: if
|
|
29
|
+
params:
|
|
30
|
+
condition: ${actions.loginResult.token}
|
|
31
|
+
then:
|
|
32
|
+
- action: app.reload
|
|
33
|
+
params: { to: / }
|
|
34
|
+
else:
|
|
35
|
+
- action: message
|
|
36
|
+
params:
|
|
37
|
+
messageType: error
|
|
38
|
+
text: 登录失败:用户名或密码错误
|
|
39
|
+
children:
|
|
40
|
+
- type: Alert
|
|
41
|
+
props:
|
|
42
|
+
variant: info
|
|
43
|
+
message: 演示账号 admin / pactor123,guest / guest123
|
|
44
|
+
description: admin 可见「报表」菜单(report:view);guest 仅可见首页。登录后 sitemap 按角色重新下发。
|
|
45
|
+
style: { marginBottom: 16 }
|
|
46
|
+
- type: Input
|
|
47
|
+
props:
|
|
48
|
+
name: username
|
|
49
|
+
label: 用户名
|
|
50
|
+
placeholder: 请输入用户名
|
|
51
|
+
rules:
|
|
52
|
+
- { required: true, message: 请输入用户名 }
|
|
53
|
+
- type: Input
|
|
54
|
+
props:
|
|
55
|
+
name: password
|
|
56
|
+
label: 密码
|
|
57
|
+
type: password
|
|
58
|
+
placeholder: 请输入密码
|
|
59
|
+
rules:
|
|
60
|
+
- { required: true, message: 请输入密码 }
|
|
61
|
+
- type: Flex
|
|
62
|
+
props: { justify: end }
|
|
63
|
+
children:
|
|
64
|
+
- type: Button
|
|
65
|
+
props:
|
|
66
|
+
text: 登 录
|
|
67
|
+
variant: primary
|
|
68
|
+
submit: true
|
|
69
|
+
loading: ${state.submitting}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 月报详情页 DSL:内联在 sitemap 中下发(需 report:view)。
|
|
2
|
+
# 隐藏页(不出现在菜单),经列表页跳转进入;${route.params.id} 演示路径参数。
|
|
3
|
+
dsl: "1.0"
|
|
4
|
+
page:
|
|
5
|
+
id: monthly-detail
|
|
6
|
+
title: 月报详情
|
|
7
|
+
|
|
8
|
+
body:
|
|
9
|
+
type: Page
|
|
10
|
+
props: { title: 月报详情 }
|
|
11
|
+
children:
|
|
12
|
+
- type: Alert
|
|
13
|
+
props:
|
|
14
|
+
variant: info
|
|
15
|
+
message: 路径参数演示:id = ${route.params.id}
|
|
16
|
+
description: 隐藏页(不出现在菜单),经列表页跳转进入。
|
|
17
|
+
style: { marginBottom: 16 }
|
|
18
|
+
- type: Button
|
|
19
|
+
props: { text: 返回月报 }
|
|
20
|
+
events:
|
|
21
|
+
onClick:
|
|
22
|
+
- action: navigate
|
|
23
|
+
params: { to: /reports/monthly }
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 月报页 DSL:懒加载页——sitemap 中仅声明 id / path / version(monthly@7),
|
|
2
|
+
# 本文件由 /api/pages/monthly 按需下发(见 src/server/sitemap.ts 的 lazyPages)。
|
|
3
|
+
dsl: "1.0"
|
|
4
|
+
page:
|
|
5
|
+
id: monthly
|
|
6
|
+
title: 月报
|
|
7
|
+
|
|
8
|
+
body:
|
|
9
|
+
type: Page
|
|
10
|
+
props: { title: 本月经营月报 }
|
|
11
|
+
children:
|
|
12
|
+
- type: Flex
|
|
13
|
+
props: { gap: 16, style: { marginBottom: 16 } }
|
|
14
|
+
children:
|
|
15
|
+
- type: Card
|
|
16
|
+
props: { title: 营收 }
|
|
17
|
+
children:
|
|
18
|
+
- type: Statistic
|
|
19
|
+
props: { title: 本月(万元), value: 128.6 }
|
|
20
|
+
- type: Card
|
|
21
|
+
props: { title: 新增客户 }
|
|
22
|
+
children:
|
|
23
|
+
- type: Statistic
|
|
24
|
+
props: { title: 本月(家), value: 342 }
|
|
25
|
+
- type: Card
|
|
26
|
+
props: { title: 转化率 }
|
|
27
|
+
children:
|
|
28
|
+
- type: Statistic
|
|
29
|
+
props: { title: 本月(%), value: 23.8 }
|
|
30
|
+
- type: Alert
|
|
31
|
+
props:
|
|
32
|
+
variant: success
|
|
33
|
+
message: 本页 DSL 由 /api/pages/monthly 懒加载下发
|
|
34
|
+
description: sitemap 中该页仅声明 id / path / version(monthly@7),点击进入时才请求页面 DSL。
|
|
35
|
+
style: { marginBottom: 16 }
|
|
36
|
+
- type: Button
|
|
37
|
+
props: { text: 查看详情(隐藏页 + 路径参数) }
|
|
38
|
+
events:
|
|
39
|
+
onClick:
|
|
40
|
+
- action: navigate
|
|
41
|
+
params: { to: /reports/monthly/2026-09 }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 注册页 DSL:内联在 sitemap 中下发(public 页,匿名可见)。
|
|
2
|
+
# 演示环境不开放注册,仅作多 public 页示例。
|
|
3
|
+
dsl: "1.0"
|
|
4
|
+
page:
|
|
5
|
+
id: register
|
|
6
|
+
title: 注册
|
|
7
|
+
|
|
8
|
+
body:
|
|
9
|
+
type: Page
|
|
10
|
+
props: { title: 注册 }
|
|
11
|
+
children:
|
|
12
|
+
- type: Alert
|
|
13
|
+
props:
|
|
14
|
+
variant: warning
|
|
15
|
+
message: 演示环境不开放注册
|
|
16
|
+
description: 请使用登录页的演示账号体验不同角色的菜单差异。
|
|
17
|
+
style: { marginBottom: 16 }
|
|
18
|
+
- type: Button
|
|
19
|
+
props: { text: 返回登录, variant: primary }
|
|
20
|
+
events:
|
|
21
|
+
onClick:
|
|
22
|
+
- action: navigate
|
|
23
|
+
params: { to: /login }
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# 用户列表页 DSL:由 /api/pages/users 懒加载下发(见 src/server/sitemap.ts)。
|
|
2
|
+
# 数据来自 /api/users(接口侧鉴权,需登录且具备 user:view 权限)。
|
|
3
|
+
dsl: "1.0"
|
|
4
|
+
page:
|
|
5
|
+
id: users
|
|
6
|
+
title: 用户列表
|
|
7
|
+
permission: user:view
|
|
8
|
+
|
|
9
|
+
state:
|
|
10
|
+
keyword: ""
|
|
11
|
+
role: ""
|
|
12
|
+
|
|
13
|
+
dataSources:
|
|
14
|
+
users:
|
|
15
|
+
type: http
|
|
16
|
+
autoLoad: true
|
|
17
|
+
request:
|
|
18
|
+
method: GET
|
|
19
|
+
url: http://localhost:9011/api/users
|
|
20
|
+
params:
|
|
21
|
+
keyword: ${state.keyword}
|
|
22
|
+
role: ${state.role}
|
|
23
|
+
|
|
24
|
+
body:
|
|
25
|
+
type: Page
|
|
26
|
+
props: { title: 用户列表 }
|
|
27
|
+
children:
|
|
28
|
+
- type: Card
|
|
29
|
+
props: { title: 筛选 }
|
|
30
|
+
children:
|
|
31
|
+
- type: Form
|
|
32
|
+
props: { layout: inline }
|
|
33
|
+
events:
|
|
34
|
+
onSubmit:
|
|
35
|
+
- action: setState
|
|
36
|
+
params:
|
|
37
|
+
keyword: ${event.keyword}
|
|
38
|
+
role: ${event.role}
|
|
39
|
+
- action: reload
|
|
40
|
+
params: { dataSource: users }
|
|
41
|
+
children:
|
|
42
|
+
- type: Input
|
|
43
|
+
props: { name: keyword, label: 关键词, placeholder: 姓名 / 用户名 }
|
|
44
|
+
- type: Select
|
|
45
|
+
props:
|
|
46
|
+
name: role
|
|
47
|
+
label: 角色
|
|
48
|
+
placeholder: 请选择角色
|
|
49
|
+
options:
|
|
50
|
+
- { label: 管理员, value: admin }
|
|
51
|
+
- { label: 成员, value: member }
|
|
52
|
+
- { label: 访客, value: guest }
|
|
53
|
+
- type: Button
|
|
54
|
+
props: { text: 查询, variant: primary, submit: true }
|
|
55
|
+
- type: Card
|
|
56
|
+
props: { title: 用户数据 }
|
|
57
|
+
children:
|
|
58
|
+
- type: Table
|
|
59
|
+
props:
|
|
60
|
+
dataSource: ${data.users}
|
|
61
|
+
loading: ${dataStatus.users.loading}
|
|
62
|
+
rowKey: id
|
|
63
|
+
pagination: { pageSize: 5 }
|
|
64
|
+
columns:
|
|
65
|
+
- { title: 姓名, dataIndex: name }
|
|
66
|
+
- { title: 用户名, dataIndex: username }
|
|
67
|
+
- title: 角色
|
|
68
|
+
dataIndex: role
|
|
69
|
+
cell:
|
|
70
|
+
type: Badge
|
|
71
|
+
props:
|
|
72
|
+
text: ${row.role}
|
|
73
|
+
variant: secondary
|
|
74
|
+
- { title: 邮箱, dataIndex: email }
|
|
75
|
+
- { title: 创建时间, dataIndex: createdAt }
|
|
76
|
+
- title: 操作
|
|
77
|
+
cell:
|
|
78
|
+
type: Button
|
|
79
|
+
props: { text: 查看, variant: primary, size: small }
|
|
80
|
+
events:
|
|
81
|
+
onClick:
|
|
82
|
+
- action: message
|
|
83
|
+
params:
|
|
84
|
+
messageType: info
|
|
85
|
+
text: 用户 ${row.name}(${row.username})
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Sitemap 入口数据(design/dynamic-page.md 方案 B):元数据 + 布局 + 页面 + 菜单全量。
|
|
2
|
+
# 本文件是会话无关的超集;可见性由 src/server/sitemap.ts 按会话裁剪:
|
|
3
|
+
# public: true → 匿名可见(登录/注册页)
|
|
4
|
+
# permission: x → 需登录且具备对应权限
|
|
5
|
+
# 无标记 → 需登录
|
|
6
|
+
# 页面 DSL 按 id 约定从 pages/<id>.page.yaml 加载;lazy: true 不随 sitemap
|
|
7
|
+
# 内联下发,客户端经 /api/pages/{id} 懒加载。updatedAt / user / permissions
|
|
8
|
+
# 为会话动态字段,由服务端在响应时注入。
|
|
9
|
+
|
|
10
|
+
id: site
|
|
11
|
+
resourceType: sitemap
|
|
12
|
+
version: 13
|
|
13
|
+
dslVersion: "1.0"
|
|
14
|
+
app: { name: 动态页面 Starter }
|
|
15
|
+
layout: admin
|
|
16
|
+
auth: { loginPath: /login }
|
|
17
|
+
|
|
18
|
+
pages:
|
|
19
|
+
- { id: login, path: /login, title: 登录, version: 1, public: true }
|
|
20
|
+
- { id: register, path: /register, title: 注册, version: 1, public: true }
|
|
21
|
+
- { id: home, path: /, title: 首页, version: 3 }
|
|
22
|
+
- { id: users, path: /users, title: 用户列表, version: 1, permission: user:view, lazy: true }
|
|
23
|
+
- { id: monthly, path: /reports/monthly, title: 月报, version: 7, permission: report:view, lazy: true }
|
|
24
|
+
- { id: monthly-detail, path: /reports/monthly/:id, title: 月报详情, version: 2, permission: report:view }
|
|
25
|
+
|
|
26
|
+
menus:
|
|
27
|
+
- { id: login, type: page, pageId: login, title: 登录, layout: login, public: true, hidden: true }
|
|
28
|
+
- { id: register, type: page, pageId: register, title: 注册, layout: login, public: true, hidden: true }
|
|
29
|
+
- { id: home, type: page, pageId: home, title: 首页, icon: home, layout: admin, order: 1 }
|
|
30
|
+
- { id: users, type: page, pageId: users, title: 用户列表, icon: users, layout: admin, permission: user:view, order: 2 }
|
|
31
|
+
- id: reports
|
|
32
|
+
type: group
|
|
33
|
+
title: 报表
|
|
34
|
+
icon: chart
|
|
35
|
+
order: 3
|
|
36
|
+
children:
|
|
37
|
+
- { id: monthly, type: page, pageId: monthly, title: 报表中心, icon: chart, layout: admin, permission: report:view }
|
|
38
|
+
- { id: monthly-detail, type: page, pageId: monthly-detail, title: 月报详情, layout: admin, hidden: true, activeMenu: monthly, permission: report:view }
|
|
39
|
+
- { id: help, type: link, title: 帮助, path: https://github.com/, external: true, permission: report:view, order: 4 }
|
|
40
|
+
|
|
41
|
+
# 布局 DSL(PageOutlet 为页面内容出口)。
|
|
42
|
+
# 布局 body 内 ${data.session.*} 由客户端注入的 session dataSource 提供
|
|
43
|
+
#(user / app / menus);${route.params.pathname} 为当前路径(客户端注入)。
|
|
44
|
+
# 登录 / 登出是普通 HTTP 调用,DSL 用内置 request 动作表达(跨域绝对地址,
|
|
45
|
+
# 客户端 httpHooks 自动改写进项目内代理前缀),无需客户端注册服务。
|
|
46
|
+
layouts:
|
|
47
|
+
# 管理端外壳:左侧 SitemapMenu 导航 + 顶栏用户菜单 + PageOutlet
|
|
48
|
+
admin:
|
|
49
|
+
dsl: "1.0"
|
|
50
|
+
body:
|
|
51
|
+
type: Flex
|
|
52
|
+
props: { gap: 0, direction: horizontal, style: { height: 100vh } }
|
|
53
|
+
children:
|
|
54
|
+
- type: Flex
|
|
55
|
+
props:
|
|
56
|
+
direction: vertical
|
|
57
|
+
style:
|
|
58
|
+
width: 224
|
|
59
|
+
flexShrink: 0
|
|
60
|
+
borderRight: 1px solid var(--border)
|
|
61
|
+
children:
|
|
62
|
+
- type: Flex
|
|
63
|
+
props:
|
|
64
|
+
style:
|
|
65
|
+
padding: 16px 16px
|
|
66
|
+
fontWeight: 600
|
|
67
|
+
borderBottom: 1px solid var(--border)
|
|
68
|
+
children:
|
|
69
|
+
- type: Text
|
|
70
|
+
props: { text: "${data.session.app.name}" }
|
|
71
|
+
- type: SitemapMenu
|
|
72
|
+
props:
|
|
73
|
+
items: ${data.session.menus}
|
|
74
|
+
collapsible: true
|
|
75
|
+
events:
|
|
76
|
+
onSelect:
|
|
77
|
+
- action: navigate
|
|
78
|
+
params: { to: "${event}" }
|
|
79
|
+
- type: Flex
|
|
80
|
+
props:
|
|
81
|
+
direction: vertical
|
|
82
|
+
style: { flex: 1, minWidth: 0 }
|
|
83
|
+
children:
|
|
84
|
+
- type: Flex
|
|
85
|
+
props:
|
|
86
|
+
justify: end
|
|
87
|
+
align: center
|
|
88
|
+
style:
|
|
89
|
+
padding: 10px 20px
|
|
90
|
+
borderBottom: 1px solid var(--border)
|
|
91
|
+
children:
|
|
92
|
+
- type: DropdownMenu
|
|
93
|
+
props:
|
|
94
|
+
items:
|
|
95
|
+
- { label: 个人设置, value: settings, icon: settings }
|
|
96
|
+
- { label: 退出登录, value: logout, icon: log-out }
|
|
97
|
+
events:
|
|
98
|
+
onSelect:
|
|
99
|
+
- action: if
|
|
100
|
+
params:
|
|
101
|
+
condition: ${event == 'logout'}
|
|
102
|
+
then:
|
|
103
|
+
- action: request
|
|
104
|
+
params:
|
|
105
|
+
method: POST
|
|
106
|
+
url: http://localhost:9011/api/auth/logout
|
|
107
|
+
- action: app.reload
|
|
108
|
+
params: { to: /login }
|
|
109
|
+
else:
|
|
110
|
+
- action: message
|
|
111
|
+
params: { text: 演示环境未实现个人设置 }
|
|
112
|
+
children:
|
|
113
|
+
- type: Button
|
|
114
|
+
props:
|
|
115
|
+
text: ${data.session.user.name}
|
|
116
|
+
variant: text
|
|
117
|
+
- type: Flex
|
|
118
|
+
props:
|
|
119
|
+
direction: vertical
|
|
120
|
+
style: { flex: 1, minHeight: 0, overflow: auto }
|
|
121
|
+
children:
|
|
122
|
+
- type: PageOutlet
|
|
123
|
+
# 登录 / 注册页外壳:居中卡片
|
|
124
|
+
login:
|
|
125
|
+
dsl: "1.0"
|
|
126
|
+
body:
|
|
127
|
+
type: Flex
|
|
128
|
+
props:
|
|
129
|
+
direction: vertical
|
|
130
|
+
justify: center
|
|
131
|
+
align: center
|
|
132
|
+
style: { minHeight: 100vh, padding: 24 }
|
|
133
|
+
children:
|
|
134
|
+
- type: Flex
|
|
135
|
+
props:
|
|
136
|
+
direction: vertical
|
|
137
|
+
style:
|
|
138
|
+
width: 380
|
|
139
|
+
padding: 24
|
|
140
|
+
border: 1px solid var(--border)
|
|
141
|
+
borderRadius: 12
|
|
142
|
+
children:
|
|
143
|
+
- type: PageOutlet
|
|
144
|
+
# 裸布局:无外壳,页面铺满
|
|
145
|
+
blank:
|
|
146
|
+
dsl: "1.0"
|
|
147
|
+
body:
|
|
148
|
+
type: PageOutlet
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
"typecheck": "tsc --noEmit"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@pactor-app/core": "^1.
|
|
14
|
-
"@pactor-app/runtime": "^1.
|
|
15
|
-
"@pactor-app/ui": "^1.
|
|
16
|
-
"pactor-app": "^1.
|
|
13
|
+
"@pactor-app/core": "^1.23.0",
|
|
14
|
+
"@pactor-app/runtime": "^1.23.0",
|
|
15
|
+
"@pactor-app/ui": "^1.23.0",
|
|
16
|
+
"pactor-app": "^1.23.0",
|
|
17
17
|
"react": "19.2.8",
|
|
18
18
|
"react-dom": "19.2.8",
|
|
19
19
|
"react-router-dom": "^7.18.2"
|