# 重构方案：将 ID 类型转换逻辑迁移至 Controller 层

## 1. 目标

将所有通过 URL 路径传入的 `id`（`string` 类型），其到 `uint` 类型的转换和验证逻辑，从 Service（业务逻辑）层统一迁移至 Controller（控制器）层。

## 2. 动机

当前实现中，Controller 将从 URL 获取的 `string` 类型的 ID 直接传递给 Service 层，由 Service 层负责使用 `strconv.ParseUint` 进行类型转换。

这种模式存在以下问题：
- **职责不清**：Service 层被迫处理了本应属于输入验证和转换的逻辑，而这部分工作更贴近 Controller 的职责。
- **Service 不纯粹**：业务核心逻辑与原始输入（字符串）耦合，降低了 Service 的可复用性。理想情况下，Service 的接口应该只处理内部定义的、类型安全的数据。
- **延迟的错误处理**：对于一个无效的 ID（如 "abc"），请求会穿透到 Service 层才会失败，而这种格式错误在 Controller 层就应该被拦截。

通过本次重构，我们将实现：
- **职责分离**：Controller 负责处理 HTTP 请求的原始数据（验证、转换），Service 负责处理核心业务。
- **接口清晰**：Service 层的所有方法将只接受类型安全的 `uint` 作为 ID，使其意图更加明确。
- **快速失败**：无效的 ID 将在 Controller 层被立即拒绝，并返回 `400 Bad Request`，提高了系统的健壮性。

## 3. 详细实施步骤

### 第 1 步：修改 `device_service.go`

#### 3.1 修改 `DeviceService` 接口
所有接收 `id string` 参数的方法签名，全部修改为接收 `id uint`。

**受影响的方法列表：**
- `GetDevice(id string)` -> `GetDevice(id uint)`
- `UpdateDevice(id string, ...)` -> `UpdateDevice(id uint, ...)`
- `DeleteDevice(id string)` -> `DeleteDevice(id uint)`
- `ManualControl(id string, ...)` -> `ManualControl(id uint, ...)`
- `GetAreaController(id string)` -> `GetAreaController(id uint)`
- `UpdateAreaController(id string, ...)` -> `UpdateAreaController(id uint, ...)`
- `DeleteAreaController(id string)` -> `DeleteAreaController(id uint)`
- `GetDeviceTemplate(id string)` -> `GetDeviceTemplate(id uint)`
- `UpdateDeviceTemplate(id string, ...)` -> `UpdateDeviceTemplate(id uint, ...)`
- `DeleteDeviceTemplate(id string)` -> `DeleteDeviceTemplate(id uint)`

#### 3.2 修改 `deviceService` 实现
在 `deviceService` 的方法实现中，移除所有 `strconv.ParseUint` 的调用，直接使用传入的 `uint` 类型的 ID。

**示例 (`DeleteDeviceTemplate`):**

**修改前:**
```go
func (s *deviceService) DeleteDeviceTemplate(id string) error {
    idUint, err := strconv.ParseUint(id, 10, 64)
    if err != nil {
        return fmt.Errorf("无效的ID格式: %w", err)
    }
    dtID := uint(idUint)
    // ... 业务逻辑
}
```

**修改后:**
```go
func (s *deviceService) DeleteDeviceTemplate(id uint) error {
    // 直接使用 id
    // ... 业务逻辑
}
```

### 第 2 步：修改 `device_controller.go`

在所有调用受影响 Service 方法的 Controller 方法中，增加 ID 的转换和错误处理逻辑。

**示例 (`DeleteDeviceTemplate`):**

**修改前:**
```go
func (c *Controller) DeleteDeviceTemplate(ctx echo.Context) error {
    const actionType = "删除设备模板"
    dtID := ctx.Param("id") // dtID is a string

    if err := c.deviceService.DeleteDeviceTemplate(dtID); err != nil {
        // ... 错误处理
    }
    // ... 成功处理
}
```

**修改后:**
```go
func (c *Controller) DeleteDeviceTemplate(ctx echo.Context) error {
    const actionType = "删除设备模板"
    idStr := ctx.Param("id")

    // 在 Controller 层进行转换和验证
    idUint, err := strconv.ParseUint(idStr, 10, 64)
    if err != nil {
        c.logger.Warnf("%s: 无效的ID格式: %s", actionType, idStr)
        return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", actionType, "ID格式错误", idStr)
    }
    dtID := uint(idUint)

    // 调用 Service，传入 uint 类型的 ID
    if err := c.deviceService.DeleteDeviceTemplate(dtID); err != nil {
        // ... 错误处理 (保持不变)
    }

    // ... 成功处理
}
```
此模式将应用于所有受影响的 Controller 方法。
