@pactor-app/skills 1.25.0 → 1.26.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/README.md +79 -19
- package/package.json +13 -4
- package/{pactor → pactor-dsl}/SKILL.md +27 -27
- package/pactor-dsl/references/page-catalog-and-layout.md +67 -0
- package/pactor-prd/SKILL.md +105 -0
- package/{prd-to-app → pactor-prd}/references/acceptance-checklist.md +3 -1
- package/pactor-prd/references/incremental-wireframe-delta.md +76 -0
- package/pactor-prd/references/page-inventory-and-files.md +65 -0
- package/{prd-to-app → pactor-prd}/references/page-templates.md +1 -1
- package/{prd-to-app → pactor-prd}/references/project-structure.md +1 -1
- package/{prd-to-app → pactor-prd}/template/README.md +1 -1
- package/pactor-project/SKILL.md +121 -0
- package/pactor-project/references/minimal-vite.md +39 -0
- package/pactor-project/references/templates.md +92 -0
- package/scripts/validate-skills.mjs +65 -0
- package/prd-to-app/SKILL.md +0 -75
- /package/{pactor → pactor-dsl}/references/dsl-authoring.md +0 -0
- /package/{prd-to-app → pactor-prd}/references/component-mapping.md +0 -0
- /package/{prd-to-app → pactor-prd}/references/mock-data-routes.md +0 -0
- /package/{prd-to-app → pactor-prd}/references/theme-and-style.md +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/[[...slug]]/page.tsx +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/api/auth/login/route.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/api/auth/logout/route.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/api/data/[...parts]/route.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/api/public/pages/[id]/route.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/api/sitemap/route.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/api/users/route.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/favicon.ico +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/globals.css +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/layout.tsx +0 -0
- /package/{prd-to-app → pactor-prd}/template/app/login.css +0 -0
- /package/{prd-to-app → pactor-prd}/template/eslint.config.mjs +0 -0
- /package/{prd-to-app → pactor-prd}/template/next-env.d.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/next.config.js +0 -0
- /package/{prd-to-app → pactor-prd}/template/package.json +0 -0
- /package/{prd-to-app → pactor-prd}/template/pnpm-lock.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/pnpm-workspace.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/postcss.config.mjs +0 -0
- /package/{prd-to-app → pactor-prd}/template/public/file.svg +0 -0
- /package/{prd-to-app → pactor-prd}/template/public/globe.svg +0 -0
- /package/{prd-to-app → pactor-prd}/template/public/next.svg +0 -0
- /package/{prd-to-app → pactor-prd}/template/public/skins/chenwunaifu.css +0 -0
- /package/{prd-to-app → pactor-prd}/template/public/skins/taijingshenlin.css +0 -0
- /package/{prd-to-app → pactor-prd}/template/public/skins/xuanzhimoyun.css +0 -0
- /package/{prd-to-app → pactor-prd}/template/public/vercel.svg +0 -0
- /package/{prd-to-app → pactor-prd}/template/public/window.svg +0 -0
- /package/{prd-to-app → pactor-prd}/template/scripts/build.mjs +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/App.tsx +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/actions.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/components/card-links.tsx +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/components/chip-filter.tsx +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/components/chip-node.tsx +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/components/debug-chat.tsx +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/components/index.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/components/log-status.tsx +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/components/status-badge.tsx +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/components/theme-switcher.tsx +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/config.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/audit-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/call-logs-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/client-debug-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/client-templates-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/clients-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/costs-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/dashboard-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/model-debug-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/models-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/ops-usage-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/providers-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/mocks/routes-mock.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/services.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/pactor/skin.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/accounts.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/cors.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/sitemap.ts +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/common/dashboard.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/common/login.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/provider/provider-create.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/provider/provider-detail.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/provider/provider-edit.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/provider/provider-list.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/route/route-create.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/route/route-detail.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/route/route-edit.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/route/route-list.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/src/server/yaml/sitemap.yaml +0 -0
- /package/{prd-to-app → pactor-prd}/template/tsconfig.json +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pactor-project
|
|
3
|
+
description: |
|
|
4
|
+
Use when initializing or scaffolding a new Pactor application — empty repo, greenfield project, or "how do I start" (skill id pactor-project). Triggers: pactor-project, create-pactor-app, pnpm create pactor-app, pactor create, 初始化项目, 创建脚手架, 新建 Pactor 工程, next-app/spa starter, copy starters/. Guides template choice (next-app vs spa vs minimal Vite), exact CLI commands, post-scaffold verification, and when to use pactor-prd or manual StaticDslLoader instead.
|
|
5
|
+
version: 1.1.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Pactor 工程初始化与脚手架
|
|
9
|
+
|
|
10
|
+
帮助 Agent **从零创建可运行的 Pactor 业务工程**:选对模板、执行官方脚手架、安装依赖、启动 dev,并说明生成后的目录该改哪里。
|
|
11
|
+
|
|
12
|
+
## When to activate
|
|
13
|
+
|
|
14
|
+
- 用户要**新建 / 初始化** Pactor 项目,或问「怎么搭架子」
|
|
15
|
+
- 提到 `pnpm create pactor-app`、`create-pactor-app`、`pactor create`
|
|
16
|
+
- 要在现有空目录生成工程,或从 monorepo 的 `starters/` 复制模板
|
|
17
|
+
- 在 **next-app(全栈)** 与 **spa(纯前端)** 之间选型
|
|
18
|
+
- 用户**不是**从 PRD 批量生成多模块后台(那种场景用 `pactor-prd` skill)
|
|
19
|
+
|
|
20
|
+
## What this skill does NOT cover
|
|
21
|
+
|
|
22
|
+
| 场景 | 使用 |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| 写/改 `*.page.yaml`、组件 props、动作编排 | `pactor-dsl` skill + `pactor-dsl/references/dsl-authoring.md` |
|
|
25
|
+
| 根据 PRD / 线框图生成整站页面与 mock API | `pactor-prd` skill(复制其 `template/`,不用本 skill 的 create 命令) |
|
|
26
|
+
| 在已有 Vite 里只加几行 `createPactorApplication` | `pactor-dsl` skill「Quick start」+ 文档 manual-setup |
|
|
27
|
+
|
|
28
|
+
## 选型(先问清楚再执行)
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
需要自带 mock API + 登录 + sitemap 端点?
|
|
32
|
+
├─ 是 → next-app(Next.js 全栈,dev :9011)
|
|
33
|
+
└─ 否,只要浏览器壳,接口已有或另起服务?
|
|
34
|
+
├─ 接口形态已是 sitemap + /pages/{id} → spa(Vite,dev :9012,baseUrl 指后端)
|
|
35
|
+
└─ 单页原型 / 教学最小集 → pactor create(Vite + StaticDslLoader,见 references/minimal-vite.md)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**默认推荐**:不确定时用 **next-app**(与 `create-pactor-app` 默认模板一致)。
|
|
39
|
+
|
|
40
|
+
## 标准流程(Agent 执行清单)
|
|
41
|
+
|
|
42
|
+
1. **确认目标路径**:目录不存在或为空;脚手架**拒绝覆盖非空目录**(退出码 2)。
|
|
43
|
+
2. **确认包管理器**:优先 `pnpm`(模板带 lockfile);用户坚持用 npm/yarn 可改,但需说明 lock 差异。
|
|
44
|
+
3. **运行脚手架**(在目标父目录执行):
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pnpm create pactor-app <dir-name> # TTY 交互选模板;非 TTY 默认 next-app
|
|
48
|
+
pnpm create pactor-app <dir-name> -t next-app # Next.js 全栈 + mock API
|
|
49
|
+
pnpm create pactor-app <dir-name> -t spa # Vite SPA + SitemapApp
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
等价:`npx create-pactor-app <dir-name> [-t next-app|spa]`。
|
|
53
|
+
|
|
54
|
+
4. **安装与启动**:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cd <dir-name>
|
|
58
|
+
pnpm install
|
|
59
|
+
pnpm dev
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
5. **验收**:
|
|
63
|
+
- **next-app**:打开 http://localhost:9011 ,用 `admin` / `pactor123` 登录
|
|
64
|
+
- **spa**:先在同一机器启动 next-app 或兼容的 sitemap 服务(:9011),再开 http://localhost:9012
|
|
65
|
+
6. **告诉用户改哪里**:见 `references/templates.md` 中的「生成后首要修改点」。
|
|
66
|
+
|
|
67
|
+
## 备选入口
|
|
68
|
+
|
|
69
|
+
### `@pactor-app/cli` 最小 Vite 工程
|
|
70
|
+
|
|
71
|
+
仅生成 **StaticDslLoader + 单页 YAML** 的瘦项目(无 sitemap、无 Next):
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pnpm add -D @pactor-app/cli
|
|
75
|
+
pnpm pactor create my-app # 模板 id 目前仅 app
|
|
76
|
+
cd my-app && pnpm install && pnpm dev
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
细节见 `references/minimal-vite.md`。
|
|
80
|
+
|
|
81
|
+
### 在 Pactor monorepo 内
|
|
82
|
+
|
|
83
|
+
不跑 npm 发布包时,可直接复制源码模板(与 `packages/create-app/templates` 同步):
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
cp -R starters/next-app-starter ../my-app # 或 spa-starter
|
|
87
|
+
cd ../my-app && pnpm install && pnpm dev
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
改框架包后若示例依赖 workspace `dist`,在 monorepo 根目录先 `pnpm build`。
|
|
91
|
+
|
|
92
|
+
### 同步模板到 create-app
|
|
93
|
+
|
|
94
|
+
维护者更新 `starters/*` 后,在 `packages/create-app` 执行 `pnpm sync-templates`(再发布 `create-pactor-app`)。
|
|
95
|
+
|
|
96
|
+
## 红线
|
|
97
|
+
|
|
98
|
+
1. **不要**对非空目录强行 `scaffold`;应新建子目录或让用户清空/换路径。
|
|
99
|
+
2. **不要**在 spa 单独开发时忘记后端:默认 `apiBaseUrl` 指向 `http://localhost:9011`。
|
|
100
|
+
3. **不要**把 PRD 整站生成与脚手架混用;PRD 流程从 `pactor-prd/template/` 复制。
|
|
101
|
+
4. 使用内置 UI 时,入口必须 `import '@pactor-app/ui/styles.css'`(模板已包含;手动接入时勿漏)。
|
|
102
|
+
5. 生成后加页:官方 next-app 默认 **`src/server/yaml/pages/*.page.yaml`**(平铺);模块多或页面 >5 时迁到 **`yaml/<模块>/<id>.yaml`**,规则见 `pactor-dsl/references/page-catalog-and-layout.md`。spa 由远端 sitemap 声明 pageId,yaml 通常在 API 侧。
|
|
103
|
+
|
|
104
|
+
## 常见问题
|
|
105
|
+
|
|
106
|
+
| 现象 | 处理 |
|
|
107
|
+
| --- | --- |
|
|
108
|
+
| 目标目录非空 | 换空目录名或新建文件夹 |
|
|
109
|
+
| spa 白屏 / 接口失败 | 确认 :9011 sitemap 已启动、`src/pactor/config.ts` 的 `apiBaseUrl` 正确 |
|
|
110
|
+
| CORS | spa 模板用 `createHttpHooks`;跨域需后端允许来源 |
|
|
111
|
+
| 想改 dev 端口 | 改各模板 `package.json` scripts 或框架 dev 配置(next/vite) |
|
|
112
|
+
|
|
113
|
+
更多结构说明:`references/templates.md`、`references/minimal-vite.md`。
|
|
114
|
+
|
|
115
|
+
## References
|
|
116
|
+
|
|
117
|
+
- `references/templates.md` — next-app / spa 目录树、端口、演示账号、首要修改点
|
|
118
|
+
- `references/minimal-vite.md` — `pactor create` 与手写 Vite 接入对比
|
|
119
|
+
- 官方文档:`docs/src/content/docs/guides/getting-started.md`
|
|
120
|
+
- 脚手架实现:`packages/create-app`(`create-pactor-app`)
|
|
121
|
+
- 生成后写页面:启用 `pactor-dsl` skill
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# 最小 Vite 工程:`pactor create` 与手写接入
|
|
2
|
+
|
|
3
|
+
## `pactor create`(@pactor-app/cli)
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pnpm add -D @pactor-app/cli
|
|
7
|
+
pnpm pactor create my-app
|
|
8
|
+
cd my-app && pnpm install && pnpm dev
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
- 当前仅模板 id **`app`**(`-t app` 可省略)
|
|
12
|
+
- 生成物:Vite + React + `@pactor-app/vite-plugin` + `StaticDslLoader` + 示例 `*.page.yaml`
|
|
13
|
+
- 适合:单页或少量静态 DSL、原型、学习 Runtime,**不含** sitemap / Next / 登录 mock
|
|
14
|
+
|
|
15
|
+
与官方 `create-pactor-app` 关系:
|
|
16
|
+
|
|
17
|
+
| 命令 | 包 | 产出 |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| `pnpm create pactor-app` | npm 包 `create-pactor-app`(skill:`pactor-project`) | next-app 或 spa(SitemapApp 驱动) |
|
|
20
|
+
| `pnpm pactor create` | `@pactor-app/cli` | 最小 Vite + StaticDslLoader |
|
|
21
|
+
|
|
22
|
+
## 手写接入检查表(已有 Vite 项目)
|
|
23
|
+
|
|
24
|
+
1. 依赖:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm add @pactor-app/app @pactor-app/ui @pactor-app/resource react react-dom
|
|
28
|
+
pnpm add -D @pactor-app/vite-plugin
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
2. `vite.config.ts`:`plugins: [react(), pactor()]`
|
|
32
|
+
3. 入口:`import '@pactor-app/ui/styles.css'`
|
|
33
|
+
4. `StaticDslLoader` 的 `bootstrap.menus` + `pages` 与 YAML 里 `page.id` 一致
|
|
34
|
+
5. 校验:`pnpm pactor validate 'src/**/*.page.yaml'`
|
|
35
|
+
|
|
36
|
+
## monorepo 参考
|
|
37
|
+
|
|
38
|
+
- `examples/vite-starter` — 与 CLI `app` 模板同思路的 workspace 示例(:5499)
|
|
39
|
+
- 修改 `packages/*` 后需根目录 `pnpm build`,示例才读到新 dist
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# 官方模板:next-app 与 spa
|
|
2
|
+
|
|
3
|
+
由 `create-pactor-app`(`packages/create-app/templates`)与仓库 `starters/` 提供,内容同步。
|
|
4
|
+
|
|
5
|
+
## 对比
|
|
6
|
+
|
|
7
|
+
| | next-app | spa |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| 模板 id | `next-app` | `spa` |
|
|
10
|
+
| 栈 | Next.js App Router + React | Vite + React |
|
|
11
|
+
| dev 端口 | 9011 | 9012 |
|
|
12
|
+
| 自带 mock API | 是(`/api/sitemap`、`/api/pages/[id]`、登录 cookie) | 否(默认连 :9011) |
|
|
13
|
+
| 路由 | Next 可选 catch-all + `SitemapApp` 内容区 | 框架内置 History 路由(不传 pathname/navigate) |
|
|
14
|
+
| 适用 | 全栈起步、会话、sitemap 裁剪 | 纯前端部署、API 独立团队 |
|
|
15
|
+
|
|
16
|
+
## next-app 目录要点
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
app/
|
|
20
|
+
layout.tsx # Pactor 壳常驻
|
|
21
|
+
[[...slug]]/page.tsx # catch-all(可为空)
|
|
22
|
+
api/
|
|
23
|
+
sitemap/route.ts # 会话感知 sitemap
|
|
24
|
+
pages/[id]/route.ts # 页面 DSL 懒加载(PageResource envelope)
|
|
25
|
+
auth/login|logout/ # 演示登录
|
|
26
|
+
src/
|
|
27
|
+
pactor/
|
|
28
|
+
config.ts # sitemapSources、apiBaseUrl(通常相对本机)
|
|
29
|
+
App.tsx # SitemapApp + Next pathname/navigate
|
|
30
|
+
server/
|
|
31
|
+
accounts.ts # 演示账号
|
|
32
|
+
sitemap.ts # mock 数据组装
|
|
33
|
+
yaml/
|
|
34
|
+
sitemap.yaml # 布局、菜单、页面 id 声明
|
|
35
|
+
pages/*.page.yaml # 页面 DSL(官方脚手架默认:平铺模式 A)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### YAML 布局:平铺 vs 模块目录
|
|
39
|
+
|
|
40
|
+
| 模式 | 路径 | 何时用 |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| **A 平铺** | `yaml/pages/<id>.page.yaml` | 本模板 / `create-pactor-app -t next-app` 默认;少量页面 |
|
|
43
|
+
| **B 模块目录** | `yaml/<模块>/<id>.yaml` | 多模块后台;**`pactor-prd` 模板**;页面 >5 时建议从 A 迁到 B |
|
|
44
|
+
|
|
45
|
+
规则与批量加页:`pactor-dsl/references/page-catalog-and-layout.md`。
|
|
46
|
+
|
|
47
|
+
演示账号:
|
|
48
|
+
|
|
49
|
+
| 账号 | 密码 | 说明 |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| admin | pactor123 | 含 `report:view`,报表页懒加载 |
|
|
52
|
+
| guest | guest123 | 仅首页 |
|
|
53
|
+
|
|
54
|
+
## spa 目录要点
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
src/
|
|
58
|
+
main.tsx
|
|
59
|
+
pactor/
|
|
60
|
+
config.ts # sitemapSources + apiBaseUrl(默认 http://localhost:9011)
|
|
61
|
+
App.tsx # SitemapApp + createHttpHooks(跨域 + envelope 拆包)
|
|
62
|
+
index.html
|
|
63
|
+
vite.config.ts # 通常无 pactor vite-plugin(页面由 API 下发)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
本地联调:**先** `next-app`(或等价后端)**:9011`,**再** spa `:9012`。
|
|
67
|
+
|
|
68
|
+
## 生成后首要修改点
|
|
69
|
+
|
|
70
|
+
### 所有模板
|
|
71
|
+
|
|
72
|
+
- `package.json` 的 `name`(脚手架已用目录名替换 `__APP_NAME__`)
|
|
73
|
+
- 品牌与标题:`src/server/yaml/sitemap.yaml`(next-app)内 `app.name`、菜单文案
|
|
74
|
+
- 换真实后端:保持端点契约不变,替换 `app/api/*` 或 spa 的 `apiBaseUrl`(见 `@pactor-app/resource` 文档)
|
|
75
|
+
|
|
76
|
+
### 仅 next-app
|
|
77
|
+
|
|
78
|
+
- 新增页面:模式 A 在 `yaml/pages/` 增加 `*.page.yaml`;模式 B 在 `yaml/<模块>/` 增加 `<id>.yaml`;均在 `sitemap.yaml` 注册 `pages` / `menus`(见 page-catalog-and-layout.md)
|
|
79
|
+
- 权限演示:改 `accounts.ts` 与 sitemap 里菜单的 permission 字段
|
|
80
|
+
|
|
81
|
+
### 仅 spa
|
|
82
|
+
|
|
83
|
+
- 部署生产:把 `apiBaseUrl` 改为生产 API 原点;确保 sitemap / pages 接口 CORS 与 cookie 策略与宿主一致
|
|
84
|
+
|
|
85
|
+
## API 契约(简记)
|
|
86
|
+
|
|
87
|
+
前端 `SitemapApp` / `createPactorApplication({ api })` 期望:
|
|
88
|
+
|
|
89
|
+
- **Sitemap 源**:返回合并后的 sitemap 对象(layouts、pages 元数据、menus、app、user、permissions…)
|
|
90
|
+
- **页面懒加载**:`GET .../pages/{id}` 返回 PageResource envelope(含页面 DSL 正文)
|
|
91
|
+
|
|
92
|
+
next-app 模板的 route 实现即参考契约;对接自有 Java/Go 等服务时按同样 JSON 形状实现即可。
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Validates @pactor-app/skills layout: directory name === SKILL.md frontmatter name,
|
|
4
|
+
* required references exist, pactor-prd ships template/.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
7
|
+
import { join, dirname } from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
|
|
10
|
+
const skillsRoot = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
11
|
+
const SKILL_DIRS = ['pactor-dsl', 'pactor-project', 'pactor-prd'];
|
|
12
|
+
|
|
13
|
+
function readSkillName(skillDir) {
|
|
14
|
+
const skillPath = join(skillDir, 'SKILL.md');
|
|
15
|
+
const text = readFileSync(skillPath, 'utf8');
|
|
16
|
+
const block = text.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
17
|
+
if (!block) return null;
|
|
18
|
+
for (const line of block[1].split('\n')) {
|
|
19
|
+
if (line.startsWith('name:')) {
|
|
20
|
+
return line.slice('name:'.length).trim().replace(/^['"]|['"]$/g, '');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function listMdReferences(skillDir) {
|
|
27
|
+
const refDir = join(skillDir, 'references');
|
|
28
|
+
if (!existsSync(refDir)) return [];
|
|
29
|
+
return readdirSync(refDir).filter((f) => f.endsWith('.md'));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let failed = false;
|
|
33
|
+
|
|
34
|
+
for (const id of SKILL_DIRS) {
|
|
35
|
+
const dir = join(skillsRoot, id);
|
|
36
|
+
if (!existsSync(dir)) {
|
|
37
|
+
console.error(`missing skill directory: ${id}`);
|
|
38
|
+
failed = true;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const name = readSkillName(dir);
|
|
42
|
+
if (name !== id) {
|
|
43
|
+
console.error(`${id}: frontmatter name "${name}" !== directory "${id}"`);
|
|
44
|
+
failed = true;
|
|
45
|
+
}
|
|
46
|
+
const refs = listMdReferences(dir);
|
|
47
|
+
for (const file of refs) {
|
|
48
|
+
if (!existsSync(join(dir, 'references', file))) {
|
|
49
|
+
console.error(`${id}: missing references/${file}`);
|
|
50
|
+
failed = true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (id === 'pactor-prd') {
|
|
54
|
+
const tpl = join(dir, 'template', 'package.json');
|
|
55
|
+
if (!existsSync(tpl)) {
|
|
56
|
+
console.error('pactor-prd: missing template/package.json');
|
|
57
|
+
failed = true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (failed) {
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
console.log(`skills OK (${SKILL_DIRS.join(', ')})`);
|
package/prd-to-app/SKILL.md
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: prd-to-app
|
|
3
|
-
description: |
|
|
4
|
-
Use when generating a complete pactor (pactor-app) project from product documents / markdown wireframes — pages described in YAML DSL (*.page.yaml). Triggers: 根据 PRD / 产品文档 / 线框图 (wireframe) 创建 / 生成管理后台或 Web 应用原型; turning a PRD directory (overview README + per-page ASCII wireframe markdown) into a runnable Next.js + pactor project, including sitemap.yaml, page yaml, http dataSources, mock API routes, theme/skin alignment with the original product, and browser acceptance.
|
|
5
|
-
version: 1.1.0
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# PRD → YAML 页面应用生成
|
|
9
|
-
|
|
10
|
-
把「产品文档 + Markdown 线框图」翻译成可运行的 pactor 项目:页面全部 YAML DSL 描述,数据一律 http 数据源 + mock 路由,样式与功能与原产品一致。
|
|
11
|
-
|
|
12
|
-
## 输入要求
|
|
13
|
-
|
|
14
|
-
- PRD/线框图目录:总览 README(模块 × 页面 × 优先级表格)+ 分页线框图 markdown(ASCII 线框 + 区域说明 + 交互描述)
|
|
15
|
-
- 原产品代码仓(可选但强烈建议):用于提取设计令牌、自定义 CSS、交互行为
|
|
16
|
-
- 目标目录:空目录或目标仓库
|
|
17
|
-
|
|
18
|
-
输入格式与样例不同时,先归纳其「模块 → 页面 → 区域 → 交互」的等价结构,再套用本流程,不要因格式差异中止。
|
|
19
|
-
|
|
20
|
-
## 红线(必须遵守)
|
|
21
|
-
|
|
22
|
-
1. **dataSources 一律 `type: http`**,指向 `/api/data/...`,不写 `type: service`,便于后续替换真实接口
|
|
23
|
-
2. **布局、样式、尺寸、间距以 `template/` 模板工程为准**:线框图只用于提取内容结构与功能(有哪些区域、字段、操作),不逐像素还原 ASCII 原型;排版模式(页头、筛选区排布、卡片网格列数、表格密度、表单分区、间距档位)一律套用模板既有页面的写法
|
|
24
|
-
3. **样式与原产品一致**:主题令牌(含深浅色)、自定义 CSS(如登录页)、换肤入口全部移植对齐,见 `references/theme-and-style.md`
|
|
25
|
-
4. **功能与原产品一致**:线框图描述的筛选/搜索/跳转/弹窗/提交等交互必须经 events/actions 闭环可用,禁止只画静态骨架;错误分支(校验失败提示等)也要实现
|
|
26
|
-
5. **表单一律用 `Form` 组件**:凡是一组「字段 + 校验 + 提交」的表单——独立表单页、页面内嵌的配置面板(如树/列表右侧的编辑表单)、弹窗/抽屉表单、**搜索栏(关键词 + 查询/重置 的筛选区,用 `Form layout: inline`)**——都必须用 `Form` 包裹,字段经 `props.name` 绑定,校验用字段级 `rules`(required + message),提交用 `submit: true` 的 Button 触发 `onSubmit`;**禁止**散放 `Input`/`Select` + `setState` 攒草稿 + `if` 动作手写校验。回填联动(如点击列表/树节点填充表单)用 `form.setValues` 动作,不要绑 `${state.x}` 到字段 value;即点即生效的 ChipFilter 快筛行没有提交语义,不属于表单
|
|
27
|
-
6. **列表页操作列规范**:操作列按钮样式统一 `Button variant: link`;「编辑」与「新建」指向同一个表单(同一路由页或同一弹窗),唯一区别是编辑以行数据预填(路由页 `initialValues: ${data.detail}`,弹窗/内嵌面板 `form.setValues`)
|
|
28
|
-
7. **文案以线框图为准**:标题、按钮、空态文案逐字取自线框图/PRD
|
|
29
|
-
8. DSL 语法细节(组件 props、表达式、动作)以 pactor skill 与 packages/ui 当前导出为准,本 skill 只约定流程与产出物
|
|
30
|
-
|
|
31
|
-
## 流程(六阶段)
|
|
32
|
-
|
|
33
|
-
### 1. 输入解析
|
|
34
|
-
|
|
35
|
-
- 读总览 README:提取模块树、页面清单(页面 id kebab-case、标题、路由路径、菜单分组、P0/P1/P2 优先级)
|
|
36
|
-
- 逐页读线框图:提取页面类型(列表/详情/表单/仪表盘)、布局区域、组件清单、字段与数据需求、交互(跳转/弹窗/操作)
|
|
37
|
-
- 输出一页纸页面清单供确认;P2 等未排期页面登记但不生成
|
|
38
|
-
|
|
39
|
-
### 2. 脚手架
|
|
40
|
-
|
|
41
|
-
- **整体复制 `template/` 目录作为新项目起点**(可运行的参考实现:完整接线 + 公共页面 + 两个参考模块),不要从空目录或 `pnpm create pactor-app` 开始
|
|
42
|
-
- 确定工程名称:**用户未明确指定时,根据原型目录 README 中的产品名生成英文名**(kebab-case):取 README 主标题/产品名(如「订单管理系统产品原型线框图」→ `order-console`),中文名先译为简洁英文;派生出的名称在创建前向用户确认一次
|
|
43
|
-
- 改名并安装:package.json name、yaml/sitemap.yaml 的 app.name 与品牌改为新产品名;`pnpm install` + 启动 dev server 验证模板可运行
|
|
44
|
-
- 按 `references/project-structure.md` 核对目录结构:`src/server/yaml/`(sitemap.yaml + 按模块分目录的页面 yaml)与 `app/api/` 路由(sitemap / public/pages/[id] / data/[...path])
|
|
45
|
-
- 模板中的 provider / route 两个模块作为页面写法参考保留在手边,新模块照其结构生成;确认全部页面生成完毕后删除参考模块及其 mock
|
|
46
|
-
|
|
47
|
-
### 3. 页面生成
|
|
48
|
-
|
|
49
|
-
- 按 `references/component-mapping.md` 把线框图区域映射为 pactor 组件
|
|
50
|
-
- 按 `references/page-templates.md` 的三类模板逐页生成 `yaml/<模块>/<id>.yaml`:列表页(筛选 + 表格/卡片 + 操作列)、详情页(描述列表 + Tab/分区)、表单页(校验 + 提交闭环);**所有表单(含页面内嵌的配置面板、弹窗/抽屉表单)一律 `Form` 组件包裹**,写法见 page-templates.md「内嵌表单面板」
|
|
51
|
-
- 每页 dataSources 全部 `type: http`;交互经 events + actions 闭环(setState → reload dataSource → router.push 等)
|
|
52
|
-
|
|
53
|
-
### 4. mock 服务
|
|
54
|
-
|
|
55
|
-
- 按 `references/mock-data-routes.md` 在 `app/api/data/[...path]/route.ts` 注册路由表 handler,返回符合线框图字段的 mock 数据(含空态/多态数据各至少一条)
|
|
56
|
-
|
|
57
|
-
### 5. 样式移植
|
|
58
|
-
|
|
59
|
-
- 按 `references/theme-and-style.md`:提取原产品设计令牌写入皮肤文件(深浅色俱全)、移植页面级自定义 CSS 并挂载、对齐换肤入口与皮肤数量、确认图表随肤切换
|
|
60
|
-
|
|
61
|
-
### 6. 功能与视觉验收(必经,不可跳过)
|
|
62
|
-
|
|
63
|
-
- 按 `references/acceptance-checklist.md` 逐页浏览器验收并输出验收结果表:路由可达、数据源 200、渲染符合线框、交互逐项操作(含错误分支)、控制台无错、深浅色切换、与原产品同页面对比
|
|
64
|
-
|
|
65
|
-
## references 索引
|
|
66
|
-
|
|
67
|
-
| 文件 | 何时加载 |
|
|
68
|
-
| --- | --- |
|
|
69
|
-
| `template/` | 阶段 2:可运行的模板工程(完整接线 + 公共页面 + provider/route 两个参考模块),整体复制后按 PRD 改造,用法见其 README.md |
|
|
70
|
-
| `references/project-structure.md` | 阶段 2:目录结构约定与 sitemap.yaml 骨架 |
|
|
71
|
-
| `references/component-mapping.md` | 阶段 3:线框图区域 → pactor 组件映射 |
|
|
72
|
-
| `references/page-templates.md` | 阶段 3:列表/详情/表单页 yaml 模板 |
|
|
73
|
-
| `references/mock-data-routes.md` | 阶段 4:mock 路由表模板与命名约定 |
|
|
74
|
-
| `references/theme-and-style.md` | 阶段 5:主题令牌提取、皮肤、自定义 CSS、换肤 |
|
|
75
|
-
| `references/acceptance-checklist.md` | 阶段 6:验收清单与结果输出格式 |
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|