# Tasks

本文档列出修复 IoT 模型架构违规所需的所有任务，按优先级和依赖关系排序。

## 阶段 1: 核心业务实体模型修复（必须优先完成）

### Task 1.1: 修复 IoT 卡模型 (IotCard)

**文件**: `internal/model/iot_card.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`CostPrice`、`DistributePrice`）从 `float64` 改为 `int64`，数据库类型从 `decimal(10,2)` 改为 `bigint`
- 表名从 `iot_cards` 改为 `tb_iot_card`
- `ICCID` 唯一索引添加 `where:deleted_at IS NULL`
- 所有关联 ID 字段（`CarrierID`、`OwnerID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过
- 使用 `gofmt` 格式化代码
- 与 `Account` 模型对比，确保风格一致

---

### Task 1.2: 修复设备模型 (Device)

**文件**: `internal/model/device.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `devices` 改为 `tb_device`
- `DeviceNo` 唯一索引添加 `where:deleted_at IS NULL`
- 所有关联 ID 字段（`OwnerID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过
- 使用 `gofmt` 格式化代码

---

### Task 1.3: 修复号卡模型 (NumberCard)

**文件**: `internal/model/number_card.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`Price`）从 `float64` 改为 `int64`，数据库类型从 `decimal(10,2)` 改为 `bigint`
- 表名从 `number_cards` 改为 `tb_number_card`
- `VirtualProductCode` 唯一索引添加 `where:deleted_at IS NULL`
- 关联 ID 字段（`AgentID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过
- 使用 `gofmt` 格式化代码

---

### Task 1.4: 修复运营商模型 (Carrier)

**文件**: `internal/model/carrier.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `carriers` 改为 `tb_carrier`
- `CarrierCode` 唯一索引添加 `where:deleted_at IS NULL`
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过
- 使用 `gofmt` 格式化代码

---

## 阶段 2: 套餐和订单模型修复

### Task 2.1: 修复套餐系列模型 (PackageSeries)

**文件**: `internal/model/package.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `package_series` 改为 `tb_package_series`
- `SeriesCode` 唯一索引添加 `where:deleted_at IS NULL`
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 2.2: 修复套餐模型 (Package)

**文件**: `internal/model/package.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`Price`）从 `float64` 改为 `int64`，数据库类型从 `decimal(10,2)` 改为 `bigint`
- 表名从 `packages` 改为 `tb_package`
- `PackageCode` 唯一索引添加 `where:deleted_at IS NULL`
- 关联 ID 字段（`SeriesID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 2.3: 修复代理套餐分配模型 (AgentPackageAllocation)

**文件**: `internal/model/package.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`CostPrice`、`RetailPrice`）从 `float64` 改为 `int64`
- 表名从 `agent_package_allocations` 改为 `tb_agent_package_allocation`
- 关联 ID 字段（`AgentID`、`PackageID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 2.4: 修复套餐使用情况模型 (PackageUsage)

**文件**: `internal/model/package.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `package_usages` 改为 `tb_package_usage`
- 关联 ID 字段（`OrderID`、`PackageID`、`IotCardID`、`DeviceID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 2.5: 修复设备-SIM 卡绑定模型 (DeviceSimBinding)

**文件**: `internal/model/package.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `device_sim_bindings` 改为 `tb_device_sim_binding`
- 添加复合索引：`DeviceID` 和 `SlotPosition` 使用 `index:idx_device_slot`
- 关联 ID 字段（`IotCardID`）添加独立 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 2.6: 修复订单模型 (Order)

**文件**: `internal/model/order.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`Amount`）从 `float64` 改为 `int64`
- `CarrierOrderData` 从 `pq.StringArray` 改为 `datatypes.JSON`，添加 `import "gorm.io/datatypes"`
- 表名从 `orders` 改为 `tb_order`
- `OrderNo` 唯一索引添加 `where:deleted_at IS NULL`
- 关联 ID 字段（`IotCardID`、`DeviceID`、`NumberCardID`、`PackageID`、`UserID`、`AgentID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过
- 检查 `datatypes.JSON` 导入是否正确

---

## 阶段 3: 分佣系统模型修复

### Task 3.1: 修复代理层级模型 (AgentHierarchy)

**文件**: `internal/model/commission.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `agent_hierarchies` 改为 `tb_agent_hierarchy`
- `AgentID` 唯一索引添加 `where:deleted_at IS NULL`
- 关联 ID 字段（`ParentAgentID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 3.2: 修复分佣规则模型 (CommissionRule)

**文件**: `internal/model/commission.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`CommissionValue`）从 `float64` 改为 `int64`
- 表名从 `commission_rules` 改为 `tb_commission_rule`
- 关联 ID 字段（`AgentID`、`SeriesID`、`PackageID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 3.3: 修复阶梯分佣配置模型 (CommissionLadder)

**文件**: `internal/model/commission.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`CommissionValue`）从 `float64` 改为 `int64`
- 表名从 `commission_ladder` 改为 `tb_commission_ladder`
- 关联 ID 字段（`RuleID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 3.4: 修复组合分佣条件模型 (CommissionCombinedCondition)

**文件**: `internal/model/commission.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`OneTimeCommissionValue`、`LongTermCommissionValue`）从 `float64` 改为 `int64`
- 表名从 `commission_combined_conditions` 改为 `tb_commission_combined_condition`
- `RuleID` 唯一索引添加 `where:deleted_at IS NULL`
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 3.5: 修复分佣记录模型 (CommissionRecord)

