@deppon/deppon-prd-mcp 0.1.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.
Files changed (48) hide show
  1. package/README.md +83 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +16 -0
  4. package/dist/config.d.ts +8 -0
  5. package/dist/config.js +30 -0
  6. package/dist/core/prd-generator.d.ts +4 -0
  7. package/dist/core/prd-generator.js +133 -0
  8. package/dist/core/project-store.d.ts +23 -0
  9. package/dist/core/project-store.js +77 -0
  10. package/dist/core/prototype-generator.d.ts +2 -0
  11. package/dist/core/prototype-generator.js +272 -0
  12. package/dist/core/types.d.ts +204 -0
  13. package/dist/core/types.js +160 -0
  14. package/dist/http/server.d.ts +2 -0
  15. package/dist/http/server.js +115 -0
  16. package/dist/index.d.ts +2 -0
  17. package/dist/index.js +2 -0
  18. package/dist/mcp/server.d.ts +4 -0
  19. package/dist/mcp/server.js +194 -0
  20. package/package.json +55 -0
  21. package/templates/examples/README.md +17 -0
  22. package/templates/examples/app-shell-navigation/layout-spec.md +54 -0
  23. package/templates/examples/app-shell-navigation/pages/demo-form.html +57 -0
  24. package/templates/examples/app-shell-navigation/pages/demo-home.html +92 -0
  25. package/templates/examples/app-shell-navigation/pages/demo-list.html +47 -0
  26. package/templates/examples/app-shell-navigation/prd.md +164 -0
  27. package/templates/examples/app-shell-navigation/prototype.html +794 -0
  28. package/templates/examples/backend-list/prd.md +97 -0
  29. package/templates/examples/backend-list/prototype.html +378 -0
  30. package/templates/examples/data-dashboard/prd.md +127 -0
  31. package/templates/examples/data-dashboard/prototype.html +281 -0
  32. package/templates/examples/form-edit/prd.md +108 -0
  33. package/templates/examples/form-edit/prototype.html +280 -0
  34. package/templates/examples/form-preview/prd.md +106 -0
  35. package/templates/examples/form-preview/prototype.html +240 -0
  36. package/templates/examples/list-crud/prd.md +151 -0
  37. package/templates/examples/list-crud/prototype.html +1348 -0
  38. package/templates/examples/user-frontend/prd.md +86 -0
  39. package/templates/examples/user-frontend/prototype.html +223 -0
  40. package/templates/template/app-shell-navigation-prd-template.md +180 -0
  41. package/templates/template/backend-form-edit-prd-template.md +116 -0
  42. package/templates/template/backend-form-preview-prd-template.md +112 -0
  43. package/templates/template/backend-list-prd-template.md +120 -0
  44. package/templates/template/data-prd-template.md +194 -0
  45. package/templates/template/user-frontend-prd-template.md +59 -0
  46. package/web/app.js +342 -0
  47. package/web/index.html +106 -0
  48. package/web/styles.css +100 -0
