# 方案:删除设备前的使用校验 ## 1. 目标 在删除设备前,检查该设备是否被任何任务关联。如果设备正在被使用,则禁止删除,并向用户返回明确的错误提示。 ## 2. 核心思路 我们将遵循您项目清晰的分层架构,将“检查设备是否被任务使用”这一业务规则放在 **应用层** (`internal/app/service/`) 中进行协调。当上层请求删除设备时,应用服务会先调用仓库层查询 `device_tasks` 关联表,如果发现设备仍被任务关联,则会拒绝删除并返回一个明确的业务错误。 ## 3. 实施步骤 ### 3.1. 仓库层 (`DeviceRepository`) - **动作**: 在 `internal/infra/repository/device_repository.go` 的 `DeviceRepository` 接口中,增加一个新方法 `IsDeviceInUse(deviceID uint) (bool, error)`。 - **实现**: 在 `gormDeviceRepository` 中实现此方法。该方法将通过对 `models.DeviceTask` 模型执行 `Count` 操作来高效地判断是否存在 `device_id` 匹配的记录。这比查询完整记录性能更好。 ### 3.2. 应用层 (`DeviceService`) - **动作**: 1. 在 `internal/app/service/device_service.go` 文件顶部定义一个新的错误变量 `ErrDeviceInUse`,例如 `var ErrDeviceInUse = errors.New("设备正在被一个或多个任务使用,无法删除")`。 2. 修改该文件中的 `DeleteDevice` 方法。 - **实现**: 在 `DeleteDevice` 方法中,在调用 `s.deviceRepo.Delete()` 之前,先调用我们刚刚创建的 `s.deviceRepo.IsDeviceInUse()` 方法。如果返回 `true`,则立即返回 `ErrDeviceInUse` 错误,中断删除流程。 ### 3.3. 表现层 (`DeviceController`) - **动作**: 修改 `internal/app/controller/device/device_controller.go` 中的 `DeleteDevice` 方法。 - **实现**: 在错误处理逻辑中,增加一个 `case` 来专门捕获从服务层返回的 `service.ErrDeviceInUse` 错误。当捕获到此错误时,返回一个带有明确提示信息(如“设备正在被任务使用,无法删除”)和合适 HTTP 状态码(例如 `409 Conflict`)的错误响应。 ## 4. 方案优势 - **职责清晰**: 业务流程的编排和校验逻辑被正确地放置在应用层,符合您项目清晰的分层架构。 - **高效查询**: 通过 `COUNT` 查询代替 `Find`,避免了不必要的数据加载,性能更佳。 - **代码内聚**: 与设备相关的数据库操作都统一封装在 `DeviceRepository` 中。 - **用户友好**: 通过在控制器层处理特定业务错误,可以给前端返回明确、可操作的错误信息。