来源:
notes/documents/网页版前端首轮体检与优化实施计划.md网页版前端首轮体检与优化实施计划
背景与范围
2026-09-22 对线上 https://vite-react-tawny-one-14.vercel.app 做了首轮前端体检:Playwright
(Chromium 1134,走代理,本机直连该域名 DNS 被污染)采集五个状态、两种系统主题、三种宽度,
逐张核对截图后定结论。
这一轮范围覆盖未登录访客能看到的那一面。笔记列表与正文在 GitHub OAuth 之后,本机没有 Neon 连接串、代码里也没有口令旁路,当时没有采集到,因此对笔记区只作代码级观察。
同日补了第二轮:用本地夹具重建登录态,把笔记面采集下来(前端是 npm run build 真产物、接口是
backend/src/lib/notes.ts 真身、数据是 notes.json 真产物 155 篇,只伪造 /api/me 身份与鉴权)。
结论写在 notes/documents/网页版笔记面体检报告.md,本文的 P5 据此改写。
体检结论
坏掉级(一处)
亮色系统主题下,登录页的说明文字完全不可见:.muted 是写死的 rgba(255,255,255,.6),
落在白底上对比度 1:1。访客只看到「Folio」加一个按钮,不知道为什么要点它。

同一屏在暗色系统主题下是正常的(.muted 约 6.5:1),问题只在亮色。

错误提示也踩同一条线:.error 的 #ff6b6b 在白底上约 2.8:1,暗色下约 5.6:1 才达标。

移动端与窄屏同样中招,且 320px 无横向溢出(scrollWidth == clientWidth == 320)。


结构性问题(不改不影响使用,但拖着会越来越贵)
web/frontend/src/index.css还是 Vite 模板原样:body { display: flex; place-items: center }、 写死的#242424。整站布局实际靠App.css里的text-align: left反着覆盖模板行为。App.css里.logo、@keyframes logo-spin、.read-the-docs是死代码,assets/react.svg也没人引用。- 颜色全是散落的
rgba(100,108,255,…)字面量,没有 token;只有 800px 一个断点。 - favicon 是 Vite 默认 logo(
/vite.svg),浏览器标签页写 Folio,品牌不一致。 - 只有一个身份源,文案却写「请用下面任一方式登录」——「任一」在只有一项时是空承诺。
- 登录页 0 个 landmark(没有
main)、0 个 live region;页面唯一动作是个没有任何身份信号的中性按钮。 - 未登录的
GET /api/me返回 401(body 是{"authenticated":false}),每次访问都往 console 打一条红色错误,对开发者工具和前端错误监控都是噪音。
明确没问题的部分
未登录时 /api/notes、/api/notes/search、/api/notes/detail 一律 401 unauthorized,不泄露
任何标题与路径;OAuth 跳转参数完整正确(redirect_uri 指生产域名、state 在、
allow_signup=false);键盘焦点实测可见(Tab 一次落在按钮上,暗色下是白环)。

实施计划
P0 修亮色主题 —— 已完成 2026-09-22(提交 dac8324)
- 文件:
web/frontend/src/index.css、web/frontend/src/App.css - 做法:
index.css收成 token 层,按定版设计的五个角色各给亮暗两套值——素纸#F1F3F4/ 夜纸#14171A、靛墨#22303C/#E6E8EA、淡墨#5C6B78/#9AA5AE、 靛青#2F5D8C/#7FA8D4、朱砂#B4442F/#E0705C。默认素纸,系统偏好为暗色时整组 换夜纸,不再靠一处半套覆盖;App.css全部改用var(--…),散落的rgba(128,128,128,…)、#646cff、#ff6b6b一并收掉。 - 同根的三处一并修掉:
.note-item-meta/.note-item-excerpt原先用opacity稀释墨色 (折算 4.27:1),改用淡墨角色;当前项原先铺靛青底色,把行内淡墨压到 4.03:1,改成设计里 写的「当前项用朱砂记号、不铺底色」;.error由白底 2.78:1 改成墨色文字加朱砂非文字记号。 - 验收(实测,非估算):本地夹具逐元素算对比度(含 alpha 合成与祖先
opacity), 451 个文本节点 × 亮暗两套 × 笔记面与登录页,四个面 0 失败,最低 4.93:1(素纸上的淡墨)、 暗色 7.17:1,console 0 错误。生产侧公开登录页(走代理)复测:素纸解析为rgb(241,243,244)、 夜纸rgb(20,23,26),四段文字 4.93–14.65:1 全过。 - 一条未达的自定阈值:淡墨落在素纸上是 4.93:1,低于设计写的「淡墨至少 5:1」,差 0.07
(WCAG AA 的 4.5:1 已过)。要么微调
#5C6B78,要么把阈值写成 4.5,等和设计一起拍板。
修好之后的公开登录页,亮暗两套:


以上两张是 2026-09-22 生产环境实拍(push main 后自动部署,20 秒内落地)。
P1 清 Vite 模板残留 —— 已完成 2026-09-22(提交 356f8a0,收尾 4187e10)
- 文件:
web/frontend/src/index.css、web/frontend/src/App.css,并删assets/react.svg - 做法:去掉
body的 flex 居中与#root的max-width/padding/text-align, 布局交回.card/.app-header/.notes-layout;删.logo、logo-spin、.read-the-docs。 - 验收:
npm run build通过,登录页与笔记页布局都不塌。 - 收尾:
frontend/src/assets/react.svg当时没删(4187e10才删掉),那一次同时把 favicon 从/vite.svg换成 Folio 标记 —— 也就是说 P2 的图标那半拖到了4187e10才补上。
P2 品牌面 —— 已完成 2026-09-22(字体与配色 356f8a0,标记 4187e10)
- 做法:定一个 Folio 的标记,替换
/vite.svg作为 favicon,并在登录页复用同一个标记。 审美方向用frontend-design定,别直接套默认字体与默认蓝紫。 - 验收:标签页图标不再是 Vite;登录页出现可辨识的品牌信号。
- 落地:字体与配色在 P0 的 token 层就位(宋体标题、五个角色、无卡片无阴影),
标记本身 2026-09-22 才补(
4187e10)——frontend/public/folio.svg:素纸底上一本对开本, 靛墨页框加一道页边缝、缝上一颗朱砂墨点(外壳的「脊 + 当前项记号」缩小版), 文件内带prefers-color-scheme: dark媒体查询,暗色下的整组值换夜纸。登录页标题旁复用同一个标记。 实测:link[rel=icon]指向/folio.svg(200 +image/svg+xml),16 / 32 / 64px 两套主题都能认出来。
P3 登录页语义与措辞 —— 已完成 2026-09-22(提交 1cd1d9d、7c478e9)
- 文件:
web/frontend/src/pages/Login.tsx、web/frontend/src/App.tsx - 做法:登录卡片包一层
main;错误与状态提示加role="alert";只有 GitHub 一个身份源时, 把「请用下面任一方式登录」改成直述,并让按钮带上 GitHub 身份信号。 - 验收:landmark ≥ 1、live region ≥ 1;文案在只有一个 provider 时不出现「任一」这类空承诺。
P4 对齐 /api/me 的状态码语义 —— 已完成 2026-09-22(提交 190469d)
- 文件:
api/me.ts(及前端web/frontend/src/auth/useSession.ts) - 做法:未登录返回 200 加
{"authenticated":false},与 body 已经表达的语义一致。 - 验收:首屏 console 不再出现红色 401;
useSession的未登录分支保持原行为。
P5 笔记区体检(已用本地夹具覆盖)
第二轮用本地夹具重建登录态,覆盖了列表、详情、搜索、亮色切主题、材料类笔记与 390px 移动端。
完整结论见 notes/documents/网页版笔记面体检报告.md,要点:
- P5.1 正文泄漏 front matter 并重复一级标题(坏掉级,108 篇受影响)。已修(ticket 02,
3fb9508)web/scripts/generate-notes.mjs的toNote()把整份文件原文塞进body,notes/documents/下 108 篇全部带 YAML front matter,于是详情页顶部渲染出note_id: … content_type: …, 后面再跟一个 51.2px 的重复 H1(Vite 模板的h1 { font-size: 3.2em })。同一个 bug 让搜索摘录 也被 front matter 占满。做法:剥 front matter 并把正文起点挪到第一个#之后(同时用于body与excerpt),改完重新生成notes.json。验收:随机抽 3 篇文档类笔记,正文首行不再是note_id:,详情页只有一个同名标题。 - P5.2 亮色主题下三处文字仍然 1:1,与 P0 同根。已修(P0
dac8324+ 外壳 token 化356f8a0).note-detail-head p(路径/大小/更新时间)、.notes-count(155 篇笔记/命中 52 篇)、.muted(头部用户名)在亮色下整行消失。 P0 的 token 化必须把这三处一起收进去,别只修登录页。 - P5.3 正文度量与字体与定版设计冲突。已修(ticket 05,
356f8a0) 实测正文块宽 956px、字体 Inter、16px/27.2px; 设计笔记要求约 640px(34 个汉字)、正文思源宋体、最小 17px。 - P5.4 列表排序把材料类条目推满首屏。已修(ticket 03 / 05,
356f8a0)books/*/source_materials一屏占 7/9 条, 材料与解读分不出身份。归到外壳改造(索引层)一起做,别单独调排序。 - 已确认正常:
header.app-header/aside.notes-sidebar/nav.notes-list/main.note-detail四个 landmark 齐全,侧栏粘性定位生效,搜索防抖后结果与命中数一致,390px 无横向溢出。 - 当时未覆盖、2026-09-22 补测完毕的:
- 空搜索结果:索引头显示「搜索结果 0」,索引里一句话「没有匹配的笔记。」,不塌。
- 超长查询:
?q=1000 字 →400。 - 笔记不存在:
?m=notes&n=documents/不存在.md→ 页里写「产物里没有这篇笔记:documents/不存在.md」 (role=alert),不是白屏也不是英文状态码。 - 代码块与表格横向溢出:在 390px 与 768px 下量过 ——
pre自己横滚(overflow-x: auto)、 表格按 100% 宽排开,页面本身没有横向滚动。 - 笔记内图片:ticket 12 已修,线上不再裂。
- 平板与窄屏宽度:外壳的 900px 断点、860px 与 420px 的月历/正文都截过图。
- 仍未覆盖:非 Chromium 内核(Safari / Firefox)、屏幕阅读器、200% 缩放、强制色模式、 已登录态的移动端横屏。
验证方式
- 每阶段改完走
frontend-testing-debugging的渲染验证闭环;本机 Browser 插件缺失,按规矩回退 Playwright 并在报告里记明原因。 - 复现采样的命令形态:Playwright 启动时带
proxy: { server: 'http://127.0.0.1:7890' }, 否则本机解析不到*.vercel.app。 - 部署走
web/下的npm run deploy;push 到main已自动部署。
不做的事
- 不引入 UI 框架与组件库:这个前端一共 744 行,引依赖的收益远小于运维成本。
- 不动
vite-react这个 Vercel 项目名、不动 OAuth 回调注册、不改部署方式。 - 不把笔记正文或图片搬进数据库或函数包:笔记只在构建期从
notes/生成。 - 不为了好看改掉「界面叫 Folio、文档叫个人助理」这个刻意的不一致。
两条已知限制
这篇文档里的图片在仓库预览与飞书 Docs 里可见,但网页版不提供笔记内图片,线上会裂。已解决(ticket 12,f505ee7/2924f97):构建期把笔记引用的图片拷进静态产物 (5 篇笔记 / 33 张 / 5.1 MiB,落在frontend/public/note-assets/),正文 URL 改写成/note-assets/…,渲染侧只放行这条前缀与https:;被拒绝的引用(缺文件、越界、非图片) 构建日志各报一行、页面上不渲染。- 本轮只测了 Chromium 一种内核;屏幕阅读器、200% 缩放、强制色模式、Safari / Firefox 都未覆盖。