@@ -0,0 +1,86 @@
1
+ # 春季拉新活动页 PRD(产品需求文档)
2
+
3
+ > **文档说明**:本文件位于技能目录 `examples/user-frontend/`,对应 **`user-frontend-prd-template.md`**(用户角色 + 功能模块 + 交互流程)。实际产出写入 `src/prototypes/<page-name>/prd.md`。
4
+
5
+ > **交互原型**:[打开 prototype.html](./prototype.html);标注 **`fetch` 同目录 `prd.md`**;须 **HTTP** 打开。
6
+
7
+ ---
8
+
9
+ ## 1. 引言
10
+
11
+ ### 1.1 背景
12
+
13
+ C 端活动页:向新用户展示权益与参与规则,引导完成注册/领券;需兼容移动端首屏与分享落地。
14
+
15
+ ### 1.2 用户角色
16
+
17
+ | 用户角色 | 描述 | 使用场景 |
18
+ | -------- | ---------- | ---------- |
19
+ | 游客 | 未登录访客 | 浏览活动规则 |
20
+ | 新用户 | 首次注册 | 领券、参与活动 |
21
+
22
+ ### 1.3 功能清单
23
+
24
+ | 模块 | 功能点 | 功能描述 |
25
+ | ------ | -------- | ------------------ |
26
+ | 活动页 | 首屏展示 | 主标题、权益、主 CTA |
27
+ | 活动页 | 规则说明 | 折叠/锚点查看细则 |
28
+ | 活动页 | 立即参与 | 跳转注册或唤起登录 |
29
+
30
+ ---
31
+
32
+ ## 2. 春季活动落地页需求说明
33
+
34
+ ### 2.1 首屏与权益说明
35
+
36
+ #### 2.1.1 功能描述
37
+
38
+ 首屏包含主视觉、活动标题、核心权益三点、主按钮「立即参与」;向下滚动可见规则摘要。
39
+
40
+ #### 2.1.2 交互流程
41
+
42
+ 1. **触发条件**:用户进入 H5/PC 落地页。
43
+ 2. **操作步骤**:
44
+ - 步骤1:浏览首屏权益。
45
+ - 步骤2:点击「立即参与」。
46
+ 3. **操作反馈**:
47
+ - 成功:已登录跳转任务页;未登录跳转注册(原型 Toast 模拟)。
48
+ - 失败:网络错误时轻提示。
49
+
50
+ ### 2.2 规则与 FAQ
51
+
52
+ #### 2.2.1 功能描述
53
+
54
+ 折叠面板展示活动时间、参与资格、奖品发放说明。
55
+
56
+ #### 2.2.2 交互流程
57
+
58
+ 1. **触发条件**:点击「活动规则」标题。
59
+ 2. **操作步骤**:展开/收起面板。
60
+ 3. **操作反馈**:`aria-expanded` 同步。
61
+
62
+ ---
63
+
64
+ ## 3. 交互与反馈
65
+
66
+ 主 CTA 使用品牌主色;次要链接下划线;Toast 与 Loading 遵循设计规范;分享缩略图与标题由运营配置(非本页范围)。
67
+
68
+ ---
69
+
70
+ ## 9. 原型与 PRD 对应关系
71
+
72
+ | PRD 章节 | prototype.html 演示点 |
73
+ | -------- | ---------------------- |
74
+ | §1 | 页内「PRD §1」 |
75
+ | §2.1 | 首屏区「PRD §2.1」 |
76
+ | §2.2 | 规则折叠「PRD §2.2」 |
77
+ | §3 | 全局反馈说明入口 |
78
+ | 走查说明 | 左下角「标注说明」 |
79
+
80
+ ---
81
+
82
+ ## 10. 修订记录
83
+
84
+ | 版本 | 日期 | 说明 |
85
+ | ---- | ---------- | ---- |
86
+ | v0.1 | 2026-05-14 | 初版:对齐 user-frontend 模板示例 |
@@ -0,0 +1,223 @@
1
+ <!--
2
+ 技能示例 examples/user-frontend/ — 对齐 user-frontend-prd-template
3
+ fetch prd.md;须 HTTP。
4
+ -->
5
+ <!DOCTYPE html>
6
+ <html lang="zh-CN">
7
+ <head>
8
+ <meta charset="UTF-8" />
9
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
10
+ <title>春季拉新活动 — 原型</title>
11
+ <script src="https://cdn.tailwindcss.com"></script>
12
+ <style>
13
+ .anno-trigger {
14
+ display: inline-flex;
15
+ border-radius: 0.375rem;
16
+ border: 1px solid rgba(253, 224, 71, 0.9);
17
+ background: rgba(254, 249, 195, 0.95);
18
+ padding: 0.15rem 0.5rem;
19
+ font-size: 0.65rem;
20
+ font-weight: 700;
21
+ color: rgb(66 32 6);
22
+ cursor: pointer;
23
+ }
24
+ #annoDlgBody .prd-md table {
25
+ width: 100%;
26
+ border-collapse: collapse;
27
+ font-size: 0.75rem;
28
+ }
29
+ #annoDlgBody .prd-md th,
30
+ #annoDlgBody .prd-md td {
31
+ border: 1px solid rgb(226 232 240);
32
+ padding: 0.35rem;
33
+ }
34
+ </style>
35
+ </head>
36
+ <body class="min-h-screen bg-gradient-to-b from-rose-50 to-white text-slate-900">
37
+ <div id="prdLoadBanner" class="hidden border-b border-amber-400 bg-amber-100 px-4 py-2 text-center text-xs text-amber-950"></div>
38
+ <div id="toast" class="fixed top-4 right-4 z-[60] hidden rounded-lg bg-slate-900 px-4 py-2 text-sm text-white"></div>
39
+ <button type="button" id="btnAnnoLegend" class="fixed bottom-5 left-5 z-[65] rounded-full border border-amber-500 bg-white/90 px-3 py-2 text-xs shadow">
40
+ 标注说明
41
+ </button>
42
+
43
+ <header class="border-b border-rose-100/80 bg-white/70 backdrop-blur">
44
+ <div class="mx-auto flex max-w-3xl items-center justify-between px-4 py-3">
45
+ <span class="text-sm font-medium text-rose-900">春季拉新</span>
46
+ <button type="button" class="anno-trigger" data-anno-key="s1">PRD §1</button>
47
+ </div>
48
+ </header>
49
+
50
+ <main class="mx-auto max-w-3xl px-4 py-10">
51
+ <section class="relative rounded-2xl border border-rose-100 bg-white/90 p-8 shadow-lg">
52
+ <button type="button" class="anno-trigger absolute right-4 top-4" data-anno-key="s21">§2.1</button>
53
+ <p class="text-xs font-semibold uppercase tracking-widest text-rose-600">限时活动</p>
54
+ <h1 class="mt-2 text-3xl font-bold text-slate-900">邀请好友 · 双倍权益</h1>
55
+ <p class="mt-3 text-sm leading-relaxed text-slate-600">
56
+ 完成注册并实名,即得优惠券包;分享链接再得积分(原型数据为示意)。
57
+ </p>
58
+ <button
59
+ type="button"
60
+ id="btnCta"
61
+ class="mt-6 w-full rounded-xl bg-blue-600 py-3 text-center text-sm font-semibold text-white shadow-md hover:bg-blue-700 sm:w-auto sm:px-10"
62
+ >
63
+ 立即参与
64
+ </button>
65
+ </section>
66
+
67
+ <section class="mt-8 rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
68
+ <button type="button" class="anno-trigger float-right ml-2" data-anno-key="s22">§2.2</button>
69
+ <h2 class="text-base font-semibold text-slate-900">活动规则</h2>
70
+ <details class="mt-3 text-sm text-slate-600" open>
71
+ <summary class="cursor-pointer font-medium text-slate-800">时间与资格</summary>
72
+ <ul class="mt-2 list-disc space-y-1 pl-5">
73
+ <li>活动时间:以运营后台配置为准。</li>
74
+ <li>新用户定义:近 90 天无注册记录的手机号。</li>
75
+ </ul>
76
+ </details>
77
+ </section>
78
+
79
+ <p class="mt-8 text-center">
80
+ <button type="button" class="anno-trigger" data-anno-key="s3">PRD §3 交互与反馈</button>
81
+ </p>
82
+ </main>
83
+
84
+ <div id="modalAnno" class="fixed inset-0 z-[70] hidden items-center justify-center bg-slate-900/55 p-4" role="dialog">
85
+ <div class="flex max-h-[88vh] w-full max-w-2xl flex-col overflow-hidden rounded-xl border-2 border-amber-400 bg-white shadow-2xl">
86
+ <div class="flex shrink-0 justify-between border-b border-amber-200 bg-amber-50 px-4 py-2">
87
+ <h3 id="annoDlgTitle" class="truncate text-sm font-semibold"></h3>
88
+ <button type="button" id="btnAnnoClose">✕</button>
89
+ </div>
90
+ <div id="annoDlgBody" class="min-h-0 flex-1 overflow-auto p-4 text-sm" tabindex="-1"></div>
91
+ </div>
92
+ </div>
93
+
94
+ <script src="https://cdn.jsdelivr.net/npm/marked@12.0.2/marked.min.js"></script>
95
+ <script>
96
+ function runPrototype(prdMd, prdLoadError) {
97
+ function $(id) {
98
+ return document.getElementById(id);
99
+ }
100
+ function escapeHtml(s) {
101
+ return String(s)
102
+ .replace(/&/g, '&amp;')
103
+ .replace(/</g, '&lt;')
104
+ .replace(/>/g, '&gt;')
105
+ .replace(/"/g, '&quot;');
106
+ }
107
+ if (typeof marked !== 'undefined' && marked.use) marked.use({ gfm: true, breaks: true });
108
+ var ban = $('prdLoadBanner');
109
+ if (ban && (!prdMd || prdLoadError)) {
110
+ ban.textContent = '未加载 prd.md:请用 HTTP 打开本目录。';
111
+ ban.classList.remove('hidden');
112
+ }
113
+
114
+ function sliceBetween(md, startRe, endRe) {
115
+ if (!md) return '';
116
+ var m = md.match(startRe);
117
+ if (!m || m.index === undefined) return '';
118
+ var i0 = m.index;
119
+ if (!endRe) return md.slice(i0).trim();
120
+ var tail = md.slice(i0 + m[0].length);
121
+ var j = tail.search(endRe);
122
+ if (j === -1) return md.slice(i0).trim();
123
+ return md.slice(i0, i0 + m[0].length + j).trim();
124
+ }
125
+ function mdToHtml(src) {
126
+ if (!src) return '<p class="text-xs">(无)</p>';
127
+ if (typeof marked !== 'undefined' && marked.parse)
128
+ return '<div class="prd-md">' + marked.parse(src) + '</div>';
129
+ return '<pre class="text-xs">' + escapeHtml(src) + '</pre>';
130
+ }
131
+
132
+ var LEG = '<p class="text-sm">C 端页标注与 <strong>prd.md</strong> 联动。</p>';
133
+ var EX = {
134
+ s1: { start: /^## 1\./m, end: /^## 2\./m, title: 'prd.md §1' },
135
+ s21: { start: /^### 2\.1/m, end: /^### 2\.2/m, title: 'prd.md §2.1' },
136
+ s22: { start: /^### 2\.2/m, end: /^## 3\./m, title: 'prd.md §2.2' },
137
+ s3: { start: /^## 3\./m, end: /^## 9\./m, title: 'prd.md §3' },
138
+ };
139
+ var FB = {
140
+ s1: { html: '<p class="text-xs">兜底</p>' },
141
+ s21: { html: '<p class="text-xs">兜底</p>' },
142
+ s22: { html: '<p class="text-xs">兜底</p>' },
143
+ s3: { html: '<p class="text-xs">兜底</p>' },
144
+ };
145
+
146
+ function openAnno(key) {
147
+ var w =
148
+ !prdMd || prdLoadError
149
+ ? '<div class="mb-2 rounded bg-amber-50 p-2 text-xs">prd 未联动</div>'
150
+ : '';
151
+ if (key === 'legend') {
152
+ $('annoDlgTitle').textContent = '说明 · §9';
153
+ var s9 = prdMd ? sliceBetween(prdMd, /^## 9\./m, /^## 10\./m) : '';
154
+ $('annoDlgBody').innerHTML = w + LEG + (s9 ? '<div class="mt-2">' + mdToHtml(s9) + '</div>' : '');
155
+ show();
156
+ return;
157
+ }
158
+ var sp = EX[key];
159
+ if (!sp) return;
160
+ var sl = prdMd ? sliceBetween(prdMd, sp.start, sp.end) : '';
161
+ $('annoDlgTitle').textContent = sp.title;
162
+ $('annoDlgBody').innerHTML = w + (sl ? mdToHtml(sl) : FB[key].html);
163
+ show();
164
+ }
165
+ function show() {
166
+ $('modalAnno').classList.remove('hidden');
167
+ $('modalAnno').classList.add('flex');
168
+ $('annoDlgBody').scrollTop = 0;
169
+ }
170
+ function closeAnno() {
171
+ $('modalAnno').classList.add('hidden');
172
+ $('modalAnno').classList.remove('flex');
173
+ }
174
+
175
+ document.addEventListener(
176
+ 'click',
177
+ function (e) {
178
+ var t = e.target.closest('[data-anno-key]');
179
+ if (!t) return;
180
+ e.preventDefault();
181
+ e.stopPropagation();
182
+ openAnno(t.getAttribute('data-anno-key'));
183
+ },
184
+ true,
185
+ );
186
+ $('btnAnnoClose').addEventListener('click', closeAnno);
187
+ $('modalAnno').addEventListener('click', function (e) {
188
+ if (e.target === $('modalAnno')) closeAnno();
189
+ });
190
+ $('btnAnnoLegend').addEventListener('click', function () {
191
+ openAnno('legend');
192
+ });
193
+ document.addEventListener('keydown', function (e) {
194
+ if (e.key === 'Escape' && !$('modalAnno').classList.contains('hidden')) closeAnno();
195
+ });
196
+
197
+ function toast(m) {
198
+ var el = $('toast');
199
+ el.textContent = m;
200
+ el.classList.remove('hidden');
201
+ clearTimeout(el._t);
202
+ el._t = setTimeout(function () {
203
+ el.classList.add('hidden');
204
+ }, 2000);
205
+ }
206
+ $('btnCta').addEventListener('click', function () {
207
+ toast('跳转注册 / 登录(模拟)');
208
+ });
209
+ }
210
+ fetch('prd.md', { cache: 'no-store' })
211
+ .then(function (r) {
212
+ if (!r.ok) throw new Error();
213
+ return r.text();
214
+ })
215
+ .then(function (t) {
216
+ runPrototype(t, null);
217
+ })
218
+ .catch(function () {
219
+ runPrototype('', new Error());
220
+ });
221
+ </script>
222
+ </body>
223
+ </html>
@@ -0,0 +1,180 @@
1
+ # [壳层 / 项目名称] 管理台壳层与导航 PRD(产品需求文档)
2
+
3
+ > **生成时对照**:生成前阅读本技能目录 `examples/app-shell-navigation/prd.md`、`layout-spec.md`(首页栅格/间距速查)与(若交付原型)`examples/app-shell-navigation/prototype.html`,对齐**栅格尺寸、侧栏层级、多页目录约定、iframe/路由跳转**写法。`prd.md` 与原型可见文案默认**简体中文**(见本技能 `SKILL.md`「语言与文案」)。用户仓库产出:`src/prototypes/<项目目录名>/prd.md`(壳层)+ `prototype.html`;**每个 iframe 子页**为 `src/prototypes/<项目目录名>/pages/<子页目录>/prd.md` + `index.html`(与 `SKILL.md`「壳层与子页目录约定」一致;**禁止**新建时仅平铺 `pages/*.html` 而无子目录,除非用户声明例外)。
4
+
5
+ > **交互原型链接(有 `prototype.html` 时必填)**:文首加入 `- **交互原型**:[打开 prototype.html](./prototype.html)`(壳层主入口);并列出各子页 `[打开 index.html](./pages/<子页>/index.html)` 等链接。仅无原型时删除。见 `SKILL.md`「PRD 与原型互链」。
6
+
7
+ ---
8
+
9
+ ## 1. 引言
10
+
11
+ ### 1.1 背景
12
+
13
+ ```
14
+ [说明:本壳层解决「多业务子页在同一管理台内统一导航、顶栏、页签」的问题;PRD 评审可在壳层原型中点击菜单/页签切换不同静态子页。控制在约 80 字内。]
15
+ ```
16
+
17
+ ### 1.2 功能清单
18
+
19
+ > 壳层 PRD **需要**描述顶栏、侧栏、页签、主区占位与跨页跳转规则;与子页 PRD(列表/表单等)区分边界:子页字段与接口以各子目录 `prd.md` 为准。
20
+
21
+ | 模块 | 功能点 | 功能描述 |
22
+ | ---------- | ---------- | -------- |
23
+ | `[壳层名]` | 全局布局 | 侧栏 + 顶栏 + 主工作区;栅格与间距见 §3 |
24
+ | `[壳层名]` | 侧栏导航 | 一级 / 二级 / 三级(含飞层)与收起态,见 §4 |
25
+ | `[壳层名]` | 顶栏与页签 | Logo、面包屑或页签、用户区等,见 §5 |
26
+ | `[壳层名]` | 子页承载 | iframe 或前端路由;子页 URL 与目录约定见 §6 |
27
+ | `[壳层名]` | 权限控制 | 菜单/路由可见性,见 §7 |
28
+
29
+ ---
30
+
31
+ ## 2. 页面菜单与权限规划
32
+
33
+ ### 2.1 入口与菜单树
34
+
35
+ **入口**:`[URL 或功能码入口说明]`
36
+
37
+ **菜单树(与侧栏一致)**:
38
+
39
+ ```
40
+ [一级]
41
+ ├─ [二级] → 子页:[文件名或路由 path]
42
+ └─ ...
43
+ ```
44
+
45
+ ### 2.2 权限规划
46
+
47
+ | 权限点 | 操作范围 | 数据范围 |
48
+ | ------ | -------- | -------- |
49
+ | 查看 | 进入壳层、可见菜单与可打开子页(只读场景) | `[个人/租户/全量]` |
50
+ | 编辑 | 含配置类子页的新增/编辑(若壳层内嵌配置入口) | `[同上]` |
51
+
52
+ ---
53
+
54
+ ## 3. 全局布局与栅格
55
+
56
+ ### 3.1 尺寸与间距
57
+
58
+ > 与视觉规范对齐;下列为**推荐默认值**(可按设计令牌替换)。
59
+
60
+ | 区域 | 规格 | 说明 |
61
+ | ---- | ---- | ---- |
62
+ | 侧栏宽度(展开) | `[如 180px]` | 固定宽,内容区横向滚动不出现双滚动条为宜 |
63
+ | 侧栏宽度(收起) | `[如 56px]` | 仅展示图标;Tooltip 展示全称 |
64
+ | 顶栏高度 | `[如 56px]` | 固定高 |
65
+ | 主区与侧栏间距 | `[如 16px]` | 侧栏右缘到主区 |
66
+ | 顶栏与主区间距 | `[如 16px]` | 顶栏底缘到主区顶 |
67
+ | 主区内模块间距 | `[如 16px]` | 卡片/区块之间 |
68
+ | 页面底边距 | `[如 24px]` | 避免内容贴底 |
69
+ | 栅格体系 | `[如 24 栅格]` | 主区内区块按列占位;大屏断点 `[列举]` |
70
+
71
+ ### 3.2 主工作区栅格
72
+
73
+ > 描述首页或默认 landing 在主区内的分栏(如顶通栏 + 下区 2:1 双列)。
74
+
75
+ - **顶通栏**:`[占满主区宽 / 占 N 栅格]`;用途:`[摘要/筛选/横幅]`。
76
+ - **下区左列**:约 `[2/3]` 宽或 `[16/24 栅格]`;用途:`[列表/图表]`。
77
+ - **下区右列**:约 `[1/3]` 宽或 `[8/24 栅格]`;用途:`[快捷入口/说明]`。
78
+
79
+ ---
80
+
81
+ ## 4. 侧栏导航
82
+
83
+ ### 4.1 一级菜单
84
+
85
+ | 项 | 说明 |
86
+ | -- | ---- |
87
+ | 行高 | `[如 52px]` |
88
+ | 左内边距 / 图标与文案间距 / 右内边距 | `[如 18px / 8px / 18px]` |
89
+ | 展开指示 | 右侧 chevron;展开后旋转或向上 |
90
+ | 选中态 | `[背景色 + 文字色 + 左侧条等]` |
91
+
92
+ ### 4.2 二级菜单
93
+
94
+ - 点击一级展开/收起二级;**手风琴**是否互斥:`[是/否]`。
95
+ - 二级项无图标或统一弱图标:`[说明]`。
96
+
97
+ ### 4.3 三级菜单(飞层)
98
+
99
+ - **触发**:悬停二级项展开右侧浮层;**或**点击展开(二选一,写明)。
100
+ - 浮层:白底、阴影、与侧栏对齐的左边距;**键盘**:`Esc` 关闭飞层。
101
+ - 当前页在三级中**高亮**规则:`[与路由 path 匹配]`。
102
+
103
+ ### 4.4 收起导航
104
+
105
+ - 切换按钮位置:`[侧栏右缘中部/顶栏左侧等]`。
106
+ - 收起后:仅图标;当前一级 `active` 样式:`[描边/底色]`。
107
+ - **Tooltip**:鼠标悬停图标展示菜单全称。
108
+
109
+ ---
110
+
111
+ ## 5. 顶栏与页签区
112
+
113
+ | 元素 | 行为与内容 |
114
+ | ---- | ---------- |
115
+ | Logo / 产品名 | `[点击回首页或外链]` |
116
+ | 页签(若启用) | 与打开的子页同步;可关闭;**右键菜单**(可选):关闭其他/全部 |
117
+ | 搜索 / 消息 / 用户 | `[占位说明,链到各子 PRD 若需要]` |
118
+
119
+ ---
120
+
121
+ ## 6. 多页跳转与文档中心目录约定
122
+
123
+ > 目标:评审时在**不启动业务工程**的情况下,通过壳层在多个静态子页间跳转。
124
+
125
+ **推荐目录(与 `deppon-prd-generator` 技能一致)**:
126
+
127
+ ```text
128
+ src/prototypes/<项目目录名>/
129
+ prd.md # 本壳层 PRD
130
+ prototype.html # 壳层入口(含侧栏/顶栏/主 iframe 或路由容器)
131
+ pages/
132
+ <feature-a>.html # 子页原型 A
133
+ <feature-b>.html # 子页原型 B
134
+ ...
135
+ ```
136
+
137
+ **跳转实现(二选一或组合)**:
138
+
139
+ | 方案 | 适用 | 说明 |
140
+ | ---- | ---- | ---- |
141
+ | A. iframe + `target` | 纯静态、零构建 | 侧栏 `<a href="pages/xxx.html" target="[iframe name]">`;子页独立 HTML,各自可带 PRD 标注 |
142
+ | B. 前端路由(hash) | 单页壳 + 多 section | `location.hash` 切换主区内模板;子区块可拆文件后构建期合并 |
143
+ | C. 多文件整页跳转 | 最简单 | `<a href="pages/xxx.html">` 整页替换;壳层重复则需每页引用同一壳或接受无壳 |
144
+
145
+ **打开方式**:若子页或壳层使用 `fetch('prd.md')`,须 **HTTP 打开** 对应目录(勿依赖 `file://`)。
146
+
147
+ ---
148
+
149
+ ## 7. 权限与菜单可见性
150
+
151
+ - 无权限的一级/二级:**隐藏**或**置灰并禁用**(写明策略)。
152
+ - 深链:用户打开无权限路由时的跳转:`[403 页 / 首页 / 提示条]`。
153
+
154
+ ---
155
+
156
+ ## 8. 无障碍与响应式
157
+
158
+ - 侧栏折叠按钮:`aria-expanded`;导航容器:`nav` + 当前项 `aria-current="page"`(若适用)。
159
+ - 飞层:`role="menu"` 或 `dialog`(按实现选型)与焦点陷阱(若 modal)。
160
+ - 小屏:`[侧栏改为抽屉 / 底栏等]`(若本期不做,写「本期仅桌面」)。
161
+
162
+ ---
163
+
164
+ ## 9. 原型与 PRD 对应关系
165
+
166
+ | PRD 章节 | 原型演示点 |
167
+ | -------- | ---------- |
168
+ | §3 | 侧栏/顶栏/主区间距与主区栅格占位 |
169
+ | §4 | 一级展开、三级飞层、收起态 |
170
+ | §5 | 顶栏与页签(若有) |
171
+ | §6 | 点击菜单/页签切换 `pages/` 下子页 |
172
+ | §8 | 焦点与 Esc 行为(与实现一致部分) |
173
+
174
+ ---
175
+
176
+ ## 10. 修订记录
177
+
178
+ | 版本 | 日期 | 说明 |
179
+ | ---- | ---- | ---- |
180
+ | v0.1 | `[YYYY-MM-DD]` | 初稿 |
@@ -0,0 +1,116 @@
1
+ # [页面名称] PRD (产品需求文档)
2
+
3
+ > **生成时对照**:整页表单编辑类 PRD 生成前阅读本技能目录 `examples/form-edit/prd.md`(及将交付原型时的 `prototype.html`)。
4
+
5
+ > **交互原型链接(有 `prototype.html` 时必填)**:文首加入 `- **交互原型**:[打开 prototype.html](./prototype.html)`;仅无原型时删除。见 `SKILL.md`「PRD 与原型互链」。
6
+
7
+ ## 1. 引言
8
+
9
+ ### 1.1 背景
10
+
11
+ > 简要说明该元素/页面的核心定位、解决的问题、用户价值(控制在50字左右)。
12
+
13
+ ```
14
+ [需求背景内容]
15
+ ```
16
+
17
+ ### 1.2 功能清单
18
+
19
+ > 以表格形式梳理出所有模块、功能点及功能描述。
20
+ >
21
+ > 功能清单不包含:页面顶栏、左侧菜单栏的样式、交互需求内容!
22
+
23
+ | 模块 | 功能点 | 功能描述 |
24
+ | ---------------- | -------------- | -------------- |
25
+ | `[功能模块标题]` | `[功能点标题]` | `[功能点描述]` |
26
+
27
+ ## 2. 页面菜单与权限规划
28
+
29
+ ### 2.1 页面菜单
30
+
31
+ > 参考菜单栏,描述页面菜单路径。仅描述菜单路径即可!不要做其他内容说明。
32
+
33
+ **菜单路径**:[一级菜单名称] / [二级菜单名称]
34
+
35
+ ### 2.2 权限规划
36
+
37
+ > 表格呈现权限点规划,仅定义权限点、可执行操作范围、数据范围(如:个人数据/全量数据),不定义具体角色;
38
+ >
39
+ > **权限点规划的基本原则:**查看类操作归集在【查看】一个权限点;编辑类操作归集在【编辑】一个权限点;导出类操作归集在【导出】一个权限点。
40
+
41
+ | 权限点 | 操作范围 | 数据范围 |
42
+ | -------------- | ------------------ | ------------- |
43
+ | `[权限点名称]` | `[支持的操作名称]` | `[个人/全量]` |
44
+
45
+ ## 3. [模块名称]需求说明
46
+
47
+ ### 3.1 表单字段说明
48
+
49
+ > 按表单字段逐一描述,包含字段名称、类型、必填性、校验规则、默认值、说明等
50
+
51
+ | 字段名称 | 字段类型 | 必填 | 默认值 | 校验规则 | 说明 |
52
+ |---------|---------|------|--------|---------|------|
53
+ | `[字段名]` | `[文本/下拉/日期/数字等]` | 是/否 | `[默认值]` | `[校验规则,如:长度1-50,手机号格式等]` | `[字段说明]` |
54
+
55
+ ### 3.2 字段详细说明
56
+
57
+ > 对每个字段进行更详细的说明,特别是有特殊逻辑的字段
58
+
59
+ #### 3.2.1 [字段名称]
60
+
61
+ - **字段说明**:[详细说明]
62
+ - **输入限制**:[具体限制]
63
+ - **校验规则**:
64
+ - 规则1:[描述]
65
+ - 规则2:[描述]
66
+ - **错误提示**:[校验失败时的提示信息]
67
+
68
+ ### 3.3 字段联动逻辑
69
+
70
+ > 描述字段之间的联动关系,如:选择A后,B字段显示/隐藏、变为必填等
71
+
72
+ | 触发字段 | 触发条件 | 影响字段 | 影响效果 |
73
+ |---------|---------|---------|---------|
74
+ | `[字段A]` | `[选择某个值]` | `[字段B]` | `[显示/隐藏/必填/可选等]` |
75
+
76
+ ### 3.4 操作按钮
77
+
78
+ #### 3.4.1 保存/提交
79
+
80
+ - **按钮位置**:表单底部
81
+ - **点击逻辑**:
82
+ 1. 前端校验所有必填字段和格式校验
83
+ 2. 校验失败:显示错误提示,光标定位到第一个错误字段
84
+ 3. 校验通过:调用后端接口提交数据
85
+ 4. 提交成功:显示成功提示,跳转至列表页
86
+ 5. 提交失败:显示失败提示,保留表单数据
87
+
88
+ #### 3.4.2 取消
89
+
90
+ - **按钮位置**:保存按钮旁边
91
+ - **点击逻辑**:
92
+ 1. 若表单有修改,弹出二次确认:"您有未保存的修改,确定要离开吗?"
93
+ 2. 确认:跳转至列表页
94
+ 3. 取消:停留在当前页面
95
+
96
+ #### 3.4.3 重置
97
+
98
+ - **按钮位置**:表单底部(可选)
99
+ - **点击逻辑**:
100
+ 1. 弹出二次确认:"确定要重置表单吗?"
101
+ 2. 确认:恢复所有字段为默认值
102
+ 3. 取消:不做操作
103
+
104
+ ## 4. 交互设计
105
+
106
+ ### 4.1 全局交互
107
+
108
+ - **加载状态**:数据请求过程中需展示 Loading 状态。
109
+ - **空状态**:无数据时需展示统一的 Empty 状态图。
110
+ - **响应式**:页面需适配不同分辨率屏幕,保证内容不遮挡、不错位。
111
+
112
+ ### 4.2 表单交互
113
+
114
+ - **实时校验**:字段失焦时进行校验,即时显示错误提示
115
+ - **必填标识**:必填字段前显示红色星号(*)
116
+ - **Tab键导航**:支持Tab键在字段间顺序切换