A2-A7 全部补齐到验收线;顺手把几处「门拦住却不给路」的坑填了
活动:A2 选型 / A3 寻源 / A4 定价 / A6 议价 / A7 归档五件各补成真活动包 —— 契约宽进(input.required 空,归一在活动内)、台账必填声明(含行级 requiredWhen)、 入场哨兵与 L1/L2 判据一律读基座数、两份件(在办可编辑 + 办结静态快照)、 三案例常备、包内自测。e2e 各三案例 released、行动被拒 0、发口正确、提交闸每单真拦。 基座(共享面,改一处影响所有活动,故每处都带回归): · 重发判断走在站上场之前 —— 人答完那步常已收掉,readyToWork 先抛「不能再往它上面挂活」, 于是「重发已答过的卡 = 无事发生」这条唯一活路在最需要时够不着,A1 基线当场熔断; · 决策卡补幂等兜底(与执行工单同一把尺):头两次无事发生,第三次起才算被拒; · 输出没成形先就地重问一次,原话进工作日志、不再摆上卡面; · 工具调用读数 tool_<名>_calls —— 「机检只读基座数」这条纪律第一次覆盖到工具; · 执行卡 steps/standard 补进出参 schema(从前能到卡面全靠厂商 JSON 模式宽松); · 件的就地更新改逐节点 morph,保存先把新值镜像进只读那份 —— 不闪、不等回声。 A1(基线,全程守住):措辞三档对齐(必填/建议/选填)、禁止拿历史价当客户目标价、 卡骨架从步骤剧本搬进说明书(压成一拍连做时剧本没摊开,会发出没有指导书的裸卡)。 契约两处**新增可选字段**(非破坏):FieldDeclaration.requiredWhen、工单 finalHtml; api-report 同批更新。docs/adr 与 docs/archive 的 13 份文件在工作树里不见了, 本次予以恢复而非提交删除。 门禁:typecheck / lint / depcruise / test(1366)全绿。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
---
|
||||
name: html-one-pager
|
||||
description: 为 JCAI 活动设计并产出可直接在浏览器打开的 standalone HTML one-pager 目标件(活动执行页/验收页/汇报页)。照仓里 PRD 方法论做「带脚本演示页」:JCAI 家族版式(PRD_CSS 三层壳)、写死示例数据、可带演示脚本让编辑态活起来;零外链,尾部带平移指引,可按《HTML报告生成规范》平移进活动包。只要用户提到:给某个活动(A1-A7 或新活动)做执行页、验收页、工单页、one-pager、目标件、报告设计稿、HTML 样稿,或要求「把活动报告做得精美/有设计感/突出结构」——即使没说 one-pager 三个字,也要用本技能。
|
||||
---
|
||||
|
||||
# html-one-pager —— 活动执行/验收页的目标件
|
||||
|
||||
## 定位:设计答案,不是提前交付的模版
|
||||
|
||||
产出 = 一份 standalone .html,照仓里 PRD 目标件的方法论做成**带脚本演示页**:
|
||||
浏览器直接打开、示例数据写死、演示脚本让编辑态与重算活起来(仓里两份 A1 原型
|
||||
`~/coding/JCAI_PRD/docs/活动执行页/` 就是这么做的)。设计定稿后由活动开发者按
|
||||
`docs/HTML报告生成规范.md` §7 平移进活动包 —— 剥脚本、换绑定,不归本技能管。
|
||||
|
||||
实测教训(2026-08-03 一轮评测得来的):模型 + 仓库本身就能出用户认可的好件,
|
||||
**版面与信息设计不需要本技能立规矩** —— 立多了反而把件做小(列缩到现有台账、
|
||||
数字照存储口径摆、按钮是死的)。本技能只补三样:**省力**(装壳脚本)、
|
||||
**可平移**(平移指引)、**底线**(自检)。其余放开发挥。
|
||||
|
||||
## 四步
|
||||
|
||||
### 1. 看范本定基调
|
||||
|
||||
打开整件读版面节奏(抄节奏不抄字):
|
||||
|
||||
- 文件件基调:A1 `activities/quote-intake/src/views/report.ts`(执行/验收/归档三张)
|
||||
- slide 基调:A2 `activities/quote-alternative/src/views/report.ts`(一页一屏、深空 hero)
|
||||
- 原型出处:`~/coding/JCAI_PRD/docs/活动执行页/`(带脚本演示页的原始形态)
|
||||
- 组件名录:`references/block-catalog.md`(点菜用,以仓内源为准)
|
||||
- 业务素材:`docs/MVP示例工作流.html`(示例数据要像真的)
|
||||
|
||||
可选:跑 ui-ux-pro-max 拿设计方向(`references/uipm-recipes.md`,注意五不取:
|
||||
字体外链/JS 库/换色/图标库/CDN —— 查询结果只进脑子不落盘)。
|
||||
|
||||
### 2. 装壳
|
||||
|
||||
```bash
|
||||
python3 <本技能目录>/scripts/assemble.py --out draft.html \
|
||||
--activity <目标活动id> --title <件名> --kicker "统一报价 · <活动> · <身份>"
|
||||
```
|
||||
|
||||
PRD_CSS 约 30KB,**手搬必静默截断**,所以走脚本抽。目标活动自带 `views/prd-style.ts`
|
||||
时优先抽它自己的,缺了落回 A1。
|
||||
|
||||
### 3. 设计上行,尽情画
|
||||
|
||||
- **业务需要什么就摆什么**:来源标签、档位列、命中留痕、数轴、走廊图 —— 不受现有
|
||||
台账声明限制。现有台账没有的列,**不缩版面**,记进平移指引的「建模欠账」清单
|
||||
(目标件本该驱动建模:A1 就是先画件、后立表的)。
|
||||
- **数字按人读形态摆**:9.2% 不是 0.092,让价 −0.17 元不是裸差值;台账口径与呈现
|
||||
口径不一致的,也记欠账。判定表带「本单命中留痕」(哪条规则命中了哪几颗料)。
|
||||
- **演示脚本可以有**:集中在 `<script>` 标签里(不写内联 `on*=`,平移一剥就净);
|
||||
初始画面不靠脚本也完整(脚本只做演示交互:开编辑、改数重算、切状态)。
|
||||
- **能映射现有台账的格子,顺手预埋真钩子**(`data-slot`/`data-col`/`data-edit`,
|
||||
语义见规范 §4/§6)—— 省平移的事,但**不为它牺牲版面**。
|
||||
- 家族底线:令牌不换色(--brand #3370ff 等)、三层壳一层不少、图标一律精灵 SVG
|
||||
(缺的照 lucide 线稿新增 symbol)、无外链、报告上不摆英文内部名、无 emoji。
|
||||
|
||||
### 4. 自检交付
|
||||
|
||||
```bash
|
||||
python3 <本技能目录>/scripts/check.py draft.html
|
||||
```
|
||||
|
||||
13 条底线全绿(它不判设计,版面好不好交给人眼);浏览器打开截图走查一遍。
|
||||
交付单文件,尾部**必带**「平移指引」注释段(骨架自带固定格式):取哪段、剥什么
|
||||
(脚本/示例值)、建模欠账清单、钩子键名对着目标活动 `manifest.ts` 核一遍。
|
||||
|
||||
## 陷阱速查
|
||||
|
||||
| 症状 | 根因 → 出路 |
|
||||
|---|---|
|
||||
| 整张样式一条不生效 | 三层壳少了一层 → `.proto-root>.app-shell>.jc-stage>article.jc-report` 一层不能省 |
|
||||
| 版面「像又不像」家族 | PRD_CSS 手搬截断(样式半死极难定位)→ 用 assemble.py;或没读范本自创版面 → 整件抄节奏 |
|
||||
| 平移后行为丢了一半 | 演示行为写成了内联 on*=,散在标记里剥不净 → 全部集中进 script 标签 |
|
||||
| 平移时不知道哪些列是编的 | 设计上行摆了台账没有的列却没记账 → 平移指引里「建模欠账」逐列点名 |
|
||||
@@ -0,0 +1,69 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
JCAI one-pager · 目标件骨架(html-one-pager 技能产出起点)
|
||||
· 浏览器直接打开;设计定稿后按 docs/HTML报告生成规范.md §7 平移进活动包
|
||||
· 照 PRD 方法论这是「带脚本演示页」:演示脚本集中写在文尾一个 script 标签里
|
||||
(不写内联事件),平移时整段剥掉;初始画面不靠脚本也要完整
|
||||
-->
|
||||
<html lang="zh-CN" class="editable">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>@TITLE@ · JCAI one-pager 目标件</title>
|
||||
<style>
|
||||
/* ⇩ standalone 包装层:真件跑在工作区 iframe 里,这几行由宿主环境承担。平移时丢弃 */
|
||||
html, body { margin: 0; padding: 0; }
|
||||
/* ⇧ 丢弃到此 */
|
||||
|
||||
/*@PRD_CSS@*/
|
||||
|
||||
/*@BIND_CSS@*/
|
||||
|
||||
/* ⇩ ONE_CSS · 本件自有补丁:平移时随模版走(补在 BIND_CSS 之后,只补不改) */
|
||||
/* ⇧ ONE_CSS 到此 */
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- ⇩⇩ 模版片段从此开始:平移进 views/report.ts 的就是这一段(样式与精灵由 doc() 工厂另拼) -->
|
||||
<!--@SPRITE@-->
|
||||
<div class="proto-root"><div class="app-shell"><div class="jc-stage">
|
||||
<article class="jc-report">
|
||||
<header class="jc-rp-head">
|
||||
<div class="jc-rp-badge"><svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><use href="#i-@BADGE@"/></svg></div>
|
||||
<div class="jc-rp-tit">
|
||||
<em>@KICKER@</em>
|
||||
<h3>@TITLE@ <span>@REF@</span></h3>
|
||||
</div>
|
||||
<span class="jc-rp-wait">@STATE@</span>
|
||||
</header>
|
||||
<div class="jc-rp-bd">
|
||||
|
||||
<!-- 正文区块从这里画。基调与组件抄仓内范本(A1/A2 report.ts、JCAI_PRD 原型),
|
||||
名录见技能 references/block-catalog.md;设计上行 —— 业务要什么摆什么,
|
||||
现有台账没有的列记进文尾平移指引的「建模欠账」。 -->
|
||||
|
||||
</div>
|
||||
<footer class="jc-rp-foot">
|
||||
<div class="jc-rp-sign">
|
||||
<span class="jc-rp-ava"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><use href="#i-user"/></svg></span>
|
||||
<div><b>冯兵</b><span>AI 拟稿,你审定 —— 落款说明按件改写</span></div>
|
||||
</div>
|
||||
<span class="jc-done-tag"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><use href="#i-git-branch"/></svg>@KICKER@</span>
|
||||
</footer>
|
||||
</article>
|
||||
</div></div></div>
|
||||
<!-- ⇧⇧ 模版片段到此为止 -->
|
||||
|
||||
<!-- 演示脚本写在这里(可选):开编辑、改数重算、切状态。平移时整段剥掉。 -->
|
||||
|
||||
<!-- ═══ 平移指引(交付必带;照 docs/HTML报告生成规范.md §7 平移法)═══
|
||||
① 取「模版片段」两枚边界注释之间的标记进 views/report.ts;样式与精灵改由 doc() 工厂拼
|
||||
(PRD_CSS/BIND_CSS 用活动自己的 views/ 那份,ONE_CSS 段随本件带走,补在最后)
|
||||
② 剥掉所有 script 标签与写死的示例数据;逐行数据换 data-rows 行模版,取值换 data-slot,
|
||||
可改格换 data-col + data-edit(语义见规范 §4/§6;本件已预埋的钩子逐个核对)
|
||||
③ 建模欠账(按件填写):本件摆了、现有台账还没有的列/呈现口径,逐条点名 ——
|
||||
该加哪张表哪一列、哪些列该标 required、存储口径要不要改成人读形态
|
||||
④ 绑定键名逐字核对目标活动 manifest.ts 的 declarations.ledger(列名照抄,不照记忆写)
|
||||
═══ -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"skill_name": "html-one-pager",
|
||||
"evals": [
|
||||
{
|
||||
"id": 1,
|
||||
"eval_name": "a4-pricing-exec",
|
||||
"prompt": "A4 成本定价那几张报告还是老外壳,太素了。给它设计一张执行页的 one-pager 目标件:核价单——人要逐行核 AI 算出来的价,单价和毛利那几格要能就地改;P-01 利润模型、P-02 底价门禁是怎么判的要摆清楚,但那部分是说明,不许人碰。参考 A1 现在那套报告的做法,做成 standalone HTML,示例数据写死,浏览器打开就能看。仓库在 /Users/chaihao/coding/JCAI-WOS。",
|
||||
"expected_output": "一份 standalone HTML:JCAI 家族版式(三层壳+PRD_CSS),编辑区是可就地改的核价表(编辑闸/缺项红带/胶囊/加一行),说明区讲 P-01/P-02 的判定规则;零脚本零外链,自带真绑定属性与 demo 行标记,尾部有平移指引。",
|
||||
"files": [],
|
||||
"assertions": [
|
||||
"无外链(样式/字体/图标/脚本全内联)",
|
||||
"无内联事件处理器(脚本集中在 script 标签里,平移一剥就净)",
|
||||
"standalone 可直接打开(doctype + charset)",
|
||||
"样式全内联(<style> 在)",
|
||||
"样式未被手搬截断(<style> 总量 ≥ 25KB)",
|
||||
"三层壳依序(proto-root → app-shell → jc-stage → jc-report)",
|
||||
"家族令牌未换色(--brand: #3370ff)",
|
||||
"图标是内联精灵(<symbol id=\"i-…\"> + <use href=\"#i-…\">)",
|
||||
"表头不摆 snake_case 内部名(列名用人读名)",
|
||||
"正文不带 markdown 星号(**)",
|
||||
"有 @keyframes 就有 prefers-reduced-motion 守卫",
|
||||
"无 emoji(图标一律精灵 SVG)",
|
||||
"交付带平移指引(文内含「平移指引」注释段)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"eval_name": "a6-negotiate-release",
|
||||
"prompt": "给 A6 报价议价做一张验收工单的 one-pager:放行前最后一屏——正式报价单草稿(币种、有效期、交期、付款条件这些条款,验收人还能就地改)+ 历轮报价往来(只读,给人当尺子)+「放行即发出」的后果说明。要有验收归档件的仪式感,参考 A1 归档那张。standalone HTML、写死示例数据,浏览器打开就能看。仓库在 /Users/chaihao/coding/JCAI-WOS。",
|
||||
"expected_output": "一份 standalone HTML:验收/归档基调(仪式感题头+落款+落地动作),编辑区是报价条款表(四件套齐),说明区含历轮往来(只读)与放行后果;零脚本零外链,自带真绑定属性,尾部有平移指引。",
|
||||
"files": [],
|
||||
"assertions": [
|
||||
"无外链(样式/字体/图标/脚本全内联)",
|
||||
"无内联事件处理器(脚本集中在 script 标签里,平移一剥就净)",
|
||||
"standalone 可直接打开(doctype + charset)",
|
||||
"样式全内联(<style> 在)",
|
||||
"样式未被手搬截断(<style> 总量 ≥ 25KB)",
|
||||
"三层壳依序(proto-root → app-shell → jc-stage → jc-report)",
|
||||
"家族令牌未换色(--brand: #3370ff)",
|
||||
"图标是内联精灵(<symbol id=\"i-…\"> + <use href=\"#i-…\">)",
|
||||
"表头不摆 snake_case 内部名(列名用人读名)",
|
||||
"正文不带 markdown 星号(**)",
|
||||
"有 @keyframes 就有 prefers-reduced-motion 守卫",
|
||||
"无 emoji(图标一律精灵 SVG)",
|
||||
"交付带平移指引(文内含「平移指引」注释段)"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
# 组件名录 —— 点菜用
|
||||
|
||||
**用法:打开出处文件抄结构,别凭记忆写。** 行号会漂移,漂了就按名字 grep;
|
||||
名录与仓内源冲突时,以源为准。两种基调:文件件(A1)与 slide 件(A2),按件的性格选。
|
||||
原型的原始形态(带脚本演示页)在 `~/coding/JCAI_PRD/docs/活动执行页/`——
|
||||
版面节奏与演示脚本怎么配合,整件读它最直观。
|
||||
|
||||
## 基调一 · 文件件(A1,`activities/quote-intake/src/views/report.ts`)
|
||||
|
||||
纸面、章节头、逐段读下去 —— 执行页/验收页/归档页的默认基调。
|
||||
|
||||
| 组件 | 出处(report.ts) | 是什么 · 何时用 |
|
||||
|---|---|---|
|
||||
| `doc()` 外壳三层 | `:265-289` | `<style>`+精灵+`.proto-root>.app-shell>.jc-stage>article.jc-report`+题头/正文/落款。骨架已内置同构,读它是为了懂结构 |
|
||||
| `part()` 章节头 | `:292` | `<b>标签</b><i class="ln">细线</i><em>右端小签</em>`——每个区块一条;编辑区的右端小签挂「可就地修订」 |
|
||||
| `sign()` 落款 | `:296` | 头像+署名(`case:owner`)+右端 `jc-done-tag` 流位签。签写「这份件在流里的位置」,不写状态 |
|
||||
| `ico()` 图标 | `:258` | `<use href="#i-名">` 引精灵 symbol |
|
||||
| `LETTER` 来源信件 | `:309` | `jc-letter`:收件签+归属 chip+正文 pre-wrap 原样照录+附件行(`data-rows="attachments"`) |
|
||||
| `four()` 要素四卡 | `:330` | `jc-four > jc-fcard ×4`;含 `jc-logo/jc-face` 方圆标(方=组织、圆=人,里面放图标)、`jc-count` 大数、`jc-segmeter` 一格一条料的刻度条 |
|
||||
| `listTable()` 可编辑表 | `:385` | `jc-tbl-wrap > table.jc-tbl-in`;`cell()` 工厂出 `req/opt/dimempty` 三态格;序号格 `jc-rn` 一列两用(读=行号,编辑=撤行 ×) |
|
||||
| `gapBar` 缺项红带 | `:438` | 「还差 N 格必填没补——差在哪」;挂 `data-class-of`,`v-0` 那档样式表隐藏 |
|
||||
| `editGate()` 编辑闸 | `:457` | 锁定说明+编辑/取消/保存三钮+`jc-editbar` 怎么改提示带 |
|
||||
| `addRowBar()` 加一行 | `:475` | 表尾虚线条;文案讲清「主键填了才存得下」 |
|
||||
| `DIST` 分布条 | `:501` | `jc-dist`:三段按条数分宽(`data-class-of` 投影 v-N 走宽度梯子)+图例 |
|
||||
| `dmnRow()/G2` 判定表 | `:598-628` | `jc-dmn` 按序求值三行+`jc-verdict` 去向横幅;命中行由壳上 `v-r1/r2/r3` 上色,「命中/未命中」两句都写在模版里、哪句现身由 class 定 |
|
||||
| `jc-acts` 落地动作 | `:679-693` | 「这一签下去会发生什么」三条;验收页收尾用 |
|
||||
| 说明带 | `:526-541` | `jc-derive`(这些数从哪来)/`jc-drop`(填报口径与边界);还有 `jc-callout/jc-hintline/jc-lockhint` 见 prd-style.ts |
|
||||
| 三张成品 | `:516 / :548 / :630` | INTAKE_OVERVIEW 执行页 / INTAKE_CLASSIFIED 中间态 / INTAKE_RELEASE 验收归档一张顶两身份——整件抄版面节奏最快的路 |
|
||||
|
||||
**区块顺序的家族习惯**(INTAKE_RELEASE 是最全样本):来源 → 要素卡 → 分布/图形 →
|
||||
清单表(编辑区)→ 判定与去向 → 落地动作 → 落款。执行页砍掉判定/落地,多说明带。
|
||||
|
||||
## 基调二 · slide 件(A2,`activities/quote-alternative/src/views/report.ts`)
|
||||
|
||||
一页一屏、深空 hero、强视觉 —— 汇报页/对比页用。规范 §8.5 是它的成文版。
|
||||
|
||||
| 组件 | 出处 | 是什么 |
|
||||
|---|---|---|
|
||||
| `ALT_WORKSHEET` | `:450` | 替代选型工作底稿(slide 语言成品) |
|
||||
| `ALT_ROSTER` | `:516` | 名册页成品 |
|
||||
| `data-page` 翻页 | `:335` | 多页件的页标记(`article.jc-duelrow` 一页一段),宿主按可见段分页 |
|
||||
|
||||
hero 规矩:深底允许局部自备色组,但须与家族蓝紫呼应;`danger/ok/warn` 三色
|
||||
不得挪作气氛渲染(它们承载判定语义)。
|
||||
|
||||
## 修饰类速查(prd-style.ts 全量定义,这里只列常用)
|
||||
|
||||
- 排版:`.mono`(等宽)`.num`(数值,**左对齐**,与表头同侧)`.dim` `.sp` `.ln`
|
||||
- 语义色:`.ok .warn .bad` · 卡面色调 `t-teal / t-ok / t-warn / t-mute`
|
||||
- 格三态:`req`(必填,空了红胶囊)`opt`(选填,空了灰胶囊)`dimempty`(归档,空=「—」)
|
||||
- 投影后缀:`v-a/v-b/v-c`(类三色)`v-0..v-20`(计数:开关与宽度梯子)`v-r1/r2/r3`(判定命中)
|
||||
|
||||
## 精灵 19 枚(`prd-style.ts` PRD_SPRITE)
|
||||
|
||||
`alert arrow-right boxes building check copy file-check file-text git-branch history
|
||||
info lock mail-open pen plus sheet shield-check user x`
|
||||
|
||||
缺图标怎么办:照 lucide 线稿风格(24×24 viewBox、stroke currentColor、round 线帽)
|
||||
**新增 symbol 进本件的精灵**,命名 `i-<名>`;平移时提醒活动开发 agent 给该活动的
|
||||
prd-style 补同名 symbol。不引图标库、不用 emoji。
|
||||
|
||||
## 概念图形
|
||||
|
||||
内联线稿 SVG(stroke currentColor、1.5-2 px 线宽)是报告的第一语言:流程走位、
|
||||
门前门后、数据流向,能画就画。图形也遵守不算不判——形状写死在模版里,
|
||||
只有上色/显隐可走 `data-class-of` 投影。
|
||||
@@ -0,0 +1,50 @@
|
||||
# 目标件约定 —— 设计答案怎么交,平移才接得住
|
||||
|
||||
目标件是**带脚本演示页**(照仓里 PRD 方法论):第一身份是给人看、给人认可的设计答案,
|
||||
第二身份是活动开发者平移的底稿。权威契约在 `docs/HTML报告生成规范.md`,本文只讲
|
||||
目标件这一侧的交付约定。
|
||||
|
||||
## 1. 平移边界(骨架已标好)
|
||||
|
||||
| 段 | 平移时 |
|
||||
|---|---|
|
||||
| doctype / head / 包装层 CSS(`⇩ standalone 包装层` 标记段) | 丢弃 |
|
||||
| PRD_CSS / BIND_CSS(assemble.py 抽来的) | 丢弃 —— 真模版从活动自己的 `views/` import |
|
||||
| ONE_CSS(本件自有补丁段) | **随模版走**,补在 BIND_CSS 之后;纪律与 BIND_CSS 同:只补不改 |
|
||||
| `⇩⇩ 模版片段` 到 `⇧⇧` 之间的标记 | 就是要平移的正文 |
|
||||
| 所有 `<script>` 标签 | **整段剥掉**(所以演示行为别写成内联 `on*=`,散在标记里剥不净) |
|
||||
| 尾部「平移指引」注释 | 给活动开发者读,不平移 |
|
||||
|
||||
`<html class="editable">` 是给编辑态样式(闸/红带)显形用的;生产里由宿主挂,不进模版。
|
||||
|
||||
## 2. 演示脚本的三条规矩
|
||||
|
||||
1. **集中**:全部写在文尾的 `<script>` 标签里,标记面零内联事件(check.py 会拦);
|
||||
2. **初始画面自足**:脚本删掉后页面内容仍然完整正确 —— 脚本只做演示交互
|
||||
(开编辑、改数重算、切状态),不负责造内容;
|
||||
3. **不引外部**:无 CDN、无外链(check.py 会拦)。
|
||||
|
||||
## 3. 设计上行与建模欠账
|
||||
|
||||
版面服务业务,不服务现有台账:来源标签、档位、命中留痕、数轴 —— 业务需要就摆,
|
||||
数字按人读形态(9.2% 不是 0.092)。代价是一笔账要记清:**平移指引的「建模欠账」清单**,
|
||||
逐条点名本件摆了、现有台账还没有的列与口径(该加哪张表哪一列、哪些该 required、
|
||||
存储口径要不要改人读形态)。欠账不记,平移的人分不清哪些是真数据哪些是设计愿望。
|
||||
|
||||
能映射现有台账的格子,顺手预埋真钩子(`data-slot`/`data-col`/`data-edit`,键名逐字抄
|
||||
目标活动 `manifest.ts` 的 `declarations.ledger`)—— 省平移的事,但不为它牺牲版面。
|
||||
|
||||
## 4. 示例数据真实感
|
||||
|
||||
- PN 像 PN(`SS8050`、`TL072CDR`),价格量级对(阻容几分几毛、IC 几块几十),
|
||||
年用量千/万级;业务素材见 `docs/MVP示例工作流.html`;
|
||||
- 人名/公司名用中文;报告上不摆系统内英文名(状态/表/列/口),表头一律人读名;
|
||||
- 演示的数自己要对得上账(偏离度 = (拟报−基准)÷基准 这类,逐行可复算);
|
||||
- 不编造没有来源的数据画面:真系统里没有写入方的数据,如实空着并写明为什么。
|
||||
|
||||
## 5. 自检与走查
|
||||
|
||||
- `python3 scripts/check.py 目标件.html` 13 条底线全绿(它不判设计);
|
||||
- 浏览器走查:整页读一遍(版面像不像家族、信息层次立不立得住)→ 点一遍演示交互
|
||||
(编辑开不开、改数重算对不对)→ 拉窄窗口看响应式 → 尾部平移指引读一遍
|
||||
(欠账清单是否把编的列全点到了)。
|
||||
@@ -0,0 +1,50 @@
|
||||
# ui-ux-pro-max 查询菜谱
|
||||
|
||||
ui-ux-pro-max 是本机的插件技能:一个 BM25 检索的本地设计库(84 风格 / 192 配色 /
|
||||
74 字体对 / 98 UX 守则 / 104 图标 / 25 图表)。**我们只用它的查询脚本拿设计方向,
|
||||
不装载它的整套工作流**——它的持久化步骤会往仓库写文件,字体/动效建议也与 JCAI
|
||||
契约相抵,见下面的过滤表。
|
||||
|
||||
## 定位与调用
|
||||
|
||||
```bash
|
||||
UIPM=$(ls -d ~/.claude/plugins/cache/ui-ux-pro-max-skill/ui-ux-pro-max/*/.claude/skills/ui-ux-pro-max 2>/dev/null | sort -V | tail -1)
|
||||
python3 "$UIPM/scripts/search.py" "<query>" --design-system -p "<件名>" --density 7
|
||||
```
|
||||
|
||||
**缺席兜底**:`$UIPM` 为空(插件没装/被移除)时不装死——按「A1 版面语言 + 中高密度」
|
||||
的默认继续走,并在交付说明里写一句「设计库缺席,走了默认」。
|
||||
|
||||
## 查询配方
|
||||
|
||||
| 场景 | query 建议 | 旋钮 |
|
||||
|---|---|---|
|
||||
| 执行页(密表核对) | `enterprise b2b workflow document review data table form` | `--density 7`(仪表密度,信息多) |
|
||||
| 验收/归档页(仪式感) | `invoice quotation official document archive certificate` | `--density 5 --variance 4` |
|
||||
| 汇报/对比 slide | `executive summary comparison dashboard presentation` | `--density 6 --variance 6` |
|
||||
| 单域深挖 UX | `--domain ux` + `form table dense data review` | `-n 5` |
|
||||
| 单域深挖版面风格 | `--domain style` + `editorial minimal document swiss` | `-n 5` |
|
||||
|
||||
0 结果:换一次关键词;仍空就走默认并明说,不编造「数据库推荐」。
|
||||
|
||||
## 三不用(命令行层面)
|
||||
|
||||
- `--persist` / `--output-dir`:会往仓库写 `design-system/<slug>/MASTER.md` —— 污染仓库
|
||||
- `--motion`:产出 GSAP JS 片段,而目标件零脚本
|
||||
- `--stack`:我们不是在选框架,产物是纯 HTML/CSS
|
||||
|
||||
## 五不取 · 四要取(结果层面)
|
||||
|
||||
| 它给的 | 取舍 | 为什么 |
|
||||
|---|---|---|
|
||||
| 字体对 + Google Fonts 外链 | **不取** | 目标件零外链;字体族固定 PRD_CSS 系统栈(Inter…PingFang SC) |
|
||||
| 配色替换 | **不取** | JCAI 家族令牌零改动(--brand #3370ff 等);`v-*` 语义色承载判定语义 |
|
||||
| GSAP/JS 动效 | **不取** | 零脚本。可译成纯 CSS 的意图(时长/缓动)可参考,且已有 reduced-motion 守卫 |
|
||||
| 图标库引用 | **不取** | 一律 PRD_SPRITE 内联 symbol(见 block-catalog) |
|
||||
| 任何 CDN/外部资源 | **不取** | 安装门与自检都拦 |
|
||||
| 版面构图(分栏/bento/层级) | **取** | 这正是要它出的「精美组件布局突出结构」 |
|
||||
| 组件形制(卡/带/表头/徽章的形) | **取** | 译成 JCAI 令牌下的 CSS |
|
||||
| 密度/留白档 | **取** | 执行页密、归档页缓 |
|
||||
| UX 守则(对比度/触达面积/反馈位置) | **取** | 出稿前对照检查 |
|
||||
|
||||
**取的东西只进脑子,不落盘**——查询结果不存文件,消化成设计决定写进件里。
|
||||
Binary file not shown.
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""拼一张 JCAI one-pager 骨架(html-one-pager 技能 · 第 3 步「装壳」)。
|
||||
|
||||
从仓库源文件机械抽取三段静态模板字符串 —— PRD_CSS / PRD_SPRITE(views/prd-style.ts)
|
||||
与 BIND_CSS(views/report.ts)—— 填进 assets/skeleton.html 的占位符,产出一份
|
||||
浏览器直接可开的 standalone 骨架。
|
||||
|
||||
为什么必须脚本抽:PRD_CSS 约 30KB,手搬必静默截断,截断后样式半死、极难肉眼定位。
|
||||
|
||||
抽取优先级:--activity 指定的活动自带 views/prd-style.ts 就抽它自己的
|
||||
(A1/A2 各持一份且已各自演化,错族的版面「像又不像」);缺了才落回 A1(quote-intake)。
|
||||
|
||||
用法:
|
||||
python3 assemble.py --out draft.html
|
||||
python3 assemble.py --out draft.html --activity quote-pricing \
|
||||
--title 核价单 --kicker "统一报价 · A4 成本定价 · 过程成果" --badge file-check
|
||||
"""
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SKILL_DIR = Path(__file__).resolve().parent.parent # .../.claude/skills/html-one-pager
|
||||
REPO = SKILL_DIR.parents[2] # 仓库根
|
||||
FALLBACK = 'quote-intake'
|
||||
|
||||
|
||||
def extract(path, name):
|
||||
if not path.is_file():
|
||||
return None
|
||||
m = re.search(r'(?:export\s+)?const\s+' + name + r'\s*=\s*`([\s\S]*?)`;',
|
||||
path.read_text(encoding='utf-8'))
|
||||
return m.group(1) if m else None
|
||||
|
||||
|
||||
def pick(activity, filename, name):
|
||||
tried = []
|
||||
order = ([activity] if activity and activity != FALLBACK else []) + [FALLBACK]
|
||||
for act in order:
|
||||
p = REPO / 'activities' / act / 'src' / 'views' / filename
|
||||
tried.append(str(p))
|
||||
got = extract(p, name)
|
||||
if got is not None:
|
||||
return got, act
|
||||
sys.exit('抽不到 %s(试过:%s)。仓库根按脚本位置推得 %s;不对就检查技能目录层级,'
|
||||
'或 grep -rn "const %s" activities/ 找真实位置。' % (name, ' | '.join(tried), REPO, name))
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description='拼 JCAI one-pager standalone 骨架')
|
||||
ap.add_argument('--out', required=True, help='输出 HTML 路径')
|
||||
ap.add_argument('--activity', default='',
|
||||
help='目标活动 id(activities/<id>);它自带 prd-style.ts 就优先抽它的')
|
||||
ap.add_argument('--title', default='工作单标题')
|
||||
ap.add_argument('--kicker', default='统一报价 · 活动名 · 过程成果')
|
||||
ap.add_argument('--ref', default='REF-2026-000')
|
||||
ap.add_argument('--state', default='在办 · 示例状态灯')
|
||||
ap.add_argument('--badge', default='file-text',
|
||||
help='题头图标名(精灵 symbol 名,不带 i- 前缀;19 枚清单见 block-catalog.md)')
|
||||
a = ap.parse_args()
|
||||
|
||||
css, css_src = pick(a.activity, 'prd-style.ts', 'PRD_CSS')
|
||||
sprite, sprite_src = pick(a.activity, 'prd-style.ts', 'PRD_SPRITE')
|
||||
bind, bind_src = pick(a.activity, 'report.ts', 'BIND_CSS')
|
||||
|
||||
if len(css) < 15000:
|
||||
print('⚠ PRD_CSS 只有 %d 字节(常态约 30KB)—— 抽取源可能不完整,继续但请人工核一眼' % len(css))
|
||||
|
||||
skeleton = (SKILL_DIR / 'assets' / 'skeleton.html').read_text(encoding='utf-8')
|
||||
out = (skeleton
|
||||
.replace('/*@PRD_CSS@*/', css)
|
||||
.replace('/*@BIND_CSS@*/', bind)
|
||||
.replace('<!--@SPRITE@-->', sprite)
|
||||
.replace('@TITLE@', a.title)
|
||||
.replace('@KICKER@', a.kicker)
|
||||
.replace('@REF@', a.ref)
|
||||
.replace('@STATE@', a.state)
|
||||
.replace('@BADGE@', a.badge))
|
||||
|
||||
dest = Path(a.out).expanduser()
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
dest.write_text(out, encoding='utf-8')
|
||||
print('已产出 %s(%.1f KB)' % (dest, len(out.encode('utf-8')) / 1024))
|
||||
print(' PRD_CSS %d 字节 ← %s · BIND_CSS %d 字节 ← %s · 精灵 %d 枚 symbol ← %s'
|
||||
% (len(css), css_src, len(bind), bind_src, sprite.count('<symbol'), sprite_src))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""JCAI one-pager 目标件的底线自检 —— 只守底线,不管设计。
|
||||
|
||||
目标件是「带脚本演示页」(照仓里 PRD 方法论):允许 <script> 做演示交互,
|
||||
平移进活动包时整段剥掉。这把尺只拦真出事的东西:外链、内联事件(剥不净)、
|
||||
壳错族、样式截断、英文内部名、没带平移指引。版面好不好交给人眼,不归它判。
|
||||
|
||||
用法:
|
||||
python3 check.py 目标件.html # 人读表格,全 PASS 退出码 0,否则 1
|
||||
python3 check.py 目标件.html --json # [{text,passed,evidence}],评测 grading 直接吃
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
EMOJI = re.compile('[\U0001F000-\U0001FAFF☀-➿️]')
|
||||
|
||||
|
||||
def strip_scripts(html):
|
||||
return re.sub(r'<script[\s\S]*?</script>', ' ', html, flags=re.I)
|
||||
|
||||
|
||||
def visible_text(html):
|
||||
"""人看得见的正文:去脚本、去注释、去 <style>,再剥标签。"""
|
||||
h = strip_scripts(html)
|
||||
h = re.sub(r'<!--[\s\S]*?-->', ' ', h)
|
||||
h = re.sub(r'<style[\s\S]*?</style>', ' ', h, flags=re.I)
|
||||
return re.sub(r'<[^>]*>', ' ', h)
|
||||
|
||||
|
||||
def run(path):
|
||||
html = Path(path).read_text(encoding='utf-8')
|
||||
markup = strip_scripts(html) # 剥掉脚本后的标记面(内联事件/外链在这上面查)
|
||||
text = visible_text(html)
|
||||
styles = ''.join(re.findall(r'<style[^>]*>([\s\S]*?)</style>', html, re.I))
|
||||
checks = []
|
||||
|
||||
def c(name, passed, evidence=''):
|
||||
checks.append({'text': name, 'passed': bool(passed), 'evidence': str(evidence)})
|
||||
|
||||
m = re.search(r'https?://', html, re.I)
|
||||
c('无外链(样式/字体/图标/脚本全内联)', not m, m.group(0) if m else '0 命中')
|
||||
m = re.search(r'\son[a-z]+=', markup, re.I)
|
||||
c('无内联事件处理器(脚本集中在 script 标签里,平移一剥就净)', not m,
|
||||
m.group(0) if m else '0 命中')
|
||||
c('standalone 可直接打开(doctype + charset)',
|
||||
html.lstrip().lower().startswith('<!doctype html') and '<meta charset' in html.lower(),
|
||||
html.lstrip()[:24])
|
||||
c('样式全内联(<style> 在)', '<style' in html.lower())
|
||||
c('样式未被手搬截断(<style> 总量 ≥ 25KB)',
|
||||
len(styles.encode('utf-8')) >= 25000, '%d 字节' % len(styles.encode('utf-8')))
|
||||
c('三层壳依序(proto-root → app-shell → jc-stage → jc-report)',
|
||||
bool(re.search(r'proto-root[\s\S]*app-shell[\s\S]*jc-stage[\s\S]*jc-report', html)))
|
||||
c('家族令牌未换色(--brand: #3370ff)', bool(re.search(r'--brand:\s*#3370ff', html)))
|
||||
c('图标是内联精灵(<symbol id="i-…"> + <use href="#i-…">)',
|
||||
'<symbol id="i-' in html and '<use href="#i-' in html)
|
||||
m = re.search(r'<th[^>]*>\s*[a-z0-9_]{2,}\s*<', markup)
|
||||
c('表头不摆 snake_case 内部名(列名用人读名)', not m, m.group(0) if m else '无')
|
||||
c('正文不带 markdown 星号(**)', '**' not in text)
|
||||
c('有 @keyframes 就有 prefers-reduced-motion 守卫',
|
||||
('@keyframes' not in styles) or ('prefers-reduced-motion' in styles))
|
||||
c('无 emoji(图标一律精灵 SVG)', not EMOJI.search(text))
|
||||
c('交付带平移指引(文内含「平移指引」注释段)', '平移指引' in html)
|
||||
|
||||
return checks
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument('file')
|
||||
ap.add_argument('--json', action='store_true')
|
||||
a = ap.parse_args()
|
||||
checks = run(a.file)
|
||||
if a.json:
|
||||
print(json.dumps(checks, ensure_ascii=False, indent=2))
|
||||
else:
|
||||
for k in checks:
|
||||
mark = 'PASS' if k['passed'] else 'FAIL'
|
||||
tail = (' —— ' + k['evidence']) if (k['evidence'] and not k['passed']) else ''
|
||||
print('%s %s%s' % (mark, k['text'], tail))
|
||||
n = sum(1 for k in checks if k['passed'])
|
||||
print('%d/%d 通过' % (n, len(checks)))
|
||||
sys.exit(0 if all(k['passed'] for k in checks) else 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user