@qilitt-mickey/vue3-temp-skill 1.1.74 → 1.1.76
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/SKILL.md +137 -137
- package/mapping/basic/color.json +35 -35
- package/mapping/basic/radius.json +17 -17
- package/mapping/basic/semantic-values.json +72 -72
- package/mapping/basic/spacing.json +21 -21
- package/mapping/basic/typography.json +21 -21
- package/mapping/component/button.json +90 -90
- package/mapping/component/card.json +31 -31
- package/mapping/component/input.json +42 -42
- package/mapping/component/overlay.json +79 -79
- package/mapping/component/pagination.json +34 -34
- package/mapping/component/table.json +42 -42
- package/mapping/component/tag.json +48 -48
- package/mapping/layout/breakpoint.json +20 -20
- package/mapping/scenes/admin/content.json +497 -494
- package/mapping/scenes/admin/layout.json +577 -574
- package/package.json +1 -1
- package/parser/fixtures/changeset-legacy.json +11 -11
- package/parser/fixtures/changeset-neg1.json +8 -8
- package/parser/fixtures/changeset-neg2.json +10 -10
- package/parser/fixtures/changeset-neg3.json +22 -22
- package/parser/fixtures/changeset-neg5-g8-stub.json +26 -26
- package/parser/fixtures/changeset-neg7-g10-dims.json +57 -57
- package/parser/fixtures/changeset-neg9-g6-token-chain.json +34 -0
- package/parser/fixtures/changeset-pos-g6-token-chain.json +35 -0
- package/parser/fixtures/changeset-pos-theme-nometa.json +260 -260
- package/parser/fixtures/changeset-registry-gap.json +29 -29
- package/parser/fixtures/fake-project/src/styles/app.scss +5 -5
- package/parser/fixtures/fake-project/src/views/list.vue +13 -13
- package/parser/fixtures/registry-bad.json +11 -11
- package/parser/fixtures/registry-g6-token-chain.json +10 -0
- package/parser/fixtures/verify/actual-clean.json +35 -35
- package/parser/fixtures/verify/actual.json +33 -33
- package/parser/fixtures/verify/mockup-g6-content.html +12 -0
- package/parser/fixtures/verify/mockup-neutral.html +26 -26
- package/parser/fixtures/verify/mockup-nometa.html +26 -26
- package/parser/fixtures/verify/snapshot-latest.json +102 -102
- package/parser/index.js +32 -1
- package/parser/loader.js +66 -66
- package/parser/validator.js +206 -206
- package/references/auth-pages.md +217 -217
- package/references/base-code-dict.md +56 -56
- package/references/data-compare.md +509 -509
- package/references/data-writeback.md +124 -124
- package/references/design-apply.md +167 -167
- package/references/detail-page.md +119 -119
- package/references/download-export.md +97 -97
- package/references/feedback-loading.md +104 -104
- package/references/feedback-ui.md +134 -134
- package/references/i18n-localization.md +230 -230
- package/references/layout-theme.md +2 -0
- package/references/project-inventory.md +438 -438
- package/references/rich-text.md +94 -94
- package/references/seamless-scroll.md +47 -47
- package/references/steps/step0-preflight.md +58 -58
- package/references/steps/step1-match.md +5 -2
- package/references/steps/step3-style.md +38 -33
- package/references/steps/step3b-shell.md +2 -0
- package/references/steps/step3c-priority.md +26 -26
- package/references/steps/step4-l3.md +14 -14
- package/references/steps/step5-gates.md +65 -63
- package/references/steps/step6-verify.md +77 -77
- package/references/verify-captcha.md +119 -119
- package/scripts/check.mjs +24 -0
- package/scripts/design-audit.mjs +208 -3
|
@@ -1,63 +1,65 @@
|
|
|
1
|
-
# design-apply · 第 5 步 · 合规闸门(变更集专属检查清单)
|
|
2
|
-
|
|
3
|
-
> **主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:施工完成后、验收前。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
### 第 5 步 · 合规闸门(变更集专属检查)
|
|
8
|
-
|
|
9
|
-
跑 `code-quality` 全量清单之外,追加:
|
|
10
|
-
|
|
11
|
-
- [ ] 变更集外的任何点位**零改动**(diff 只含变更集提到的文件/选择器)
|
|
12
|
-
- [ ] **页面清单零增量(G13 页面绑定闸)**:diff 中不得出现新增的路由定义 / 菜单项 / 页面文件,除非变更集 `page_bindings` 显式声明 `target:"new"` 且 `notes` 已申报。效果图页面默认是设计角色坐标系(演示标题),落地 = 映射已有页面同步结构与样式;`page_bindings` 缺省时本项必须为零增量。验收只比「结构与样式」,不比「页面标题文字」
|
|
13
|
-
- [ ] `visible: false` 的模块代码仍存在(只是隐藏)
|
|
14
|
-
- [ ] **`!important` 使用合规**:新增 `!important` 仅允许两种情形——① 词典 `priority.strategy = self_plus_important`(对手带 `!important`);② 对手为组件 scoped 且提权后**实测**仍平手;且每条带理由注释。其余一律靠作用域限定解决。无内联 style 硬编码色值(全部走变量)
|
|
15
|
-
- [ ] 未修改 `src/components/`(Re* 组件库源码——**底线一**)
|
|
16
|
-
- [ ] 未改动业务逻辑层(API/状态/事件——**底线二**;样式与结构通道内的 DOM 调整除外)
|
|
17
|
-
- [ ] 两层样式全部落在 `style_scope` 作用域内,无全局泄漏
|
|
18
|
-
- [ ] **类名冲突检查(AI 施工硬性步骤)**:新增 class 之前先在目标文件与同作用域全局样式中检索同名类——已存在时禁止直接追加重复定义,按三选一处理并在交付说明申报:① 语义相同 → **合并**进既有规则;② 语义不同 → 改用带点位前缀的新类名(如 `vts-<语义id末段>`);③ 确需覆盖 → 走作用域内更高优先级(不写 `!important`)。重复类名(尤其跨 `<style>` 块的 scoped 样式重复定义)会触发编辑器/构建报错,**本项不通过不得交付**
|
|
19
|
-
- [ ] **出厂中性检查(架构红线,不通过必须回退重做)**:diff 中不得出现「为表达本次设计而改写出厂文件」的产物——典型症状:把指示条方位/问候语 DOM/某个具体尺寸直接写进 `sidebar.scss`、`element-plus.scss`、`lay-navbar/index.vue`、`lay-content/index.vue` 等出厂载体;在出厂 `<component>` 上硬编码 `data-content-mode`/样式钩子。出厂文件若被改动,只能是「补通道」(补变量消费者 / 补 form 枚举 / 修层叠优先级,如已修的 `:has()` 与显式模式优先级反转),且必须在交付说明单列「补通道」条目写明缺失点;非此情形一律回退,改由 `design-shell.scss` + 变更集驱动。**模板源码注释保持中性**:diff 中不得出现「语义 ID / 本协议步骤号 / 面向 AI 的纪律条款」写进模板源码注释(如 `lay-content/index.vue`、`element-plus.scss`、`design-shell.scss` 的文件头与段落注释);这类内容只允许存在于技能侧文档
|
|
20
|
-
- [ ] **文本溢出回归检查**:改动侧栏菜单/顶栏/页签等含文字的模块后,必须确认「长文本显示」未被破坏(菜单项名称完整可见,必要时保留 ellipsis 溢出策略而不是隐藏/截断);宽度相关字段(width/min-width/padding)改动后逐项目视验证
|
|
21
|
-
- [ ] **尺寸意图兑现检查(每个尺寸字段都要能回答「谁决定这个数」)**:按下限语义落地——`≥N` → `min-width`、`≤N` → `max-width`、`exact` → `width`。逐项确认:① 由文案撑开的盒子(按钮 / 标签 / 页签 / 表头列宽 / 操作槽)**没有**写成固定 `exact`;② 写了 `exact` 的盒子要么内容恒定、要么已声明收口(形态收口 / 文案隐藏 / 改为下限);③ **同一尺寸只有一个权威来源**——发现「列定义写死 X、模板或公式又算成 Y」「设计层 CSS 写一套、业务配置写另一套」时**先收敛再施工**,否则改一处不生效、排查时按死值反推必然误判。**实测口径**:把文案换成更长的(改名 / 多语言 / 长数据)看盒子是撑开还是畸形——撑开 = 下限语义正确;畸形(压缩 / 换行 / 重叠)= 硬约束没兜底,返工。**接受「看起来还行」不算通过**:静态尺寸对了不等于内容装得下,必须按内容度量复核一次
|
|
22
|
-
- [ ] **形态与存在性目视验证(历史漏还原高发区,声明即必须验证,没做视同未交付)**:变更集声明了以下意图时,逐项在页面上确认真实生效——
|
|
23
|
-
- 语言切换 form=inline_switch → 顶栏出现「中|EN」并排文字(不再是纯图标)
|
|
24
|
-
- 折叠按钮 form=header_inline → 顶栏最左出现 40×40 折叠按钮且与首页页签左对齐;**同时侧栏底部出厂折叠条按设计隐藏(visible:false 声明时)**,避免双折叠按钮并存
|
|
25
|
-
- 侧栏 `menu_active_*` / `form=indicator_*` → **按变更集声明的 form 逐项核对**(indicator_left → 左侧竖条;indicator_right → 右侧竖条;indicator_underline → 底部横线;pill → 胶囊底色;none → 无指示):方位/粗细/长度/圆角与变更集 style 字段一致,且出厂胶囊已关闭(`--vts-theme-menu-active-bg: transparent`)、`--vts-theme-menu-active-before` 消费者真实建成。**禁止用「左侧 3px」这类历史/词典结论替代当次声明**——设计换了就必须是新的方位与数值
|
|
26
|
-
- 顶栏未声明点位(设置按钮等)→ 已收口不显示;用户区 → 按 `form` 核对组合形态(`avatar_name` / `greeting_avatar_name` / `greeting_name` / `avatar_only` / `name_only`),其中 greeting 为结构增量节点(出厂无此 DOM,需 AI 按 form 插入后再验)
|
|
27
|
-
- 页签图标 → 按 `form` 核对(item 的 `text_only`/`with_icon`,home_tab 的 `icon_only`/`text`),出处是路由 `meta.icon` 数据或本次隐藏规则,不是源码常量
|
|
28
|
-
- 内容区 form=scroll/fixed → `data-content-mode` 属性落在**页面根节点**(不是样式文件、不是壳层组件),列表页自动定高未被压掉;填满链逐层带 `data-fill`(详见下方「高度链存活检查」)
|
|
29
|
-
- 操作栏 form=with_tools/left_batch → 刷新/密度/列设置三件套齐全;批量删除红底/导出白底/未选中置灰;**效果图上有状态性表现(禁用置灰/选中态)的控件必须已申报 `oracle.states`(G14)**——交付前用浏览器脚本触发对应交互态核对,静态目视激活态不算验证通过
|
|
30
|
-
- 操作列 form=text_link → **业务列定义的 icon 字段已移除**(纯文字无图标,只改 CSS 保留图标 = 未还原);**按钮单行不换行且不被压缩**——列宽必须由内容度量推出,不得照抄某个固定数:`列宽 ≥ 平铺槽数 × 槽宽 + 实际单元格水平内边距`(槽宽与组件同源公式;**内边距取设计层实际生效的 td padding,而不是列宽公式内置的默认留白**——两者口径不一致就必然溢出,表现为按钮文字被压成两行或字符重叠);删除项红色;≥3 个折叠「更多」带箭头
|
|
31
|
-
- tabs form → 页签形态切换生效(chrome/card);激活态表现(有无下划线 / 是否仅文字变色 / 字重)按当次变更集 style 字段核对,**不以历史设计稿口径为准**
|
|
32
|
-
- [ ] **高度链存活检查(结构层不被设计改动压垮,也不被"保高度"绑架)**:定高页(`form=fixed` 或列表页自动定高)还原后逐项确认——
|
|
33
|
-
- `data-content-mode` 落在**页面根节点**;从页面根到表格/画布容器**每层需填满的节点都带 `data-fill`**(换了视觉容器时属性已平移;横向分栏用 `data-fill="row"`);
|
|
34
|
-
- `content` ref 仍绑在定高容器上(换容器后未丢),`otherRef` 仍在表格上方、分页仍在表格正下方;
|
|
35
|
-
- 表头 / 行 / 分页都在视口内,仅表格体内滚动,无外层滚动条、无拉伸 / 塌陷 / 双滚动条,`tableHeight > 0`;
|
|
36
|
-
- **结构层 diff 为空**:`lay-content/index.vue` 的 `.main-content[data-content-mode]` 与 `element-plus.scss` 的 `[data-fill]` 未被改动;同时确认没有「为保高度而放弃设计还原」(出厂卡片 / 内边距 / 内部排布原样未动而变更集声明了改动)——两个方向任一命中即返工
|
|
37
|
-
- [ ] **映射通道活性检查(杂必查)**:样式落地引用的每个 CSS 变量必须在项目样式中**存在消费者**(`变量名` 有 `var(--xxx)` 引用点);只定义不消费的变量 = 通道死路,翻译再准也不生效(例如 menu_active_indicator 缺 `--vts-theme-menu-active-before` 消费者时会「映射了却没效果」)。施工时 grep 核对,无消费者时改走消费者存在的作用域或补挂载点并申报。
|
|
38
|
-
- [ ] **结构施工兑现检查(structure_ops 逐条对账,与红线同级)**:变更集 `structure_ops[]` 的**每一条 op** 都必须在交付说明给出「op → 落在哪个文件 / 哪个节点 / 怎么落的」;`add_node` 必须真的新增了元素或渲染分支(模板 diff 可验),`bind_source` 必须真的改了绑定(`class-name` / `align` / `formatter`)。出现「声明了 op、代码里找不到对应改动」= 交付不完整,禁止只改 CSS 冒充结构施工
|
|
39
|
-
- [ ] **同权重失效检查( · 专查「写了不生效」)**:逐条核对设计层新增规则是否真能取胜——① 对手是组件 `<style scoped>` 时,本条特异度必须**严格高于**它(**平手即错**,因为组件样式在全局之后注入);② 对手带 `!important` 时本条必须同样 `!important`,或改走通道变量。**判定方法(必须真数,不许目测)**:对每条新规则与其对手分别写出特异度三元组 `(a,b,c)` 并**逐位比较(先 b 后 c)**,本条的 `b` 不大于对手即判为「失效」;`html` / `body` 只加 `c` 位,**对手 `b` 更高时加 `html body` 无效**,必须靠**加类**(祖先链补稳定语义类,如 `.el-menu`)把 `b` 抬到相等。同 `b` 时,`c` 更高者胜。③ **出厂用语义令牌间接设置该属性时(`var(--vts-theme-*)`),必须先走「令牌重映射」而不是抢属性**——在令牌宿主作用域重声明令牌即生效、零权重战争;只有无令牌或令牌语义不符时才抢属性。典型失效例:面包屑 `display:none`(与组件 scoped 同为 0,2,0)→ 照旧显示;页签关闭钮 `opacity`(同为 0,5,0)→ 仍要 hover 才显;页签项 `padding`(对手带 `!important`)→ 无论怎么抬特异度都改不动;**侧栏菜单 `color`(`b=2` 输给出厂 `b=3` + `!important`)→ 整栏菜单文字用浅色主题的黑色落在深色侧栏上、字全部消失**
|
|
40
|
-
- [ ] **oracle 基线可用性检查**:变更集带 `oracle` 时——① `oracle.mockup` 必须是**本页型的场景基线图**(**与主题无关**:任何主题都读**同一张**,不得因换主题而改图、漏读或跳抽)。基线图色板与本次主题不一致时(图内 `data-mockup-theme` ↔ `changeset.theme`),声明 `oracle.theme_mapping: { "from": "<基线图色板>", "to": "<本次主题>" }`——它**只是色值归一**(verify 须带 `--from-theme/--to-theme`,几何 / 结构 / 字号逐点照比),**不减免任何读取与声明**;**不得因换主题色就判死闭环**,**也不得因换了主题色就降低本轮应有的覆盖期待**(「只有钴蓝能正经还原」是误读:基线图是场景基线、不是某主题的专属产物);结构 / 形态与基线图有差异时另立基线图并登记 `baseline`;② `oracle.sids` 与 `changes[]` **双向闭合**:效果图里有、changes[] 未声明 = **欠声明**(该点位永远不可能被还原);changes[] 已声明、效果图无 sid = **无基线**——**仅 `visible:false` 的隐藏点位豁免**(效果图上无可见元素可标 `data-sid`,parser 已自动豁免并打印清单)。其余两类出现即回流设计侧补齐,**不得直接开工**(`parser match` 已自动报出);③ **状态性期望与孤儿对账(G14/G15,抽取产物层)**:效果图上有可见状态性表现的点位(禁用置灰 / 激活 / 选中)→ `oracle.json.states` 必须有对应 `<sid>@<state>` 期望(缺失 = 状态维度放弃验收);交付前核对项目页渲染的每个区块都在 oracle 全集(sids ∪ absent ∪ residual ∪ states)内——孤儿点位 verify 当场 exit 1,提前自查可省一轮返工
|
|
41
|
-
- [ ] **设计层闭环审计闸(机器断言,ERROR 必须清零)**:施工完成后跑 `node scripts/design-audit.mjs --project <落地项目> --container-width <内容区实际宽>`,或 `VUE3_AUDIT_PROJECT=<落地项目> npm run check`。本闸把「声明了 ≠ 生效」拆成逐条静态断言,替代肉眼目视,任一 ERROR 即视为未交付。**与 `parser/index.js audit` 的分工**:parser audit 管「通道与挂载点」(selector 有没有挂载点、变量有没有消费者),本闸管「生效性与形态」(层路由、层叠胜负、列宽预算、收口断言、形态成对);E1/E4 是两者的故意重叠项,用作交叉校验:
|
|
42
|
-
- E1 变量悬空 → 使用了项目内无定义且无 `var()` 回退的自有变量,整条声明失效
|
|
43
|
-
- E2 层错位 → 内层盒属性族(`white-space` / `text-overflow` / `overflow` / `text-align` / `line-height` / `vertical-align` / `word-break`)写在表格宿主盒 `th/td.el-table__cell` 上而非 `> .cell`,会被 Element Plus 内层 `.cell` 覆盖
|
|
44
|
-
- E3 **层叠败北** → 本条声明的作用元素上的特异度 ≤ 组件 scoped 竞争者的实际特异度(scoped 编译会给末位选择器追加 `[data-v]`,等价 +1 类级;平手判负,因为组件样式晚于全局注入)
|
|
45
|
-
- E4 选择器挂空 → 设计层使用的项目类名在 `src/` 无挂载点(锚点必须锚「实际在」)
|
|
46
|
-
- E5 **列宽预算** → 存在既无 `width` 又无 `min-width` 的业务列;或 `min-width` 小于该列表头文案的最小占宽;或列宽合计溢出容器而未见滚动策略
|
|
47
|
-
- E6 收口断言 → 变更集 `visible:false` 的点位必须在设计层找到「命中该锚点且 `display:none !important`」的落点
|
|
48
|
-
- E7 激活态越层 → 激活胶囊/指示条写到了可展开分组的标题上(`.el-sub-menu__title` 须显式排除)
|
|
49
|
-
- E8 浮层残留 → 声明收口下拉浮层的 form,组件却仍保留 `ElDropdown` / `#dropdown` 消费(teleport 浮层样式层收不掉,必须结构收口)
|
|
50
|
-
- E9 形态收口缺件 → `icon_only` 只落了「显图标」而没有**在同一作用域内**收口文案(作用域外的兄弟变体收口不算成对)
|
|
51
|
-
- E10 scoped 挂空 → 组件 scoped 规则依赖运行时并不存在的类(结构重构后残留,永不命中)
|
|
52
|
-
- E11 **交付完整性** → `mode=restore` 时 `covered < applicable`(欠声明)/ `gaps` 非空 / 缺口未在 `pending[]` 台账化(下游「继续」无工作项可执行)/ 自报 `registrable` 与登记表实物不符 / `notes` 的成功话术与 `coverage` 字段互相矛盾。**该项是「只换了主题色」的第一现场**:上游残缺口 + 下游挑拣落地,两头都能被它抓住
|
|
53
|
-
- E12 **设计层累积性** → 设计层文件行数或变更集点位相比历史峰值骤降(上一轮成果被重建覆盖)。本项会写 `.design/ledger.json` 台账(`--no-ledger` 可关;`--changeset <path>` / `--design-layer <path>` 可指定),**台账同时是「继续」的断点续传依据**:`applicable − 已落地点数` 即剩余工作项,不再依赖自然语言回忆
|
|
54
|
-
- E13 **固定尺寸内容度量** → 设计层出现「固定 `width` 小于内容需求、且未声明收口兜底」的规则(典型:页签位 40px 里还留着标题、图标位里塞着文案)。固定宽装不下内容时文字会换行、被压缩、甚至字符重叠渲染——**「设计说 40px 就固定 40px」必然复现**。判据:盒内还有文案却用 exact 宽度又无收口
|
|
55
|
-
- E14 **列宽预算链自洽** → 列宽(含公式推出的值)扣掉**实际生效的 td 水平内边距**后装不下该列内容(操作列 = 平铺槽数 × 槽宽);或同一列宽存在两个来源且值不一致(列定义死值 vs 模板公式)。**这是「按钮文字换行 / 重叠」的第一现场**
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
- [ ]
|
|
60
|
-
|
|
61
|
-
- [ ]
|
|
62
|
-
- [ ]
|
|
63
|
-
- [ ] `
|
|
1
|
+
# design-apply · 第 5 步 · 合规闸门(变更集专属检查清单)
|
|
2
|
+
|
|
3
|
+
> **主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:施工完成后、验收前。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### 第 5 步 · 合规闸门(变更集专属检查)
|
|
8
|
+
|
|
9
|
+
跑 `code-quality` 全量清单之外,追加:
|
|
10
|
+
|
|
11
|
+
- [ ] 变更集外的任何点位**零改动**(diff 只含变更集提到的文件/选择器)
|
|
12
|
+
- [ ] **页面清单零增量(G13 页面绑定闸)**:diff 中不得出现新增的路由定义 / 菜单项 / 页面文件,除非变更集 `page_bindings` 显式声明 `target:"new"` 且 `notes` 已申报。效果图页面默认是设计角色坐标系(演示标题),落地 = 映射已有页面同步结构与样式;`page_bindings` 缺省时本项必须为零增量。验收只比「结构与样式」,不比「页面标题文字」
|
|
13
|
+
- [ ] `visible: false` 的模块代码仍存在(只是隐藏)
|
|
14
|
+
- [ ] **`!important` 使用合规**:新增 `!important` 仅允许两种情形——① 词典 `priority.strategy = self_plus_important`(对手带 `!important`);② 对手为组件 scoped 且提权后**实测**仍平手;且每条带理由注释。其余一律靠作用域限定解决。无内联 style 硬编码色值(全部走变量)
|
|
15
|
+
- [ ] 未修改 `src/components/`(Re* 组件库源码——**底线一**)
|
|
16
|
+
- [ ] 未改动业务逻辑层(API/状态/事件——**底线二**;样式与结构通道内的 DOM 调整除外)
|
|
17
|
+
- [ ] 两层样式全部落在 `style_scope` 作用域内,无全局泄漏
|
|
18
|
+
- [ ] **类名冲突检查(AI 施工硬性步骤)**:新增 class 之前先在目标文件与同作用域全局样式中检索同名类——已存在时禁止直接追加重复定义,按三选一处理并在交付说明申报:① 语义相同 → **合并**进既有规则;② 语义不同 → 改用带点位前缀的新类名(如 `vts-<语义id末段>`);③ 确需覆盖 → 走作用域内更高优先级(不写 `!important`)。重复类名(尤其跨 `<style>` 块的 scoped 样式重复定义)会触发编辑器/构建报错,**本项不通过不得交付**
|
|
19
|
+
- [ ] **出厂中性检查(架构红线,不通过必须回退重做)**:diff 中不得出现「为表达本次设计而改写出厂文件」的产物——典型症状:把指示条方位/问候语 DOM/某个具体尺寸直接写进 `sidebar.scss`、`element-plus.scss`、`lay-navbar/index.vue`、`lay-content/index.vue` 等出厂载体;在出厂 `<component>` 上硬编码 `data-content-mode`/样式钩子。出厂文件若被改动,只能是「补通道」(补变量消费者 / 补 form 枚举 / 修层叠优先级,如已修的 `:has()` 与显式模式优先级反转),且必须在交付说明单列「补通道」条目写明缺失点;非此情形一律回退,改由 `design-shell.scss` + 变更集驱动。**模板源码注释保持中性**:diff 中不得出现「语义 ID / 本协议步骤号 / 面向 AI 的纪律条款」写进模板源码注释(如 `lay-content/index.vue`、`element-plus.scss`、`design-shell.scss` 的文件头与段落注释);这类内容只允许存在于技能侧文档
|
|
20
|
+
- [ ] **文本溢出回归检查**:改动侧栏菜单/顶栏/页签等含文字的模块后,必须确认「长文本显示」未被破坏(菜单项名称完整可见,必要时保留 ellipsis 溢出策略而不是隐藏/截断);宽度相关字段(width/min-width/padding)改动后逐项目视验证
|
|
21
|
+
- [ ] **尺寸意图兑现检查(每个尺寸字段都要能回答「谁决定这个数」)**:按下限语义落地——`≥N` → `min-width`、`≤N` → `max-width`、`exact` → `width`。逐项确认:① 由文案撑开的盒子(按钮 / 标签 / 页签 / 表头列宽 / 操作槽)**没有**写成固定 `exact`;② 写了 `exact` 的盒子要么内容恒定、要么已声明收口(形态收口 / 文案隐藏 / 改为下限);③ **同一尺寸只有一个权威来源**——发现「列定义写死 X、模板或公式又算成 Y」「设计层 CSS 写一套、业务配置写另一套」时**先收敛再施工**,否则改一处不生效、排查时按死值反推必然误判。**实测口径**:把文案换成更长的(改名 / 多语言 / 长数据)看盒子是撑开还是畸形——撑开 = 下限语义正确;畸形(压缩 / 换行 / 重叠)= 硬约束没兜底,返工。**接受「看起来还行」不算通过**:静态尺寸对了不等于内容装得下,必须按内容度量复核一次
|
|
22
|
+
- [ ] **形态与存在性目视验证(历史漏还原高发区,声明即必须验证,没做视同未交付)**:变更集声明了以下意图时,逐项在页面上确认真实生效——
|
|
23
|
+
- 语言切换 form=inline_switch → 顶栏出现「中|EN」并排文字(不再是纯图标)
|
|
24
|
+
- 折叠按钮 form=header_inline → 顶栏最左出现 40×40 折叠按钮且与首页页签左对齐;**同时侧栏底部出厂折叠条按设计隐藏(visible:false 声明时)**,避免双折叠按钮并存
|
|
25
|
+
- 侧栏 `menu_active_*` / `form=indicator_*` → **按变更集声明的 form 逐项核对**(indicator_left → 左侧竖条;indicator_right → 右侧竖条;indicator_underline → 底部横线;pill → 胶囊底色;none → 无指示):方位/粗细/长度/圆角与变更集 style 字段一致,且出厂胶囊已关闭(`--vts-theme-menu-active-bg: transparent`)、`--vts-theme-menu-active-before` 消费者真实建成。**禁止用「左侧 3px」这类历史/词典结论替代当次声明**——设计换了就必须是新的方位与数值
|
|
26
|
+
- 顶栏未声明点位(设置按钮等)→ 已收口不显示;用户区 → 按 `form` 核对组合形态(`avatar_name` / `greeting_avatar_name` / `greeting_name` / `avatar_only` / `name_only`),其中 greeting 为结构增量节点(出厂无此 DOM,需 AI 按 form 插入后再验)
|
|
27
|
+
- 页签图标 → 按 `form` 核对(item 的 `text_only`/`with_icon`,home_tab 的 `icon_only`/`text`),出处是路由 `meta.icon` 数据或本次隐藏规则,不是源码常量
|
|
28
|
+
- 内容区 form=scroll/fixed → `data-content-mode` 属性落在**页面根节点**(不是样式文件、不是壳层组件),列表页自动定高未被压掉;填满链逐层带 `data-fill`(详见下方「高度链存活检查」)
|
|
29
|
+
- 操作栏 form=with_tools/left_batch → 刷新/密度/列设置三件套齐全;批量删除红底/导出白底/未选中置灰;**效果图上有状态性表现(禁用置灰/选中态)的控件必须已申报 `oracle.states`(G14)**——交付前用浏览器脚本触发对应交互态核对,静态目视激活态不算验证通过
|
|
30
|
+
- 操作列 form=text_link → **业务列定义的 icon 字段已移除**(纯文字无图标,只改 CSS 保留图标 = 未还原);**按钮单行不换行且不被压缩**——列宽必须由内容度量推出,不得照抄某个固定数:`列宽 ≥ 平铺槽数 × 槽宽 + 实际单元格水平内边距`(槽宽与组件同源公式;**内边距取设计层实际生效的 td padding,而不是列宽公式内置的默认留白**——两者口径不一致就必然溢出,表现为按钮文字被压成两行或字符重叠);删除项红色;≥3 个折叠「更多」带箭头
|
|
31
|
+
- tabs form → 页签形态切换生效(chrome/card);激活态表现(有无下划线 / 是否仅文字变色 / 字重)按当次变更集 style 字段核对,**不以历史设计稿口径为准**
|
|
32
|
+
- [ ] **高度链存活检查(结构层不被设计改动压垮,也不被"保高度"绑架)**:定高页(`form=fixed` 或列表页自动定高)还原后逐项确认——
|
|
33
|
+
- `data-content-mode` 落在**页面根节点**;从页面根到表格/画布容器**每层需填满的节点都带 `data-fill`**(换了视觉容器时属性已平移;横向分栏用 `data-fill="row"`);
|
|
34
|
+
- `content` ref 仍绑在定高容器上(换容器后未丢),`otherRef` 仍在表格上方、分页仍在表格正下方;
|
|
35
|
+
- 表头 / 行 / 分页都在视口内,仅表格体内滚动,无外层滚动条、无拉伸 / 塌陷 / 双滚动条,`tableHeight > 0`;
|
|
36
|
+
- **结构层 diff 为空**:`lay-content/index.vue` 的 `.main-content[data-content-mode]` 与 `element-plus.scss` 的 `[data-fill]` 未被改动;同时确认没有「为保高度而放弃设计还原」(出厂卡片 / 内边距 / 内部排布原样未动而变更集声明了改动)——两个方向任一命中即返工
|
|
37
|
+
- [ ] **映射通道活性检查(杂必查)**:样式落地引用的每个 CSS 变量必须在项目样式中**存在消费者**(`变量名` 有 `var(--xxx)` 引用点);只定义不消费的变量 = 通道死路,翻译再准也不生效(例如 menu_active_indicator 缺 `--vts-theme-menu-active-before` 消费者时会「映射了却没效果」)。施工时 grep 核对,无消费者时改走消费者存在的作用域或补挂载点并申报。
|
|
38
|
+
- [ ] **结构施工兑现检查(structure_ops 逐条对账,与红线同级)**:变更集 `structure_ops[]` 的**每一条 op** 都必须在交付说明给出「op → 落在哪个文件 / 哪个节点 / 怎么落的」;`add_node` 必须真的新增了元素或渲染分支(模板 diff 可验),`bind_source` 必须真的改了绑定(`class-name` / `align` / `formatter`)。出现「声明了 op、代码里找不到对应改动」= 交付不完整,禁止只改 CSS 冒充结构施工
|
|
39
|
+
- [ ] **同权重失效检查( · 专查「写了不生效」)**:逐条核对设计层新增规则是否真能取胜——① 对手是组件 `<style scoped>` 时,本条特异度必须**严格高于**它(**平手即错**,因为组件样式在全局之后注入);② 对手带 `!important` 时本条必须同样 `!important`,或改走通道变量。**判定方法(必须真数,不许目测)**:对每条新规则与其对手分别写出特异度三元组 `(a,b,c)` 并**逐位比较(先 b 后 c)**,本条的 `b` 不大于对手即判为「失效」;`html` / `body` 只加 `c` 位,**对手 `b` 更高时加 `html body` 无效**,必须靠**加类**(祖先链补稳定语义类,如 `.el-menu`)把 `b` 抬到相等。同 `b` 时,`c` 更高者胜。③ **出厂用语义令牌间接设置该属性时(`var(--vts-theme-*)`),必须先走「令牌重映射」而不是抢属性**——在令牌宿主作用域重声明令牌即生效、零权重战争;只有无令牌或令牌语义不符时才抢属性。典型失效例:面包屑 `display:none`(与组件 scoped 同为 0,2,0)→ 照旧显示;页签关闭钮 `opacity`(同为 0,5,0)→ 仍要 hover 才显;页签项 `padding`(对手带 `!important`)→ 无论怎么抬特异度都改不动;**侧栏菜单 `color`(`b=2` 输给出厂 `b=3` + `!important`)→ 整栏菜单文字用浅色主题的黑色落在深色侧栏上、字全部消失**
|
|
40
|
+
- [ ] **oracle 基线可用性检查**:变更集带 `oracle` 时——① `oracle.mockup` 必须是**本页型的场景基线图**(**与主题无关**:任何主题都读**同一张**,不得因换主题而改图、漏读或跳抽)。基线图色板与本次主题不一致时(图内 `data-mockup-theme` ↔ `changeset.theme`),声明 `oracle.theme_mapping: { "from": "<基线图色板>", "to": "<本次主题>" }`——它**只是色值归一**(verify 须带 `--from-theme/--to-theme`,几何 / 结构 / 字号逐点照比),**不减免任何读取与声明**;**不得因换主题色就判死闭环**,**也不得因换了主题色就降低本轮应有的覆盖期待**(「只有钴蓝能正经还原」是误读:基线图是场景基线、不是某主题的专属产物);结构 / 形态与基线图有差异时另立基线图并登记 `baseline`;② `oracle.sids` 与 `changes[]` **双向闭合**:效果图里有、changes[] 未声明 = **欠声明**(该点位永远不可能被还原);changes[] 已声明、效果图无 sid = **无基线**——**仅 `visible:false` 的隐藏点位豁免**(效果图上无可见元素可标 `data-sid`,parser 已自动豁免并打印清单)。其余两类出现即回流设计侧补齐,**不得直接开工**(`parser match` 已自动报出);③ **状态性期望与孤儿对账(G14/G15,抽取产物层)**:效果图上有可见状态性表现的点位(禁用置灰 / 激活 / 选中)→ `oracle.json.states` 必须有对应 `<sid>@<state>` 期望(缺失 = 状态维度放弃验收);交付前核对项目页渲染的每个区块都在 oracle 全集(sids ∪ absent ∪ residual ∪ states)内——孤儿点位 verify 当场 exit 1,提前自查可省一轮返工
|
|
41
|
+
- [ ] **设计层闭环审计闸(机器断言,ERROR 必须清零)**:施工完成后跑 `node scripts/design-audit.mjs --project <落地项目> --container-width <内容区实际宽>`,或 `VUE3_AUDIT_PROJECT=<落地项目> npm run check`。本闸把「声明了 ≠ 生效」拆成逐条静态断言,替代肉眼目视,任一 ERROR 即视为未交付。**与 `parser/index.js audit` 的分工**:parser audit 管「通道与挂载点」(selector 有没有挂载点、变量有没有消费者),本闸管「生效性与形态」(层路由、层叠胜负、列宽预算、收口断言、形态成对);E1/E4 是两者的故意重叠项,用作交叉校验:
|
|
42
|
+
- E1 变量悬空 → 使用了项目内无定义且无 `var()` 回退的自有变量,整条声明失效
|
|
43
|
+
- E2 层错位 → 内层盒属性族(`white-space` / `text-overflow` / `overflow` / `text-align` / `line-height` / `vertical-align` / `word-break`)写在表格宿主盒 `th/td.el-table__cell` 上而非 `> .cell`,会被 Element Plus 内层 `.cell` 覆盖
|
|
44
|
+
- E3 **层叠败北** → 本条声明的作用元素上的特异度 ≤ 组件 scoped 竞争者的实际特异度(scoped 编译会给末位选择器追加 `[data-v]`,等价 +1 类级;平手判负,因为组件样式晚于全局注入)
|
|
45
|
+
- E4 选择器挂空 → 设计层使用的项目类名在 `src/` 无挂载点(锚点必须锚「实际在」)
|
|
46
|
+
- E5 **列宽预算** → 存在既无 `width` 又无 `min-width` 的业务列;或 `min-width` 小于该列表头文案的最小占宽;或列宽合计溢出容器而未见滚动策略
|
|
47
|
+
- E6 收口断言 → 变更集 `visible:false` 的点位必须在设计层找到「命中该锚点且 `display:none !important`」的落点
|
|
48
|
+
- E7 激活态越层 → 激活胶囊/指示条写到了可展开分组的标题上(`.el-sub-menu__title` 须显式排除)
|
|
49
|
+
- E8 浮层残留 → 声明收口下拉浮层的 form,组件却仍保留 `ElDropdown` / `#dropdown` 消费(teleport 浮层样式层收不掉,必须结构收口)
|
|
50
|
+
- E9 形态收口缺件 → `icon_only` 只落了「显图标」而没有**在同一作用域内**收口文案(作用域外的兄弟变体收口不算成对)
|
|
51
|
+
- E10 scoped 挂空 → 组件 scoped 规则依赖运行时并不存在的类(结构重构后残留,永不命中)
|
|
52
|
+
- E11 **交付完整性** → `mode=restore` 时 `covered < applicable`(欠声明)/ `gaps` 非空 / 缺口未在 `pending[]` 台账化(下游「继续」无工作项可执行)/ 自报 `registrable` 与登记表实物不符 / `notes` 的成功话术与 `coverage` 字段互相矛盾。**该项是「只换了主题色」的第一现场**:上游残缺口 + 下游挑拣落地,两头都能被它抓住
|
|
53
|
+
- E12 **设计层累积性** → 设计层文件行数或变更集点位相比历史峰值骤降(上一轮成果被重建覆盖)。本项会写 `.design/ledger.json` 台账(`--no-ledger` 可关;`--changeset <path>` / `--design-layer <path>` 可指定),**台账同时是「继续」的断点续传依据**:`applicable − 已落地点数` 即剩余工作项,不再依赖自然语言回忆
|
|
54
|
+
- E13 **固定尺寸内容度量** → 设计层出现「固定 `width` 小于内容需求、且未声明收口兜底」的规则(典型:页签位 40px 里还留着标题、图标位里塞着文案)。固定宽装不下内容时文字会换行、被压缩、甚至字符重叠渲染——**「设计说 40px 就固定 40px」必然复现**。判据:盒内还有文案却用 exact 宽度又无收口
|
|
55
|
+
- E14 **列宽预算链自洽** → 列宽(含公式推出的值)扣掉**实际生效的 td 水平内边距**后装不下该列内容(操作列 = 平铺槽数 × 槽宽);或同一列宽存在两个来源且值不一致(列定义死值 vs 模板公式)。**这是「按钮文字换行 / 重叠」的第一现场**
|
|
56
|
+
- E17 **层间令牌链对账** → 词典标记「层间令牌链对账」的条目(父子两层盒共享同链间距令牌,如 `.app-main` ↔ `.main-content` 同链 `--layout-content-padding → --vts-margin`)在设计层抢写了物理 padding/margin,而同链令牌在项目内仍有非零定义——父层设计值 + 子层令牌值叠加(24px + 8px = 32px/侧),**这是「内容区边距很大」的第一现场**。修复:改走令牌通道(重映射 `--layout-content-padding` / `--vts-margin`,两层同变),或把另一层同链间距归零
|
|
57
|
+
- E18 **激活态消费者成对落地** → 词典标记「激活态消费者成对落地」的条目(如 `admin.layout.sidebar.menu`)声明了指示条形态(form 含 `indicator` 或 style 含 `menu_active_indicator` / `active_indicator_*`),但设计层 ① 没有任何规则消费 `--vts-theme-menu-active-before`(只供值不建消费者);② 消费者建了但令牌最终定义仍是 transparent(消费者在渲染、色值透明);③ 消费者与出厂 sidebar.scss 同名 `::before` 胶囊对决权重不足(无 `!important` 背景且无 `html body` 提权,③ 为警告级)——三者任一命中,**竖条都不可见**。**这是「菜单激活态竖条消失」的第一现场**:同名伪元素是二选一对决,输 = 几何整体不渲染
|
|
58
|
+
- E16 **引用完整性** → 变更集 `oracle.mockup` / `coverage.registry` 指向的实物不存在(标识改名后未同步引用,全链路静默降级为无基线还原);`mode=restore` 缺顶层 `theme` 字段
|
|
59
|
+
- [ ] **列宽由表头文案反推(E5 落地口径)**:每个业务列(含选择列、序号列)都要显式声明 `width` 或 `min-width`,取值 ≥ 该列表头文案宽度 + 左右各 16px 内边距(CJK 按 1em、ASCII 按 0.6em 估)。无宽列只能拿出厂兜底宽度参与布局,会被相邻固定宽列挤压——**表头换行与省略号截断的唯一根因就在这里**,不接受「跑起来看着还行」
|
|
60
|
+
|
|
61
|
+
- [ ] **缺口清单只含意图缺口**:清单每一项都必须是「设计侧未给值 / 值非法」且已注明「回流设计侧补齐」;能力缺口(词典缺 ID / 缺字段枚举 / 缺 form)不得出现在清单里——出现即把可落地项搁置
|
|
62
|
+
- [ ] **台账逐行兑现对账(对账闸门)**:把设计侧交付的提取台账逐行过一遍,每行必须有落地结论——已落地(写明落在哪个文件/选择器)或已入缺口清单(写明缺失字段)。存在「台账有行、落地无结论」的行 = 交付不完整,与红线同级
|
|
63
|
+
- [ ] **登记表覆盖率对账(子项级细闸,)**:带登记表交付时必须跑 `match --registry`——`C = A` 且无缺口才可交付;同时确认无「效果图标注缺口」(`always:true` 子项在效果图上都有同名 `data-sid`)。**禁止采信设计侧自报的 `coverage` 数字**(parser 会当场重算,自报数不参与);缺口逐条点名回流设计侧
|
|
64
|
+
- [ ] **零搁置交付**:最终回复不含「待确认」类停顿项;交付说明的「补映射 / 补通道 / 缺口回流」三段齐全(无内容写「无」)
|
|
65
|
+
- [ ] `node parser/index.js build --dry` 通过(mapping 若有临时新增)
|
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
# design-apply · 第 6 步 · 渲染态验收(oracle 逐点 diff · 快照回归 · 残差豁免)
|
|
2
|
-
|
|
3
|
-
> **主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:变更集含 oracle 时强制。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
### 第 6 步 · 渲染态验收(变更集含 `oracle` 时强制 · 闭环回路)
|
|
8
|
-
|
|
9
|
-
第 5 步是静态自查,查不出「值对了、位置不对 / 写了没生效」。**只要变更集带 `oracle`(效果图基线),落地后必须做机器逐点比对**——这是「1:1 还原」能被证明、且不再漂移的唯一手段。
|
|
10
|
-
|
|
11
|
-
**链路(抽取由浏览器完成,diff 由 parser 完成)**:
|
|
12
|
-
|
|
13
|
-
1. **抽取期望值**:在浏览器打开效果图(`oracle.mockup`,元素已带 `data-sid`),对 `oracle.sids` 中每个 sid 取其代表性元素的 computed style,导出为 `{ "<sid>": { "<css属性>": "<值>" } }` → `oracle.json`。
|
|
14
|
-
2. **抽取实测值**:在浏览器打开已落地页面,**按词典 `selector` / `anchors.target` 定位元素**(**项目页不要求打 `data-sid`**)做抽取 → `actual.json`。
|
|
15
|
-
- 先跑 `node parser/index.js verify --oracle oracle.json --resolve` 得到「sid → 词典 selector」定位计划;
|
|
16
|
-
- 抽取脚本(Playwright / 浏览器控制台)按计划 selector 取 `getComputedStyle(el)` 的白名单属性(padding / font-size / font-weight / text-align / color / background-color / border-radius / gap 等);
|
|
17
|
-
- **期望端(效果图)用 `data-sid`、实测端(项目页)用词典 selector——两侧定位方式不必对称**:效果图是设计侧自控产物,项目页是消费方、不感知设计坐标。selector 挂载点错位由 `audit` 先于 `verify` 报出,责任链回到词典;
|
|
18
|
-
- 期望值**优先直接消费设计侧交付的 `oracle.json` 抽取产物**(期望 / 实测同源同口径);无产物时再从 `oracle.mockup` 现场抽取;
|
|
19
|
-
- 两个页面的属性白名单必须一致,否则出现假缺口。
|
|
20
|
-
3. **逐点 diff**:
|
|
21
|
-
```bash
|
|
22
|
-
node parser/index.js verify --oracle oracle.json --actual actual.json
|
|
23
|
-
# 可选 --sids admin.content.table.header_cell,admin.layout.tabs.item 只验部分点位
|
|
24
|
-
# 同构异色归一(oracle.theme_mapping 已声明时必带)——基线图色值按语义槽位归一为本主题色值再比(几何/结构/字号照比):
|
|
25
|
-
node parser/index.js verify --oracle oracle.json --actual actual.json --from-theme 钴蓝 --to-theme 橘橙
|
|
26
|
-
```
|
|
27
|
-
退出码:存在缺口(含存在性缺口 / 基线漂移)→ `1`。
|
|
28
|
-
|
|
29
|
-
**归因与处置(四类 + 状态/孤儿两类扩展,禁止用 `!important` 掩盖)**:
|
|
30
|
-
|
|
31
|
-
| 归因 | 触发 | 处置 |
|
|
32
|
-
|---|---|---|
|
|
33
|
-
| **选择器落空** | oracle 有点位、actual 无(或某属性取不到) | 补挂载点:按 `structure_ops` 挂类 / 补 `data-sid` / 确认元素已渲染(属能力缺口,交付说明申报) |
|
|
34
|
-
| **权重被压** | 颜色 / 字重 / 透明度 / 阴影类属性值不符 | 按词典 `priority` 声明的策略提权(`scope_qualified` / `self_plus_important` / `deep_qualified`) |
|
|
35
|
-
| **语境错位** | 几何 / 盒模型属性(padding / 尺寸 / 对齐 / 行高)值不符 | 校准 `layer`(`host` vs `inner`)——值对了落错层 |
|
|
36
|
-
| **存在性缺口(G12)** | `oracle.absent` 点位在页面仍渲染可见(`display` 非 `none`) | 补 `visible:false` 收口并按词典 `priority` 提权(面包屑 `display:none` 被同权重 scoped 规则反压即属此类——写了不生效) |
|
|
37
|
-
| **状态缺口(G14)** | `oracle.states` 的 `<sid>@<state>` 交互态期望与实测不符 / 实测未取到 | 浏览器脚本**触发交互态**(`.click()` / `hover()` / `dispatchEvent`)后抽取到 `actual.states` 同名键;禁用态走结构通道(`disabled` 属性 / `:disabled` 类)+ 设计层样式(如效果图「批量按钮置灰 opacity:.4」在静态快照上取不到——页面静态抽的是激活态值,逐点 diff 验不到) |
|
|
38
|
-
| **孤儿点位(G15)** | actual 中存在、oracle 全集(sids ∪ absent ∪ residual ∪ states)均无申报 | 两选一回流设计侧:应消失 → 收进 `oracle.absent`;该还原 → 补 `oracle.sids` + 效果图 `data-sid`。**G12 只断言「已申报的该消失」,孤儿闸补齐「未申报的出现了」——申报缺一个 = 漏网一个** |
|
|
39
|
-
|
|
40
|
-
**存在性闸(`oracle.absent`)**:效果图上不存在的出厂点位(面包屑 / 设置铃铛等)逐条列入变更集 `oracle.absent`,verify 逐个断言「actual 不存在或 `display:none` / `visibility:hidden`」。**这类缺口无期望值,逐点 diff 永远验不到——不进 absent 就不在验收范围内**。
|
|
41
|
-
|
|
42
|
-
**状态断言闸(`oracle.states`,G14)**:交互态(disabled / active / hover / focus / checked)在静态页面快照上取不到——效果图标注的状态性样式(批量按钮禁用置灰、页签激活字重)与页面静态抽取值**永远对不上或永远碰巧对上**,逐点 diff 均验不到。设计侧在 `oracle.json` 顶层声明:
|
|
43
|
-
|
|
44
|
-
```json
|
|
45
|
-
{
|
|
46
|
-
"sids": { "…": { "…": "…" } },
|
|
47
|
-
"states": {
|
|
48
|
-
"admin.content.list.batch_delete@disabled": { "opacity": "0.4", "cursor": "not-allowed" }
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
`changes[] oracle.sids` **保持纯 sid**(不带 `@state` 后缀——G8 双向闭合与效果图 `data-sid` 对账不感知后缀);状态期望只落 `oracle.json.states` 抽取产物层。实测端对称:`actual.json` 顶层 `states` 子对象,浏览器脚本对每键触发交互态后抽取。verify 逐键断言、计入缺口与归因(处置见上表);`hover/focus/active` 等瞬态**必须**走 states 子对象(主条目静态值不能代表交互态),`disabled/checked` 可降级用 sid 主条目属性。**效果图上可见的状态性差异(禁用置灰 / 激活态)必须申报 states——不申报 = 状态维度放弃验收**。
|
|
54
|
-
|
|
55
|
-
**孤儿点位对账闸(G15)**:verify 自动对账 actual 顶层点位与 oracle 全集(`sids ∪ absent ∪ residual_accepted ∪ states` 的 sid 部分),**未申报即出现 = 孤儿,exit 1**——效果图是验收的完备性基准,「图上没有、清单也没说」的页面元素不允许静默存活(它是下一轮「图上怎么多了个东西」体感的来源)。结构性键(`$` 前缀注释 / `sids` / `states`)不参与对账。
|
|
56
|
-
|
|
57
|
-
**残差豁免(`oracle.residual_accepted`)**:`[{ "sid": …, "reason": … }]`(reason 必填)。命中豁免的属性差异降级为「已申报固有残差」提示行,不进缺口计数;验收报告单列豁免明细,逐条可审计。**机制推算值(等宽槽宽)、业务资产(logo 图形)必须申报**——不申报 = 每轮验收重新报缺口 = 「反复调整仍无改善」的体感来源。
|
|
58
|
-
|
|
59
|
-
**快照回归(`--snapshot` / `--baseline`,治「上一轮改对的这一轮漂回」)**:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
# 每轮动工前:先对当前页面跑一次 verify 并导出快照
|
|
63
|
-
node parser/index.js verify --oracle oracle.json --actual actual.json --snapshot snapshot-r1.json
|
|
64
|
-
# 本轮交付前:带 --baseline 与上轮快照比对
|
|
65
|
-
node parser/index.js verify --oracle oracle.json --actual actual.json --baseline snapshot-r1.json
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
- 上轮 `hit` / `absent-hit`、本轮退步的点位 / 属性 = **基线漂移**,逐条列出且 `exit 1`——先回归上轮修法,再谈新缺口。(G14 状态键命中、G15 对账通过同样纳入上轮「命中」口径;上轮 `state-miss` / `orphan` 修复后本轮变 `hit` 属正常改善,不算漂移。)
|
|
69
|
-
- 项目还原到出厂(design-shell 回空壳)后第一轮验证**不带** `--baseline`(基线已失真),改以 clean 夹具重新起拍。
|
|
70
|
-
|
|
71
|
-
**夹具与设计资产的边界(职责单侧沉淀红线)**:设计侧效果图库的**基线图命名用中性名**(页面名 / 场景名,如 `后台管理端.html`)——**文件名里不要出现主题词**:主题身份只由图内 `data-mockup-theme` 与注册表 `baseline.<页型>.theme` 承担;文件名一旦带主题词,就会被读成「这是某主题专属的图」,换主题时误判成「无基线」而跳过读取。该命名是设计侧效果图库的专属资产命名——**项目侧(含 parser/fixtures 回归夹具)禁止出现与设计侧资产同名的文件**。回归需要 mockup 实物时,一律用「回归夹具-」前缀合成名(如 `回归夹具-列表页-钴蓝.html`),点集为回归机制定制、与真基线**不同且不可互替**;真实效果图基线唯一沉淀在设计侧 `page-specs/styles/<方案>/scenes/<场景>/mockups/`,项目侧 `oracle.mockup` 指向它靠 `resolveFirstExisting` 跨库解析(变更集同目录 → cwd → 技能根 → 设计侧兄弟目录),不做本地拷贝。
|
|
72
|
-
|
|
73
|
-
- 验收结果写入最终回复(命中 N / 缺口 M / 归因分布 / 修正)与 `code-quality` 结果块;**不得只报「已完成」**。
|
|
74
|
-
- **入场前置:闭环审计闸必须已清零**。`node scripts/design-audit.mjs --project <落地项目> --container-width <内容区实际宽>` 存在 ERROR 时不得进入渲染态验收——层错位 / 层叠败北 / 无宽列这类失效会让 verify 侧出现「期望值取不到」或「值对但不生效」的假缺口,先修闸门再比对,否则每轮都在给同一个根因换皮。
|
|
75
|
-
- 变更集无 `oracle` 时输出 `N/A`(无基线),并在交付说明注明「无验收基线」——这是设计侧应补的项,回流设计侧。
|
|
76
|
-
- 静态审计(audit)与渲染态验收(verify)**互补**:audit 查「通道是否存在」,verify 查「渲染结果是否一致」,两者都过才算闭环。
|
|
77
|
-
- **三闸自洽口径(无 oracle 时也不放行)**:`mapping coverage` 全绿只证明「点位被覆盖」,`parser audit` 全绿只证明「通道与挂载点存在」,`design-audit` 全绿只证明「声明具备生效条件」——三者都不证明「渲染结果与效果图一致」。缺 `oracle` 的批次必须显式声明「本轮无渲染态基线」,不得用前两闸的绿灯冒充闭环。
|
|
1
|
+
# design-apply · 第 6 步 · 渲染态验收(oracle 逐点 diff · 快照回归 · 残差豁免)
|
|
2
|
+
|
|
3
|
+
> **主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:变更集含 oracle 时强制。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### 第 6 步 · 渲染态验收(变更集含 `oracle` 时强制 · 闭环回路)
|
|
8
|
+
|
|
9
|
+
第 5 步是静态自查,查不出「值对了、位置不对 / 写了没生效」。**只要变更集带 `oracle`(效果图基线),落地后必须做机器逐点比对**——这是「1:1 还原」能被证明、且不再漂移的唯一手段。
|
|
10
|
+
|
|
11
|
+
**链路(抽取由浏览器完成,diff 由 parser 完成)**:
|
|
12
|
+
|
|
13
|
+
1. **抽取期望值**:在浏览器打开效果图(`oracle.mockup`,元素已带 `data-sid`),对 `oracle.sids` 中每个 sid 取其代表性元素的 computed style,导出为 `{ "<sid>": { "<css属性>": "<值>" } }` → `oracle.json`。
|
|
14
|
+
2. **抽取实测值**:在浏览器打开已落地页面,**按词典 `selector` / `anchors.target` 定位元素**(**项目页不要求打 `data-sid`**)做抽取 → `actual.json`。
|
|
15
|
+
- 先跑 `node parser/index.js verify --oracle oracle.json --resolve` 得到「sid → 词典 selector」定位计划;
|
|
16
|
+
- 抽取脚本(Playwright / 浏览器控制台)按计划 selector 取 `getComputedStyle(el)` 的白名单属性(padding / font-size / font-weight / text-align / color / background-color / border-radius / gap 等);
|
|
17
|
+
- **期望端(效果图)用 `data-sid`、实测端(项目页)用词典 selector——两侧定位方式不必对称**:效果图是设计侧自控产物,项目页是消费方、不感知设计坐标。selector 挂载点错位由 `audit` 先于 `verify` 报出,责任链回到词典;
|
|
18
|
+
- 期望值**优先直接消费设计侧交付的 `oracle.json` 抽取产物**(期望 / 实测同源同口径);无产物时再从 `oracle.mockup` 现场抽取;
|
|
19
|
+
- 两个页面的属性白名单必须一致,否则出现假缺口。
|
|
20
|
+
3. **逐点 diff**:
|
|
21
|
+
```bash
|
|
22
|
+
node parser/index.js verify --oracle oracle.json --actual actual.json
|
|
23
|
+
# 可选 --sids admin.content.table.header_cell,admin.layout.tabs.item 只验部分点位
|
|
24
|
+
# 同构异色归一(oracle.theme_mapping 已声明时必带)——基线图色值按语义槽位归一为本主题色值再比(几何/结构/字号照比):
|
|
25
|
+
node parser/index.js verify --oracle oracle.json --actual actual.json --from-theme 钴蓝 --to-theme 橘橙
|
|
26
|
+
```
|
|
27
|
+
退出码:存在缺口(含存在性缺口 / 基线漂移)→ `1`。
|
|
28
|
+
|
|
29
|
+
**归因与处置(四类 + 状态/孤儿两类扩展,禁止用 `!important` 掩盖)**:
|
|
30
|
+
|
|
31
|
+
| 归因 | 触发 | 处置 |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| **选择器落空** | oracle 有点位、actual 无(或某属性取不到) | 补挂载点:按 `structure_ops` 挂类 / 补 `data-sid` / 确认元素已渲染(属能力缺口,交付说明申报) |
|
|
34
|
+
| **权重被压** | 颜色 / 字重 / 透明度 / 阴影类属性值不符 | 按词典 `priority` 声明的策略提权(`scope_qualified` / `self_plus_important` / `deep_qualified`) |
|
|
35
|
+
| **语境错位** | 几何 / 盒模型属性(padding / 尺寸 / 对齐 / 行高)值不符 | 校准 `layer`(`host` vs `inner`)——值对了落错层 |
|
|
36
|
+
| **存在性缺口(G12)** | `oracle.absent` 点位在页面仍渲染可见(`display` 非 `none`) | 补 `visible:false` 收口并按词典 `priority` 提权(面包屑 `display:none` 被同权重 scoped 规则反压即属此类——写了不生效) |
|
|
37
|
+
| **状态缺口(G14)** | `oracle.states` 的 `<sid>@<state>` 交互态期望与实测不符 / 实测未取到 | 浏览器脚本**触发交互态**(`.click()` / `hover()` / `dispatchEvent`)后抽取到 `actual.states` 同名键;禁用态走结构通道(`disabled` 属性 / `:disabled` 类)+ 设计层样式(如效果图「批量按钮置灰 opacity:.4」在静态快照上取不到——页面静态抽的是激活态值,逐点 diff 验不到) |
|
|
38
|
+
| **孤儿点位(G15)** | actual 中存在、oracle 全集(sids ∪ absent ∪ residual ∪ states)均无申报 | 两选一回流设计侧:应消失 → 收进 `oracle.absent`;该还原 → 补 `oracle.sids` + 效果图 `data-sid`。**G12 只断言「已申报的该消失」,孤儿闸补齐「未申报的出现了」——申报缺一个 = 漏网一个** |
|
|
39
|
+
|
|
40
|
+
**存在性闸(`oracle.absent`)**:效果图上不存在的出厂点位(面包屑 / 设置铃铛等)逐条列入变更集 `oracle.absent`,verify 逐个断言「actual 不存在或 `display:none` / `visibility:hidden`」。**这类缺口无期望值,逐点 diff 永远验不到——不进 absent 就不在验收范围内**。
|
|
41
|
+
|
|
42
|
+
**状态断言闸(`oracle.states`,G14)**:交互态(disabled / active / hover / focus / checked)在静态页面快照上取不到——效果图标注的状态性样式(批量按钮禁用置灰、页签激活字重)与页面静态抽取值**永远对不上或永远碰巧对上**,逐点 diff 均验不到。设计侧在 `oracle.json` 顶层声明:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"sids": { "…": { "…": "…" } },
|
|
47
|
+
"states": {
|
|
48
|
+
"admin.content.list.batch_delete@disabled": { "opacity": "0.4", "cursor": "not-allowed" }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`changes[] oracle.sids` **保持纯 sid**(不带 `@state` 后缀——G8 双向闭合与效果图 `data-sid` 对账不感知后缀);状态期望只落 `oracle.json.states` 抽取产物层。实测端对称:`actual.json` 顶层 `states` 子对象,浏览器脚本对每键触发交互态后抽取。verify 逐键断言、计入缺口与归因(处置见上表);`hover/focus/active` 等瞬态**必须**走 states 子对象(主条目静态值不能代表交互态),`disabled/checked` 可降级用 sid 主条目属性。**效果图上可见的状态性差异(禁用置灰 / 激活态)必须申报 states——不申报 = 状态维度放弃验收**。
|
|
54
|
+
|
|
55
|
+
**孤儿点位对账闸(G15)**:verify 自动对账 actual 顶层点位与 oracle 全集(`sids ∪ absent ∪ residual_accepted ∪ states` 的 sid 部分),**未申报即出现 = 孤儿,exit 1**——效果图是验收的完备性基准,「图上没有、清单也没说」的页面元素不允许静默存活(它是下一轮「图上怎么多了个东西」体感的来源)。结构性键(`$` 前缀注释 / `sids` / `states`)不参与对账。
|
|
56
|
+
|
|
57
|
+
**残差豁免(`oracle.residual_accepted`)**:`[{ "sid": …, "reason": … }]`(reason 必填)。命中豁免的属性差异降级为「已申报固有残差」提示行,不进缺口计数;验收报告单列豁免明细,逐条可审计。**机制推算值(等宽槽宽)、业务资产(logo 图形)必须申报**——不申报 = 每轮验收重新报缺口 = 「反复调整仍无改善」的体感来源。
|
|
58
|
+
|
|
59
|
+
**快照回归(`--snapshot` / `--baseline`,治「上一轮改对的这一轮漂回」)**:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# 每轮动工前:先对当前页面跑一次 verify 并导出快照
|
|
63
|
+
node parser/index.js verify --oracle oracle.json --actual actual.json --snapshot snapshot-r1.json
|
|
64
|
+
# 本轮交付前:带 --baseline 与上轮快照比对
|
|
65
|
+
node parser/index.js verify --oracle oracle.json --actual actual.json --baseline snapshot-r1.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- 上轮 `hit` / `absent-hit`、本轮退步的点位 / 属性 = **基线漂移**,逐条列出且 `exit 1`——先回归上轮修法,再谈新缺口。(G14 状态键命中、G15 对账通过同样纳入上轮「命中」口径;上轮 `state-miss` / `orphan` 修复后本轮变 `hit` 属正常改善,不算漂移。)
|
|
69
|
+
- 项目还原到出厂(design-shell 回空壳)后第一轮验证**不带** `--baseline`(基线已失真),改以 clean 夹具重新起拍。
|
|
70
|
+
|
|
71
|
+
**夹具与设计资产的边界(职责单侧沉淀红线)**:设计侧效果图库的**基线图命名用中性名**(页面名 / 场景名,如 `后台管理端.html`)——**文件名里不要出现主题词**:主题身份只由图内 `data-mockup-theme` 与注册表 `baseline.<页型>.theme` 承担;文件名一旦带主题词,就会被读成「这是某主题专属的图」,换主题时误判成「无基线」而跳过读取。该命名是设计侧效果图库的专属资产命名——**项目侧(含 parser/fixtures 回归夹具)禁止出现与设计侧资产同名的文件**。回归需要 mockup 实物时,一律用「回归夹具-」前缀合成名(如 `回归夹具-列表页-钴蓝.html`),点集为回归机制定制、与真基线**不同且不可互替**;真实效果图基线唯一沉淀在设计侧 `page-specs/styles/<方案>/scenes/<场景>/mockups/`,项目侧 `oracle.mockup` 指向它靠 `resolveFirstExisting` 跨库解析(变更集同目录 → cwd → 技能根 → 设计侧兄弟目录),不做本地拷贝。
|
|
72
|
+
|
|
73
|
+
- 验收结果写入最终回复(命中 N / 缺口 M / 归因分布 / 修正)与 `code-quality` 结果块;**不得只报「已完成」**。
|
|
74
|
+
- **入场前置:闭环审计闸必须已清零**。`node scripts/design-audit.mjs --project <落地项目> --container-width <内容区实际宽>` 存在 ERROR 时不得进入渲染态验收——层错位 / 层叠败北 / 无宽列这类失效会让 verify 侧出现「期望值取不到」或「值对但不生效」的假缺口,先修闸门再比对,否则每轮都在给同一个根因换皮。
|
|
75
|
+
- 变更集无 `oracle` 时输出 `N/A`(无基线),并在交付说明注明「无验收基线」——这是设计侧应补的项,回流设计侧。
|
|
76
|
+
- 静态审计(audit)与渲染态验收(verify)**互补**:audit 查「通道是否存在」,verify 查「渲染结果是否一致」,两者都过才算闭环。
|
|
77
|
+
- **三闸自洽口径(无 oracle 时也不放行)**:`mapping coverage` 全绿只证明「点位被覆盖」,`parser audit` 全绿只证明「通道与挂载点存在」,`design-audit` 全绿只证明「声明具备生效条件」——三者都不证明「渲染结果与效果图一致」。缺 `oracle` 的批次必须显式声明「本轮无渲染态基线」,不得用前两闸的绿灯冒充闭环。
|
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: verify-captcha
|
|
3
|
-
description: 滑块拼图 ReVerify、拖拽验证 ReDragVerify、图片验证码、短信验证码
|
|
4
|
-
scope: project
|
|
5
|
-
tags: [验证码, 滑块, 短信验证, captcha, 拖拽验证, 图片验证码]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# 验证码与校验组件
|
|
9
|
-
|
|
10
|
-
> 按本文件示例编写,复用项目已有验证码相关组件与封装,勿另起一套校验交互。
|
|
11
|
-
|
|
12
|
-
规范滑块拼图、拖拽验证、图片验证码、短信倒计时等校验组件的使用。在登录、敏感操作、防刷场景时参照。
|
|
13
|
-
|
|
14
|
-
## 依赖(缺则先装)
|
|
15
|
-
|
|
16
|
-
| 包 | 版本 | 用途 |
|
|
17
|
-
|---|---|---|
|
|
18
|
-
| `vue3-puzzle-vcode` | `1.1.7` | `ReVerify` 滑块拼图 |
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
pnpm add vue3-puzzle-vcode@1.1.7
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
装包后按 **`addon-enable.md` 章节 H** 移除 `ReVerify/**` exclude。
|
|
25
|
-
|
|
26
|
-
`ReDragVerify` / `ReImageVerify` / `ReSmsCode` 为项目自研,无需额外 npm 包。
|
|
27
|
-
|
|
28
|
-
## 组件选型
|
|
29
|
-
|
|
30
|
-
| 场景 | 组件 | 说明 |
|
|
31
|
-
| ------------ | --------------- | ------------------------ |
|
|
32
|
-
| 滑块拼图弹窗 | `ReVerify` | 基于 `vue3-puzzle-vcode` |
|
|
33
|
-
| 拖拽滑块 | `ReDragVerify` | 自定义拖拽验证条 |
|
|
34
|
-
| 图片验证码 | `ReImageVerify` | canvas 随机字符 |
|
|
35
|
-
| 短信验证码 | `ReSmsCode` | 发送按钮 + 倒计时 |
|
|
36
|
-
|
|
37
|
-
## ReVerify 滑块拼图
|
|
38
|
-
|
|
39
|
-
```vue
|
|
40
|
-
<script setup lang="ts">
|
|
41
|
-
import ReVerify from "@/components/ReVerify";
|
|
42
|
-
|
|
43
|
-
const verifyShow = ref(true);
|
|
44
|
-
|
|
45
|
-
function onVerifyPass(success: boolean) {
|
|
46
|
-
console.log("验证通过", success);
|
|
47
|
-
}
|
|
48
|
-
</script>
|
|
49
|
-
|
|
50
|
-
<template>
|
|
51
|
-
<ReVerify v-model:verify-show="verifyShow" @verify-pass="onVerifyPass" />
|
|
52
|
-
</template>
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## ReDragVerify 拖拽验证
|
|
56
|
-
|
|
57
|
-
```vue
|
|
58
|
-
<ReDragVerify
|
|
59
|
-
v-model:value="isPass"
|
|
60
|
-
width="100%"
|
|
61
|
-
:height="40"
|
|
62
|
-
:text="$t('请拖动滑块完成验证')"
|
|
63
|
-
:success-text="$t('验证成功')"
|
|
64
|
-
@success="onSuccess"
|
|
65
|
-
/>
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Events
|
|
69
|
-
|
|
70
|
-
- `success({ isPassing, time })`:验证通过,返回耗时(秒)。
|
|
71
|
-
- `update:value`:同步验证状态。
|
|
72
|
-
- `start` / `move` / `end`:拖拽生命周期。
|
|
73
|
-
|
|
74
|
-
### Expose
|
|
75
|
-
|
|
76
|
-
- `resume()`:重置验证条状态。
|
|
77
|
-
|
|
78
|
-
## ReImageVerify 图片验证码
|
|
79
|
-
|
|
80
|
-
```vue
|
|
81
|
-
<script setup lang="ts">
|
|
82
|
-
import ReImageVerify from "@/components/ReImageVerify";
|
|
83
|
-
|
|
84
|
-
const code = ref("");
|
|
85
|
-
const imgVerifyRef = ref();
|
|
86
|
-
|
|
87
|
-
function refresh() {
|
|
88
|
-
imgVerifyRef.value?.getImgCode();
|
|
89
|
-
}
|
|
90
|
-
</script>
|
|
91
|
-
|
|
92
|
-
<template>
|
|
93
|
-
<ReImageVerify ref="imgVerifyRef" v-model:code="code" @click="refresh" />
|
|
94
|
-
</template>
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## ReSmsCode 短信倒计时
|
|
98
|
-
|
|
99
|
-
```vue
|
|
100
|
-
<script setup lang="ts">
|
|
101
|
-
import ReSmsCode from "@/components/ReSmsCode";
|
|
102
|
-
|
|
103
|
-
const phone = ref("13800138000");
|
|
104
|
-
</script>
|
|
105
|
-
|
|
106
|
-
<template>
|
|
107
|
-
<ReSmsCode :phone="phone" :seconds="120" />
|
|
108
|
-
</template>
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
- 内置手机号正则校验。
|
|
112
|
-
- 发送成功后自动倒计时,按钮禁用期间不可重复点击。
|
|
113
|
-
|
|
114
|
-
## 关键约定
|
|
115
|
-
|
|
116
|
-
1. 滑块验证通过后通过 `update:verifyShow` 关闭弹窗,不要直接修改 prop。
|
|
117
|
-
2. 图片验证码支持 `getImgCode()` 主动刷新。
|
|
118
|
-
3. 短信验证码 `seconds` 默认 120 秒,按需调整。
|
|
119
|
-
4. 校验组件仅做前端防刷,关键业务必须配合后端二次校验。
|
|
1
|
+
---
|
|
2
|
+
name: verify-captcha
|
|
3
|
+
description: 滑块拼图 ReVerify、拖拽验证 ReDragVerify、图片验证码、短信验证码
|
|
4
|
+
scope: project
|
|
5
|
+
tags: [验证码, 滑块, 短信验证, captcha, 拖拽验证, 图片验证码]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 验证码与校验组件
|
|
9
|
+
|
|
10
|
+
> 按本文件示例编写,复用项目已有验证码相关组件与封装,勿另起一套校验交互。
|
|
11
|
+
|
|
12
|
+
规范滑块拼图、拖拽验证、图片验证码、短信倒计时等校验组件的使用。在登录、敏感操作、防刷场景时参照。
|
|
13
|
+
|
|
14
|
+
## 依赖(缺则先装)
|
|
15
|
+
|
|
16
|
+
| 包 | 版本 | 用途 |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `vue3-puzzle-vcode` | `1.1.7` | `ReVerify` 滑块拼图 |
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add vue3-puzzle-vcode@1.1.7
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
装包后按 **`addon-enable.md` 章节 H** 移除 `ReVerify/**` exclude。
|
|
25
|
+
|
|
26
|
+
`ReDragVerify` / `ReImageVerify` / `ReSmsCode` 为项目自研,无需额外 npm 包。
|
|
27
|
+
|
|
28
|
+
## 组件选型
|
|
29
|
+
|
|
30
|
+
| 场景 | 组件 | 说明 |
|
|
31
|
+
| ------------ | --------------- | ------------------------ |
|
|
32
|
+
| 滑块拼图弹窗 | `ReVerify` | 基于 `vue3-puzzle-vcode` |
|
|
33
|
+
| 拖拽滑块 | `ReDragVerify` | 自定义拖拽验证条 |
|
|
34
|
+
| 图片验证码 | `ReImageVerify` | canvas 随机字符 |
|
|
35
|
+
| 短信验证码 | `ReSmsCode` | 发送按钮 + 倒计时 |
|
|
36
|
+
|
|
37
|
+
## ReVerify 滑块拼图
|
|
38
|
+
|
|
39
|
+
```vue
|
|
40
|
+
<script setup lang="ts">
|
|
41
|
+
import ReVerify from "@/components/ReVerify";
|
|
42
|
+
|
|
43
|
+
const verifyShow = ref(true);
|
|
44
|
+
|
|
45
|
+
function onVerifyPass(success: boolean) {
|
|
46
|
+
console.log("验证通过", success);
|
|
47
|
+
}
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<ReVerify v-model:verify-show="verifyShow" @verify-pass="onVerifyPass" />
|
|
52
|
+
</template>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## ReDragVerify 拖拽验证
|
|
56
|
+
|
|
57
|
+
```vue
|
|
58
|
+
<ReDragVerify
|
|
59
|
+
v-model:value="isPass"
|
|
60
|
+
width="100%"
|
|
61
|
+
:height="40"
|
|
62
|
+
:text="$t('请拖动滑块完成验证')"
|
|
63
|
+
:success-text="$t('验证成功')"
|
|
64
|
+
@success="onSuccess"
|
|
65
|
+
/>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Events
|
|
69
|
+
|
|
70
|
+
- `success({ isPassing, time })`:验证通过,返回耗时(秒)。
|
|
71
|
+
- `update:value`:同步验证状态。
|
|
72
|
+
- `start` / `move` / `end`:拖拽生命周期。
|
|
73
|
+
|
|
74
|
+
### Expose
|
|
75
|
+
|
|
76
|
+
- `resume()`:重置验证条状态。
|
|
77
|
+
|
|
78
|
+
## ReImageVerify 图片验证码
|
|
79
|
+
|
|
80
|
+
```vue
|
|
81
|
+
<script setup lang="ts">
|
|
82
|
+
import ReImageVerify from "@/components/ReImageVerify";
|
|
83
|
+
|
|
84
|
+
const code = ref("");
|
|
85
|
+
const imgVerifyRef = ref();
|
|
86
|
+
|
|
87
|
+
function refresh() {
|
|
88
|
+
imgVerifyRef.value?.getImgCode();
|
|
89
|
+
}
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<template>
|
|
93
|
+
<ReImageVerify ref="imgVerifyRef" v-model:code="code" @click="refresh" />
|
|
94
|
+
</template>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## ReSmsCode 短信倒计时
|
|
98
|
+
|
|
99
|
+
```vue
|
|
100
|
+
<script setup lang="ts">
|
|
101
|
+
import ReSmsCode from "@/components/ReSmsCode";
|
|
102
|
+
|
|
103
|
+
const phone = ref("13800138000");
|
|
104
|
+
</script>
|
|
105
|
+
|
|
106
|
+
<template>
|
|
107
|
+
<ReSmsCode :phone="phone" :seconds="120" />
|
|
108
|
+
</template>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- 内置手机号正则校验。
|
|
112
|
+
- 发送成功后自动倒计时,按钮禁用期间不可重复点击。
|
|
113
|
+
|
|
114
|
+
## 关键约定
|
|
115
|
+
|
|
116
|
+
1. 滑块验证通过后通过 `update:verifyShow` 关闭弹窗,不要直接修改 prop。
|
|
117
|
+
2. 图片验证码支持 `getImgCode()` 主动刷新。
|
|
118
|
+
3. 短信验证码 `seconds` 默认 120 秒,按需调整。
|
|
119
|
+
4. 校验组件仅做前端防刷,关键业务必须配合后端二次校验。
|