@pactor-app/skills 1.32.0 → 1.34.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pactor-app/skills",
3
- "version": "1.32.0",
3
+ "version": "1.34.0",
4
4
  "description": "Agent skills for rapidly building pactor Server-Driven UI applications",
5
5
  "keywords": [
6
6
  "pactor",
@@ -30,7 +30,7 @@ version: 1.3.0
30
30
  3. **样式与原产品一致**:主题令牌(含深浅色)、自定义 CSS(如登录页)、换肤入口全部移植对齐,见 `references/theme-and-style.md`
31
31
  4. **功能与原产品一致**:线框图描述的筛选/搜索/跳转/弹窗/提交等交互必须经 events/actions 闭环可用,禁止只画静态骨架;错误分支(校验失败提示等)也要实现
32
32
  5. **表单一律用 `Form` 组件**:凡是一组「字段 + 校验 + 提交」的表单——独立表单页、页面内嵌的配置面板(如树/列表右侧的编辑表单)、弹窗/抽屉表单、**搜索栏(关键词 + 查询/重置 的筛选区,用 `Form layout: inline`)**——都必须用 `Form` 包裹,字段经 `props.name` 绑定,校验用字段级 `rules`(required + message),提交用 `submit: true` 的 Button 触发 `onSubmit`;**禁止**散放 `Input`/`Select` + `setState` 攒草稿 + `if` 动作手写校验。上下结构的字段一律用 `Field` 包裹:label、必填星号(`required: true`)、行右提示(`labelHint`)由 `Field` 渲染,控件上只留 `name`/`rules` 等(`Form layout: inline` 的搜索栏除外,label 直接挂控件);禁止手写 `Text("*") + Label` 拼标签。回填联动(如点击列表/树节点填充表单)用 `form.setValues` 动作,不要绑 `${state.x}` 到字段 value;即点即生效的 ChipFilter 快筛行没有提交语义,不属于表单
33
- 6. **列表页操作列规范**:操作列按钮样式统一 `Button variant: link`;「编辑」与「新建」指向同一个表单(同一路由页或同一弹窗),唯一区别是编辑以行数据预填(路由页 `initialValues: ${data.detail}`,弹窗/内嵌面板 `form.setValues`)
33
+ 6. **列表页操作列规范**:操作列按钮样式统一 `Button variant: link`;「编辑」与「新建」指向同一个表单(同一路由页或同一弹窗),唯一区别是编辑以行数据预填(路由页 `initialValues: ${data.detail}`,弹窗/内嵌面板 `form.setValues`);**数据列表页(搜索 + 表格 + 新建/编辑)以 `template/src/server/yaml/models/data-list.yaml` 为标准骨架生成**(结构与要点见 `references/page-templates.md`「数据列表标准模型」)
34
34
  7. **文案以线框图为准**:标题、按钮、空态文案逐字取自线框图/PRD
35
35
  8. DSL 语法细节(组件 props、表达式、动作)以 `pactor-dsl` skill 与 packages/ui 当前导出为准,本 skill 只约定流程与产出物
36
36
 
@@ -57,7 +57,7 @@ version: 1.3.0
57
57
  - **整体复制 `template/`** 为新项目起点;不要用 `pnpm create pactor-app` 替代
58
58
  - 工程名:README 产品名 → kebab-case 英文名,创建前确认一次
59
59
  - `pnpm install` + dev 验证;核对 `references/project-structure.md`
60
- - 参考模块 provider/route 作样板;**全站生成完成后删除**参考模块及 mock
60
+ - 参考模块 provider/route 作样板;`yaml/models/` 是页面骨架目录(按模块目录结构存放,已注册 sitemap、菜单「页面骨架」分组可直接预览),生成时复制到目标模块目录改字段与文案;**全站生成完成后删除**参考模块、models/ 及对应 mock
61
61
 
62
62
  **增量**
63
63
 
@@ -69,7 +69,7 @@ version: 1.3.0
69
69
  - **新建工程**:清单一行 = 一个文件 `yaml/<模块>/<page-id>.yaml`(或工程既定 A/B 规则);`mkdir` 模块目录;N = P0/P1 行数
70
70
  - **增量**:仅 **add** 新建文件;**update** 改已有 yaml;**deprecate** 删文件并改 sitemap(须用户确认)
71
71
  - 校验见 `page-inventory-and-files.md`(全量)或 `incremental-wireframe-delta.md`(增量)
72
- - 按 `references/component-mapping.md` 映射组件;按 `references/page-templates.md` 选列表/详情/表单模板;表单一律 `Form` 包裹
72
+ - 按 `references/component-mapping.md` 映射组件;按 `references/page-templates.md` 选列表/详情/表单模板(**数据列表页直接复制 `yaml/models/data-list.yaml` 替换占位符**);表单一律 `Form` 包裹
73
73
  - 同步更新 `sitemap.yaml` 的 `pages` + `menus`(hidden 详情/编辑带 `activeMenu`)
74
74
  - 每页 dataSources 全部 `type: http`;交互 events + actions 闭环
75
75
 
@@ -93,7 +93,7 @@ version: 1.3.0
93
93
  | `references/incremental-wireframe-delta.md` | **已有工程**:线框图 add/update/deprecate、改 sitemap/mock/样式 |
94
94
  | `references/project-structure.md` | 阶段 2:目录结构约定与 sitemap.yaml 骨架 |
95
95
  | `references/component-mapping.md` | 阶段 3:线框图区域 → pactor 组件映射 |
96
- | `references/page-templates.md` | 阶段 3:列表/详情/表单页 yaml 模板 |
96
+ | `references/page-templates.md` | 阶段 3:列表/详情/表单页 yaml 模板;数据列表页默认用「数据列表标准模型」(搜索 Form + 表格 + 抽屉新建/编辑) |
97
97
  | `references/mock-data-routes.md` | 阶段 4:mock 路由表模板与命名约定 |
98
98
  | `references/theme-and-style.md` | 阶段 5:主题令牌提取、皮肤、自定义 CSS、换肤 |
99
99
  | `references/acceptance-checklist.md` | 阶段 6:验收清单与结果输出格式 |
@@ -1,8 +1,344 @@
1
1
  # 页面 YAML 模板
2
2
 
3
- 三类常用页面模板。占位符:`{{kebab-id}}` 页面 id、`{{页面标题}}`、`{{模块名}}`、`{{resource}}` 数据接口名(单段,见 mock-data-routes.md)。DSL 语法细节以 `pactor-dsl` skill 与 packages/ui 当前导出为准。
3
+ 常用页面模板。占位符:`{{kebab-id}}` 页面 id、`{{页面标题}}`、`{{模块名}}`、`{{resource}}` 数据接口名(单段,见 mock-data-routes.md)、`{{实体名}}` 业务实体中文名。DSL 语法细节以 `pactor-dsl` skill 与 packages/ui 当前导出为准。
4
4
 
5
- ## 列表页(筛选 + 表格/卡片 + 操作列)
5
+ **数据列表页(搜索 + 表格 + 新建/编辑)默认套用「数据列表标准模型」**;仅当新建/编辑是独立路由表单页时才用轻量变体。
6
+
7
+ ## 数据列表标准模型(搜索 Form + 表格 + 抽屉新建/编辑)
8
+
9
+ 从成熟实现提取的完整闭环:搜索过滤、新建/编辑共用抽屉表单(分区 + 条件显隐 + 预填)、操作列 link 按钮。**完整可拷贝的骨架文件:`template/src/server/yaml/models/data-list.yaml`**(已注册进模板 sitemap 的可运行示例,菜单「页面骨架 / 数据列表」直接预览;复制后替换页面信息、字段、接口名与文案即可,配套 mock 为 `template/src/pactor/mocks/data-list-mock.ts`)。结构照抄,字段按线框图替换:
10
+
11
+ ```yaml
12
+ dsl: "1.0"
13
+ page:
14
+ id: {{kebab-id}}
15
+ title: {{页面标题}}
16
+ name: {{camelName}}
17
+ state:
18
+ # 搜索条件镜像:Form submit 后写入,驱动列表请求参数
19
+ keyword: ""
20
+ status: all
21
+ editingId: ""
22
+ # 表单条件显隐镜像(onValuesChange 写入;按线框图需要增减,可多个)
23
+ fType: ""
24
+ dataSources:
25
+ list:
26
+ type: http
27
+ autoLoad: true
28
+ request:
29
+ method: GET
30
+ url: /api/data/{{resource}}
31
+ params:
32
+ keyword: ${state.keyword}
33
+ status: ${state.status}
34
+ editing: # 编辑预填;autoLoad: false,打开抽屉前手动 reload
35
+ type: http
36
+ autoLoad: false
37
+ request:
38
+ method: GET
39
+ url: /api/data/{{resource}}/${state.editingId}
40
+ body:
41
+ type: Page
42
+ children:
43
+ - type: Breadcrumb
44
+ props:
45
+ items:
46
+ - label: {{模块名}}
47
+ - label: {{页面标题}}
48
+ # 标题行:左标题 + 副标题,右新建按钮
49
+ - type: Flex
50
+ props:
51
+ justify: space-between
52
+ align: center
53
+ children:
54
+ - type: Flex
55
+ props:
56
+ direction: vertical
57
+ gap: 2
58
+ children:
59
+ - type: Typography
60
+ props:
61
+ variant: h3
62
+ text: {{页面标题}}
63
+ - type: Typography
64
+ props:
65
+ variant: muted
66
+ text: {{页面副标题(取自线框图说明文字)}}
67
+ - type: Button
68
+ props:
69
+ text: + 新建{{实体名}}
70
+ variant: primary
71
+ events:
72
+ onClick:
73
+ - action: setState # 清空编辑态与显隐镜像
74
+ params:
75
+ editingId: ""
76
+ fType: ""
77
+ - action: reload # 清空 editing 数据(${state.editingId} 为空 → 接口返回空对象)
78
+ params:
79
+ dataSource: editing
80
+ - action: overlay.open # 锚点 &entityDrawer 在此定义,表格行内用 *entityDrawer 引用
81
+ params:
82
+ overlay: &entityDrawer
83
+ type: drawer
84
+ title: "${state.editingId == '' ? '新建{{实体名}}' : '编辑{{实体名}}'}"
85
+ width: 720
86
+ content:
87
+ type: Form
88
+ props:
89
+ name: entityForm
90
+ layout: vertical
91
+ initialValues: ${data.editing}
92
+ events:
93
+ # 条件显隐字段镜像到 state(其他字段变化时保持原值)
94
+ onValuesChange:
95
+ - action: setState
96
+ params:
97
+ fType: "${event.type != null ? event.type : state.fType}"
98
+ onSubmit:
99
+ - action: request
100
+ params:
101
+ method: POST
102
+ url: /api/data/ops/{{resource}}-save
103
+ body:
104
+ id: ${state.editingId}
105
+ name: ${event.name}
106
+ # ... 其余字段照抄 event
107
+ - action: message
108
+ params:
109
+ messageType: success
110
+ text: 已保存(演示)
111
+ - action: overlay.close
112
+ children:
113
+ # 分区结构:标题 → 分割线 → 字段组(不用 Card)
114
+ - type: Flex
115
+ props:
116
+ direction: vertical
117
+ gap: middle
118
+ children:
119
+ - type: Text
120
+ props:
121
+ text: 基本信息
122
+ strong: true
123
+ - type: Separator
124
+ - type: Flex
125
+ props:
126
+ direction: vertical
127
+ gap: small
128
+ children:
129
+ - type: Field
130
+ props:
131
+ label: 名称
132
+ required: true
133
+ children:
134
+ - type: Input
135
+ props:
136
+ name: name
137
+ rules:
138
+ - required: true
139
+ message: 请输入名称
140
+ # 成对字段用 Grid 两列
141
+ - type: Grid
142
+ props:
143
+ columns: 2
144
+ gap: 16
145
+ children:
146
+ - type: Field
147
+ props:
148
+ label: 类型
149
+ required: true
150
+ children:
151
+ - type: Select
152
+ props:
153
+ name: type
154
+ placeholder: 请选择类型
155
+ options: ${data.list.filters.type}
156
+ rules:
157
+ - required: true
158
+ message: 请选择类型
159
+ - type: Field
160
+ props:
161
+ label: 排序
162
+ children:
163
+ - type: NumberInput
164
+ props:
165
+ name: sort
166
+ className: w-full
167
+ min: 0
168
+ precision: 0
169
+ # 条件显隐字段:依赖镜像 state
170
+ - when: ${state.fType == 'XXX'}
171
+ type: Field
172
+ props:
173
+ label: 条件字段
174
+ children:
175
+ - type: Input
176
+ props:
177
+ name: extra
178
+ # 编辑时禁用关键字段
179
+ - type: Field
180
+ props:
181
+ label: 编码
182
+ required: true
183
+ children:
184
+ - type: Input
185
+ props:
186
+ name: code
187
+ disabled: ${state.editingId != ''}
188
+ rules:
189
+ - required: true
190
+ message: 请输入编码
191
+ # 底部按钮:取消关抽屉,保存触发 Form onSubmit
192
+ - type: Flex
193
+ props:
194
+ justify: end
195
+ gap: small
196
+ className: mt-4
197
+ children:
198
+ - type: Button
199
+ props:
200
+ text: 取消
201
+ events:
202
+ onClick:
203
+ - action: overlay.close
204
+ - type: Button
205
+ props:
206
+ text: 保存
207
+ variant: primary
208
+ submit: true
209
+ htmlType: submit
210
+ - action: reload # overlay.open 阻塞到关闭,关闭后刷新列表
211
+ params:
212
+ dataSource: list
213
+ # 搜索栏:Form(layout: inline) + Field 包裹控件
214
+ - type: Card
215
+ children:
216
+ - type: Form
217
+ props:
218
+ name: search
219
+ layout: inline
220
+ events:
221
+ onSubmit:
222
+ - action: setState
223
+ params:
224
+ keyword: ${event.keyword}
225
+ status: ${event.status}
226
+ - action: reload
227
+ params:
228
+ dataSource: list
229
+ children:
230
+ - type: Field
231
+ props:
232
+ label: 编码/名称
233
+ children:
234
+ - type: Input
235
+ props:
236
+ name: keyword
237
+ placeholder: 支持模糊查询
238
+ - type: Field
239
+ props:
240
+ label: 状态
241
+ children:
242
+ - type: Select
243
+ props:
244
+ name: status
245
+ placeholder: 请选择状态
246
+ options: ${data.list.filters.status} # 选项由接口下发
247
+ # 按钮也放进 Field:label 用不间断空格(U+00A0)占位,与左侧控件底部对齐
248
+ - type: Field
249
+ props:
250
+ label: " "
251
+ children:
252
+ - type: Flex
253
+ props:
254
+ gap: small
255
+ align: center
256
+ children:
257
+ - type: Button
258
+ props:
259
+ text: 查询
260
+ submit: true
261
+ htmlType: submit
262
+ - type: Button
263
+ props:
264
+ text: 重置
265
+ events:
266
+ onClick:
267
+ - action: form.setValues
268
+ params:
269
+ form: search
270
+ values:
271
+ keyword: ""
272
+ status: all
273
+ - action: setState
274
+ params:
275
+ keyword: ""
276
+ status: all
277
+ - action: reload
278
+ params:
279
+ dataSource: list
280
+ # 表格:名称列/操作列按钮统一 variant: link size: small
281
+ - type: Table
282
+ props:
283
+ dataSource: ${data.list.items}
284
+ rowKey: id
285
+ pagination: false
286
+ className: mt-4
287
+ columns:
288
+ - title: 名称
289
+ cell:
290
+ type: Button
291
+ props:
292
+ text: ${row.name}
293
+ variant: link
294
+ size: small
295
+ events:
296
+ onClick: &editRow # 行点击 = 编辑,锚点在此定义
297
+ - action: setState # 写入编辑 id + 显隐镜像(取自行数据)
298
+ params:
299
+ editingId: ${row.id}
300
+ fType: ${row.type}
301
+ - action: reload
302
+ params:
303
+ dataSource: editing
304
+ - action: overlay.open
305
+ params:
306
+ overlay: *entityDrawer
307
+ - action: reload
308
+ params:
309
+ dataSource: list
310
+ - title: 编码
311
+ dataIndex: code
312
+ - title: 状态
313
+ dataIndex: status
314
+ - title: 操作
315
+ cell:
316
+ type: Button
317
+ props:
318
+ text: 编辑
319
+ variant: link
320
+ size: small
321
+ events:
322
+ onClick: *editRow # 与名称列同一动作
323
+ - type: Text
324
+ props:
325
+ text: 共 ${data.list.total} 条
326
+ type: secondary
327
+ className: mt-3
328
+ ```
329
+
330
+ 要点:
331
+
332
+ - **新建/编辑共用同一抽屉**:YAML 锚点 `&entityDrawer` 在「新建」按钮的 `overlay.open` 中定义(必须先出现),表格行内 `*entityDrawer` 引用;`title` 用 `${state.editingId == '' ? ... }` 三元切换;唯一区别是编辑以 `initialValues: ${data.editing}` 预填
333
+ - **抽屉宽度 720**(`overlay.open type: drawer` 的 `width` 生效);抽屉内分区**不用 Card**:`Text(strong) 标题 → Separator → 字段组`,多个分区重复此结构
334
+ - **搜索栏按钮对齐**:查询/重置放进 `Field`,其 `label` 用不间断空格 U+00A0(直接敲 `" "` 普通空格可能被压缩),与左侧控件基线对齐
335
+ - **Form 不能嵌套**(渲染原生 `<form>`,submit 冒泡):抽屉内只用一个 Form;主从多值(如字典项)的子项编辑在**同一 Form** 内做「子 Table + 行下展开表单」,`onSubmit` 用 `if` 动作按 state 分流提交目标(子项保存走独立 ops 接口 + `reload editing`);表达式不支持数组方法/箭头函数,子项草稿必须走 mock 接口不能前端拼
336
+ - **编辑预填链路**:`setState(editingId + 显隐镜像)` → `reload editing` → `overlay.open`;镜像值取自行数据(`${row.type}`),不要等 editing 接口
337
+ - **overlay.open 阻塞到关闭**,关闭后 `reload list`;新建按钮同理(先重置 state 再 reload editing 清空)
338
+ - **条件显隐**:`onValuesChange` 把字段值镜像到 state(`"${event.x != null ? event.x : state.x}"` 保持其他字段变化时原值),再用 `when` 控制显隐;编辑时关键字段 `disabled: ${state.editingId != ''}`
339
+ - 空 `editingId` 时 mock 的 detail 接口须返回空对象而非 404
340
+
341
+ ## 列表页(轻量变体:新建/编辑跳独立表单页)
6
342
 
7
343
  ```yaml
8
344
  dsl: "1.0"
@@ -27,6 +27,8 @@ const ROUTE_TABLE: Record<string, string> = {
27
27
  costs: "cost.list",
28
28
  audit: "audit.list",
29
29
  "audit-operators": "audit.operators",
30
+ "data-list": "dataList.list",
31
+ "ops/data-list-save": "dataList.save",
30
32
  "ops/model-usage": "ops.modelUsage",
31
33
  "ops/provider-usage": "ops.providerUsage",
32
34
  "ops/client-usage": "ops.clientUsage",
@@ -43,6 +45,7 @@ const DETAIL_TABLE: Record<string, string> = {
43
45
  "call-logs": "callLog.detail",
44
46
  costs: "cost.detail",
45
47
  audit: "audit.detail",
48
+ "data-list": "dataList.detail",
46
49
  };
47
50
 
48
51
  const SUB_TABLE: Record<string, string> = {
@@ -114,5 +117,44 @@ export async function GET(
114
117
  });
115
118
  }
116
119
 
120
+ /** 写操作(ops 前缀的保存类接口,如骨架示例的新建/编辑提交) */
121
+ export async function POST(
122
+ request: Request,
123
+ context: RouteContext<"/api/data/[...parts]">,
124
+ ) {
125
+ const store = await cookies();
126
+ const user = findUserBySession(store.get(SESSION_COOKIE)?.value);
127
+ if (!user) {
128
+ return Response.json(
129
+ { error: "未登录" },
130
+ { status: 401, headers: corsHeaders(request) },
131
+ );
132
+ }
133
+
134
+ const { parts } = await context.params;
135
+ if (parts[0] !== "ops") {
136
+ return Response.json(
137
+ { error: "仅 ops 接口支持 POST" },
138
+ { status: 405, headers: corsHeaders(request) },
139
+ );
140
+ }
141
+ const resolved = resolveService(parts);
142
+ if (!resolved) {
143
+ return Response.json(
144
+ { error: `未知数据接口: /api/data/${parts.join("/")}` },
145
+ { status: 404, headers: corsHeaders(request) },
146
+ );
147
+ }
148
+
149
+ const body = (await request.json().catch(() => ({}))) as Record<
150
+ string,
151
+ unknown
152
+ >;
153
+ const result = await pactorServices[resolved.service](body);
154
+ return Response.json(result ?? null, {
155
+ headers: { "cache-control": "no-store", ...corsHeaders(request) },
156
+ });
157
+ }
158
+
117
159
  /** 预检(跨源带凭据 / 自定义头时) */
118
160
  export const OPTIONS = corsPreflight;
@@ -1,7 +1,7 @@
1
1
  /// <reference types="next" />
2
2
  /// <reference types="next/image-types/global" />
3
- import "./.next/dev/types/routes.d.ts";
4
- import "./.next/dev/types/root-params.d.ts";
3
+ import "./.next/types/routes.d.ts";
4
+ import "./.next/types/root-params.d.ts";
5
5
 
6
6
  // NOTE: This file should not be edited
7
7
  // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -11,12 +11,12 @@
11
11
  "build:test": "node scripts/build.mjs test"
12
12
  },
13
13
  "dependencies": {
14
- "@pactor-app/core": "^1.27.0",
15
- "@pactor-app/runtime": "^1.27.0",
16
- "@pactor-app/ui": "^1.27.0",
14
+ "@pactor-app/core": "^1.34.0",
15
+ "@pactor-app/runtime": "^1.34.0",
16
+ "@pactor-app/ui": "^1.34.0",
17
17
  "lucide-react": "1.45.0",
18
18
  "next": "16.3.5",
19
- "pactor-app": "^1.27.0",
19
+ "pactor-app": "^1.34.0",
20
20
  "react": "19.2.8",
21
21
  "react-dom": "19.2.8",
22
22
  "yaml": "^2.9.1"
@@ -9,14 +9,14 @@ importers:
9
9
  .:
10
10
  dependencies:
11
11
  '@pactor-app/core':
12
- specifier: ^1.27.0
13
- version: 1.27.0
12
+ specifier: ^1.33.0
13
+ version: 1.33.0
14
14
  '@pactor-app/runtime':
15
- specifier: ^1.27.0
16
- version: 1.27.0(react@19.2.8)
15
+ specifier: ^1.33.0
16
+ version: 1.33.0(react@19.2.8)
17
17
  '@pactor-app/ui':
18
- specifier: ^1.27.0
19
- version: 1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
18
+ specifier: ^1.33.0
19
+ version: 1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
20
20
  lucide-react:
21
21
  specifier: 1.45.0
22
22
  version: 1.45.0(react@19.2.8)
@@ -24,8 +24,8 @@ importers:
24
24
  specifier: 16.3.5
25
25
  version: 16.3.5(@babel/core@7.29.7)(@types/node@20.19.43)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
26
26
  pactor-app:
27
- specifier: ^1.27.0
28
- version: 1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)(vite@8.3.1(@types/node@20.19.43)(jiti@2.7.0)(yaml@2.9.1))
27
+ specifier: ^1.33.0
28
+ version: 1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)(vite@8.3.1(@types/node@20.19.43)(jiti@2.7.0)(yaml@2.9.1))
29
29
  react:
30
30
  specifier: 19.2.8
31
31
  version: 19.2.8
@@ -501,73 +501,73 @@ packages:
501
501
  '@oxc-project/types@0.151.0':
502
502
  resolution: {integrity: sha512-J1yXrIlNDZVzE3ada310xeAw7nH8yCAyLPuUIsjKatFPmfn5bS1oW+cM+QsGOtVWd5nhSpbwZWx/rue+r5Z+PA==}
503
503
 
504
- '@pactor-app/app@1.27.0':
505
- resolution: {integrity: sha512-c7Ig/Azmjduh3ATzn2ruJVilNwwljN7RR7hPa4+LwD4v35dqH2sobz6yrORckh+7ztd7A3DVo83zlVH95bHE4Q==}
504
+ '@pactor-app/app@1.33.0':
505
+ resolution: {integrity: sha512-/T3AnTgV3J9gvtwP48uSqp951GJFVt09758RyU3BQMnw3ZJXnLaqfUNMiZ6UlXkd8x32Cfpq3SqbJQRVB1fYlg==}
506
506
  engines: {node: '>=18'}
507
507
  peerDependencies:
508
508
  react: '>=18'
509
509
  react-dom: '>=18'
510
510
  react-router-dom: '>=6'
511
511
 
512
- '@pactor-app/chat@1.27.0':
513
- resolution: {integrity: sha512-CAgreyhMczlmNFuLD+P8FnjnnilwNkr/UwEDDrWh1HsnGqAIAiQAHC2gW9IWDTCVvyoV1p8BoIIaEi7NxvwQNQ==}
512
+ '@pactor-app/chat@1.33.0':
513
+ resolution: {integrity: sha512-tj3pOA8JXXDzC0jVHr1MQduAuYExP76M0AAsba55mqQ7N64fb2zJDUzMPxYiuv8z9bMr8acKpuOGi/a2tO5hEQ==}
514
514
  engines: {node: '>=18'}
515
515
  peerDependencies:
516
516
  react: '>=18'
517
517
 
518
- '@pactor-app/cli@1.27.0':
519
- resolution: {integrity: sha512-K0towebCS4sp5SbzF7RdjSBlnZOtHY4BI9ao5dOVD4RvNAlie5vw28/xHvbUGww4X0L3uydc1+xyR05IEE8vPQ==}
518
+ '@pactor-app/cli@1.33.0':
519
+ resolution: {integrity: sha512-x8+DLqH93Vd0Lkd2zc4stuuc+z0kp++sEnaV49LIktccKBTXNIe6q1BaF8vIX14HrPtSpTtuiMnnlwNR2Nsx/A==}
520
520
  engines: {node: '>=18'}
521
521
  hasBin: true
522
522
 
523
- '@pactor-app/core@1.27.0':
524
- resolution: {integrity: sha512-VjjJwwrG37j7xMD5tANubb6FRki9pGSpdjJwGM37zB2KedHYMbzt84ZSvd8xn417+pUxB+AvwsP/wg8IV3vcuA==}
523
+ '@pactor-app/core@1.33.0':
524
+ resolution: {integrity: sha512-XTdm/f7Xom1ifPKwhpvy8WR5cVyLstAtrNAOWcJhs4AdOwYkmuk1MeznRp66Yl9bTJyzhJCEVhsZ7telb0HS6Q==}
525
525
  engines: {node: '>=18'}
526
526
 
527
- '@pactor-app/expression@1.27.0':
528
- resolution: {integrity: sha512-228qrxEfmdD9uAIvv7UGSOxT692MGlu6SiDGrZpUS5tPEoLyeBsoI61+XCeaXu7KSVXcigMzPDoTDEw9oiRcqQ==}
527
+ '@pactor-app/expression@1.33.0':
528
+ resolution: {integrity: sha512-0Z3JUf3NLpEfHUhvzUunmEEZ3B+hEHTz+ATF4RpDVbBVnjmQBdwNcXw1/ybt1I9sJ3eDPOQQtejonsrCX0VzQA==}
529
529
  engines: {node: '>=18'}
530
530
 
531
- '@pactor-app/markdown@1.27.0':
532
- resolution: {integrity: sha512-YpD/wGdcwGeiTk6HGchEFHy9D7GH11X4IQujDuJWrwj9PAeJtqCOh2BTJZHE+xcujYwQuVWwgUOF1GzGu3rjcQ==}
531
+ '@pactor-app/markdown@1.33.0':
532
+ resolution: {integrity: sha512-C6u8wZKD4ayRZND4k6HbTz7SDiqb+Pwxwu9xYgYVwRBDugLWVBIfZGSZNThoXcJRumcP5EEsQKeIuNkXbt541g==}
533
533
  engines: {node: '>=18'}
534
534
  peerDependencies:
535
535
  react: '>=18'
536
536
 
537
- '@pactor-app/permission@1.27.0':
538
- resolution: {integrity: sha512-fO/BA5/FcnMPqLUdRS+a7CeQS3OmWnw0Wg2tChOGMkoqWTq6OS3Ee628tAVTDVtxpeA+reNaXYZFAKr6V7TATA==}
537
+ '@pactor-app/permission@1.33.0':
538
+ resolution: {integrity: sha512-CYfW3pfqI6bml5woxTtvlFE/l5ZBeQZe+x1mJigy3dc9gThMVdPKSc9b541RP6Km93tKOz2LK8HOhoE4SlvaxQ==}
539
539
  engines: {node: '>=18'}
540
540
 
541
- '@pactor-app/resource@1.27.0':
542
- resolution: {integrity: sha512-peVCWyJ7xUjFNdOBsKJWlkmjv2MQnhtii1wgOtIJEBF+5cPIjr4T6f0GuTvmw0MbtA7ppS3Mf7mJf1uzVksHSw==}
541
+ '@pactor-app/resource@1.33.0':
542
+ resolution: {integrity: sha512-ezcM72IFOvHdlUCnQmLiJenVX0Ij/B51hJB87nisJbrDmj3HfPKFoDr1UcRgU5aSlR/yt9Dp/TGTIF4Em7sesQ==}
543
543
  engines: {node: '>=18'}
544
544
 
545
- '@pactor-app/router@1.27.0':
546
- resolution: {integrity: sha512-+591RqB/BgVXPZodr1t0OK9Jfx6+olNx4YVdCnAHdBmQmir6G03U0J3HknTaPYGVBDSJkXgOgM7lGcSuLq3Lxg==}
545
+ '@pactor-app/router@1.33.0':
546
+ resolution: {integrity: sha512-vhtyczWSzJTe/7rcAK4LsKIdwWEP2vT21fpyNkYzcjIUOXVe2SHmPDu7bmQdW5yB5hQz0IQPkyeLI9HI4xJrcw==}
547
547
  engines: {node: '>=18'}
548
548
  peerDependencies:
549
549
  react: '>=18'
550
550
  react-router-dom: '>=6'
551
551
 
552
- '@pactor-app/runtime@1.27.0':
553
- resolution: {integrity: sha512-SkTUFcQfXoOj2ldazZH/YECX0/XpTZAQ3jSSaanAK3bIP4QRWhAecARhcO9YQUrAaeFRuZMNS7VFaZr/vy5r8w==}
552
+ '@pactor-app/runtime@1.33.0':
553
+ resolution: {integrity: sha512-JZOTgoo0jeSG5+gp1bpD1Rey4ZDCwBo2IQ6w6tp5SFI9LOOsXxdg8hy2wpX1fQAuS6iO2AtVRIIWbNesghIeTg==}
554
554
  engines: {node: '>=18'}
555
555
  peerDependencies:
556
556
  react: '>=18'
557
557
 
558
- '@pactor-app/schema@1.27.0':
559
- resolution: {integrity: sha512-ICzNoh/p0fTrOeCgA+smdYNt6CMwd8w7QbFoM1LauaiFjisue7YfAHslB+TUcEEWv/jTND0/5PMXHr0s7AvpgQ==}
558
+ '@pactor-app/schema@1.33.0':
559
+ resolution: {integrity: sha512-2J7uvpwUUcwFB01I+xc0w18B9LWMqyL9l1B6Kog5sU/oWsn4pFcQ/bncBKYpW3UW4FVGFz5AVeyN4Rd+uPIcWQ==}
560
560
  engines: {node: '>=18'}
561
561
 
562
- '@pactor-app/ui@1.27.0':
563
- resolution: {integrity: sha512-hu+/2TzvkJwGXJLJpOIO3SBtqtRmMTy0znrSi/Oj+JDHQEWpFUzYHYepWSgN5WQABoEG2A9DUchDya+yXe8P1Q==}
562
+ '@pactor-app/ui@1.33.0':
563
+ resolution: {integrity: sha512-mhpWWkRfKraQaPQPN1ZuTFQdb4tf/WwWdfa3ULqFf6u+lp+8b1FrsW7cNY7lbElN46e+BgobR2fG+Yy9LurJ3w==}
564
564
  engines: {node: '>=18'}
565
565
  peerDependencies:
566
566
  react: '>=18'
567
567
  react-dom: '>=18'
568
568
 
569
- '@pactor-app/vite-plugin@1.27.0':
570
- resolution: {integrity: sha512-+YOSrbnDU0JzF4QFG1YzqywbURGHUzIu8arqd9vClGE34RDADDHFt/LJRK3wOIAl7Cz6QTuz8Yjctn2VszMuPQ==}
569
+ '@pactor-app/vite-plugin@1.33.0':
570
+ resolution: {integrity: sha512-9bNPV95H7h0/DVv5Vc431mLUkuRGX9nnwRdhoUGdcSPkReGJrTH2866i4t8w0ODtUpZ3rD9AexgatpNBlw8NvA==}
571
571
  engines: {node: '>=18'}
572
572
  peerDependencies:
573
573
  vite: '>=5'
@@ -2529,8 +2529,8 @@ packages:
2529
2529
  resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
2530
2530
  engines: {node: '>=6'}
2531
2531
 
2532
- pactor-app@1.27.0:
2533
- resolution: {integrity: sha512-0rapzSaI0+bAUAgzLCR4fIsX2b+DtKgUhW4EY9JfQL72FpgcpLobYtc6BnwvIVYWU1trXOV3dO13VgiEHZIC4w==}
2532
+ pactor-app@1.33.0:
2533
+ resolution: {integrity: sha512-BJxBNIG40chRob0veFRAXTKkplnIipZOP4MkKJ52Udn3wYQ9srey2sAr0/S+LtjRSL0P+/rjWeTuqyoJOeVlrQ==}
2534
2534
  engines: {node: '>=18'}
2535
2535
  peerDependencies:
2536
2536
  react: '>=18'
@@ -3613,16 +3613,16 @@ snapshots:
3613
3613
 
3614
3614
  '@oxc-project/types@0.151.0': {}
3615
3615
 
3616
- '@pactor-app/app@1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
3616
+ '@pactor-app/app@1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
3617
3617
  dependencies:
3618
- '@pactor-app/core': 1.27.0
3619
- '@pactor-app/expression': 1.27.0
3620
- '@pactor-app/permission': 1.27.0
3621
- '@pactor-app/resource': 1.27.0
3622
- '@pactor-app/router': 1.27.0(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
3623
- '@pactor-app/runtime': 1.27.0(react@19.2.8)
3624
- '@pactor-app/schema': 1.27.0
3625
- '@pactor-app/ui': 1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
3618
+ '@pactor-app/core': 1.33.0
3619
+ '@pactor-app/expression': 1.33.0
3620
+ '@pactor-app/permission': 1.33.0
3621
+ '@pactor-app/resource': 1.33.0
3622
+ '@pactor-app/router': 1.33.0(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
3623
+ '@pactor-app/runtime': 1.33.0(react@19.2.8)
3624
+ '@pactor-app/schema': 1.33.0
3625
+ '@pactor-app/ui': 1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
3626
3626
  react: 19.2.8
3627
3627
  react-dom: 19.2.8(react@19.2.8)
3628
3628
  react-router-dom: 7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
@@ -3632,13 +3632,13 @@ snapshots:
3632
3632
  - '@types/react-dom'
3633
3633
  - supports-color
3634
3634
 
3635
- '@pactor-app/chat@1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
3635
+ '@pactor-app/chat@1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
3636
3636
  dependencies:
3637
- '@pactor-app/core': 1.27.0
3638
- '@pactor-app/markdown': 1.27.0(@types/react@19.3.0)(react@19.2.8)
3639
- '@pactor-app/permission': 1.27.0
3640
- '@pactor-app/runtime': 1.27.0(react@19.2.8)
3641
- '@pactor-app/ui': 1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
3637
+ '@pactor-app/core': 1.33.0
3638
+ '@pactor-app/markdown': 1.33.0(@types/react@19.3.0)(react@19.2.8)
3639
+ '@pactor-app/permission': 1.33.0
3640
+ '@pactor-app/runtime': 1.33.0(react@19.2.8)
3641
+ '@pactor-app/ui': 1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
3642
3642
  react: 19.2.8
3643
3643
  transitivePeerDependencies:
3644
3644
  - '@date-fns/tz'
@@ -3648,22 +3648,22 @@ snapshots:
3648
3648
  - react-router-dom
3649
3649
  - supports-color
3650
3650
 
3651
- '@pactor-app/cli@1.27.0':
3651
+ '@pactor-app/cli@1.33.0':
3652
3652
  dependencies:
3653
- '@pactor-app/core': 1.27.0
3654
- '@pactor-app/expression': 1.27.0
3655
- '@pactor-app/schema': 1.27.0
3653
+ '@pactor-app/core': 1.33.0
3654
+ '@pactor-app/expression': 1.33.0
3655
+ '@pactor-app/schema': 1.33.0
3656
3656
  yaml: 2.9.1
3657
3657
 
3658
- '@pactor-app/core@1.27.0': {}
3658
+ '@pactor-app/core@1.33.0': {}
3659
3659
 
3660
- '@pactor-app/expression@1.27.0':
3660
+ '@pactor-app/expression@1.33.0':
3661
3661
  dependencies:
3662
- '@pactor-app/core': 1.27.0
3662
+ '@pactor-app/core': 1.33.0
3663
3663
 
3664
- '@pactor-app/markdown@1.27.0(@types/react@19.3.0)(react@19.2.8)':
3664
+ '@pactor-app/markdown@1.33.0(@types/react@19.3.0)(react@19.2.8)':
3665
3665
  dependencies:
3666
- '@pactor-app/core': 1.27.0
3666
+ '@pactor-app/core': 1.33.0
3667
3667
  katex: 0.18.9
3668
3668
  react: 19.2.8
3669
3669
  react-markdown: 10.1.0(@types/react@19.3.0)(react@19.2.8)
@@ -3675,41 +3675,41 @@ snapshots:
3675
3675
  - '@types/react'
3676
3676
  - supports-color
3677
3677
 
3678
- '@pactor-app/permission@1.27.0':
3678
+ '@pactor-app/permission@1.33.0':
3679
3679
  dependencies:
3680
- '@pactor-app/core': 1.27.0
3680
+ '@pactor-app/core': 1.33.0
3681
3681
 
3682
- '@pactor-app/resource@1.27.0':
3682
+ '@pactor-app/resource@1.33.0':
3683
3683
  dependencies:
3684
- '@pactor-app/core': 1.27.0
3684
+ '@pactor-app/core': 1.33.0
3685
3685
 
3686
- '@pactor-app/router@1.27.0(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
3686
+ '@pactor-app/router@1.33.0(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
3687
3687
  dependencies:
3688
- '@pactor-app/core': 1.27.0
3689
- '@pactor-app/permission': 1.27.0
3688
+ '@pactor-app/core': 1.33.0
3689
+ '@pactor-app/permission': 1.33.0
3690
3690
  react: 19.2.8
3691
3691
  react-router-dom: 7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
3692
3692
 
3693
- '@pactor-app/runtime@1.27.0(react@19.2.8)':
3693
+ '@pactor-app/runtime@1.33.0(react@19.2.8)':
3694
3694
  dependencies:
3695
- '@pactor-app/core': 1.27.0
3696
- '@pactor-app/expression': 1.27.0
3697
- '@pactor-app/schema': 1.27.0
3695
+ '@pactor-app/core': 1.33.0
3696
+ '@pactor-app/expression': 1.33.0
3697
+ '@pactor-app/schema': 1.33.0
3698
3698
  react: 19.2.8
3699
3699
 
3700
- '@pactor-app/schema@1.27.0':
3700
+ '@pactor-app/schema@1.33.0':
3701
3701
  dependencies:
3702
- '@pactor-app/core': 1.27.0
3702
+ '@pactor-app/core': 1.33.0
3703
3703
  ajv: 8.20.0
3704
3704
 
3705
- '@pactor-app/ui@1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
3705
+ '@pactor-app/ui@1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
3706
3706
  dependencies:
3707
3707
  '@base-ui/react': 1.8.0(@date-fns/tz@1.5.0)(@types/react@19.3.0)(date-fns@4.4.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
3708
- '@pactor-app/core': 1.27.0
3709
- '@pactor-app/markdown': 1.27.0(@types/react@19.3.0)(react@19.2.8)
3710
- '@pactor-app/permission': 1.27.0
3711
- '@pactor-app/router': 1.27.0(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
3712
- '@pactor-app/runtime': 1.27.0(react@19.2.8)
3708
+ '@pactor-app/core': 1.33.0
3709
+ '@pactor-app/markdown': 1.33.0(@types/react@19.3.0)(react@19.2.8)
3710
+ '@pactor-app/permission': 1.33.0
3711
+ '@pactor-app/router': 1.33.0(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
3712
+ '@pactor-app/runtime': 1.33.0(react@19.2.8)
3713
3713
  class-variance-authority: 0.7.1
3714
3714
  clsx: 2.1.1
3715
3715
  cmdk: 1.1.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
@@ -3734,10 +3734,10 @@ snapshots:
3734
3734
  - react-router-dom
3735
3735
  - supports-color
3736
3736
 
3737
- '@pactor-app/vite-plugin@1.27.0(vite@8.3.1(@types/node@20.19.43)(jiti@2.7.0)(yaml@2.9.1))':
3737
+ '@pactor-app/vite-plugin@1.33.0(vite@8.3.1(@types/node@20.19.43)(jiti@2.7.0)(yaml@2.9.1))':
3738
3738
  dependencies:
3739
- '@pactor-app/core': 1.27.0
3740
- '@pactor-app/schema': 1.27.0
3739
+ '@pactor-app/core': 1.33.0
3740
+ '@pactor-app/schema': 1.33.0
3741
3741
  vite: 8.3.1(@types/node@20.19.43)(jiti@2.7.0)(yaml@2.9.1)
3742
3742
  yaml: 2.9.1
3743
3743
 
@@ -5996,21 +5996,21 @@ snapshots:
5996
5996
 
5997
5997
  p-try@2.2.0: {}
5998
5998
 
5999
- pactor-app@1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)(vite@8.3.1(@types/node@20.19.43)(jiti@2.7.0)(yaml@2.9.1)):
6000
- dependencies:
6001
- '@pactor-app/app': 1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
6002
- '@pactor-app/chat': 1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
6003
- '@pactor-app/cli': 1.27.0
6004
- '@pactor-app/core': 1.27.0
6005
- '@pactor-app/expression': 1.27.0
6006
- '@pactor-app/markdown': 1.27.0(@types/react@19.3.0)(react@19.2.8)
6007
- '@pactor-app/permission': 1.27.0
6008
- '@pactor-app/resource': 1.27.0
6009
- '@pactor-app/router': 1.27.0(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
6010
- '@pactor-app/runtime': 1.27.0(react@19.2.8)
6011
- '@pactor-app/schema': 1.27.0
6012
- '@pactor-app/ui': 1.27.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
6013
- '@pactor-app/vite-plugin': 1.27.0(vite@8.3.1(@types/node@20.19.43)(jiti@2.7.0)(yaml@2.9.1))
5999
+ pactor-app@1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)(vite@8.3.1(@types/node@20.19.43)(jiti@2.7.0)(yaml@2.9.1)):
6000
+ dependencies:
6001
+ '@pactor-app/app': 1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
6002
+ '@pactor-app/chat': 1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
6003
+ '@pactor-app/cli': 1.33.0
6004
+ '@pactor-app/core': 1.33.0
6005
+ '@pactor-app/expression': 1.33.0
6006
+ '@pactor-app/markdown': 1.33.0(@types/react@19.3.0)(react@19.2.8)
6007
+ '@pactor-app/permission': 1.33.0
6008
+ '@pactor-app/resource': 1.33.0
6009
+ '@pactor-app/router': 1.33.0(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
6010
+ '@pactor-app/runtime': 1.33.0(react@19.2.8)
6011
+ '@pactor-app/schema': 1.33.0
6012
+ '@pactor-app/ui': 1.33.0(@date-fns/tz@1.5.0)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.2.8(react@19.2.8))(react-router-dom@7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
6013
+ '@pactor-app/vite-plugin': 1.33.0(vite@8.3.1(@types/node@20.19.43)(jiti@2.7.0)(yaml@2.9.1))
6014
6014
  react: 19.2.8
6015
6015
  react-dom: 19.2.8(react@19.2.8)
6016
6016
  react-router-dom: 7.18.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 数据列表骨架示例 mock(对应 yaml/models/data-list.yaml)。
3
+ * query / get / save 注册为 dataList.* 服务;生成业务列表页时复制本文件
4
+ * 改名并替换字段;接入真实后端后删除。
5
+ */
6
+
7
+ export interface DataListItem {
8
+ id: string;
9
+ name: string;
10
+ code: string;
11
+ /** 基础 | 高级(高级显示扩展说明字段,演示条件显隐) */
12
+ type: string;
13
+ extra: string;
14
+ sort: number;
15
+ /** 启用 | 禁用 */
16
+ status: string;
17
+ }
18
+
19
+ const ITEMS: DataListItem[] = [
20
+ { id: "1", name: "示例记录甲", code: "DEMO_ALPHA", type: "基础", extra: "", sort: 1, status: "启用" },
21
+ { id: "2", name: "示例记录乙", code: "DEMO_BETA", type: "高级", extra: "高级类型的扩展配置", sort: 2, status: "启用" },
22
+ { id: "3", name: "示例记录丙", code: "DEMO_GAMMA", type: "基础", extra: "", sort: 3, status: "禁用" },
23
+ { id: "4", name: "示例记录丁", code: "DEMO_DELTA", type: "高级", extra: "", sort: 4, status: "启用" },
24
+ ];
25
+
26
+ let seq = ITEMS.length;
27
+
28
+ export interface DataListQuery {
29
+ keyword?: string;
30
+ status?: string;
31
+ }
32
+
33
+ /** 列表查询:items + total + 筛选选项(filters 由接口下发,搜索栏/表单的 Select 直接消费) */
34
+ export function queryDataList(params: DataListQuery) {
35
+ const keyword = (params.keyword ?? "").trim().toLowerCase();
36
+ const status = params.status ?? "all";
37
+ const items = ITEMS.filter(
38
+ (it) =>
39
+ (status === "all" || it.status === status) &&
40
+ (keyword === "" ||
41
+ it.name.toLowerCase().includes(keyword) ||
42
+ it.code.toLowerCase().includes(keyword)),
43
+ );
44
+ return {
45
+ items,
46
+ total: items.length,
47
+ filters: {
48
+ status: [
49
+ { label: "全部", value: "all" },
50
+ { label: "启用", value: "启用" },
51
+ { label: "禁用", value: "禁用" },
52
+ ],
53
+ type: [
54
+ { label: "基础", value: "基础" },
55
+ { label: "高级", value: "高级" },
56
+ ],
57
+ },
58
+ };
59
+ }
60
+
61
+ /** 编辑预填;空 id(新建)返回空对象,Form initialValues 各字段即空 */
62
+ export function getDataListItem(id: string): Partial<DataListItem> {
63
+ return ITEMS.find((it) => it.id === id) ?? {};
64
+ }
65
+
66
+ /** 新建 / 编辑保存(upsert,按 id 区分) */
67
+ export function saveDataListItem(body: Partial<DataListItem>) {
68
+ if (body.id) {
69
+ const idx = ITEMS.findIndex((it) => it.id === body.id);
70
+ if (idx >= 0) ITEMS[idx] = { ...ITEMS[idx], ...body, id: body.id } as DataListItem;
71
+ return { ok: true, id: body.id };
72
+ }
73
+ const id = String(++seq);
74
+ ITEMS.push({
75
+ id,
76
+ name: body.name ?? "",
77
+ code: body.code ?? "",
78
+ type: body.type ?? "基础",
79
+ extra: body.extra ?? "",
80
+ sort: body.sort ?? 0,
81
+ status: body.status ?? "启用",
82
+ });
83
+ return { ok: true, id };
84
+ }
@@ -28,6 +28,11 @@ import {
28
28
  import { getCallLog, queryCallLogs } from "./mocks/call-logs-mock";
29
29
  import { getCost, queryCosts } from "./mocks/costs-mock";
30
30
  import { getAudit, listAuditOperators, queryAudits } from "./mocks/audit-mock";
31
+ import {
32
+ getDataListItem,
33
+ queryDataList,
34
+ saveDataListItem,
35
+ } from "./mocks/data-list-mock";
31
36
  import {
32
37
  queryAvailability,
33
38
  queryClientUsage,
@@ -182,4 +187,14 @@ export const pactorServices: Record<string, ServiceHandler> = {
182
187
  queryClientUsage({ start: opt(params.start), end: opt(params.end) }),
183
188
  "ops.availability": (params) =>
184
189
  queryAvailability({ start: opt(params.start), end: opt(params.end) }),
190
+
191
+ // 数据列表骨架示例(yaml/models/data-list.yaml);生成业务列表页时成组复制改名
192
+ "dataList.list": (params) =>
193
+ queryDataList({
194
+ keyword: str(params.keyword),
195
+ status: str(params.status) || "all",
196
+ }),
197
+ "dataList.detail": (params) => getDataListItem(str(params.code)),
198
+ "dataList.save": (params) =>
199
+ saveDataListItem(params as Parameters<typeof saveDataListItem>[0]),
185
200
  };
@@ -0,0 +1,344 @@
1
+ # 数据列表标准骨架 —— 「搜索 + 表格 + 抽屉新建/编辑」数据列表页的复制起点。
2
+ # 本页已注册进 sitemap.yaml(菜单「页面骨架 / 数据列表」,路径 /models/data-list),
3
+ # 在模板工程中可直接运行预览;生成业务列表页时复制本文件到 yaml/<模块>/ 下,
4
+ # 替换页面信息、字段、接口名(data-list → 业务资源名)与文案。
5
+ # 结构与交互约定见 skills/pactor-prd/references/page-templates.md「数据列表标准模型」。
6
+ dsl: "1.0"
7
+ page:
8
+ id: data-list
9
+ title: 数据列表
10
+ name: dataList
11
+ state:
12
+ # 搜索条件镜像:Form submit 后写入,驱动列表请求参数
13
+ keyword: ""
14
+ status: all
15
+ editingId: ""
16
+ # 表单条件显隐镜像(onValuesChange 写入;按页面需要增减,可多个)
17
+ fType: ""
18
+ dataSources:
19
+ list:
20
+ type: http
21
+ autoLoad: true
22
+ request:
23
+ method: GET
24
+ url: /api/data/data-list
25
+ params:
26
+ keyword: ${state.keyword}
27
+ status: ${state.status}
28
+ editing: # 编辑预填;autoLoad: false,打开抽屉前手动 reload
29
+ type: http
30
+ autoLoad: false
31
+ request:
32
+ method: GET
33
+ url: /api/data/data-list/${state.editingId}
34
+ body:
35
+ type: Page
36
+ children:
37
+ - type: Breadcrumb
38
+ props:
39
+ items:
40
+ - label: 页面骨架
41
+ - label: 数据列表
42
+ # 标题行:左标题 + 副标题,右新建按钮
43
+ - type: Flex
44
+ props:
45
+ justify: space-between
46
+ align: center
47
+ children:
48
+ - type: Flex
49
+ props:
50
+ direction: vertical
51
+ gap: 2
52
+ children:
53
+ - type: Typography
54
+ props:
55
+ variant: h3
56
+ text: 数据列表
57
+ - type: Typography
58
+ props:
59
+ variant: muted
60
+ text: 标准列表示例:搜索 + 表格 + 抽屉新建/编辑,复制本页生成业务列表。
61
+ - type: Button
62
+ props:
63
+ text: + 新建记录
64
+ variant: primary
65
+ events:
66
+ onClick:
67
+ - action: setState # 清空编辑态与显隐镜像
68
+ params:
69
+ editingId: ""
70
+ fType: ""
71
+ - action: reload # 清空 editing 数据(editingId 为空 → mock 返回空对象)
72
+ params:
73
+ dataSource: editing
74
+ - action: overlay.open # 锚点 &entityDrawer 在此定义,表格行内用 *entityDrawer 引用
75
+ params:
76
+ overlay: &entityDrawer
77
+ type: drawer
78
+ title: "${state.editingId == '' ? '新建记录' : '编辑记录'}"
79
+ width: 720
80
+ content:
81
+ type: Form
82
+ props:
83
+ name: entityForm
84
+ layout: vertical
85
+ initialValues: ${data.editing}
86
+ events:
87
+ # 条件显隐字段镜像到 state(其他字段变化时保持原值)
88
+ onValuesChange:
89
+ - action: setState
90
+ params:
91
+ fType: "${event.type != null ? event.type : state.fType}"
92
+ onSubmit:
93
+ - action: request
94
+ params:
95
+ method: POST
96
+ url: /api/data/ops/data-list-save
97
+ body:
98
+ id: ${state.editingId}
99
+ name: ${event.name}
100
+ code: ${event.code}
101
+ type: ${event.type}
102
+ extra: ${event.extra}
103
+ sort: ${event.sort}
104
+ status: ${event.status}
105
+ - action: message
106
+ params:
107
+ messageType: success
108
+ text: 已保存(演示)
109
+ - action: overlay.close
110
+ children:
111
+ # 分区结构:标题 → 分割线 → 字段组(不用 Card);多个分区重复此结构
112
+ - type: Flex
113
+ props:
114
+ direction: vertical
115
+ gap: middle
116
+ children:
117
+ - type: Text
118
+ props:
119
+ text: 基本信息
120
+ strong: true
121
+ - type: Separator
122
+ - type: Flex
123
+ props:
124
+ direction: vertical
125
+ gap: small
126
+ children:
127
+ - type: Field
128
+ props:
129
+ label: 名称
130
+ required: true
131
+ children:
132
+ - type: Input
133
+ props:
134
+ name: name
135
+ placeholder: 请输入名称
136
+ rules:
137
+ - required: true
138
+ message: 请输入名称
139
+ # 编辑时禁用关键字段
140
+ - type: Field
141
+ props:
142
+ label: 编码
143
+ required: true
144
+ children:
145
+ - type: Input
146
+ props:
147
+ name: code
148
+ placeholder: 大写字母 + 下划线,如 DEMO_ITEM
149
+ disabled: ${state.editingId != ''}
150
+ rules:
151
+ - required: true
152
+ message: 请输入编码
153
+ # 成对字段用 Grid 两列
154
+ - type: Grid
155
+ props:
156
+ columns: 2
157
+ gap: 16
158
+ children:
159
+ - type: Field
160
+ props:
161
+ label: 类型
162
+ required: true
163
+ children:
164
+ - type: Select
165
+ props:
166
+ name: type
167
+ placeholder: 请选择类型
168
+ options: ${data.list.filters.type}
169
+ rules:
170
+ - required: true
171
+ message: 请选择类型
172
+ - type: Field
173
+ props:
174
+ label: 状态
175
+ children:
176
+ - type: Select
177
+ props:
178
+ name: status
179
+ value: 启用
180
+ options: ${data.list.filters.status}
181
+ - type: Grid
182
+ props:
183
+ columns: 2
184
+ gap: 16
185
+ children:
186
+ - type: Field
187
+ props:
188
+ label: 排序
189
+ children:
190
+ - type: NumberInput
191
+ props:
192
+ name: sort
193
+ className: w-full
194
+ min: 0
195
+ precision: 0
196
+ # 条件显隐字段:依赖镜像 state
197
+ - when: ${state.fType == '高级'}
198
+ type: Field
199
+ props:
200
+ label: 扩展说明
201
+ children:
202
+ - type: Input
203
+ props:
204
+ name: extra
205
+ placeholder: 高级类型的扩展配置说明
206
+ # 底部按钮:取消关抽屉,保存触发 Form onSubmit
207
+ - type: Flex
208
+ props:
209
+ justify: end
210
+ gap: small
211
+ className: mt-4
212
+ children:
213
+ - type: Button
214
+ props:
215
+ text: 取消
216
+ events:
217
+ onClick:
218
+ - action: overlay.close
219
+ - type: Button
220
+ props:
221
+ text: 保存
222
+ variant: primary
223
+ submit: true
224
+ htmlType: submit
225
+ - action: reload # overlay.open 阻塞到关闭,关闭后刷新列表
226
+ params:
227
+ dataSource: list
228
+ # 搜索栏:Form(layout: inline) + Field 包裹控件
229
+ - type: Card
230
+ children:
231
+ - type: Form
232
+ props:
233
+ name: search
234
+ layout: inline
235
+ events:
236
+ onSubmit:
237
+ - action: setState
238
+ params:
239
+ keyword: ${event.keyword}
240
+ status: ${event.status}
241
+ - action: reload
242
+ params:
243
+ dataSource: list
244
+ children:
245
+ - type: Field
246
+ props:
247
+ label: 编码/名称
248
+ children:
249
+ - type: Input
250
+ props:
251
+ name: keyword
252
+ placeholder: 支持模糊查询
253
+ - type: Field
254
+ props:
255
+ label: 状态
256
+ children:
257
+ - type: Select
258
+ props:
259
+ name: status
260
+ placeholder: 请选择状态
261
+ options: ${data.list.filters.status} # 选项由接口下发
262
+ # 按钮也放进 Field:label 为 U+00A0 不间断空格(普通空格会被压缩),与左侧控件基线对齐
263
+ - type: Field
264
+ props:
265
+ label: " "
266
+ children:
267
+ - type: Flex
268
+ props:
269
+ gap: small
270
+ align: center
271
+ children:
272
+ - type: Button
273
+ props:
274
+ text: 查询
275
+ submit: true
276
+ htmlType: submit
277
+ - type: Button
278
+ props:
279
+ text: 重置
280
+ events:
281
+ onClick:
282
+ - action: form.setValues
283
+ params:
284
+ form: search
285
+ values:
286
+ keyword: ""
287
+ status: all
288
+ - action: setState
289
+ params:
290
+ keyword: ""
291
+ status: all
292
+ - action: reload
293
+ params:
294
+ dataSource: list
295
+ # 表格:名称列/操作列按钮统一 variant: link size: small
296
+ - type: Table
297
+ props:
298
+ dataSource: ${data.list.items}
299
+ rowKey: id
300
+ pagination: false
301
+ className: mt-4
302
+ columns:
303
+ - title: 名称
304
+ cell:
305
+ type: Button
306
+ props:
307
+ text: ${row.name}
308
+ variant: link
309
+ size: small
310
+ events:
311
+ onClick: &editRow # 行点击 = 编辑,锚点在此定义
312
+ - action: setState # 写入编辑 id + 显隐镜像(取自行数据,不等 editing 接口)
313
+ params:
314
+ editingId: ${row.id}
315
+ fType: ${row.type}
316
+ - action: reload
317
+ params:
318
+ dataSource: editing
319
+ - action: overlay.open
320
+ params:
321
+ overlay: *entityDrawer
322
+ - action: reload
323
+ params:
324
+ dataSource: list
325
+ - title: 编码
326
+ dataIndex: code
327
+ - title: 类型
328
+ dataIndex: type
329
+ - title: 状态
330
+ dataIndex: status
331
+ - title: 操作
332
+ cell:
333
+ type: Button
334
+ props:
335
+ text: 编辑
336
+ variant: link
337
+ size: small
338
+ events:
339
+ onClick: *editRow # 与名称列同一动作
340
+ - type: Text
341
+ props:
342
+ text: 共 ${data.list.total} 条
343
+ type: secondary
344
+ className: mt-3
@@ -49,6 +49,14 @@ pages:
49
49
  }
50
50
  # 模块二:模型路由 / 路由(卡片式列表 + 单页纵向详情 + 单页表单)
51
51
  - { id: route-list, path: /routes, title: 路由, version: 1, lazy: true }
52
+ # 页面骨架:数据列表标准模型(搜索 + 表格 + 抽屉新建/编辑),可复制生成业务列表页
53
+ - {
54
+ id: data-list,
55
+ path: /models/data-list,
56
+ title: 数据列表,
57
+ version: 1,
58
+ lazy: true,
59
+ }
52
60
  - {
53
61
  id: route-create,
54
62
  path: /routes/new,
@@ -116,6 +124,19 @@ menus:
116
124
  title: 路由,
117
125
  layout: admin,
118
126
  }
127
+ - id: skeletons
128
+ type: group
129
+ title: 页面骨架
130
+ icon: folder
131
+ order: 4
132
+ children:
133
+ - {
134
+ id: data-list,
135
+ type: page,
136
+ pageId: data-list,
137
+ title: 数据列表,
138
+ layout: admin,
139
+ }
119
140
  # 隐藏页(不出现在菜单,经列表页跳转进入;activeMenu 保持所属菜单高亮)
120
141
  - {
121
142
  id: provider-create,