diff --git a/.opencode/skills/code-refactoring/SKILL.md b/.opencode/skills/code-refactoring/SKILL.md new file mode 100644 index 0000000..0be8dce --- /dev/null +++ b/.opencode/skills/code-refactoring/SKILL.md @@ -0,0 +1,465 @@ +--- +name: code-refactoring +description: 代码重构技能 - 强调保持功能不变的前提下优化代码结构,充分理解需求和交互式确认 +tags: + - refactoring + - code-quality + - clean-code + - interactive +version: 1.0.0 +--- + +# 代码重构技能 + +## 技能概述 + +专门用于在**不改变现有功能逻辑**的前提下优化代码结构,包括: +- 抽取公共方法、组件和工具类 +- 消除重复代码(DRY原则) +- 移除无用代码(死代码、注释代码、未使用的依赖) +- 改善代码可读性和可维护性 +- 优化代码结构和命名规范 + +## ⚠️ 核心原则(MUST FOLLOW) + +### 1. 功能不变保证 +**禁止在重构过程中改变功能行为!** +- ✅ 重构前后的输入输出必须完全一致 +- ✅ 重构前后的副作用必须一致(数据库操作、文件IO、日志等) +- ✅ 重构不应改变性能特征(除非明确以性能优化为目标) +- ❌ 严禁"顺便"添加新功能或修复bug + +### 2. 充分理解需求 +**禁止根据模糊的需求开始重构!** +- ✅ 彻底理解重构的目标和范围 +- ✅ 识别需求中的模糊点和二义性 +- ✅ 使用 `question` 工具获取明确的用户意图 +- ❌ 不要基于假设进行重构 + +### 3. 先确认再动手 +**禁止未经用户确认就直接修改代码!** +- ✅ 先列出所有修改点和影响范围 +- ✅ 使用 `question` 工具让用户确认重构方案 +- ✅ 获得明确的同意后再执行修改 +- ❌ 不要边分析边修改 + +## ⚠️ 强制交互规则(MUST FOLLOW) + +**遇到需要用户确认的情况时,必须立即调用 `question` 工具:** + +❌ **禁止**:"我需要向用户确认..."、"建议向用户询问..."、"在执行前应该确认..." +✅ **必须**:直接调用 `question` 工具,不要描述或延迟 + +**调用格式**: +```javascript +question({ + header: "重构确认", + questions: [{ + question: "是否要将重复的验证逻辑抽取到公共方法中?", + options: ["是,抽取到工具类", "是,抽取到基类", "否,保持现状", "其他"] + }] +}) +``` + +**规则**: +- 每次最多 **3个问题** +- 每个问题 **3-6个选项**(穷举常见情况 + "其他"兜底) +- 用户通过**上下键导航**选择 +- 适用于**所有阶段**(需求理解、方案确认、风险评估) + +## 重构流程 + +### 阶段1: 需求理解(必须交互确认) + +#### 1.1 理解重构目标 +**获取用户意图**: +- 用户想重构什么?(文件、模块、类、方法) +- 重构的原因是什么?(代码重复、难以维护、命名不清晰、结构混乱) +- 期望达到什么效果?(提高复用性、提升可读性、简化逻辑、统一规范) + +**触发 `question` 工具的场景**: +- 用户只说"重构这个文件"但未说明具体问题 +- 用户提到"优化"但没有明确优化方向 +- 用户的需求包含多个可能的重构方向 +- 重构范围不明确(单个文件 vs 整个模块) + +**示例问题**: +```javascript +question({ + header: "明确重构目标", + questions: [ + { + question: "您主要关注哪方面的重构?", + options: [ + "抽取重复代码", + "改善命名和结构", + "移除无用代码", + "提取公共组件/方法", + "全面优化" + ] + }, + { + question: "重构范围是?", + options: [ + "仅当前文件", + "当前模块(相关的几个文件)", + "整个项目", + "让我分析后建议" + ] + } + ] +}) +``` + +#### 1.2 识别约束条件 +**必须明确的约束**: +- 是否有不能改动的接口或API(对外暴露的) +- 是否有特殊的性能要求 +- 是否需要保持特定的代码风格 +- 是否有测试覆盖(如有,重构后测试必须通过) + +**触发 `question` 工具的场景**: +- 发现公开API可能需要调整 +- 代码涉及性能敏感的操作 +- 存在多种重构方式,各有权衡 +- 不确定某些代码是否仍在使用 + +**示例问题**: +```javascript +question({ + header: "重构约束确认", + questions: [ + { + question: "发现 `ProcessData` 方法被多个外部模块调用,重构时:", + options: [ + "保持方法签名不变,仅优化内部实现", + "可以修改方法签名,我会同步更新调用方", + "先告诉我影响范围,我再决定", + "其他" + ] + } + ] +}) +``` + +#### 1.3 理解代码上下文 +**分析现有代码**: +- 使用 `semantic_search` 查找相关代码 +- 使用 `grep_search` 查找重复模式 +- 使用 `list_code_usages` 分析调用关系 +- 阅读相关文件理解业务逻辑 + +**注意事项**: +- 不要在分析阶段进行任何修改 +- 记录发现的问题点和重构机会 +- 识别可能的风险和边界情况 + +### 阶段2: 方案设计(必须交互确认) + +#### 2.1 列出重构点 +**详细列出每个修改点**: +- 修改的文件和位置 +- 修改的具体内容(前后对比) +- 修改的原因和收益 +- 可能的影响范围 + +**示例格式**: +``` +## 重构点清单 + +### 1. 抽取重复的数据验证逻辑 +**位置**: TransactionController.cs (L45-L60, L120-L135) +**操作**: 将重复的金额验证逻辑抽取到 ValidationHelper.ValidateAmount() +**原因**: 两处代码完全相同,违反DRY原则 +**影响**: 无,纯内部优化 + +### 2. 移除未使用的导入和变量 +**位置**: BudgetService.cs (L5, L23) +**操作**: 删除 `using System.Text.RegularExpressions;` 和未使用的 `_tempValue` 字段 +**原因**: 死代码,增加维护负担 +**影响**: 无 + +### 3. 重命名方法提高可读性 +**位置**: DataProcessor.cs (L89) +**操作**: `DoWork()` → `ProcessTransactionData()` +**原因**: 原名称不够清晰,无法表达具体功能 +**影响**: 4个调用点需要同步更新 +``` + +#### 2.2 评估风险和影响 +**必须分析的风险**: +- 是否影响公开API +- 是否影响性能 +- 是否影响测试 +- 是否涉及数据迁移 +- 是否存在隐藏的依赖关系 + +**触发 `question` 工具的场景**: +- 发现重构会影响多个模块 +- 存在潜在的兼容性问题 +- 有多种实现方式可选 +- 需要在代码质量和改动风险间权衡 + +**示例问题**: +```javascript +question({ + header: "重构方案确认", + questions: [ + { + question: "发现3处重复的日期格式化代码,建议:", + options: [ + "抽取到工具类(Common项目)", + "抽取到当前服务的私有方法", + "保留重复(代码简单,抽取收益小)", + "让我看看代码再决定" + ] + }, + { + question: "重构会影响4个controller和2个service,是否继续?", + options: [ + "是,一次性全部重构", + "否,先重构影响小的部分", + "告诉我每个的影响详情", + "其他" + ] + } + ] +}) +``` + +#### 2.3 提交方案供确认 +**必须向用户展示**: +1. 完整的重构点清单(如2.1格式) +2. 风险评估和影响分析 +3. 建议的执行顺序 +4. 预计改动的文件数量 + +**必须调用 `question` 工具获得最终确认**: +```javascript +question({ + header: "最终确认", + questions: [{ + question: "我已列出所有重构点和影响分析,是否开始执行?", + options: [ + "是,按计划执行", + "需要调整部分重构点", + "取消重构", + "其他问题" + ] + }] +}) +``` + +**重要**: +- ❌ 不要在得到明确的"是,按计划执行"之前修改任何代码 +- ❌ 不要假设用户会同意 +- ✅ 如用户选择"需要调整",返回阶段1重新理解需求 + +### 阶段3: 执行重构 + +#### 3.1 执行原则 +- **小步快跑**: 一次完成一个重构点,不要多个同时进行 +- **频繁验证**: 每完成一个点就运行测试或构建验证 +- **保持可逆**: 确保随时可以回滚 +- **记录进度**: 使用 `manage_todo_list` 跟踪进度 + +#### 3.2 执行步骤 +1. **创建TODO清单**: +```javascript +manage_todo_list({ + todoList: [ + { + id: 1, + title: "抽取重复验证逻辑到ValidationHelper", + description: "TransactionController.cs L45-L60, L120-L135", + status: "not-started" + }, + { + id: 2, + title: "移除BudgetService.cs中的未使用导入", + description: "删除using System.Text.RegularExpressions", + status: "not-started" + }, + // ... 更多任务 + ] +}) +``` + +2. **逐个执行**: + - 标记任务为 `in-progress` + - 使用 `multi_replace_string_in_file` 或 `replace_string_in_file` 修改代码 + - 运行测试验证: `dotnet test` 或 `pnpm test` + - 标记任务为 `completed` + - 继续下一个 + +3. **验证每个步骤**: + - 后端重构后运行: `dotnet build && dotnet test` + - 前端重构后运行: `pnpm lint && pnpm build` + - 确保没有引入编译错误或测试失败 + +#### 3.3 异常处理 +**如果遇到预期外的问题**: +- ✅ 立即停止后续重构 +- ✅ 报告问题详情 +- ✅ 调用 `question` 工具询问如何处理 + +```javascript +question({ + header: "重构遇到问题", + questions: [{ + question: "抽取方法后发现测试 `TestValidation` 失败了,如何处理?", + options: [ + "回滚这个改动", + "修复测试用例", + "暂停,我来看看", + "继续其他重构点" + ] + }] +}) +``` + +### 阶段4: 验证和总结 + +#### 4.1 全面验证 +**必须执行的验证**: +- 所有单元测试通过 +- 项目成功构建 +- Lint检查通过 +- 关键功能手动验证(如适用) + +**验证命令**: +```bash +# 后端 +dotnet clean +dotnet build EmailBill.sln +dotnet test WebApi.Test/WebApi.Test.csproj + +# 前端 +cd Web +pnpm lint +pnpm build +``` + +#### 4.2 总结报告 +**提供清晰的总结**: +``` +## 重构完成总结 + +### ✅ 已完成的重构 +1. 抽取重复验证逻辑 (ValidationHelper.cs) + - 消除了 3 处重复代码 + - 减少代码行数 45 行 + +2. 移除未使用的导入和变量 + - BudgetService.cs: 移除 2 个未使用的 using + - TransactionController.cs: 移除 1 个未使用字段 + +3. 改善方法命名 + - DoWork → ProcessTransactionData (4 处调用点已更新) + - Calculate → CalculateMonthlyBudget (2 处调用点已更新) + +### 📊 重构影响 +- 修改文件数: 6 +- 新增文件数: 1 (ValidationHelper.cs) +- 删除代码行数: 78 +- 新增代码行数: 42 +- 净减少代码: 36 行 + +### ✅ 验证结果 +- ✓ 所有测试通过 (23/23) +- ✓ 项目构建成功 +- ✓ Lint检查通过 +- ✓ 功能验证正常 + +### 📝 建议的后续工作 +- 考虑为 ValidationHelper 添加单元测试 +- 可以进一步重构 DataProcessor 类的其他方法 +``` + +## 常见重构模式 + +### 1. 抽取公共方法 +**识别标准**: 代码块在多处重复出现(≥2次) +**操作**: +- 创建独立方法或工具类 +- 保持方法签名简洁明确 +- 添加必要的注释和文档 + +### 2. 抽取公共组件 +**识别标准**: UI组件或业务逻辑在多个视图/页面重复 +**操作**: +- 创建可复用组件(Vue组件、Service类等) +- 使用Props/参数传递可变部分 +- 确保组件职责单一 + +### 3. 移除死代码 +**识别标准**: +- 未被调用的方法 +- 未被使用的变量、导入、依赖 +- 注释掉的代码 +**操作**: +- 使用 `list_code_usages` 确认真正未使用 +- 谨慎删除(可能有隐式调用) +- 使用Git历史作为备份 + +### 4. 改善命名 +**识别标准**: +- 名称不能表达意图(如 `DoWork`, `Process`, `temp`) +- 名称与实际功能不符 +- 违反命名规范 +**操作**: +- 使用 `list_code_usages` 找到所有使用点 +- 使用 `multi_replace_string_in_file` 批量更新 +- 确保命名符合项目规范(见AGENTS.md) + +### 5. 简化复杂逻辑 +**识别标准**: +- 深层嵌套(>3层) +- 过长方法(>50行) +- 复杂条件判断 +**操作**: +- 早返回模式(guard clauses) +- 拆分子方法 +- 使用策略模式或查表法 + +## 注意事项 + +### ❌ 不要做 +- 在重构中添加新功能 +- 在重构中修复bug(除非bug是重构导致的) +- 未经确认就大范围修改 +- 改变公开API而不考虑兼容性 +- 跳过测试验证 + +### ✅ 要做 +- 保持每次重构的范围可控 +- 频繁提交代码(每完成一个重构点提交一次) +- 确保测试覆盖率不降低 +- 保持代码风格一致 +- 记录重构的原因和收益 + +## 项目特定规范 + +### C# 代码重构 +- 遵循 `AGENTS.md` 中的 C# 代码风格 +- 使用 file-scoped namespace +- 公共方法使用 XML 注释 +- 业务逻辑使用中文注释 +- 工具方法考虑放入 `Common` 项目 + +### Vue/TypeScript 代码重构 +- 使用 Composition API +- 组件放入 `src/components` +- 遵循 ESLint 和 Prettier 规则 +- 使用 `@/` 别名避免相对路径 +- 提取的组件使用 Vant UI 风格 + +## 总结 + +代码重构是一个**谨慎的、迭代的、需要充分确认的**过程。核心要点: + +1. **理解先于行动** - 彻底理解需求和约束 +2. **交互式确认** - 使用 `question` 工具消除歧义 +3. **计划后执行** - 列出修改点并获得确认 +4. **小步快跑** - 逐个完成重构点,频繁验证 +5. **功能不变** - 始终确保行为一致性 diff --git a/Web/index.html b/Web/index.html index 9af539e..d7f5761 100644 --- a/Web/index.html +++ b/Web/index.html @@ -10,7 +10,7 @@ - + diff --git a/Web/src/App.vue b/Web/src/App.vue index 4298590..ef13d92 100644 --- a/Web/src/App.vue +++ b/Web/src/App.vue @@ -240,6 +240,7 @@ const handleAddTransactionSuccess = () => { padding-top: max(0px, calc(env(safe-area-inset-top, 0px) * 0.75)); box-sizing: border-box; overflow: hidden; + background: transparent; } /* TabBar 固定在底部 */ diff --git a/Web/src/views/calendarV2/Index.vue b/Web/src/views/calendarV2/Index.vue index 1694db5..96f3855 100644 --- a/Web/src/views/calendarV2/Index.vue +++ b/Web/src/views/calendarV2/Index.vue @@ -334,7 +334,6 @@ onBeforeUnmount(() => { /* ========== 页面容器 ========== */ .calendar-v2-wrapper { - background-color: var(--bg-primary); font-family: var(--font-primary); color: var(--text-primary); } @@ -344,6 +343,7 @@ onBeforeUnmount(() => { overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; + background-color: var(--van-background); } /* ========== 头部 ========== */