# 设备与任务多对多关联模型设计

## 需求背景

用户需要为系统中的“设备”和“任务”增加多对多关联，即一个设备可以执行多个任务，一个任务可以被多个设备执行。

## 现有模型分析

### `internal/infra/models/device.go`

`Device` 模型定义：

```go
type Device struct {
	gorm.Model
	Name             string `gorm:"not null" json:"name"`
	DeviceTemplateID uint   `gorm:"not null;index" json:"device_template_id"`
	DeviceTemplate   DeviceTemplate `json:"device_template"`
	AreaControllerID uint   `gorm:"not null;index" json:"area_controller_id"`
	AreaController   AreaController `json:"area_controller"`
	Location         string `gorm:"index" json:"location"`
	Properties       datatypes.JSON `json:"properties"`
}
```

### `internal/infra/models/plan.go`

`Task` 模型定义：

```go
type Task struct {
	ID        int `gorm:"primarykey"`
	CreatedAt time.Time
	UpdatedAt time.Time
	DeletedAt gorm.DeletedAt `gorm:"index"`

	PlanID         uint           `gorm:"not null;index" json:"plan_id"`
	Name           string         `gorm:"not null" json:"name"`
	Description    string         `json:"description"`
	ExecutionOrder int            `gorm:"not null" json:"execution_order"`
	Type           TaskType       `gorm:"not null" json:"type"`
	Parameters     datatypes.JSON `json:"parameters"`
}
```

## 方案设计

为了实现设备和任务的多对多关系，我们将引入一个中间关联模型 `DeviceTask`。考虑到 `Task` 模型定义在 `plan.go` 中，为了保持相关模型的内聚性，我们将 `DeviceTask` 模型也定义在 `internal/infra/models/plan.go` 文件中。

### 1. 在 `internal/infra/models/plan.go` 中新增 `DeviceTask` 关联模型

`DeviceTask` 模型将包含 `DeviceID` 和 `TaskID` 作为外键，以及 GORM 的标准模型字段。

```go
// DeviceTask 是设备和任务之间的关联模型，表示一个设备可以执行多个任务，一个任务可以被多个设备执行。
type DeviceTask struct {
	gorm.Model
	DeviceID uint `gorm:"not null;index"` // 设备ID
	TaskID   uint `gorm:"not null;index"` // 任务ID

	// 可选：如果需要存储关联的额外信息，可以在这里添加字段，例如：
	// Configuration datatypes.JSON `json:"configuration"` // 任务在特定设备上的配置
}

// TableName 自定义 GORM 使用的数据库表名
func (DeviceTask) TableName() string {
	return "device_tasks"
}
```

### 2. 修改 `internal/infra/models/device.go`

在 `Device` 结构体中添加 `Tasks` 字段，通过 `gorm:"many2many:device_tasks;"` 标签声明与 `Task` 的多对多关系，并指定中间表名为 `device_tasks`。

```go
// Device 代表系统中的所有普通设备
type Device struct {
	gorm.Model

	// ... 其他现有字段 ...

	// Tasks 是与此设备关联的任务列表，通过 DeviceTask 关联表实现多对多关系
	Tasks []Task `gorm:"many2many:device_tasks;" json:"tasks"`
}
```

### 3. 修改 `internal/infra/models/plan.go`

在 `Task` 结构体中添加 `Devices` 字段，通过 `gorm:"many2many:device_tasks;"` 标签声明与 `Device` 的多对多关系，并指定中间表名为 `device_tasks`。

```go
// Task 代表计划中的一个任务，具有执行顺序
type Task struct {
	// ... 其他现有字段 ...

	// Devices 是与此任务关联的设备列表，通过 DeviceTask 关联表实现多对多关系
	Devices []Device `gorm:"many2many:device_tasks;" json:"devices"`
}
```

## 总结

通过上述修改，我们将在数据库中创建一个名为 `device_tasks` 的中间表，用于存储 `Device` 和 `Task` 之间的关联关系。在 Go 代码层面，`Device` 和 `Task` 模型将能够直接通过 `Tasks` 和 `Devices` 字段进行多对多关系的查询和操作。