**文件**: `internal/model/commission.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`Amount`）从 `float64` 改为 `int64`
- 表名从 `commission_records` 改为 `tb_commission_record`
- 关联 ID 字段（`AgentID`、`OrderID`、`RuleID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 3.6: 修复分佣审批模型 (CommissionApproval)

**文件**: `internal/model/commission.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `commission_approvals` 改为 `tb_commission_approval`
- 关联 ID 字段（`CommissionRecordID`、`ApproverID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 3.7: 修复分佣模板模型 (CommissionTemplate)

**文件**: `internal/model/commission.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`CommissionValue`）从 `float64` 改为 `int64`
- 表名从 `commission_templates` 改为 `tb_commission_template`
- `TemplateName` 唯一索引添加 `where:deleted_at IS NULL`
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 3.8: 修复运营商结算模型 (CarrierSettlement)

**文件**: `internal/model/commission.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`SettlementAmount`）从 `float64` 改为 `int64`，数据库类型从 `decimal(18,2)` 改为 `bigint`
- 表名从 `carrier_settlements` 改为 `tb_carrier_settlement`
- `CommissionRecordID` 唯一索引添加 `where:deleted_at IS NULL`
- 关联 ID 字段（`AgentID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

## 阶段 4: 财务和系统模型修复

### Task 4.1: 修复佣金提现申请模型 (CommissionWithdrawalRequest)

**文件**: `internal/model/financial.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`Amount`、`Fee`、`ActualAmount`）从 `float64` 改为 `int64`，数据库类型从 `decimal(18,2)` 改为 `bigint`
- `AccountInfo` 从 `pq.StringArray` 改为 `datatypes.JSON`
- 表名从 `commission_withdrawal_requests` 改为 `tb_commission_withdrawal_request`
- 关联 ID 字段（`AgentID`、`ApprovedBy`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过
- 检查 `datatypes.JSON` 导入是否正确

---

### Task 4.2: 修复佣金提现设置模型 (CommissionWithdrawalSetting)

**文件**: `internal/model/financial.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 金额字段（`MinWithdrawalAmount`）从 `float64` 改为 `int64`，数据库类型从 `decimal(10,2)` 改为 `bigint`
- 表名从 `commission_withdrawal_settings` 改为 `tb_commission_withdrawal_setting`
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 4.3: 修复收款商户设置模型 (PaymentMerchantSetting)

**文件**: `internal/model/financial.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `payment_merchant_settings` 改为 `tb_payment_merchant_setting`
- 关联 ID 字段（`UserID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 4.4: 修复开发能力配置模型 (DevCapabilityConfig)

**文件**: `internal/model/system.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `dev_capability_configs` 改为 `tb_dev_capability_config`
- `AppID` 唯一索引添加 `where:deleted_at IS NULL`
- 关联 ID 字段（`UserID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 4.5: 修复换卡申请模型 (CardReplacementRequest)

**文件**: `internal/model/system.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `card_replacement_requests` 改为 `tb_card_replacement_request`
- 关联 ID 字段（`UserID`、`ApprovedBy`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 4.6: 修复轮询配置模型 (PollingConfig)

**文件**: `internal/model/polling.go`

