Web 应用美学加固流程
> 与知识库 05-技能库/技能|Web应用美学加固流程.md 一一对应(三处同步之一)。
适用场景
对单文件巨石 Web 应用(FastAPI + pywebview 无边框壳 + 内联 HTML/JS 前端,如知识库工作台 <项目根目录>\kb_workbench\app.py)做"程序美学 + 体验一致性 + 健壮性"加固。功能已齐备,按程序第一原则(反应速度 + 代码最简)消除"能用但不够专业"的观感与可达性短板。
触发词
程序美学加固、前端体验改进、统一错误态、登录冷启动体感、焦点环、快捷键、状态不唯色、清理死 CSS、失效双链入监控、Web 应用观感提升、把界面做得更专业、去 AI 味、去掉 emoji 装饰、装饰 emoji 清理、营销腔文案、界面有模板感/像 AI 生成的、toast 显式 kind、提示分成功失败、状态点改 CSS 圆点、emoji 当图标改 CSS、提示没颜色区分
操作步骤
-
A 登录冷启动体感:在独立登录模板(LOGIN_HTML)注入旋转 spinner,消除约 1.6s 冷启动"卡死"观感。
- CSS:@keyframes spin{to{transform:rotate(360deg)}} .go-spin{width:14px;height:14px;border:2px solid rgba(255,255,255,.5);border-top-color:#fff;border-radius:50%;animation:spin .7s linear infinite;display:inline-block;vertical-align:-2px} .go-tx{margin-left:6px}
- 按钮<button id="go">进 入 工 作 台</button>→ 点击后go.disabled=true; go.innerHTML='<span class="go-spin"></span><span class="go-tx">验 证 中 …</span>'
- 成功:location.href="/";失败还原:go.disabled=false; go.innerHTML='进 入 工 作 台'
- 注意:登录模板用document.getElementById而非$,JS 须一致。 -
C 统一错误态卡片:全站失败态从散落的
toast("…加载失败")收敛为带"重试"的.err-card。
- CSS.err-card{…}(图标 + 标题 + 文案 +#ec-retry重试按钮)。
- 辅助errCard(title,msg,retryFn)返回 HTML 串;showErr(sel,title,msg,retryFn)注入容器并el.querySelector('#ec-retry').onclick=retryFn绑定重试(不绑重载后会失灵)。
- 改造 4 处页面级失败点:首页搜索doHomeSearch、全屏搜索doSearchXL、库洞察(insight 加载)、双链图谱afterGraph(图谱需先在容器加#gerr占位)。 -
D 状态不唯色:仅颜色区分的状态补形状/文字冗余,提升色盲可达性。
- 导航 live 点补title="实时数据";监控状态已带"故障/告警/正常"文字标签、停滞卡已含"停滞"文字——只补缺失的title。 -
E 焦点环 + 快捷键:注入键盘可达性。
- CSS:*:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}(SPA 与登录页 LOGIN_HTML 都要加)。
- 全局Esc关层:document.addEventListener('keydown',e=>{if(e.key==='Escape')_closeLayers()})。
-←/→环形切导航页:ArrowLeft/ArrowRight→ 在 navPages 数组里循环show()。
- ⚠ 录入型系统不加裸←/→(见步骤 13 N1):表单/录入密集的页面里←/→是光标移动刚需,劫持后操作员在输入框按左右键会整页跳走。 -
F 清理死 CSS:删未使用样式,消灭屎山。
- 先 grep 确认 HTML 零引用(如class="kan"/class="grid")→ 删.kan{}与.libgrid>.grid{}共 3 行;保留核心类(如.libgrid是七库三列核心类,只删其子选择器)。 -
G 失效双链入监控:把只读全库扫描发现的失效双链(如 42 处)自动列示进监控告警,零扫描开销。
- 在monitor_alerts()读既有obsidian_compat_report.md,提取"失效双链"计数,add("warn","失效双链","…N 处…")(复用既有报告,不重新全库扫)。 -
H 去 AI 味(装饰 emoji 清零 + 文案说事实 + 身份化徽标):
- 先统计 emoji 计数:专业系统常常本来就是 0(如安检系统)。计数为 0 ⇒ 跳过本段与步骤 K,改走步骤 13 N2 的四条替代杠杆(文案 / 排版密度 / 术语一致 / 配色),别在零 emoji 的项目上空跑 emoji 清理。
- 判定线:装饰性 emoji(🚀🤖⚙🔍📥🎉👍🏆🕰🕸📅🚨🔤🏠 等作图标/前缀/庆祝)= AI 味,清除;功能性符号(✕ 关闭、💤 后台、⛶ 全屏、📂 折叠、📚 品牌、⚠ 警告、🟢🔴🟡 状态点、📄 文件)保留。
- ⚠ 头号坑:toast/提示里的✓ ❌ ✅往往是唯一的成败视觉区分(toast 函数可能只加on类、无配色)。必须先给 toast 加err/ok配色,再删 emoji,否则错误提示失去红色警示。- 最小改法:改写
toast()一处,用中文失败关键词自动加err类 → CSS#toast.err{background:rgba(153,27,27,.94)}(并用 replace_all 清源码 53 处前缀,一处函数覆盖全部调用点)。 - 身份化徽标:库/分类 emoji → 汉字首字徽标(如 PARA 八库
灵 项 资 源 档 技 维 原)+.lc-icon徽标 CSS(34px圆角底 +--acc强调色)、.sm(22px 导航/标题)、.hero(白底,深色头图防低对比)。 - 导航/章节/页标题/按钮统一去 emoji;状态语义改由
--acc左色条 + 文字承担(活跃=绿条、停滞=红条),不靠 🟢🔴。 - 文案去营销腔:自夸式("AI 全链路本机执行")→ 说事实("全程本机执行,数据不出本机");空态去庆祝填充(
全部已蒸馏 🎉→全部已蒸馏)。 - 光效收敛:登录锁等"科技蓝辉光"(
drop-shadow(... .5))→ 弱光(.2)。
- 最小改法:改写
-
I toast 显式 kind(消除关键词启发式漏判):启发式只能治标——凡文案不含"失败/错误"的错误(如动态
""+r.error)就判不出红色。升级为显式三态:
- 签名保持(m, ms=2600, kind=""),ms 仍是第二参——既有toast(x,4200)调用行为不变,零破坏性。切勿把 kind 放第二参。
- 加三个薄封装:const toastOk=(m,ms=2600)=>toast(m,ms,"ok"),toastErr=…"err",toastWarn=…"warn";
- 用脚本按位置倒序批量把静态调用点改名为toastOk/toastErr/toastWarn(参数一字不动),配合启发式作动态文案兜底。
- 提升 toastWarn 用途:把表单校验提示(输入关键词/先选笔记/都要填/需 ≤2MB)从中性黑条升为琥珀警示。
- 补#toast.warn琥珀配色,与 err 红 / ok 绿 构成完整三态。 -
J 状态点改 CSS 圆点(消最后一处 emoji 态):新增纯 CSS 一套,不引第三方图标库。
css .st{display:inline-flex;align-items:center;gap:6px} .sdot{display:inline-block;width:8px;height:8px;border-radius:50%;flex:none;vertical-align:middle;background:#9ca3af} .sdot.ok{background:#10b981}.sdot.warn{background:#f59e0b}.sdot.err{background:#dc2626}
- 必须给纯 emoji 状态补文字(如队列✅/⚠️/⏳→ 圆点 +已发送/发送失败/待发送),否则违反 D 项"状态不唯色"。
- 保留判定:🍠🦊🐼🦉等头像素材属内容资产;✕💤⛶📚📂📄✎▶属功能字形;后端业务数据格式符(如选题表✓❌✅)不可动。
- 全面收口:别按清单扫,直接正则全 Unicode 符号范围[\U0001F000-\U0001FAFF…]列出全部残留再逐个判定,清单式扫描必漏(本次靠全扫揪出📦🥇🧠等 40 处)。 -
K 装饰 emoji 收尾(按钮 / 标题 / 卡片签名 / 参数瘦身):前两轮做完还有约 40 处残留,这才是真·收尾。
- 按钮与小节标题一律让中文承担语义:🎞 提交出片→提交出片、📦 备包→备包、💾 保存→保存、🧹 清空队列、🔎 Obsidian 兼容校验、🎨 全局皮肤、🔐 登录密码……共 50+ 处。
- 列表行首的"来源/序号"不要靠 emoji:🎬/📣→ 删(来源交给tag标签);🥇🥈🥉→#1 #2 #3,且与同页另一处排行共用同一个.tag样式,顺手把两处排版统一。
- 工厂函数带图标参数且有人传空串 ⇒ 参数本身就是负担:pubCard(icon,title,body)→pubCard(title,body),7 处调用同步去首参,随之失效的.pico三行 CSS 一并删(不删就是新的死 CSS)。
- 内容资产不能当文字用:恢复默认 🍠→恢复默认头像(头像素材是内容,混进文案就成了装饰)。
- 开关状态不唯符号:标签✓ / 标签✕→标签:显示 / 标签:隐藏。
- 唯一安全的批量改法:cp app.py app.py.bak_<tag>→ 写(old, new, 期望次数)列表 → 先逐组count断言,全部通过才统一 replace;任一组不符就报错退出、不落盘;跨行片段绝不按行号(前面的组一旦增删行,行号就漂,且\'转义在 Python 字面量里极易对不上),改用[k for k,l in enumerate(lines) if key in l]定位后整行替换。
- 顺带:查询参数一律给默认值(date: str = ""),避免 FastAPI 缺参 422 给 SPA 吐非 JSON。 -
质量门(必做):每项改完
py_compile app.py;改了大量内联 JS 时,必须导出内联 JS 走node --check(正则提<script>…</script>存临时 .js →node --check),否则py_compile只校验 Python、JS 语法错会导致页面白屏;重启 8765(看门狗自动拉起);带 cookie 登录后逐项实测:登录页含go-spin+@keyframes spin、SPA 含err-card/focus-visible/_closeLayers/.lc-icon/#toast.err、/api/monitor含失效双链告警、遍历装饰 emoji 断言零残留。 -
L 缺陷探针三件套(测试视角,比肉眼可靠):改完美学必须再跑一遍,脚本留在项目里可复算。
- 差分探针_probe_defects.py:① 未登录逐个打接口,看返回 401 JSON 还是 HTML 登录页;② 路径穿越(../..、%00、空值);③ 异常入参(非法类型、超长串、<script>);④ 12 并发验证无 500/无串会话;⑤ 退出登录后旧会话是否立即失效;⑥ 错误契约一致性(同时存在{"ok":false,"error"}、{"detail":"Not Found"}、{"ok":false,"hits":[]}就是缺陷)。
- 一致性探针_probe_consistency.py:接口返回值 ↔ 真实磁盘逐篇比对(各库条目数、图节点数、每篇 rel),差值落清单;再拿 3 篇文件名反查搜索能否命中自身。自造差分前先确认字段名(我曾把rel当dir,差点把自家脚本的 KeyError 报成产品缺陷)。
- 先证伪再写进报告:探针构造的 query 经过字符串替换(如把|换空格)会制造假阳性;同一现象要用「随机串应 0 命中 + 精确词应命中本体」双向交叉验证后才算缺陷。
- 探针铁律:只打只读/幂等接口,不写知识库、不真跑任务;静态推断的条目必须标注「静态结论,未实跑」。探针自身也要防错:URL 里的中文/日文 path 必须urllib.parse.quote(p, safe='/'),否则UnicodeEncodeError会让探针报 EXC,看起来像服务端爆炸,其实是脚本自己的问题。 -
N 录入型系统四条硬边界:前 12 项默认面向浏览型 SPA(知识库工作台这类"看得多、写得少")。遇到录入/表单密集的专业系统(如安检数据采集
D:\安检系统)必须先过这四条,否则会好心办坏事:
- N1 方向键切页不适用于录入系统:浏览型 SPA 用←/→环形切页是提升(步骤 4 E);但录入系统里←/→是光标移动 / 字符选择的刚需,劫持后操作员在输入框里按左右键会整页跳走,直接毁掉录入效率。- 判定:页面以表单 / 表格录入为主 ⇒ 不加裸
←/→切页;只有以浏览 / 阅读为主的页面才加。 - 要加就加守卫:
if(/^(INPUT|TEXTAREA|SELECT)$/.test(document.activeElement.tagName))return;(输入框聚焦时不拦截),或改用带修饰键的Ctrl/Alt+←→。 - 同理
Esc关层在录入系统也要确认不会打断未保存的表单。 - N2 emoji 已为零时,去 AI 味改走替代打法:步骤 H/K 的前提是"有装饰 emoji 可清"。专业系统往往本来 emoji 就是 0(如安检系统),此时清 emoji 这条路径收益为零,必须换四条替代杠杆:
① 文案:说事实不自夸(同 M 项),去营销腔、去黑话,空态不卖萌、不堆感叹号;
② 排版与信息密度:数字右对齐 / 等宽字体、表格列对齐、同页同类元素间距统一、去掉过度圆角与阴影;
③ 术语一致:同一概念全站同一叫法("展会 / 展会名"不与"展览 / 会议"混用)——术语不一致比 emoji 更像 AI;
④ 配色克制:减少高饱和渐变、辉光收敛(同 H 项)。 - 先统计再动手:改前先正则全扫一遍 emoji 计数;计数为 0 ⇒ 跳过 H/K 整段,直接走上述四条。
- N3「请求参数与数据源不匹配」是高危静默缺陷:前端传的入参与后端真正消费的字段 / 数据源对不上——参数名写错、传了不用的死参数、按 A 字段传值后端却按 B 字段查、页面要 2026 库后端却读 2025 库。
- 为什么高危:这类错不报 500、不报 422,HTTP 200 照常返回,只是数据为空或串库;肉眼和日志都发现不了,越用越错,属"接口撒谎"里最难查的一类。
- 探针怎么抓(补进步骤 12 L 的一致性探针):对每个读接口做「入参被消费」证据断言——改一个入参的值,返回结果必须变化;不变 ⇒ 该参数根本没被后端消费(死参数 / 字段名不匹配)。再反向验一次:传非法值应被拒绝或返回空,而不是静默返回全量。
- 正确做法:入参必须有消费证据;多余 / 拼错的参数要显式拒绝或记 warning,绝不静默忽略后返回全量;跨库 / 跨年的接口把库选择参数显式透传并校验。
- N4 加校验前先查存量写法:想加任何校验(名称清洗、必填、范围、格式)前,先 grep 存量实现,确认三件事:① 是否已有同类校验(避免重复 / 双写);② 既有文案口径与报错形状(对齐
{"ok":false,"error":"中文"},别造第二种形状);③ 是否已有可复用的辅助函数(如clean_name/_normalize_name)——复用优先于新写。 - 反直觉点:凭空加的校验常与另一条路径的存量校验打架或互相覆盖,结果"加了等于没加",还留下两套不一致的提示。
- 落点:新增校验补在最靠近数据源的那一层(导入 / 写入层),而不是散在前端各调用点。
- 判定:页面以表单 / 表格录入为主 ⇒ 不加裸
-
M 安全与健壮性收尾(探针报出来的缺陷怎么改,全部是减法):这一步专治「看着能用、实则撒谎/会抢跑」的问题,顺序如下:
- 免登录接口的返回值不许写死:public白名单里的接口(如/api/me)login必须按 Cookie 真实校验(request.cookies.get("wb_session","")==a.get("token","");未登录只返回登录页所需的最小字段(不给default_pw/has_recovery/last_login)。(P1-1)
- 错误形状归一:注册@app.exception_handler(StarletteHTTPException)(需from starlette.exceptions import HTTPException),映射401/403/404/422 → 中文,统一返回{"ok":false,"error":"中文","auth":code in (401,403)};同时把缺error的自家返回(如{"ok":false,"hits":[]})补上文案。全站错误只有一种形状,前端不必按状态码猜字段。(P2-3)
- 并发占位用 set 做 CAS:不要「先查 busy 再加 busy」。抽_claim(task)(before=len(busy); busy.add(task); return len(busy)>before),三处入口共用;重活(subprocess.run(timeout=1800))不能包在全局锁内,锁只包占位。删掉因此失效的锁变量。验证方法:6 线程并发打同一个任务,应只见 1 个ok:true,其余 0.02s 返回「正在执行中」。(P1-2)
- 超时收敛 + 前端降级:_llm类默认超时 900s → ≤180s(批处理 300s);api(u,opt,ms)用AbortController做MODEL_MS=20000降级,不取消服务端执行(结果照样落库),返回{ok:false,slow:true,error:"本地模型仍在处理,完成后刷新可看结果"};再抽resToast(r,okMsg,ms)统一处理 slow/成功/失败三态,替掉各写各的三元判断。删除类等瞬时操作不套超时。(P2-4)
- 被跳过的文件别真丢:过滤生成/规则类文件不让污染统计是对的,但要在同一遍 os.walk 里顺手登记路径(只 getmtime/getsize,不读全文,零 I/O 感知),接口多返回一个generated数组,页面给一个默认折叠的开关。显示与否都不改变任何统计,最近产出才不会失真。(P2-5)
- AI 味文案:说事实不自夸——军事/企业级黑话(作战室、运营中心、XX引擎、全链路、全自动、进化)换成时间/频率/步骤的事实描述;同一短语内可有可无的名词堆砌(高频被引资产→高频被引)一并精简。技能名本身带pipeline的「流水线」保留(是工序不是宣传语);「一键」是通用 UI 用语可留,但不与「全自动」叠用。改完全量复扫这些词应全部归零。 -
O 打包产物与守护进程的一致性收尾(改了源码却仍在跑旧二进制,是最隐蔽的一类"改了没生效"):
- 每次改完 Python / 内联前端都要重打包:mv dist/<产品> dist/_prev_<日期>保底 →--distpath 全新目录(绕开 COLLECT 整删旧目录被拦且删一半)→ 回位。改完必须取证(_verify_frozen.py:隔离端口让 exe 自己起服务,抓渲染后 HTML 断言新代码的特征串在、旧文案不在)。
判断是否需要重打包:看Analysis([...])入口,被import链追踪到的文件(如app.py)要打包;独立进程由计划任务直接跑源码的(如kb_watchdog.pyw)不用。
- 守护/看门狗类的"一次性标志"必须有失效条件:.kb_quit这种"用户主动退出"标志,若清理逻辑只存在于某个不被自启动覆盖的进程里,就会变成永久否决票(典型死局:关闭→写标志→关机→开机只起看门狗→看到标志→永不拉起)。三条兜底:① 服务存活即清除;② 标志早于本次开机时刻(GetTickCount64反推)即失效;③ 超过保鲜期(如 2h)失效。
- 端到端实测脚本三条铁律:
① 单条命令跑完(后台进程跨 Bash 命令就被会话回收,必须写一个脚本一口气测完);
② 绝不批量杀 python 进程(会误伤工具自身进程、也会杀掉测试脚本自己)——只杀占用目标端口的那一个 PID(netstat -ano反查LISTENING);
③ 诊断期用-u免缓冲(重定向到文件时块缓冲,进程被杀则日志全空)。
枚举进程用tasklist /FI ... /FO CSV /NH;写成taskkill会因缺/PID|/IM报错并返回空列表,导致"一个都没杀到"而场景结论全是假的。 -
落盘与同步:写《全流程改进落地报告 Vx.y》进
<项目根目录>;本技能同步进~/.workbuddy/skills/与05-技能库(三处同步);跑gen_kb_catalog.py刷新目录表。
注意边界
- 不新增后端功能体积:G 复用既有报告、spinner/快捷键/焦点环均为前端轻量,符合"最简形式最大功能"。
- 不阻塞热路径:spinner/快捷键/焦点环纯前端;重接口(wechat/check、obsidian_check)加 60s TTL 缓存,首次点击仍约 1.5s 但非首屏。
- 登录模板是独立 HTML 片段(LOGIN_HTML),与 SPA 模板分离——改登录页样式须同时加焦点环,否则登录态漏掉可达性。
- 死 CSS 删除前必须 grep 零引用;核心布局类(
.libgrid等)不可删。
反例避雷
| 反例 | 为什么错 | 正确做法 |
|---|---|---|
| 用裸 urllib 不带 cookie 测 SPA 焦点环 | 未登录态返回登录页 HTML,误判"焦点环未注入" | 用 cookiejar 登录后再取 SPA HTML 验证 |
| 登录冷启动单次计时 1.6s 判"慢" | 是首次请求触发索引预热的一次性开销,后续约 12ms | 隔离计时 3 次确认 |
删 .libgrid>.grid 时连 .libgrid 一起删 |
七库三列布局崩 | 只删子选择器,核心类保留;删前 grep |
| 错误卡片重试按钮只注入 HTML 不绑 onclick | 点了"重试"无反应 | showErr 内 el.querySelector('#ec-retry').onclick=retryFn |
| G 项重新跑全库扫描取失效双链 | 重复约 1.2s 重扫描,违背"能缓存" | 读既有 obsidian_compat_report.md,零扫描 |
登录模板 JS 用 $() 但模板里用 getElementById |
选择器不一致,元素取不到 | 同一模板内统一用 document.getElementById |
脚本批量改函数名用 src[:st]+k+src[en:] |
把 toast( 连同左括号一起吞掉,48 处变 toastOk"..." 语法错 |
区间是函数名+左括号,须写成 src[:st]+k+"("+src[en:];大文件批量正则改写必须先 cp app.py app.py.bak,出错立刻回滚重跑 |
从 Python 源码正则提 <script>…</script> 做 JS 校验 |
HTML 由多个 Python 字符串拼接,script 起止跨字符串边界,会把 Python 代码(flags=re.I)当成 JS,得出假 FAIL |
必须启动服务、拉取渲染后 HTML 再提取 script 走 node --check |
.sdot 等圆点忘写 display:inline-block |
<span> 行内元素宽高失效,圆点完全不显示;而 py_compile 与 node --check 都查不出 |
状态圆点一律写 display:inline-block(flex 子项除外另加 flex:none) |
把 kind 放在 toast 第二参 |
既有 toast(x,4200) 会把 ms 当 kind,行为静默错乱 |
签名用 (m, ms, kind),kind 永远第三参 |
| 直接 replace_all 删掉 toast 的 ❌ 而没先加配色 | 原 toast 只靠 emoji 区分成败,删后错误提示变中性色,丢失红色警示 | 先改 toast() 加 err/ok 配色(关键词判定),再清 emoji |
大改内联 JS 后只跑 py_compile 就交付 |
py_compile 只校验 Python;内联 JS 语法错会让整页白屏且后端仍 200 | 导出内联 JS → node --check 语法校验 |
| 把功能性符号(✕💤⛶⚠🟢🔴🟡)当装饰 emoji 一并删 | 关闭/后台/全屏/警告/状态点是有语义的功能指示 | 只清装饰性 emoji,功能符号保留 |
| 回归脚本用裸 urllib 打本机接口 | 环境里有 HTTP_PROXY 时 urllib 照单全收,45 个端点全部 502(约 2s,"upstream connect failed")——症状像服务崩了,服务其实好好的 |
build_opener(ProxyHandler({})) 强制直连 |
用裸的解释器路径起服务(如 binaries\python\versions\x\python.exe) |
依赖装在 venv 里,裸解释器 ModuleNotFoundError: fastapi,进程秒退、端口无监听 |
一律用装了依赖的 ...\python\envs\default\Scripts\python.exe |
多行替换按行号写死 old |
前面的组一旦增删行,行号漂移;再加 \' 转义,Python 字面量极易对不上,count=0 却静默跳过 |
按内容关键字定位行后改整行;整段替换一律精确字面量 + 计数断言,不符即退出 |
| 卡片工厂保留图标参数、调用方传空串 | 视觉上出现"空图标芯片",参数纯负担,配套 CSS 变死 CSS | 删参数 + 改全部调用点 + 删配套死 CSS,一次做完 |
FastAPI 查询参数写成必填(date: str) |
前端漏传 → 422 HTML 错误页,SPA 拿到非 JSON,页面白/静默失败 | 查询参数一律给默认值,内部用正则/空串兜底返回 {"ok":false,...} |
把免登录白名单接口写成 'login': True(如 /api/me) |
登录页要读它 → 放进 public,但写死 True 等于"任何本机进程都被告知已登录",连 default_pw(是否仍在用默认密码)、用户名、上次登录时间一起泄露;且该字段常无人消费 |
public 可以保留,但 login 必须按 Cookie 真实校验;未登录态只返回登录页所需的最小字段 |
run_task 里「先查 busy 再加 busy」不带锁 |
API 线程 / 监听线程 / 调度线程三方同时通过检查 → 同一脚本并发跑两遍,互相覆盖写入 | 用 set.add 的原子性做 CAS(_claim(task)),三处共用 |
把 subprocess.run(timeout=1800) 包在全局 _state["lock"] 里 |
单任务可占锁 30 分钟,第二个任务请求排队干等,前端无超时反馈只会一直转圈 | 锁只包住"占位",重活挪出锁;_llm 类超时默认压到 ≤180s,前端加 20s 降级提示 |
差分探针里照自己猜的字段名取值(如 item['dir']) |
实际字段是 rel/folder,KeyError 会把自家脚本的错报成产品缺陷 |
先打印一个样本的完整键再写断言;异常点位要交叉验证后才落进报告 |
| 探针/回归脚本把中文路径直接拼进 URL | urllib 会抛 UnicodeEncodeError,探针把它打成 EXC,看着像服务端爆炸,其实是脚本自己的问题 |
请求 URL 一律 urllib.parse.quote(p, safe='/');探针报 EXC 先查探针本身 |
断言式替换里解包写成 for o, n, _ in PAIRS(PAIRS 是 (old,new,count)) |
n 其实是 new 字符串,计数永远不等 → 四条用例全部误报 FAIL |
解包必须 (old, new, cnt),变量名区分 new 与 cnt |
| 全局替换只出现在局部的句式(如 6 处里只有 3 处要改) | 会误伤不应降级的瞬时操作(删除类却被套 20s 超时) | 「上一行含特征串 → 向下 N 行窗口定位」,比全局替换安全,比行号可靠 |
| 删掉"看起来还有用"的锁/变量前不 grep | 删完才发现早已无引用(白担风险),或删到仍有引用(直接崩) | 删除前后各 grep 一次全量引用,确认零残留 |
录入型系统照抄浏览型 SPA 的「←/→ 切页」快捷键 |
录入页 ←/→ 是光标移动刚需,劫持后操作员在输入框里按左右键整页跳走,录入效率被毁 |
录入为主 ⇒ 不加;要加先判 document.activeElement 是否输入框,或改用 Ctrl/Alt+←→(N1) |
| emoji 计数已是 0 还在跑 H/K 的 emoji 清理 | 零 emoji 项目上空跑,收益为零,还漏掉真正该做的文案 / 排版 / 术语 | 先全扫统计 emoji 计数;为 0 直接跳过去 AI 味的四条替代杠杆(文案 / 排版密度 / 术语一致 / 配色)(N2) |
| 把「传了不用的参数」不当缺陷 | 参数名与后端消费字段对不上时,HTTP 200 照返空 / 串库数据,静默错误最难发现 | 一致性探针加「入参被消费」断言:改入参值结果必须变化;多余参数显式拒绝而非静默忽略(N3) |
| 想加校验就直接新写一个 | 与另一条路径的存量校验重复 / 打架 / 互相覆盖,还造出第二种错误形状 | 加校验前先 grep 存量写法,复用既有辅助函数与文案口径,补在最靠近数据源的一层(N4) |
关联
- 知识库条目:
05-技能库/技能|Web应用美学加固流程.md - 第一原则实证:
<项目根目录>\知识库工作台全流程改进落地报告V1.8.md;去 AI 味实证:<项目根目录>\知识库工作台去AI味改进报告V1.9.md
版本记录
| 版本 | 日期 | 变更 |
|---|---|---|
| v1.0.0 | 2026-09-28 | 首版实战固化(A/C/D/E/F/G);含 6 条反例避雷 |
| v1.1.0 | 2026-09-28 | 加步骤 H 去 AI 味(装饰 emoji 清零 / toast 先加配色再删 emoji / 汉字徽标身份化 / 文案说事实 / 光效收敛);质量门加内联 JS node --check;新增 3 条反例避雷(删 toast emoji 丢警示、只 py_compile 漏 JS 白屏、误删功能符号) |
| v1.3.0 | 2026-09-28 | 加步骤 K 装饰 emoji 收尾(按钮/标题去前缀 50+ 处、行首来源 emoji 交 tag、🥇🥈🥉→#N 并与同页统一样式、工厂函数去图标参数并删 .pico 死 CSS、资产 emoji 不当文案、开关改文字);新增全部 Unicode 全扫 + 期望次数断言式批量替换规范;新增 5 条反例避雷(urllib 被 HTTP_PROXY 劫持全 502、裸解释器起服务 ModuleNotFound、按行号多行替换漂移、空图标芯片参数、必填查询参数 422) |
| v1.4.0 | 2026-09-28 | 加步骤 L 缺陷探针三件套(差分探针:越权/穿越/异常入参/并发/错误契约/登出失效;一致性探针:接口↔磁盘逐篇差分 + 搜索自反查;先证伪再写报告;探针只打只读接口);新增 5 条反例避雷(/api/me 写死 login:true 泄露 default_pw、busy 检查非原子三方竞态、重任务占全局锁 30 分钟、探针按猜的字段名取值误报、Full Unicode 扫描按清单会漏) |
| v1.5.0 | 2026-09-28 | 加步骤 M 安全与健壮性收尾(/api/me 最小信息面、全局 StarletteHTTPException 归一为 {"ok":false,"error":"中文","auth":bool}、_claim 原子占位并删失效全局锁、超时收敛 + 前端 resToast 20s 降级、被跳过文件在索引里只登记路径以支撑「显示生成文件」开关);新增 4 条反例避雷(PAIRS 解包把 new 当 count、跨行调用点按内容+窗口定位、探针自身 URL 未编码会把自己的错报成产品缺陷、删东西前必须 grep 全量确认无引用) |
| v1.6.0 | 2026-09-28 | 加步骤 N 录入型系统四条硬边界(N1 方向键切页不适用于录入系统 / 要加须 activeElement 守卫或改 Ctrl/Alt+←→;N2 emoji 为零时去 AI 味改走文案 + 排版密度 + 术语一致 + 配色四条替代杠杆,且先统计计数再决定跳不跳 H/K;N3「请求参数与数据源不匹配」高危静默缺陷 + 「入参被消费」探针断言;N4 加校验前先 grep 存量写法、复用既有辅助函数与错误形状、补在最靠近数据源一层);E 项补录入型系统边界、H 项补「先统计 emoji 计数」前置;新增 4 条反例避雷(录入系统照抄 ←/→ 切页、零 emoji 还跑 emoji 清理、传了不用的参数不当缺陷、凭空新写校验) |
| v1.7.0 | 2026-09-28 | 加步骤 O 打包产物与守护进程一致性收尾(源码改动必重打包+隔离端口取证、判断是否需要打包看 Analysis 入口是否被 import 链追踪、--distpath 全新目录防 COLLECT 删一半;看门狗一次性标志 .kb_quit 的死局与三条失效兜底:服务存活即清除 / 早于本次开机 GetTickCount64 即失效 / 超 2h 保鲜期失效;端到端实测三铁律:单条命令跑完、只杀端口 PID 不批量杀 python、诊断用 -u);新增 4 条反例避雷(改完源码不重打包导致日常路径跑旧二进制、一次性标志无失效条件等于永久否决自愈、tasklist 写成 taskkill 返回空列表使结论失真、块缓冲导致被杀丢日志) |
| v1.8.0 | 2026-09-29 | 拆分重构:L/M/O/H-K 各自抽出为知识库独立篇(全要素缺陷探针法 / PyInstaller打包与取证SOP / 看门狗守护与自愈SOP / 本机服务回归测试与计时法 / AI味清零与文案事实化法 / 单文件应用并发与安全收尾SOP),本技能保留 A–O 完整总纲并加双链索引;补「生成文件可搜兜底」(正文 0 命中才按需读,命中带 gen:true)与 NSIS 缺 makensis 的外部阻塞标注 |