@deppon/deppon-skills 2.4.18 → 2.4.21
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/dist/deppon-npm-skills/SKILL.md +3 -3
- package/dist/deppon-prd-generator/SKILL.md +81 -18
- package/dist/deppon-prd-generator/examples/README.md +17 -0
- package/dist/deppon-prd-generator/examples/app-shell-navigation/layout-spec.md +54 -0
- package/dist/deppon-prd-generator/examples/app-shell-navigation/pages/demo-form.html +57 -0
- package/dist/deppon-prd-generator/examples/app-shell-navigation/pages/demo-home.html +92 -0
- package/dist/deppon-prd-generator/examples/app-shell-navigation/pages/demo-list.html +47 -0
- package/dist/deppon-prd-generator/examples/app-shell-navigation/prd.md +164 -0
- package/dist/deppon-prd-generator/examples/app-shell-navigation/prototype.html +794 -0
- package/dist/deppon-prd-generator/examples/backend-list/prd.md +91 -0
- package/dist/deppon-prd-generator/examples/backend-list/prototype.html +369 -0
- package/dist/deppon-prd-generator/examples/data-dashboard/prd.md +127 -0
- package/dist/deppon-prd-generator/examples/data-dashboard/prototype.html +281 -0
- package/dist/deppon-prd-generator/examples/form-edit/prd.md +108 -0
- package/dist/deppon-prd-generator/examples/form-edit/prototype.html +280 -0
- package/dist/deppon-prd-generator/examples/form-preview/prd.md +106 -0
- package/dist/deppon-prd-generator/examples/form-preview/prototype.html +240 -0
- package/dist/deppon-prd-generator/{user-management → examples/list-crud}/prd.md +9 -4
- package/dist/deppon-prd-generator/{user-management → examples/list-crud}/prototype.html +246 -94
- package/dist/deppon-prd-generator/examples/user-frontend/prd.md +86 -0
- package/dist/deppon-prd-generator/examples/user-frontend/prototype.html +223 -0
- package/dist/deppon-prd-generator/quick-reference.md +23 -6
- package/dist/deppon-prd-generator/template/app-shell-navigation-prd-template.md +180 -0
- package/dist/deppon-prd-generator/template/backend-form-edit-prd-template.md +4 -0
- package/dist/deppon-prd-generator/template/backend-form-preview-prd-template.md +4 -0
- package/dist/deppon-prd-generator/template/backend-list-prd-template.md +4 -0
- package/dist/deppon-prd-generator/template/data-prd-template.md +4 -0
- package/dist/deppon-prd-generator/template/user-frontend-prd-template.md +4 -0
- package/dist/deppon-prd-generator/workflow.md +34 -16
- package/package.json +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
|
|
2
|
+
用户管理高保真可交互原型(技能内置参考示例:examples/list-crud/)
|
|
3
3
|
对应文档:同目录 prd.md(§3 列表、§4 详情、§5 表单、§6 删除、§9 对照表)
|
|
4
|
-
技术:Tailwind Play CDN + 原生 JS
|
|
5
|
-
|
|
4
|
+
技术:Tailwind Play CDN + marked(Markdown)+ 原生 JS;业务数据为 mock。
|
|
5
|
+
需求标注:运行时 fetch 同目录 prd.md,按章节切片渲染进标注弹框(与 PRD 联动);请用本地 HTTP 打开本目录,勿依赖 file://。
|
|
6
|
+
弹层内长表格/长文:纵向 + 横向可滚动(见样式 #annoDlgBody .prd-md)。
|
|
6
7
|
-->
|
|
7
8
|
<!DOCTYPE html>
|
|
8
9
|
<html lang="zh-CN">
|
|
@@ -44,9 +45,60 @@
|
|
|
44
45
|
outline: 2px solid rgb(217 119 6);
|
|
45
46
|
outline-offset: 2px;
|
|
46
47
|
}
|
|
48
|
+
/* 标注弹框内:Markdown 渲染区,表格过宽时可横向滚动 */
|
|
49
|
+
#annoDlgBody .prd-md {
|
|
50
|
+
max-width: none;
|
|
51
|
+
}
|
|
52
|
+
#annoDlgBody .prd-md table {
|
|
53
|
+
width: 100%;
|
|
54
|
+
border-collapse: collapse;
|
|
55
|
+
font-size: 0.75rem;
|
|
56
|
+
line-height: 1.35;
|
|
57
|
+
}
|
|
58
|
+
#annoDlgBody .prd-md th,
|
|
59
|
+
#annoDlgBody .prd-md td {
|
|
60
|
+
border: 1px solid rgb(226 232 240);
|
|
61
|
+
padding: 0.35rem 0.5rem;
|
|
62
|
+
vertical-align: top;
|
|
63
|
+
}
|
|
64
|
+
#annoDlgBody .prd-md th {
|
|
65
|
+
background: rgb(248 250 252);
|
|
66
|
+
font-weight: 600;
|
|
67
|
+
text-align: left;
|
|
68
|
+
}
|
|
69
|
+
#annoDlgBody .prd-md h2 {
|
|
70
|
+
font-size: 1rem;
|
|
71
|
+
font-weight: 700;
|
|
72
|
+
margin: 0.75rem 0 0.5rem;
|
|
73
|
+
color: rgb(15 23 42);
|
|
74
|
+
}
|
|
75
|
+
#annoDlgBody .prd-md h3 {
|
|
76
|
+
font-size: 0.875rem;
|
|
77
|
+
font-weight: 600;
|
|
78
|
+
margin: 0.65rem 0 0.35rem;
|
|
79
|
+
color: rgb(30 41 59);
|
|
80
|
+
}
|
|
81
|
+
#annoDlgBody .prd-md ul {
|
|
82
|
+
margin: 0.35rem 0 0.35rem 1.1rem;
|
|
83
|
+
list-style: disc;
|
|
84
|
+
}
|
|
85
|
+
#annoDlgBody .prd-md p {
|
|
86
|
+
margin: 0.35rem 0;
|
|
87
|
+
}
|
|
88
|
+
#annoDlgBody .prd-md code {
|
|
89
|
+
font-size: 0.7rem;
|
|
90
|
+
border-radius: 0.25rem;
|
|
91
|
+
background: rgb(241 245 249);
|
|
92
|
+
padding: 0.1rem 0.3rem;
|
|
93
|
+
}
|
|
47
94
|
</style>
|
|
48
95
|
</head>
|
|
49
96
|
<body class="min-h-screen bg-slate-100 text-slate-800 antialiased">
|
|
97
|
+
<div
|
|
98
|
+
id="prdLoadBanner"
|
|
99
|
+
class="hidden border-b border-amber-300 bg-amber-100 px-4 py-2 text-center text-xs text-amber-950"
|
|
100
|
+
role="status"
|
|
101
|
+
></div>
|
|
50
102
|
<div
|
|
51
103
|
id="toast"
|
|
52
104
|
class="fixed top-4 right-4 z-[60] hidden max-w-sm rounded-lg bg-slate-900 px-4 py-3 text-sm text-white shadow-lg"
|
|
@@ -109,7 +161,7 @@
|
|
|
109
161
|
<input
|
|
110
162
|
type="text"
|
|
111
163
|
id="fUsername"
|
|
112
|
-
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-
|
|
164
|
+
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
113
165
|
placeholder="模糊匹配"
|
|
114
166
|
autocomplete="off"
|
|
115
167
|
/>
|
|
@@ -119,7 +171,7 @@
|
|
|
119
171
|
<input
|
|
120
172
|
type="text"
|
|
121
173
|
id="fName"
|
|
122
|
-
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-
|
|
174
|
+
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
123
175
|
placeholder="模糊匹配"
|
|
124
176
|
autocomplete="off"
|
|
125
177
|
/>
|
|
@@ -129,7 +181,7 @@
|
|
|
129
181
|
<input
|
|
130
182
|
type="text"
|
|
131
183
|
id="fPhone"
|
|
132
|
-
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-
|
|
184
|
+
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
133
185
|
placeholder="精准"
|
|
134
186
|
inputmode="numeric"
|
|
135
187
|
autocomplete="off"
|
|
@@ -139,7 +191,7 @@
|
|
|
139
191
|
>用户状态
|
|
140
192
|
<select
|
|
141
193
|
id="fStatus"
|
|
142
|
-
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-
|
|
194
|
+
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
143
195
|
>
|
|
144
196
|
<option value="">全部</option>
|
|
145
197
|
<option value="启用">启用</option>
|
|
@@ -151,7 +203,7 @@
|
|
|
151
203
|
<button
|
|
152
204
|
type="button"
|
|
153
205
|
id="btnQuery"
|
|
154
|
-
class="rounded-lg bg-
|
|
206
|
+
class="rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
|
|
155
207
|
>
|
|
156
208
|
查询
|
|
157
209
|
</button>
|
|
@@ -194,7 +246,7 @@
|
|
|
194
246
|
<button
|
|
195
247
|
type="button"
|
|
196
248
|
id="btnAdd"
|
|
197
|
-
class="rounded-lg bg-
|
|
249
|
+
class="rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
|
|
198
250
|
>
|
|
199
251
|
新增用户
|
|
200
252
|
</button>
|
|
@@ -230,7 +282,7 @@
|
|
|
230
282
|
<button
|
|
231
283
|
type="button"
|
|
232
284
|
id="btnPrev"
|
|
233
|
-
class="rounded border border-slate-300 px-3 py-1.5 text-xs font-medium hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-
|
|
285
|
+
class="rounded border border-slate-300 px-3 py-1.5 text-xs font-medium hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
234
286
|
>
|
|
235
287
|
上一页
|
|
236
288
|
</button>
|
|
@@ -238,7 +290,7 @@
|
|
|
238
290
|
<button
|
|
239
291
|
type="button"
|
|
240
292
|
id="btnNext"
|
|
241
|
-
class="rounded border border-slate-300 px-3 py-1.5 text-xs font-medium hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-
|
|
293
|
+
class="rounded border border-slate-300 px-3 py-1.5 text-xs font-medium hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
242
294
|
>
|
|
243
295
|
下一页
|
|
244
296
|
</button>
|
|
@@ -314,7 +366,7 @@
|
|
|
314
366
|
<input
|
|
315
367
|
name="username"
|
|
316
368
|
id="formUsername"
|
|
317
|
-
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-
|
|
369
|
+
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
318
370
|
autocomplete="off"
|
|
319
371
|
/>
|
|
320
372
|
<p id="errUsername" class="mt-1 hidden text-xs text-red-600"></p>
|
|
@@ -326,7 +378,7 @@
|
|
|
326
378
|
<input
|
|
327
379
|
name="name"
|
|
328
380
|
id="formName"
|
|
329
|
-
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-
|
|
381
|
+
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
330
382
|
autocomplete="off"
|
|
331
383
|
/>
|
|
332
384
|
<p id="errName" class="mt-1 hidden text-xs text-red-600"></p>
|
|
@@ -338,7 +390,7 @@
|
|
|
338
390
|
<input
|
|
339
391
|
name="phone"
|
|
340
392
|
id="formPhone"
|
|
341
|
-
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-
|
|
393
|
+
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
342
394
|
inputmode="numeric"
|
|
343
395
|
autocomplete="off"
|
|
344
396
|
/>
|
|
@@ -350,7 +402,7 @@
|
|
|
350
402
|
name="email"
|
|
351
403
|
id="formEmail"
|
|
352
404
|
type="email"
|
|
353
|
-
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-
|
|
405
|
+
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
354
406
|
autocomplete="off"
|
|
355
407
|
/>
|
|
356
408
|
<p id="errEmail" class="mt-1 hidden text-xs text-red-600"></p>
|
|
@@ -361,7 +413,7 @@
|
|
|
361
413
|
>
|
|
362
414
|
<select
|
|
363
415
|
id="formDept"
|
|
364
|
-
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-
|
|
416
|
+
class="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
365
417
|
>
|
|
366
418
|
<option value="">请选择</option>
|
|
367
419
|
<option value="研发中心">研发中心</option>
|
|
@@ -380,7 +432,7 @@
|
|
|
380
432
|
type="checkbox"
|
|
381
433
|
name="role"
|
|
382
434
|
value="管理员"
|
|
383
|
-
class="rounded border-slate-300 text-
|
|
435
|
+
class="rounded border-slate-300 text-blue-600 focus:ring-blue-500"
|
|
384
436
|
/>
|
|
385
437
|
管理员</label
|
|
386
438
|
>
|
|
@@ -389,7 +441,7 @@
|
|
|
389
441
|
type="checkbox"
|
|
390
442
|
name="role"
|
|
391
443
|
value="开发"
|
|
392
|
-
class="rounded border-slate-300 text-
|
|
444
|
+
class="rounded border-slate-300 text-blue-600 focus:ring-blue-500"
|
|
393
445
|
/>
|
|
394
446
|
开发</label
|
|
395
447
|
>
|
|
@@ -398,7 +450,7 @@
|
|
|
398
450
|
type="checkbox"
|
|
399
451
|
name="role"
|
|
400
452
|
value="运营"
|
|
401
|
-
class="rounded border-slate-300 text-
|
|
453
|
+
class="rounded border-slate-300 text-blue-600 focus:ring-blue-500"
|
|
402
454
|
/>
|
|
403
455
|
运营</label
|
|
404
456
|
>
|
|
@@ -414,7 +466,7 @@
|
|
|
414
466
|
name="status"
|
|
415
467
|
value="启用"
|
|
416
468
|
checked
|
|
417
|
-
class="text-
|
|
469
|
+
class="text-blue-600 focus:ring-blue-500"
|
|
418
470
|
/>
|
|
419
471
|
启用</label
|
|
420
472
|
>
|
|
@@ -423,7 +475,7 @@
|
|
|
423
475
|
type="radio"
|
|
424
476
|
name="status"
|
|
425
477
|
value="禁用"
|
|
426
|
-
class="text-
|
|
478
|
+
class="text-blue-600 focus:ring-blue-500"
|
|
427
479
|
/>
|
|
428
480
|
禁用</label
|
|
429
481
|
>
|
|
@@ -439,7 +491,7 @@
|
|
|
439
491
|
</button>
|
|
440
492
|
<button
|
|
441
493
|
type="submit"
|
|
442
|
-
class="rounded-lg bg-
|
|
494
|
+
class="rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
|
|
443
495
|
>
|
|
444
496
|
保存
|
|
445
497
|
</button>
|
|
@@ -527,20 +579,22 @@
|
|
|
527
579
|
aria-labelledby="annoDlgTitle"
|
|
528
580
|
>
|
|
529
581
|
<div
|
|
530
|
-
class="max-h-[88vh] w-full max-w-
|
|
582
|
+
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 ring-4 ring-amber-300/30"
|
|
531
583
|
role="document"
|
|
532
584
|
>
|
|
533
|
-
<div
|
|
534
|
-
|
|
585
|
+
<div
|
|
586
|
+
class="flex shrink-0 items-center justify-between border-b border-amber-200 bg-amber-50 px-4 py-2"
|
|
587
|
+
>
|
|
588
|
+
<div class="min-w-0 pr-2">
|
|
535
589
|
<p class="text-[10px] font-bold uppercase tracking-wider text-amber-900">
|
|
536
590
|
需求标注 · 非业务弹窗
|
|
537
591
|
</p>
|
|
538
|
-
<h3 id="annoDlgTitle" class="mt-0.5 text-sm font-semibold text-slate-900"></h3>
|
|
592
|
+
<h3 id="annoDlgTitle" class="mt-0.5 truncate text-sm font-semibold text-slate-900"></h3>
|
|
539
593
|
</div>
|
|
540
594
|
<button
|
|
541
595
|
type="button"
|
|
542
596
|
id="btnAnnoClose"
|
|
543
|
-
class="rounded-md p-1.5 text-slate-600 hover:bg-amber-200/60 hover:text-slate-900 focus:outline-none focus:ring-2 focus:ring-amber-600"
|
|
597
|
+
class="shrink-0 rounded-md p-1.5 text-slate-600 hover:bg-amber-200/60 hover:text-slate-900 focus:outline-none focus:ring-2 focus:ring-amber-600"
|
|
544
598
|
aria-label="关闭标注"
|
|
545
599
|
>
|
|
546
600
|
✕
|
|
@@ -548,13 +602,15 @@
|
|
|
548
602
|
</div>
|
|
549
603
|
<div
|
|
550
604
|
id="annoDlgBody"
|
|
551
|
-
class="
|
|
605
|
+
class="min-h-0 flex-1 overflow-y-auto overflow-x-auto p-4 text-sm leading-relaxed text-slate-700"
|
|
606
|
+
tabindex="-1"
|
|
552
607
|
></div>
|
|
553
608
|
</div>
|
|
554
609
|
</div>
|
|
555
610
|
|
|
611
|
+
<script src="https://cdn.jsdelivr.net/npm/marked@12.0.2/marked.min.js"></script>
|
|
556
612
|
<script>
|
|
557
|
-
|
|
613
|
+
function runPrototype(prdMd, prdLoadError) {
|
|
558
614
|
const MOCK = [
|
|
559
615
|
{
|
|
560
616
|
id: '10001',
|
|
@@ -628,6 +684,152 @@
|
|
|
628
684
|
return document.getElementById(id);
|
|
629
685
|
};
|
|
630
686
|
|
|
687
|
+
function escapeHtml(s) {
|
|
688
|
+
return String(s)
|
|
689
|
+
.replace(/&/g, '&')
|
|
690
|
+
.replace(/</g, '<')
|
|
691
|
+
.replace(/>/g, '>')
|
|
692
|
+
.replace(/"/g, '"');
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (typeof marked !== 'undefined' && marked.use) {
|
|
696
|
+
marked.use({ gfm: true, breaks: true });
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
(function showPrdBanner() {
|
|
700
|
+
var el = $('prdLoadBanner');
|
|
701
|
+
if (!el) return;
|
|
702
|
+
if (prdLoadError || !prdMd) {
|
|
703
|
+
el.textContent =
|
|
704
|
+
'未加载到同目录 prd.md:需求标注仅显示兜底摘要。请在本文件所在目录启动本地静态服务后刷新页面(勿直接 file:// 双击打开)。';
|
|
705
|
+
el.classList.remove('hidden');
|
|
706
|
+
}
|
|
707
|
+
})();
|
|
708
|
+
|
|
709
|
+
function sliceBetween(md, startRe, endRe) {
|
|
710
|
+
if (!md) return '';
|
|
711
|
+
var m = md.match(startRe);
|
|
712
|
+
if (!m || m.index === undefined) return '';
|
|
713
|
+
var i0 = m.index;
|
|
714
|
+
if (!endRe) return md.slice(i0).trim();
|
|
715
|
+
var tail = md.slice(i0 + m[0].length);
|
|
716
|
+
var j = tail.search(endRe);
|
|
717
|
+
if (j === -1) return md.slice(i0).trim();
|
|
718
|
+
return md.slice(i0, i0 + m[0].length + j).trim();
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
function mdToHtml(src) {
|
|
722
|
+
if (!src)
|
|
723
|
+
return '<p class="text-slate-500 text-xs">(在 prd.md 中未匹配到对应章节,请检查标题层级是否与 ANNO_EXTRACT 正则一致。)</p>';
|
|
724
|
+
if (typeof marked !== 'undefined' && typeof marked.parse === 'function') {
|
|
725
|
+
return '<div class="prd-md">' + marked.parse(src) + '</div>';
|
|
726
|
+
}
|
|
727
|
+
return (
|
|
728
|
+
'<pre class="max-h-[60vh] overflow-auto whitespace-pre-wrap rounded border border-slate-200 bg-slate-50 p-3 font-mono text-[11px] leading-snug">' +
|
|
729
|
+
escapeHtml(src) +
|
|
730
|
+
'</pre>'
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
var LEGEND_INTRO =
|
|
735
|
+
'<ul class="list-disc space-y-2 pl-4 text-slate-700"><li>琥珀色顶栏弹框为 <strong>PRD 走查标注</strong>,正文由<strong>同目录 prd.md</strong>按章节切片后经 Markdown 渲染得到;修改 prd.md 后<strong>刷新页面</strong>即可同步。</li><li>表格或章节较长时,可在本弹框内<strong>上下左右滚动</strong>查看。</li><li>按 <kbd class="rounded border border-slate-300 bg-slate-50 px-1 text-xs">Esc</kbd>、点遮罩或 ✕ 关闭;本层 z-index 高于业务弹窗。</li></ul>';
|
|
736
|
+
|
|
737
|
+
var ANNO_EXTRACT = {
|
|
738
|
+
s1: { start: /^## 1\./m, end: /^## 2\./m, title: 'prd.md §1 引言(原文)' },
|
|
739
|
+
s2_toolbar: {
|
|
740
|
+
start: /^## 2\./m,
|
|
741
|
+
end: /^### 3\.2/m,
|
|
742
|
+
title: 'prd.md §2·§3.1 原文(菜单权限至 §3.2 之前)',
|
|
743
|
+
},
|
|
744
|
+
s31: { start: /^### 3\.1/m, end: /^### 3\.2/m, title: 'prd.md §3.1 筛选查询区(原文)' },
|
|
745
|
+
s32: { start: /^### 3\.2/m, end: /^## 4\./m, title: 'prd.md §3.2 数据列表(原文)' },
|
|
746
|
+
s4: { start: /^## 4\./m, end: /^## 5\./m, title: 'prd.md §4 用户详情(原文)' },
|
|
747
|
+
s5: { start: /^## 5\./m, end: /^## 6\./m, title: 'prd.md §5 新增/编辑表单(原文)' },
|
|
748
|
+
s6: { start: /^## 6\./m, end: /^## 7\./m, title: 'prd.md §6 删除与审计(原文)' },
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
var ANNO_FALLBACK = {
|
|
752
|
+
s1: {
|
|
753
|
+
title: 'prd.md §1 引言(兜底)',
|
|
754
|
+
html: '<ul class="list-disc space-y-2 pl-4"><li>定位:后台用户账号统一管理(查、增、改、删)。</li><li>功能清单见 PRD §1.2;本原型用 mock 数据演示主路径。</li><li>请用 HTTP 打开同目录以加载 prd.md 全文联动。</li></ul>',
|
|
755
|
+
},
|
|
756
|
+
s2_toolbar: {
|
|
757
|
+
title: 'prd.md §2·§3.1(兜底)',
|
|
758
|
+
html: '<ul class="list-disc space-y-2 pl-4"><li><strong>新增用户</strong>需「编辑」类权限(PRD §2.2)。</li><li>「新增用户」位于列表标题行右侧。</li></ul>',
|
|
759
|
+
},
|
|
760
|
+
s31: {
|
|
761
|
+
title: 'prd.md §3.1(兜底)',
|
|
762
|
+
html: '<ul class="list-disc space-y-2 pl-4"><li>变更条件后须点击<strong>查询</strong>才刷新列表。</li><li><strong>重置</strong>恢复默认。</li></ul>',
|
|
763
|
+
},
|
|
764
|
+
s32: {
|
|
765
|
+
title: 'prd.md §3.2(兜底)',
|
|
766
|
+
html: '<ul class="list-disc space-y-2 pl-4"><li>列字段、分页以 PRD 表格为准。</li><li>行操作:查看 / 编辑 / 删除。</li></ul>',
|
|
767
|
+
},
|
|
768
|
+
s4: {
|
|
769
|
+
title: 'prd.md §4(兜底)',
|
|
770
|
+
html: '<ul class="list-disc space-y-2 pl-4"><li>只读详情弹层;字段见 PRD §4。</li></ul>',
|
|
771
|
+
},
|
|
772
|
+
s5: {
|
|
773
|
+
title: 'prd.md §5(兜底)',
|
|
774
|
+
html: '<ul class="list-disc space-y-2 pl-4"><li>新增与编辑校验见 PRD §5 表格。</li></ul>',
|
|
775
|
+
},
|
|
776
|
+
s6: {
|
|
777
|
+
title: 'prd.md §6(兜底)',
|
|
778
|
+
html: '<ul class="list-disc space-y-2 pl-4"><li>删除须二次确认;建议审计日志。</li></ul>',
|
|
779
|
+
},
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
function openAnno(key) {
|
|
783
|
+
var warn =
|
|
784
|
+
!prdMd || prdLoadError
|
|
785
|
+
? '<div class="mb-3 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-900"><strong>prd.md 未联动:</strong>请用本地静态服务打开与本文件同级目录(勿 file://),以下为兜底摘要。</div>'
|
|
786
|
+
: '';
|
|
787
|
+
|
|
788
|
+
if (key === 'legend') {
|
|
789
|
+
$('annoDlgTitle').textContent = '需求标注说明(附录 · prd.md §9)';
|
|
790
|
+
var s9 = prdMd ? sliceBetween(prdMd, /^## 9\./m, /^## 10\./m) : '';
|
|
791
|
+
$('annoDlgBody').innerHTML =
|
|
792
|
+
warn +
|
|
793
|
+
LEGEND_INTRO +
|
|
794
|
+
(s9
|
|
795
|
+
? '<div class="mt-4 border-t border-amber-100 pt-3"><p class="mb-2 text-xs font-semibold text-slate-700">prd.md · §9 原型与 PRD 对应关系(原文)</p>' +
|
|
796
|
+
mdToHtml(s9) +
|
|
797
|
+
'</div>'
|
|
798
|
+
: '');
|
|
799
|
+
$('modalAnno').classList.remove('hidden');
|
|
800
|
+
$('modalAnno').classList.add('flex');
|
|
801
|
+
$('annoDlgBody').scrollTop = 0;
|
|
802
|
+
$('annoDlgBody').focus({ preventScroll: true });
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
var spec = ANNO_EXTRACT[key];
|
|
807
|
+
if (!spec) return;
|
|
808
|
+
var slice = prdMd ? sliceBetween(prdMd, spec.start, spec.end) : '';
|
|
809
|
+
if (slice) {
|
|
810
|
+
$('annoDlgTitle').textContent = spec.title;
|
|
811
|
+
$('annoDlgBody').innerHTML = warn + mdToHtml(slice);
|
|
812
|
+
} else if (ANNO_FALLBACK[key]) {
|
|
813
|
+
$('annoDlgTitle').textContent = ANNO_FALLBACK[key].title;
|
|
814
|
+
$('annoDlgBody').innerHTML = warn + ANNO_FALLBACK[key].html;
|
|
815
|
+
} else {
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
$('modalAnno').classList.remove('hidden');
|
|
819
|
+
$('modalAnno').classList.add('flex');
|
|
820
|
+
$('annoDlgBody').scrollTop = 0;
|
|
821
|
+
$('annoDlgBody').focus({ preventScroll: true });
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
function closeAnno() {
|
|
825
|
+
$('modalAnno').classList.add('hidden');
|
|
826
|
+
$('modalAnno').classList.remove('flex');
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
function isAnnoOpen() {
|
|
830
|
+
return $('modalAnno') && !$('modalAnno').classList.contains('hidden');
|
|
831
|
+
}
|
|
832
|
+
|
|
631
833
|
function getFormStateJson() {
|
|
632
834
|
var roles = [];
|
|
633
835
|
document.querySelectorAll('input[name="role"]:checked').forEach(function (c) {
|
|
@@ -672,60 +874,6 @@
|
|
|
672
874
|
$('modalFormLeave').classList.remove('flex');
|
|
673
875
|
}
|
|
674
876
|
|
|
675
|
-
var ANNO = {
|
|
676
|
-
legend: {
|
|
677
|
-
title: '如何使用本页「需求标注」',
|
|
678
|
-
html: '<ul class="list-disc space-y-2 pl-4"><li>带<strong class="text-amber-800"> 琥珀色顶栏 </strong>的弹框为 <strong>PRD 走查标注</strong>,不是生产系统功能。</li><li>各区块旁的 <code class="rounded bg-slate-100 px-1 text-xs">PRD §…</code> 与 <code class="rounded bg-slate-100 px-1 text-xs">prd.md</code> 章节对应,便于评审对照。</li><li>按 <kbd class="rounded border border-slate-300 bg-slate-50 px-1 text-xs">Esc</kbd> 或点遮罩、点 ✕ 可关闭标注弹框。</li><li>本层 <code class="text-xs">z-index: 70</code>,高于业务弹窗,避免被盖住。</li></ul>',
|
|
679
|
-
},
|
|
680
|
-
s1: {
|
|
681
|
-
title: 'prd.md §1 引言',
|
|
682
|
-
html: '<ul class="list-disc space-y-2 pl-4"><li>定位:后台用户账号统一管理(查、增、改、删)。</li><li>功能清单见 PRD §1.2;本原型用 mock 数据演示主路径。</li><li>落地时以接口字段、UUMS 权限码为准修订 PRD。</li></ul>',
|
|
683
|
-
},
|
|
684
|
-
s2_toolbar: {
|
|
685
|
-
title: 'prd.md §2 权限 · §3.1 工具区',
|
|
686
|
-
html: '<ul class="list-disc space-y-2 pl-4"><li><strong>新增用户</strong>需「编辑」类权限(PRD §2.2)。</li><li>「新增用户」位于<strong>用户列表</strong>标题行右侧,与列表同区。</li><li>真实环境可能还有导出等按钮,见 PRD 可选导出条款。</li></ul>',
|
|
687
|
-
},
|
|
688
|
-
s31: {
|
|
689
|
-
title: 'prd.md §3.1 筛选查询区',
|
|
690
|
-
html: '<ul class="list-disc space-y-2 pl-4"><li>变更条件后须点击<strong>查询</strong>才刷新列表(页码回到第 1 页)。</li><li><strong>重置</strong>清空条件并恢复默认列表。</li><li>用户名/姓名为模糊;手机号为精准;状态为枚举精准(见 PRD 字段表)。</li></ul>',
|
|
691
|
-
},
|
|
692
|
-
s32: {
|
|
693
|
-
title: 'prd.md §3.2 数据列表',
|
|
694
|
-
html: '<ul class="list-disc space-y-2 pl-4"><li>列字段、排序能力、分页规则以 PRD 表格为准;原型中手机号为脱敏展示。</li><li>行操作:<strong>查看 / 编辑 / 删除</strong>;删除需二次确认(§6)。</li><li>批量删除为可选能力,本原型未演示多选。</li></ul>',
|
|
695
|
-
},
|
|
696
|
-
s4: {
|
|
697
|
-
title: 'prd.md §4 用户详情(只读)',
|
|
698
|
-
html: '<ul class="list-disc space-y-2 pl-4"><li>由列表「查看」打开;只读,无保存。</li><li>字段集合与 PRD §4 一致;真实项目可增减审计字段。</li><li>本弹层为<strong>业务弹窗</strong>(灰遮罩),与琥珀色「需求标注」弹框区分。</li></ul>',
|
|
699
|
-
},
|
|
700
|
-
s5: {
|
|
701
|
-
title: 'prd.md §5 新增 / 编辑表单',
|
|
702
|
-
html: '<ul class="list-disc space-y-2 pl-4"><li>新增:用户名可编;编辑:用户名<strong>只读</strong>(常见安全策略)。</li><li>校验:必填、手机号正则、角色至少一项等见 PRD §5.1。</li><li>保存成功应关闭弹层并刷新列表;原型用 Toast 模拟。</li></ul>',
|
|
703
|
-
},
|
|
704
|
-
s6: {
|
|
705
|
-
title: 'prd.md §6 删除与审计',
|
|
706
|
-
html: '<ul class="list-disc space-y-2 pl-4"><li>文案须含用户姓名,避免误删(PRD 建议话术)。</li><li>确认后调删除接口;原型仅从本地 mock 数组移除。</li><li>生产环境建议后端记操作审计日志。</li></ul>',
|
|
707
|
-
},
|
|
708
|
-
};
|
|
709
|
-
|
|
710
|
-
function openAnno(key) {
|
|
711
|
-
var item = ANNO[key];
|
|
712
|
-
if (!item) return;
|
|
713
|
-
$('annoDlgTitle').textContent = item.title;
|
|
714
|
-
$('annoDlgBody').innerHTML = item.html;
|
|
715
|
-
$('modalAnno').classList.remove('hidden');
|
|
716
|
-
$('modalAnno').classList.add('flex');
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
function closeAnno() {
|
|
720
|
-
$('modalAnno').classList.add('hidden');
|
|
721
|
-
$('modalAnno').classList.remove('flex');
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
function isAnnoOpen() {
|
|
725
|
-
return $('modalAnno') && !$('modalAnno').classList.contains('hidden');
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
// 捕获阶段:业务弹层内白底容器使用了 stopPropagation,冒泡到不了 body,故必须在捕获阶段处理
|
|
729
877
|
document.addEventListener(
|
|
730
878
|
'click',
|
|
731
879
|
function (e) {
|
|
@@ -823,10 +971,10 @@
|
|
|
823
971
|
'<td class="whitespace-nowrap px-4 py-3 text-right text-xs">' +
|
|
824
972
|
'<button type="button" data-a="view" data-id="' +
|
|
825
973
|
u.id +
|
|
826
|
-
'" class="mr-2 text-
|
|
974
|
+
'" class="mr-2 text-blue-600 hover:underline focus:outline-none focus:ring-2 focus:ring-blue-500 rounded px-1">查看</button>' +
|
|
827
975
|
'<button type="button" data-a="edit" data-id="' +
|
|
828
976
|
u.id +
|
|
829
|
-
'" class="mr-2 text-
|
|
977
|
+
'" class="mr-2 text-blue-600 hover:underline focus:outline-none focus:ring-2 focus:ring-blue-500 rounded px-1">编辑</button>' +
|
|
830
978
|
'<button type="button" data-a="del" data-id="' +
|
|
831
979
|
u.id +
|
|
832
980
|
'" class="text-red-600 hover:underline focus:outline-none focus:ring-2 focus:ring-red-500 rounded px-1">删除</button>' +
|
|
@@ -835,14 +983,6 @@
|
|
|
835
983
|
});
|
|
836
984
|
}
|
|
837
985
|
|
|
838
|
-
function escapeHtml(s) {
|
|
839
|
-
return String(s)
|
|
840
|
-
.replace(/&/g, '&')
|
|
841
|
-
.replace(/</g, '<')
|
|
842
|
-
.replace(/>/g, '>')
|
|
843
|
-
.replace(/"/g, '"');
|
|
844
|
-
}
|
|
845
|
-
|
|
846
986
|
function openDetail(u) {
|
|
847
987
|
var body = $('detailBody');
|
|
848
988
|
body.innerHTML =
|
|
@@ -1181,7 +1321,19 @@
|
|
|
1181
1321
|
});
|
|
1182
1322
|
|
|
1183
1323
|
renderTable();
|
|
1184
|
-
}
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
fetch('prd.md', { cache: 'no-store' })
|
|
1327
|
+
.then(function (r) {
|
|
1328
|
+
if (!r.ok) throw new Error('HTTP ' + r.status);
|
|
1329
|
+
return r.text();
|
|
1330
|
+
})
|
|
1331
|
+
.then(function (text) {
|
|
1332
|
+
runPrototype(text, null);
|
|
1333
|
+
})
|
|
1334
|
+
.catch(function () {
|
|
1335
|
+
runPrototype('', new Error('fetch'));
|
|
1336
|
+
});
|
|
1185
1337
|
</script>
|
|
1186
1338
|
</body>
|
|
1187
1339
|
</html>
|
|
@@ -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 模板示例 |
|