**修改内容:**
- 嵌入 `gorm.Model` 和 `BaseModel`
- 移除手动定义的 `ID`、`CreatedAt`、`UpdatedAt` 字段
- 所有字段显式指定 `column` 标签
- 表名从 `polling_configs` 改为 `tb_polling_config`
- `ConfigName` 唯一索引添加 `where:deleted_at IS NULL`
- 关联 ID 字段（`CarrierID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过

---

### Task 4.7: 修复流量使用记录模型 (DataUsageRecord)

**文件**: `internal/model/data_usage.go`

**修改内容:**
- **不嵌入** `gorm.Model`（简化模型，只包含 ID 和 CreatedAt）
- **不嵌入** `BaseModel`（日志表不需要审计）
- 保留 `ID`、`CreatedAt` 字段，移除 `UpdatedAt`
- 所有字段显式指定 `column` 标签
- 表名从 `data_usage_records` 改为 `tb_data_usage_record`
- 关联 ID 字段（`IotCardID`）添加 `index` 标签
- 完善所有字段的中文注释

**验证方法:**
- 运行 `go build` 确保编译通过
- 确认模型不包含 `UpdatedAt` 和 `DeletedAt`

---

## 阶段 5: 验证和测试

### Task 5.1: 编译验证

**内容:**
- 运行 `go build ./...` 确保所有模型文件编译通过
- 运行 `gofmt -w internal/model/` 格式化所有模型文件
- 运行 `go vet ./internal/model/` 静态分析检查

**依赖**: 所有模型修复任务完成

**验证方法:**
- 无编译错误
- 无静态分析警告

---

### Task 5.2: 模型定义一致性检查

**内容:**
- 手动检查所有模型是否遵循规范（参考验证清单）
- 对比 `Account` 模型，确保风格一致
- 检查所有金额字段是否使用 `int64` 类型
- 检查所有表名是否使用 `tb_` 前缀 + 单数
- 检查所有唯一索引是否包含 `where:deleted_at IS NULL`

**依赖**: Task 5.1

**验证方法:**
- 完成验证清单（设计文档第 8 节）

---

### Task 5.3: 生成数据库迁移脚本（可选）

**内容:**
- 如果 IoT 模块尚未创建迁移脚本，跳过此任务
- 如果已有迁移脚本，生成新的迁移脚本或修改现有脚本
- 包含表重命名、字段修改、索引创建等 SQL 语句

**依赖**: Task 5.2

**验证方法:**
- 在开发环境测试迁移脚本
- 确认所有表和字段正确创建

---

### Task 5.4: 文档更新

**内容:**
- 更新 IoT SIM 管理提案（`openspec/changes/archive/2026-01-12-iot-sim-management/`）的模型定义部分（可选）
- 在 `docs/` 目录创建模型修复总结文档（可选）
- 更新 `README.md` 添加模型规范说明（可选）

**依赖**: Task 5.2

**验证方法:**
- 文档清晰易懂，准确反映当前实现

---

### Task 5.5: 更新全局规范文档

**内容:**
- 更新 `CLAUDE.md` 中的数据库设计原则和模型规范部分
- 确保 CLAUDE.md 中的示例代码与修复后的模型风格完全一致
- 如果需要，更新 `openspec/AGENTS.md`（如果其中包含模型相关指导）
- 添加或完善以下规范内容：
  - GORM 模型字段规范（显式 column 标签、类型定义、注释要求）
  - 金额字段使用整数类型（分为单位）的详细说明和示例
  - 表名命名规范（`tb_` 前缀 + 单数）
  - BaseModel 嵌入和审计字段使用说明
  - 唯一索引软删除兼容性（`where:deleted_at IS NULL`）
  - JSONB 字段使用 `datatypes.JSON` 类型的说明

**具体修改位置（CLAUDE.md）:**

1. **数据库设计原则** 部分：
   - 补充完整的 GORM 模型字段定义规范
   - 添加金额字段整数存储的要求和理由
   - 添加字段标签完整性要求（显式 column、type、comment）

2. **GORM 模型字段规范** 新增小节：
   ```markdown
   **GORM 模型字段规范:**
   - 数据库字段名必须使用下划线命名法（snake_case），如 `user_id`、`email_address`、`created_at`
   - Go 结构体字段名必须使用驼峰命名法（PascalCase），如 `UserID`、`EmailAddress`、`CreatedAt`
   - **所有字段必须显式指定数据库列名**：使用 `gorm:"column:字段名"` 标签明确指定数据库字段名，不依赖 GORM 的自动转换
     - 示例：`UserID uint gorm:"column:user_id;not null" json:"user_id"`
     - 禁止省略 `column:` 标签，即使 GORM 能自动推断字段名
     - 这确保了 Go 字段名和数据库字段名的映射关系清晰可见，避免命名歧义
   - 字符串字段长度必须明确定义且保持一致性：
     - 短文本（名称、标题等）：`VARCHAR(255)` 或 `VARCHAR(100)`
     - 中等文本（描述、备注等）：`VARCHAR(500)` 或 `VARCHAR(1000)`
     - 长文本（内容、详情等）：`TEXT` 类型
   - 货币金额字段必须使用 `int64` 类型，数据库类型为 `bigint`，单位为"分"（1元 = 100分）
   - 所有字段必须添加中文注释，说明字段用途和业务含义
   ```

3. **示例代码更新**：
   - 将现有的模型示例（如果有）更新为包含完整字段标签的版本

**依赖**: Task 5.2

**验证方法:**
- CLAUDE.md 中的规范描述与实际实现的模型完全一致
- 所有示例代码可以直接复制使用，无需修改
- 规范描述清晰、完整、无歧义
- 运行 `git diff CLAUDE.md` 检查修改内容

---

## 依赖关系图

```
阶段 1 (核心模型)
  ├─ Task 1.1: IotCard
  ├─ Task 1.2: Device
  ├─ Task 1.3: NumberCard
  └─ Task 1.4: Carrier
      ↓
