grading-frontend
给 AI 培训项目前端实现打分。50 学员分成 ~12 组,按 spec-driven 方式实现本地部署的网站。本 skill 让 Claude(或 Qoder / Cursor / Claude Code agent)按统一 rubric 给某一组的前端打分,产出可给学员的 markdown 报告 + 可汇总 leaderboard 的 JSON。
前置依赖
- 本地可跑:待评项目能在本机
npm run dev/pnpm dev/yarn dev启动,默认http://localhost:3000(按项目 README 调整)。 - Spec 文档位置:
<project>/docs/spec.md或<project>/README.md或<project>/spec/*。找不到则先向用户确认 spec 路径再开工,不要凭空评分。 - Node.js 环境:Node ≥ 18,用来跑
npx playwright截图、npx ajv-cli校验 JSON。首次使用时npx playwright install chromium。 - 输出目录:所有证据和报告写到待评项目根目录下的
.grading/(已由 spec 约定 gitignore)。
约定的工作目录:所有 probe 脚本和 .grading/ 输出都默认在待评项目根目录下执行。即评分时:
- cd 到被评项目(如
cd group-workshop/group-2) - 用绝对路径调用 probe:
bash $WORKSHOP_ROOT/skills/grading-frontend/probes/probe-screenshots.sh team-2 http://localhost:3000 .grading/会落到被评项目根下,与该项目共生
共享契约(必读)
评分开始前,必须先读完本文件 ## 评分标尺 / ## 报告模板 / ## 证据硬约束 三段,以及 ../score-schema.json。这些是 frontend / backend 两个 skill 共用的硬约束,不读会导致输出格式不一致、无法汇总 leaderboard:
- 见本文件 ## 评分标尺 — 0–10 标尺含义 + S/A/B/C/D 档位定义。所有维度打分必须对照此标尺。
- 见本文件 ## 报告模板 — 统一 Markdown 报告模板。产出的
report.md必须照此结构填充。 ../score-schema.json— JSON 摘要的 schema。产出的summary.json必须通过此 schema 校验。- 见本文件 ## 证据硬约束 — 打分 ≥7 或 ≤4 必须 ≥2 条证据,5–6 分必须 ≥1 条。违反则打分视为无效。
评分标尺(0–10)
本段是 grading-frontend 与 grading-backend 两个 skill 共享的唯一打分锚点。两侧所有维度得分都必须按本表落点,再用证据说明为什么不是相邻的锚点。
1. 分数锚点
| 分数 | 名称 | 判定标准 |
|---|---|---|
| 10 | 工业级范本 | 可直接作为下一届教学样例;评分人找不到该维度的改进空间;相对已见过的最好学员作业也明显领先 |
| 9 | 优秀 | 核心完全到位,仅 1–2 处非关键瑕疵(例如边缘场景文案、极端断点、冷路径日志) |
| 7 | 良好 | 主流程到位,但存在 ≥3 处可改进;不影响交付但明显看得出赶工痕迹 |
| 5 | 及格 | Happy path 能跑,但明显粗糙;有 1 类系统性漏洞(如缺状态、缺校验)但未致命 |
| 3 | 不及格 | 该项存在尝试痕迹但严重不完整;主要子项缺失或逻辑错误 |
| 0 | 未实现 | 完全缺失,或实现了但跑不起来 |
| N/A | 不适用 | spec 明确未要求,或该维度在本项目栈上无意义;必须写原因,不计入总分 |
允许的分数:0、3、5、7、9、10 是锚点;1/2/4/6/8 仅在证据支持"介于两锚点之间"时使用。不允许出现小数。
2. 打分操作规则
- 先选锚点,再微调:拿到证据后先对齐最接近的锚点(10/9/7/5/3/0),再用证据决定 ±1 微调。禁止"先拍个 8 再补证据"。
- 高低分必须有证据:
score ≥ 7→ 至少 2 条证据score ≤ 4→ 至少 2 条证据5–6→ 至少 1 条证据- 详细规则见本文件
## 证据硬约束段
- N/A 必须写原因:
na_reason字段必填,格式"spec §X.Y 未涉及此项"或"技术栈 Z 无此概念"。N/A 不计入总分。 - 不能同时低分 + 高评:如果评语是"很好,只差一点",分数不能 ≤ 5。
- 锚点冲突时就低不就高:若一个维度既符合 9 的正面描述也命中 5 的负面描述,取 5(警戒作用)。
3. 总分计算
公式(N/A 不计入分母):
total = Σ(score_i × weight_i) / Σ(weight_i for dim_i where score_i != null) × 100 / 10
等价形式:先对非 N/A 维度算加权平均(0–10),再把有效权重归一化到 100,最后乘 10 映射到 0–100。
例子:前端 10 维总权重 100,若 微文案 (权重 6) 被判 N/A:
- 有效权重总和 = 94
- 其余 9 维加权和 = Σ(score_i × weight_i)
total = (Σ / 94) × 10
4. 总分档位
| 档位 | 分数区间 | 含义 |
|---|---|---|
| S | ≥ 90 | 可作为本届教学样例 |
| A | 80–89 | 合格交付,小范围打磨即可上线 |
| B | 70–79 | 主流程 OK,系统性问题需要返工 |
| C | 60–69 | 能 demo,不能交付;多处结构性缺陷 |
| D | < 60 | 未达培训目标,需重做关键模块 |
档位只用于班级 leaderboard 横向对比,学员反馈以维度得分 + 证据 + 改进清单为主。
报告模板
两个 grading skill 产出的 .grading/reports/<team>-<side>.md 必须严格按本模板。字段缺一不可;无信息时填 —,不要省略行。模板本体用四个反引号包裹的 Markdown 代码块呈现,复制时去掉最外层反引号。
使用说明
- 占位符形如
{队伍名},落地时替换为实际值 - 维度详评块按
grading-frontend10 维 /grading-backend9 维完整展开,不能合并或省略 - 任一维度证据不足时,score 填
null,na_reason填EVIDENCE_MISSING: ...,并在末尾"评分风险"段汇总 - 报告的同级必须存在对应 JSON:
<team>-<side>.json,schema 见../score-schema.json
模板
# 项目评分报告 — {队伍名}({前端 | 后端})
- 评分人:{Claude@model-id / 助教姓名}
- 日期:{YYYY-MM-DD}
- Spec 版本:{git sha 或 docs/spec.md 路径}
- 被评项目 commit:{sha}
- 评分耗时:{xx 分钟}
## 总分:{score} / 100 — 等级 {S | A | B | C | D}
## 维度汇总
| # | 维度 | 得分 | 权重 | 加权 | 一句话 |
|---:|---|---:|---:|---:|---|
| 1 | {维度名} | {0–10 或 N/A} | {w} | {score×w/10} | {一句话概述} |
| 2 | ... | ... | ... | ... | ... |
> 有效权重总和:{Σw_non-NA};N/A 维度:{列表或 "无"}
## 逐维度详评
### 1. {维度名} — {score}/10(权重 {w})
**证据**
- `path/to/file.ext:L12-L40` — {这条证据说明了什么}
- 截图:`.grading/shots/{team}-{view}.png`
- 命令:`curl -s localhost:8080/api/x` → `.grading/probes/{team}-x.log`
**要到 10 差什么**
1. {具体、可操作的改进建议}
2. {...}
3. {...}
---
### 2. {维度名} — {score}/10(权重 {w})
(同样模板,完整列出所有维度)
---
## 亮点
- {值得表扬的 2–4 条,要带证据}
## 最该优先修的 3 件事
1. **{问题}** — 影响:{哪个维度掉了多少分};改法:{一两句话说清}
2. ...
3. ...
## 评分风险(可选)
仅当出现以下情况时填写,否则删除整节:
- 证据不足被判 `EVIDENCE_MISSING` 的维度列表
- 评分人对某维度存疑但无法进一步取证的原因
- 项目未跑起来 / spec 缺失等影响评分可信度的事实
校验清单(写完报告后自检)
- 总分 = Σ(加权列) × 10 / Σ(有效权重),数值对得上
- 每个维度都有至少一条引用(证据 / 截图 / 日志 / spec 条目)
- 所有 N/A 都有
na_reason - "最该优先修的 3 件事" 每条都回指了具体维度
- 对应 JSON 已写入
.grading/reports/<team>-<side>.json
证据硬约束
本段是打分是否有效的判定规则。grading-frontend 和 grading-backend 两个 skill 在写入每个维度分数前必须先检查本表;证据不达标的打分视为无效。
设计目的:防止 agent 在缺乏实际观察的情况下拍脑袋打分。宁可多一个 EVIDENCE_MISSING,不要编一个好看的分数。
1. 证据条数规则
| 分数段 | 最少证据条数 | 说明 |
|---|---|---|
| 9–10 | 3 | 高分必须可复现;至少覆盖:1 条代码引用 + 1 条运行期证据(截图/probe/log) + 1 条 spec 比对 |
| 7–8 | 2 | 需同时体现"主流程到位"与"非关键瑕疵" |
| 5–6 | 1 | 一条即可,但必须能指出具体缺陷 |
| 3–4 | 2 | 低分不能靠印象;必须列出 ≥2 个具体失败点 |
| 0 | 1 | 至少证明"真的没有":grep 结果、spec 条目 + 代码库缺失、启动失败日志 |
| N/A | 1 | 必须引用 spec 条目或技术栈说明,证明该项"不适用" |
2. 证据合法形式
每条证据必须是以下 4 类之一,不得为自然语言转述:
- 代码引用:
path/to/file.ext:L{start}-L{end}或path/to/file.ext:L{line}- 路径必须相对项目根
- 必须真实存在(评分前 open / grep 确认过)
- 截图:
.grading/shots/<team>-<view>.png- 文件必须存在;后端维度一般不使用
- 可附简短说明:"登录页 desktop 1280×800,有 layout shift"
- 命令日志:
.grading/probes/<team>-<probe>.log或在证据行内直接给出命令与关键输出- 形如:
curl -s -o /dev/null -w "%{http_code}" localhost:8080/api/x -d '{}' → 500 - 压测结果引用 autocannon 输出文件
- 形如:
- Spec 引用:
spec §3.2/docs/spec.md:L120-L145/ issue 链接- 判定 N/A 或 Spec 一致性时必用
3. 违规处理
3.1 证据不足
若按 §1 无法凑够所需证据条数:
score置为nullna_reason写为"EVIDENCE_MISSING: 需要 N 条证据,仅能取得 M 条(已尝试:<动作清单>)"- 在报告末尾
## 评分风险段落列出该维度 - 该维度不计入总分分母(与正常 N/A 一致),但在评分风险段标注"非 spec 排除项"
3.2 证据伪造 / 占位
评分人/agent 若写入以下任一形式的证据,该维度直接作废并降级为 EVIDENCE_MISSING:
- 路径不存在的 file:line(lint:评分后用
test -f批量校验) - 截图文件不存在或大小为 0
- 命令日志内容与结论自相矛盾
- 描述性语言("代码组织得不错")未附具体引用
3.3 高低分无证据
score ≥ 7但证据 < 2 条 → 降为 6,或标EVIDENCE_MISSINGscore ≤ 4但证据 < 2 条 → 升为 5,或标EVIDENCE_MISSING
选择哪个处理取决于评分人对维度的把握;两种方式都必须在"评分风险"中注明。
4. 证据收集建议顺序
先做便宜的、可批量的,再做昂贵的:
- 静态 (cheap):
grep/rg扫关键词、看 package.json / schema / migration - Spec 对齐:逐条把 spec 检查项对到代码文件
- 运行期:启 dev server / 后端服务,跑截图脚本 / probe 脚本
- 交互:走完主流程,看 console / network / 日志
- 测试:跑 test suite,看覆盖率与失败清单
每跑完一步把产物落盘到 .grading/,在报告证据行里引用相对路径即可。
配套资源
按需读取(不是每次都读全部):
./anti-patterns.md— AI slop 前端反模式清单。打"主题与审美"和"代码质量"两个维度时必读,用来识别默认 shadcn 灰白调、无主题色、按钮都bg-blue-500、空态只写 "No data" 等典型滑坡。./examples/good-report.md和./examples/mediocre-report.md— 两份标定样例报告。打分前读一次做分布校准,避免全班都打 8 分这种分不开档的问题。./probes/probe-screenshots.sh— 批量跑 4 态 + 3 断点截图(login / dashboard / empty / error × desktop / tablet / mobile)。取证时直接bash ./probes/probe-screenshots.sh <team> <base-url>即可,不要手搓 playwright 命令。./probes/probe-performance.sh— 跑 Lighthouse 测关键页面性能,输出.grading/probes/<team>-lighthouse.json(原始 Lighthouse JSON)和.grading/probes/<team>-lighthouse-mapping.txt(rubric 映射建议)。./probes/probe-a11y.sh— 跑 axe-core CLI 扫关键页面的 a11y 违规项,输出.grading/probes/<team>-axe.json和.grading/probes/<team>-axe-summary.txt。
评分流程(5 步)
步骤 1:定位与启动
- 确认 spec 路径,记录
spec_sha(若 spec 在 git 仓库内)。 - 读完 spec,列出:路由清单 / 核心组件 / 主流程(登录、提交、列表、详情、管理等)。
- 读
package.json识别技术栈(React/Vue、TS/JS、Tailwind/CSS-in-JS、状态管理等),记录project_sha。 - 启动 dev server,确认
http://localhost:<port>可访问。
步骤 2:收集证据(evidence-first)
静态证据:
- 用 Grep/Glob 扫组件树、路由表、全局样式、TS 类型、状态管理。
- 为每个维度预留至少 1 处
file:line引用。
动态证据:
# 一次性把主要页面的 3 断点 × 4 态截图跑完
bash ./probes/probe-screenshots.sh <team> http://localhost:3000
# 性能 & a11y
bash ./probes/probe-performance.sh <team> http://localhost:3000
bash ./probes/probe-a11y.sh <team> http://localhost:3000
所有截图落到 .grading/shots/<team>-*.png,所有 probe 日志落到 .grading/probes/<team>-*.log。
如果 playwright 不可用,fallback 为:提示评分人手动放置截图到 .grading/shots/ 后再继续。
交互证据:手动或用 playwright 过一遍主流程(登录 → 核心 CRUD → 提交 → 错误路径),记录 console / network 异常。
步骤 3:按 10 维度逐条打分
⚠️ 取证不足时的强制行为
- 维度打分 ≥7 或 ≤4 时,证据条数低于 evidence-requirements.md 规定的最低条数 → score 必须置 null,na_reason 写 "EVIDENCE_MISSING: 已尝试 X、Y,未能取得 Z"
- 这与 "spec 未要求" 的 N/A 是两回事:N/A 写 "N/A — spec §X.Y 未规定"
- 所有 EVIDENCE_MISSING 维度必须在报告底部 "## 评分风险" 段汇总列出
对照本文件下方 rubric(以及本文件 ## 评分标尺 段),逐维度 0–10 打分。每一条打分必须附证据(file:line / 截图路径 / probe log 行号)。spec 未要求的维度写 "N/A — 原因",不计入总分。
步骤 4:产出 report.md + summary.json
按本文件 ## 报告模板 段填 .grading/reports/<team>-frontend.md;按 ../score-schema.json 填 .grading/reports/<team>-frontend.json。每维度附"要到 10 差什么"2–4 条。
步骤 5:自检(必须通过)
# JSON schema 校验
npx ajv-cli validate -s skills/score-schema.json \
-d .grading/reports/<team>-frontend.json
# 证据数量自检(每维度统计 file:line + 截图 + log 引用总数)
grep -cE "\.(tsx?|jsx?|vue|css|png|log):" .grading/reports/<team>-frontend.md
自检不过则回到步骤 2 补证据,不得放过。
10 个评分维度(权重合计 100)
| # | 维度 | 权重 |
|---|---|---|
| 1 | Spec 一致性 | 20 |
| 2 | 主题与审美 | 12 |
| 3 | 动画与流畅度 | 10 |
| 4 | 状态完备性 | 10 |
| 5 | 代码质量 | 10 |
| 6 | 响应式适配 | 8 |
| 7 | 表单与输入反馈 | 8 |
| 8 | 性能 | 8 |
| 9 | 无障碍 (a11y) | 8 |
| 10 | 微文案 | 6 |
1. Spec 一致性(权重 20)
关注点
- spec 列出的每一条路由 / 页面 / 组件是否都实现了。
- 核心流程字段、状态、文案是否与 spec 对齐,没有偷工减料也没有无关超纲。
- 权限 / 角色分支(如管理员页面)是否完整。
锚点
- 10:spec 列出的所有页面和流程 100% 实现;字段、状态码、文案与 spec 完全一致;超纲功能明确标注为增强。
- 9:所有 spec 页面都实现,仅 1–2 个非关键字段或文案与 spec 微差(如详情页副标题文案差一个字、次要表头顺序略有不同),核心字段 / 状态码 / 路由 100% 对齐。
- 8:主流程和所有主要页面完整对齐 spec,spec 边角有遗漏(如非主路径的 1–2 个交互细节、1 个次要筛选项未实现),不影响核心业务闭环。
- 7:主流程对齐,但遗漏 1–2 个次要页面或 2–3 处字段细节。
- 5:核心页面都在,但多处字段偏离 spec,或 1 个关键流程(如提交 / 审核)未实现。
- 3:大段偏离 spec,或只实现了 demo 页面,真实业务流程缺失。
取证方法
- 把 spec 的路由清单和
src/routes/app/目录对应关系列表。 - 核心流程逐步点一遍,截图 + 对照 spec 条款。
- 对每个缺失项记录 spec 章节号 + 期望行为。
证据要求
- 至少 3 条
file:line引用到组件 / 路由文件。 - 至少 2 张主流程截图。
- 一张 spec vs 实现的对齐表(在报告里用 markdown 表格)。
2. 主题与审美(权重 12)
关注点
- 配色是否有主题色,不是一地灰白。
- 字体、字号层次、间距是否成体系(不是全用默认)。
- 卡片、阴影、圆角是否有设计感(不是默认
rounded-lg shadow)。 - AI slop 味(见
./anti-patterns.md)。
锚点
- 10:有明确主题色系(主 / 辅 / 强调),自定义字体栈,间距节奏一致,视觉层次清晰到像一个真产品。
- 9:配色几近完美,字体 / 间距成体系,但有 1 处对比度差一点点(如次要文本 gray-500 on gray-50)或 1 个按钮 hover 颜色没定义。
- 8:主题色 / 字体 / 卡片风格都立住了,少数次要页面(如 404 / 设置)沿用了默认组件外观未统一改皮。
- 7:有基本主题色和字体选择,多数页面一致,但 1–2 个页面掉档或默认组件未改皮。
- 5:能看出改过样式,但主题不明、灰白主导,大量 shadcn 默认外观。
- 3:通篇灰白 + 默认
bg-blue-500按钮 +gray-100背景,典型 AI slop。
取证方法
- 读
./anti-patterns.md,对照本项目截图逐条判断命中了哪些反模式。 - 看
tailwind.config.*/theme/*/ 全局 CSS,确认是否真的定义了主题 token。 - 多张截图拼对比:不同页面的按钮、卡片、标题层次是否一致。
证据要求
- 至少 3 张截图覆盖 3 个不同页面。
- 至少 1 条
tailwind.config.*:line或theme.ts:line的引用。 - 反模式命中清单(至少覆盖
anti-patterns.md中前 5 条)。
3. 动画与流畅度(权重 10)
关注点
- 页面切换 / 弹窗 / Toast / 菜单的过渡是否自然,不是突变。
- 微交互(hover、按压、图标反馈)是否有。
- 无明显 layout shift,列表加载不跳动。
- 主交互保持 60fps,不卡顿。
锚点
- 10:关键过渡用 spring / cubic-bezier,有进入 / 离开动画;微交互覆盖主要按钮;无 layout shift;滚动和拖拽流畅。
- 9:主流程过渡都做了且曲线合理,微交互覆盖充分,仅 1 处 Toast 或弹窗离场略生硬(直接消失而非 fade-out)。
- 8:主要页面切换 / 弹窗过渡自然,有 hover / active 反馈,偶有 1 处列表加载时图片未占位导致轻微 layout shift。
- 7:主要过渡做了 fade / slide,微交互覆盖部分按钮,偶有 1–2 处抖动。
- 5:只有默认 Tailwind
transition,弹窗 / 路由硬切,hover 仅变色。 - 3:零动画,UI 突变,列表加载瞬间 reflow 一大片。
取证方法
- 录屏或跑 playwright 的 trace(
--trace on)观察过渡。 - 搜
transition/motion/framer-motion/@keyframes的使用。 - 在 DevTools Performance 面板看关键交互的 FPS。
证据要求
- 至少 1 段 trace 截图或录屏帧。
- 至少 2 条
file:line证明动画实现(或证明没有)。
4. 状态完备性(权重 10)
关注点
- loading / empty / error / success 四态在关键列表和详情页是否都覆盖。
- loading 有 skeleton 或 spinner,不白屏。
- empty 有引导(不只是 "No data")。
- error 有可操作出路(重试、返回)。
锚点
- 10:所有主要数据组件都实现了 4 态,空态有插画或引导 CTA,错误态有重试按钮且区分网络 / 业务错误。
- 9:主要组件 4 态齐全且各态都有 CTA,仅 1 处空态缺插画 / 引导图(但仍有文案引导),或 error 未区分 offline vs 业务错误。
- 8:关键列表和详情页 4 态都在且可用,次要页面(如设置、帮助)缺 empty 态或 error 态回退到默认 error boundary。
- 7:主流程四态到位,但 1–2 个次要页面缺 empty 或 error。
- 5:只有 loading + success,empty 是 "No data",error 是
alert(err)。 - 3:接口慢就白屏,接口错就崩白页或 console 报错。
取证方法
- 用 DevTools Network 面板把关键接口设为 Slow 3G + 手动 Fail,分别截图。
- 把数据清空 / mock 空数组看 empty 态。
bash ./probes/probe-screenshots.sh已内置 empty / error view 的路由截图。
证据要求
- 至少 4 张截图覆盖 loading / empty / error / success。
- 至少 2 条
file:line引用组件的状态分支代码。
5. 代码质量(权重 10)
关注点
- 组件拆分粒度合理(不是一个 500 行的巨型组件)。
- TypeScript 类型真实有效,不是满屏
any。 - hooks 使用正确(依赖数组齐全,无不必要 re-render)。
- 没有严重 prop drilling,状态管理有章法。
- 复用度(公共组件、常量、工具函数)。
锚点
- 10:目录分层清晰,组件 ≤ 200 行,类型覆盖 100%,hooks 无警告,状态管理边界清楚,复用充分。
- 9:分层和类型都到位,仅 1–2 处
any出现在第三方类型缺口位置且有注释,组件行数和 hooks 依赖都干净。 - 8:整体架构清晰、复用良好,个别组件接近 300 行但职责单一,或有 1 处轻度 prop drilling(≤3 层)。
- 7:整体干净,偶有 1–2 处
any或轻微 prop drilling,但架构能看懂。 - 5:能跑,但有巨型组件或
any满天飞,hooks 依赖数组乱填。 - 3:意大利面式代码,大量 console.log,类型形同虚设,复制粘贴成灾。
取证方法
- Grep
any、@ts-ignore、console.log数量。 - 按文件行数排序,挑最长的几个 component 文件看。
- 抽 2–3 个 hook 检查依赖数组。
- 对照
./anti-patterns.md中的前端代码反模式。
证据要求
- 至少 4 条
file:line引用(好的和差的都要有)。 - 一组 grep 统计数据(any / ts-ignore / console.log 计数)。
6. 响应式适配(权重 8)
关注点
- desktop (≥1280) / tablet (768–1279) / mobile (<768) 三个断点都能看、能用。
- 布局不断裂,按钮不压成一坨。
- 手势和触达(最小 44px 触控区域)。
锚点
- 10:三断点均精心布局,mobile 有专门导航(抽屉 / tab bar),内容优先级调整合理。
- 9:三断点都精心布局且 mobile 有专属导航,仅 1 处次要弹窗在 mobile 下略宽 / 按钮组偶尔换行。
- 8:desktop / tablet / mobile 都可用且 mobile 导航做了重构,但 1–2 个次要页面(如长表格)在 mobile 下需要横向滚动。
- 7:三断点可用,但 mobile 多处拥挤或需要横向滚动。
- 5:只在 desktop 看着正常,mobile 勉强能用但布局错乱。
- 3:只做 desktop,mobile 直接溢出 / 重叠 / 不可点。
取证方法
bash ./probes/probe-screenshots.sh已生成 3 断点截图。- 查
tailwind.config断点设置和组件里sm:/md:/lg:分布。
证据要求
- 3 断点 × 至少 2 个页面 = 至少 6 张截图。
- 至少 2 条
file:line体现断点处理代码。
7. 表单与输入反馈(权重 8)
关注点
- 客户端校验(必填、格式、长度)。
- 错误提示贴近字段,不是 alert。
- 提交过程中按钮禁用 + loading,防重复提交。
- 成功后有明确反馈(toast / 跳转 / inline success)。
锚点
- 10:全表单含行内校验 + 提交防抖 + 成功态 toast,键盘可 tab 过全部字段,有
aria-invalid标注。 - 9:所有表单行内校验 + 防重复提交 + 成功反馈到位,仅 1 处缺
aria-invalid或 1 处错误样式与全站不完全统一。 - 8:主表单校验 / 禁用态 / 成功反馈完整,次要表单(如反馈、设置)仅做必填校验未覆盖格式 / 长度。
- 7:主表单有基本校验和禁用态,1–2 处错误提示样式不统一。
- 5:只有后端兜底校验,错误用 alert,能双击提交产生两条记录。
- 3:没校验,没禁用,错了崩掉,没有任何反馈。
取证方法
- 对每个表单跑:空提交 / 非法格式 / 超长字段 / 快速连点提交,截图 + 录 network。
- 搜
useForm/zod/yup/disabled/isSubmitting的使用。
证据要求
- 至少 3 张截图(空提交 / 非法 / 成功)。
- 至少 2 条
file:line引用校验逻辑。 - 一条 network log 证明是否防重复提交。
8. 性能(权重 8)
关注点
- 首屏 TTFB + FCP + LCP 合理(本地 dev 下 LCP < 2s 可接受)。
- bundle 体积合理,无重复依赖、无未用的大库。
- 长列表虚拟化、图片懒加载。
- 交互响应(INP)流畅。
锚点
- 10:Lighthouse Performance ≥ 90(本地 dev 下),关键页面 LCP < 1.5s,bundle < 500KB gzip,长列表虚拟化。
- 9:Lighthouse 85–89,LCP < 2s,bundle 500–700KB gzip,图片懒加载和 code splitting 都做了,仅缺长列表虚拟化。
- 8:Lighthouse 80–84,首屏可接受(LCP < 2.5s),bundle 合理但有 1 处未 code-split 的路由或未压缩的大图。
- 7:Lighthouse 75–89,有明显可优化点但不影响体验。
- 5:Lighthouse 50–74,首屏偏慢或 bundle 臃肿(> 1MB gzip 无理由)。
- 3:Lighthouse < 50,切页面要等几秒,JS 主线程长期占满。
取证方法
bash ./probes/probe-performance.sh生成 TTFB / FCP / LCP 数据。npm run build看产物大小;npx source-map-explorer看 bundle 组成(可选)。- 搜
React.lazy/import()/loading="lazy"/ 虚拟列表库使用。
证据要求
- 至少 1 份
<team>-lighthouse.json+<team>-lighthouse-mapping.txt。 - 至少 1 条 build 产物大小数据。
- 至少 2 条
file:line体现优化手段或缺失。
9. 无障碍 a11y(权重 8)
关注点
- 键盘可导航(Tab 顺序合理,焦点可见)。
- 语义化标签(button / a / label / heading 层级)。
- 颜色对比度达 WCAG AA(正文 4.5:1,大字 3:1)。
- ARIA 属性用对(不滥用)。
focus-visible样式存在。
锚点
- 10:axe 扫描零严重违规,全键盘可操作,
focus-visible清晰,表单有 label 关联,对比度全过。 - 9:axe 零严重 + 零中等违规,仅 1–2 条 minor(如冗余 role、landmark 命名),键盘 / 焦点 / 对比度全过。
- 8:axe 仅 1 条中等违规(如单处对比度 4.3:1),键盘可用且
focus-visible覆盖主要交互元素,label 全关联。 - 7:axe 有 1–2 条中等违规,键盘可用但焦点环偶尔消失。
- 5:多条对比度不足,部分按钮用
<div>,无focus-visible。 - 3:大量
<div onClick>,Tab 键按下去什么都不响应。
取证方法
bash ./probes/probe-a11y.sh跑 axe-core,看违规清单。- 手动 Tab 一遍关键页面。
- 搜
role=/aria-/focus-visible/<label的使用密度。
证据要求
- 1 份
<team>-axe.json+<team>-axe-summary.txt。 - 至少 2 条
file:line引用(正或反面)。 - 至少 1 张键盘焦点截图。
10. 微文案(权重 6)
关注点
- 按钮文案是动词 + 对象,不是 "OK" / "Submit"。
- 空态文案告诉用户下一步做什么。
- 错误信息具体且可操作(不是 "Something went wrong")。
- 文案风格统一(全站同一人称、同一语气)。
锚点
- 10:所有按钮、空态、错误态的文案都经过润色,一致、具体、有品牌语气。
- 9:主要按钮 / 空态 / 错误文案都具体且一致,仅 1–2 条次要操作按钮沿用了"确定 / 取消"通用文案。
- 8:关键流程文案具体有引导(空态有 CTA、错误有可操作指引),但错误信息在 2–3 处直接透传后端 message 未本地化。
- 7:关键按钮和空态文案良好,但错误信息偶有通用模板。
- 5:按钮是 "提交" / "确定",空态是 "暂无数据",错误是 "操作失败"。
- 3:混用中英文,或全英文但像机翻,文案语气不统一。
取证方法
- 把所有按钮 / 空态 / 错误文案抽样列表(grep 关键 string)。
- 看同一操作在不同页面的按钮文案是否一致。
证据要求
- 至少 1 份文案抽样表(按钮 / 空态 / 错误 各 ≥ 3 条)。
- 至少 2 条
file:line引用具体文案位置。
产出 checklist
评分结束前逐项勾选,任一不通过就回到相应步骤补齐:
-
.grading/reports/<team>-frontend.md已按本文件## 报告模板段结构填完,10 个维度全部评完(或明确标 N/A)。 -
.grading/reports/<team>-frontend.json已产出,并通过npx ajv-cli validate -s skills/score-schema.json校验。 - 每个维度都有证据引用,且满足本文件
## 证据硬约束段(≥7 / ≤4 分 ≥2 条;5–6 分 ≥1 条)。 -
.grading/shots/含至少 3 断点 × 4 态的截图;.grading/probes/含<team>-lighthouse.json+<team>-lighthouse-mapping.txt+<team>-axe.json+<team>-axe-summary.txt。 - 报告末尾给出"最该优先修的 3 件事",每条对应到具体维度和 file:line。