临时备份一次

This commit is contained in:
2026-07-13 12:01:18 +09:00
parent 5cdcdad534
commit 2e130b98f5
17 changed files with 3938 additions and 0 deletions

View File

@@ -0,0 +1,154 @@
# 需求08设备批量分配代理和套餐系列Excel导入
---
## 背景
设备号不连续,无法通过号段批量分配。需要通过上传 Excel 表(表头:设备号)来批量指定分配目标。
`Device` 表已有 `shop_id *uint``series_id *uint` 字段,分配即更新这两个字段。
---
## 数据库变更
新建批量分配任务表(不复用 `DeviceImportTask`,业务语义不同):
```sql
CREATE TABLE tb_device_batch_allocation_task (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ,
creator BIGINT NOT NULL DEFAULT 0,
updater BIGINT NOT NULL DEFAULT 0,
task_no VARCHAR(30) NOT NULL,
shop_id BIGINT NOT NULL,
series_id BIGINT,
operator_id BIGINT NOT NULL,
total_count INT NOT NULL DEFAULT 0,
success_count INT NOT NULL DEFAULT 0,
fail_count INT NOT NULL DEFAULT 0,
status INT NOT NULL DEFAULT 1,
failed_items JSONB,
started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ
);
CREATE UNIQUE INDEX idx_device_batch_allocation_task_no ON tb_device_batch_allocation_task(task_no) WHERE deleted_at IS NULL;
```
状态常量1=处理中2=已完成3=失败。
失败明细存 JSONB`failed_items`),失败条数有限,无需单独明细表。
---
## Model`internal/model/device_batch_allocation_task.go`
```go
// DeviceBatchAllocationTask 设备批量分配任务模型
type DeviceBatchAllocationTask struct {
gorm.Model
BaseModel `gorm:"embedded"`
TaskNo string `gorm:"column:task_no;type:varchar(30);uniqueIndex:idx_device_batch_allocation_task_no,where:deleted_at IS NULL;not null" json:"task_no"`
ShopID uint `gorm:"column:shop_id;not null;comment:分配目标代理店铺ID" json:"shop_id"`
SeriesID *uint `gorm:"column:series_id;comment:套餐系列ID可选" json:"series_id,omitempty"`
OperatorID uint `gorm:"column:operator_id;not null;comment:操作人ID" json:"operator_id"`
TotalCount int `gorm:"column:total_count;default:0;comment:总记录数" json:"total_count"`
SuccessCount int `gorm:"column:success_count;default:0;comment:成功数" json:"success_count"`
FailCount int `gorm:"column:fail_count;default:0;comment:失败数" json:"fail_count"`
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 1=处理中 2=已完成 3=失败" json:"status"`
FailedItems ImportResultItems `gorm:"column:failed_items;type:jsonb;comment:失败记录详情" json:"failed_items"`
StartedAt *time.Time `gorm:"column:started_at" json:"started_at"`
CompletedAt *time.Time `gorm:"column:completed_at" json:"completed_at"`
}
func (DeviceBatchAllocationTask) TableName() string {
return "tb_device_batch_allocation_task"
}
```
> `ImportResultItems` 复用 `internal/model/device_import_task.go` 中已定义的类型。
---
## API 设计
### 1. 下载 Excel 模板
```
GET /admin/devices/batch-allocation/template
```
响应Excel 文件,表头为"设备号"(一列)。
### 2. 上传并提交
```
POST /admin/devices/batch-allocation
Content-Type: multipart/form-data
字段:
shop_id: 123 (必填,分配给哪个代理)
series_id: 45 (可选,同时分配套餐系列)
file: <Excel文件>
```
**处理逻辑Asynq 异步)**
1. 解析 Excel读取"设备号"列
2. 逐行查找 `tb_device` 中匹配的设备(按 `virtual_no``imei`
3. 对找到的设备:更新 `shop_id` + `series_id`
4. 未找到的:记录失败原因"设备号不存在"
5. 已分配给其他代理的:记录"该设备已分配,请先回收"
### 3. 查询任务状态
```
GET /admin/devices/batch-allocation/{task_id}
```
响应:
```json
{
"task_no": "DBA20240101001",
"status": 2,
"status_name": "已完成",
"total_count": 100,
"success_count": 95,
"fail_count": 5,
"failed_items": [
{ "line": 3, "virtual_no": "12345", "reason": "设备号不存在" },
{ "line": 7, "virtual_no": "67890", "reason": "该设备已分配,请先回收" }
],
"started_at": "2024-01-01T10:00:00Z",
"completed_at": "2024-01-01T10:00:05Z"
}
```
---
## 前端对接
### 入口
设备管理页 > 批量操作 > "批量分配代理"
### 操作流程
1. 点击"批量分配代理"
2. 弹框内:
- 代理选择器(搜索+选择目标代理,必填)
- 套餐系列选择器(可选)
- Excel 上传区域(含模板下载链接)
3. 上传后点击"提交" → `POST /admin/devices/batch-allocation`
4. 提示"任务提交成功,正在处理..."
5. 轮询 `GET /admin/devices/batch-allocation/{task_id}` 直到 `status != 1`
6. 展示结果成功X条失败X条失败明细在页面展示
### Excel 规范
- 表头:`设备号`
- 每行一个设备号支持虚拟号或IMEI