阶段 2 (套餐和订单)
  ├─ Task 2.1: PackageSeries
  ├─ Task 2.2: Package (依赖 Task 2.1)
  ├─ Task 2.3: AgentPackageAllocation (依赖 Task 2.2)
  ├─ Task 2.4: PackageUsage (依赖 Task 2.2)
  ├─ Task 2.5: DeviceSimBinding (依赖 Task 1.1, Task 1.2)
  └─ Task 2.6: Order (依赖 Task 1.1, Task 1.2, Task 1.3, Task 2.2)
      ↓
阶段 3 (分佣系统)
  ├─ Task 3.1: AgentHierarchy
  ├─ Task 3.2: CommissionRule
  ├─ Task 3.3: CommissionLadder (依赖 Task 3.2)
  ├─ Task 3.4: CommissionCombinedCondition (依赖 Task 3.2)
  ├─ Task 3.5: CommissionRecord (依赖 Task 3.2)
  ├─ Task 3.6: CommissionApproval (依赖 Task 3.5)
  ├─ Task 3.7: CommissionTemplate
  └─ Task 3.8: CarrierSettlement (依赖 Task 3.5)
      ↓
阶段 4 (财务和系统)
  ├─ Task 4.1: CommissionWithdrawalRequest
  ├─ Task 4.2: CommissionWithdrawalSetting
  ├─ Task 4.3: PaymentMerchantSetting
  ├─ Task 4.4: DevCapabilityConfig
  ├─ Task 4.5: CardReplacementRequest
  ├─ Task 4.6: PollingConfig
  └─ Task 4.7: DataUsageRecord (依赖 Task 1.1)
      ↓
阶段 5 (验证和测试)
  ├─ Task 5.1: 编译验证
  ├─ Task 5.2: 一致性检查 (依赖 Task 5.1)
  ├─ Task 5.3: 生成迁移脚本 (依赖 Task 5.2, 可选)
  ├─ Task 5.4: 文档更新 (依赖 Task 5.2, 可选)
  └─ Task 5.5: 更新全局规范文档 (依赖 Task 5.2, 必需)
```

## 估算工作量

- **阶段 1**: 约 2-3 小时（4 个核心模型）
- **阶段 2**: 约 3-4 小时（6 个套餐和订单模型）
- **阶段 3**: 约 4-5 小时（8 个分佣系统模型）
- **阶段 4**: 约 3-4 小时（7 个财务和系统模型）
- **阶段 5**: 约 2-3 小时（验证、测试和全局规范文档更新）

**总计**: 约 14-19 小时（~2-3 个工作日）

## 注意事项

1. **并行执行**: 阶段内的任务可以并行执行（除非明确依赖）
2. **增量提交**: 建议每完成一个阶段提交一次 Git commit
3. **回归测试**: 修复完成后需要运行完整的单元测试套件（如有）
4. **代码审查**: 修复完成后需要进行 Code Review，确保符合项目规范
