diff --git a/README.md b/README.md index 7b6853a..de69277 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A personal collection of [Agent Skills](https://docs.claude.com/en/docs/claude-c | Skill | What it does | | --- | --- | | [github-star-recall](./skills/github-star-recall) | Rediscover and prune forgotten GitHub stars, one at a time. | -| [j10c-frontend-playbook](./skills/j10c-frontend-playbook) | My personal React + TypeScript rules for AI agents writing code on my behalf. | +|| [j10c-frontend-playbook](./skills/j10c-frontend-playbook) | My personal React + TypeScript rules for AI agents writing code on my behalf. Includes fix-patterns/ — empirical weakness patterns from Taro/Vue projects with self-check lists and fix templates. | | [soco-cli](./skills/soco-cli) | Sonos automation — alarms, sleep timers, scripted scenes. | ## Install diff --git a/skills/j10c-frontend-playbook/fix-patterns/INDEX.md b/skills/j10c-frontend-playbook/fix-patterns/INDEX.md new file mode 100644 index 0000000..cc178ef --- /dev/null +++ b/skills/j10c-frontend-playbook/fix-patterns/INDEX.md @@ -0,0 +1,18 @@ +# Fix Patterns Index + +基于 WeJH-Taro 全仓库 321 条 fix commit 分析提炼的前端薄弱模式库。 +每个模式含定义、触发条件、真实 commit 引证、自检清单和修复模板。 + +持续监控:每日 23:00 Hermes cron job 自动扫描 j10ccc 新合入的 PR, +命中既有薄弱模式时自动追加具体例子到对应文件。 + +| 模式 | 文件 | Commit 数 | 占比 | 一句话定义 | +|------|------|-----------|------|-----------| +| UI/样式架构缺陷 | [weak-ui-style.md](weak-ui-style.md) | 101 | 31.5% | CSS 隔离缺失、z-index 冲突、深色模式未同步 | +| 业务逻辑盲区 | [weak-logic-bug.md](weak-logic-bug.md) | 89 | 27.7% | 边界输入未处理、浮点精度丢失、key 重复 | +| 类型守卫与空指针 | [weak-type-null.md](weak-type-null.md) | 34 | 10.6% | 类型定义不当、null/undefined 未守卫、不当断言 | + +--- + +*数据来源:zjutjh/WeJH-Taro 全仓库 fix commit 审计(2023-08 至 2026-05)* +*持续追加:Hermes cron job `daily-pr-fix-pattern-review`(ID: e10817b586fb)* diff --git a/skills/j10c-frontend-playbook/fix-patterns/weak-logic-bug.md b/skills/j10c-frontend-playbook/fix-patterns/weak-logic-bug.md new file mode 100644 index 0000000..4c4048b --- /dev/null +++ b/skills/j10c-frontend-playbook/fix-patterns/weak-logic-bug.md @@ -0,0 +1,46 @@ +# 业务逻辑盲区 + +> 边界输入未处理、浮点精度丢失、key 重复、数据流不完整等业务逻辑遗漏 + +## 触发条件 + +- 新功能涉及数值计算(特别是浮点运算) +- 使用 `v-for`/`map` 渲染列表但 key 生成逻辑可能重复 +- API 返回值可能为空数组/null/undefined +- 功能模块涉及状态切换或多步骤流程 +- 日期/时间格式化与展示 + +## 真实 Commit 引证 + +| # | Commit | 说明 | +|---|--------|------| +| 1 | [9cc0789](https://github.com/zjutjh/WeJH-Taro/commit/9cc07895a8d32c8c439592ab753e23bd22860508) | fix(score): 修复浮点数加法导致绩点值出错 | +| 2 | [6bd1134](https://github.com/zjutjh/WeJH-Taro/commit/6bd113411cce523f32dd1dae5dc99ddcf7ce3f15) | fix(lessonTable): 某天上下午有同一节课, v-for中key会一样导致问题 | +| 3 | [646af91](https://github.com/zjutjh/WeJH-Taro/commit/646af9196aff81a25f83da2149b243e56e25f25a) | fix: 消费记录保留两位小数 | + +本项目共 89 条业务逻辑 Bug + 数据展示 fix commit(占 27.7%),为第二大修复类别。 + +## 自检清单 + +- [ ] 浮点运算是否使用 `toFixed()` 或整数化后计算? +- [ ] `v-for`/`map` 的 key 是否保证唯一(日期+节次+课程ID 等组合 key)? +- [ ] API 返回空值/null/undefined 是否有兜底展示(非空白区域)? +- [ ] 边界输入(零值/空数组/极值)是否逐一测试? +- [ ] 多步骤流程是否有"上一步未完成就进入下一步"的防护? + +## 修复模板 + +```typescript +// 1. 浮点精度 +const gpa = +(totalPoints / totalCredits).toFixed(2); + +// 2. 唯一 key 生成 +const lessonKey = `${day}-${period}-${course.id}`; + +// 3. 空值兜底 +const displayName = data?.name ?? '暂无数据'; + +// 4. 边界守卫 +const items = Array.isArray(data) ? data : []; +const first = items[0] ?? defaultItem; +``` diff --git a/skills/j10c-frontend-playbook/fix-patterns/weak-type-null.md b/skills/j10c-frontend-playbook/fix-patterns/weak-type-null.md new file mode 100644 index 0000000..708f17a --- /dev/null +++ b/skills/j10c-frontend-playbook/fix-patterns/weak-type-null.md @@ -0,0 +1,53 @@ +# 类型守卫与空指针 + +> TypeScript 类型定义不当、null/undefined 未守卫、不当类型断言导致的运行时错误 + +## 触发条件 + +- 访问 API 返回值的嵌套属性 +- 从 Store/Vuex/Pinia 获取状态 +- 使用 `as` 类型断言或 `!` 非空断言 +- 数组索引访问(`arr[0]`)未判断长度 +- 对 `Record` 的值做属性访问 +- 重构/重命名后修改类型定义 + +## 真实 Commit 引证 + +| # | Commit | 说明 | +|---|--------|------| +| 1 | [27a32d4](https://github.com/zjutjh/WeJH-Taro/commit/27a32d4d2baad7fe08850502a9966949cf5c7991) | fix: term-picker default value fits the type defination | +| 2 | [c6ec966](https://github.com/zjutjh/WeJH-Taro/commit/c6ec9665f00f6cc46bfbdc6620ce46b61eeef9e1) | fix(bus): placeholder 取值越界 | +| 3 | [2caeff1](https://github.com/zjutjh/WeJH-Taro/commit/2caeff15c8790a5169c088a524517a057d1d03e5) | fix: 可能的空指针问题,以及预处理 parseFloat | + +本项目共 34 条类型错误 + 空指针 + 边界 fix commit(占 10.6%),是代码质量的系统性薄弱点。 + +## 自检清单 + +- [ ] 所有 API 返回值是否标注了可能为 `undefined` 的字段? +- [ ] 是否存在 `as X` 或 `!` 非空断言在业务逻辑中?(应替换为类型守卫) +- [ ] 数组索引访问前是否检查了 `.length`? +- [ ] `Record` 的值访问是否用了可选链 `?.`? +- [ ] 重构(重命名/移动/拆分)后是否运行了 `pnpm typecheck`? + +## 修复模板 + +```typescript +// 1. 用类型守卫替代 as 断言 +function isUser(val: unknown): val is User { + return typeof val === 'object' && val !== null && 'id' in val; +} + +// 2. 可选链 + 空值合并 +const name = user?.profile?.name ?? '未知用户'; + +// 3. 数组安全访问 +const first = arr.length > 0 ? arr[0] : undefined; + +// 4. 收紧类型定义(而非放宽) +interface ApiResp { + data: UserInfo | null; // 明确 null 可能 +} + +// 5. 重构后必须 typecheck +// pnpm typecheck +``` diff --git a/skills/j10c-frontend-playbook/fix-patterns/weak-ui-style.md b/skills/j10c-frontend-playbook/fix-patterns/weak-ui-style.md new file mode 100644 index 0000000..e81d817 --- /dev/null +++ b/skills/j10c-frontend-playbook/fix-patterns/weak-ui-style.md @@ -0,0 +1,53 @@ +# UI/样式架构缺陷 + +> CSS 隔离缺失、z-index 冲突、深色模式未同步、样式穿透等视觉层面反复修复的问题 + +## 触发条件 + +- 新增页面/组件涉及深色模式适配 +- 使用了全局 CSS 或未采用 CSS Modules 隔离 +- 设置了硬编码 z-index 值 +- 修改主题色/主题系统相关代码 +- Taro 组件样式穿透(`styleIsolation` 配置) + +## 真实 Commit 引证 + +| # | Commit | 说明 | +|---|--------|------| +| 1 | [9da5cb8](https://github.com/zjutjh/WeJH-Taro/commit/9da5cb81719ea2e589662ddf0bb16b2935184e2b) | fix(lessonstable): 统一了深色,亮色模式,统一了css modules | +| 2 | [2d375bb](https://github.com/zjutjh/WeJH-Taro/commit/2d375bb9d03fea5caecd08f02c110ae55c56a1a9) | fix(lessonstable): 修复了边框毛玻璃层高显示与课表和时间线冲突的问题 | +| 3 | [27cbe9d](https://github.com/zjutjh/WeJH-Taro/commit/27cbe9d2d0f9729112d07a6364a418a3981dc7a4) | fix(nav-bar): style isolation | + +本项目共 101 条 UI/样式 fix commit(占 31.5%),为最高频修复类别。 + +## 自检清单 + +- [ ] 新组件是否使用 CSS Modules(`*.module.scss`)隔离样式? +- [ ] 深色模式下所有颜色是否已同步定义(CSS 变量或 `@media (prefers-color-scheme: dark)`)? +- [ ] z-index 是否遵循项目约定层级,而非随意赋值? +- [ ] Taro 组件是否配置了 `styleIsolation: 'apply-shared'` 或 `'isolated'`? +- [ ] 主题色变更是否覆盖了所有使用该色的组件? + +## 修复模板 + +```scss +// 1. 使用 CSS Modules 隔离 +// index.module.scss +.container { /* scoped styles */ } + +// 2. CSS 变量适配深色模式 +.card { + background: var(--wjh-color-bg-card); +} + +@media (prefers-color-scheme: dark) { + :root { + --wjh-color-bg-card: #1a1a1a; + } +} + +// 3. z-index 约定 +// < 100: 内容层级 +// 100-200: 弹层/浮层 +// 200+: 模态/全局 +```