七月迭代短暂完结,还有很多后端的关键东西没有弄,这是一版赶时间做的东西
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m26s

This commit is contained in:
2026-07-25 17:06:58 +08:00
parent ad9f613dd6
commit 73f5125d3d
249 changed files with 17137 additions and 877 deletions

View File

@@ -55,3 +55,19 @@ func newDeviceImportAuditParams(
AfterData: afterData,
}
}
func newDeviceBatchAllocationAuditParams(taskID uint, taskNo string, req *dto.CreateDeviceBatchAllocationRequest, resultStatus string, err error) assetAuditSvc.BuildLogParams {
afterData := map[string]any{}
if req != nil {
afterData["file_key"] = req.FileKey
afterData["operation_type"] = req.OperationType
afterData["target_id"] = req.TargetID
}
errorCode, errorMsg := assetAuditSvc.BuildErrorInfo(err)
return assetAuditSvc.BuildLogParams{
AssetID: taskID, AssetIdentifier: taskNo,
OperationType: constants.AssetAuditOpDeviceBatchTaskCreate,
OperationDesc: "创建设备CSV批量分配任务", ResultStatus: resultStatus,
ErrorCode: errorCode, ErrorMsg: errorMsg, AfterData: afterData,
}
}

View File

@@ -3,6 +3,7 @@ package device_import
import (
"context"
"path/filepath"
"strings"
"time"
"github.com/break/junhong_cmp_fiber/internal/model"
@@ -55,6 +56,7 @@ func (s *Service) CreateImportTask(ctx context.Context, req *dto.ImportDeviceReq
task := &model.DeviceImportTask{
TaskNo: taskNo,
OperationType: constants.DeviceImportOperationCreate,
Status: model.ImportTaskStatusPending,
BatchNo: req.BatchNo,
FileName: fileName,
@@ -94,6 +96,58 @@ func (s *Service) CreateImportTask(ctx context.Context, req *dto.ImportDeviceReq
}, nil
}
// CreateBatchAllocationTask 复用设备导入任务创建单列 CSV 批量分配任务。
func (s *Service) CreateBatchAllocationTask(ctx context.Context, req *dto.CreateDeviceBatchAllocationRequest) (*dto.CreateDeviceBatchAllocationResponse, error) {
userID := middleware.GetUserIDFromContext(ctx)
userType := middleware.GetUserTypeFromContext(ctx)
if userID == 0 || (userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform && userType != constants.UserTypeAgent) {
appErr := errors.New(errors.CodeForbidden, "仅平台和代理后台账号可创建设备批量分配任务")
s.logDeviceImportAudit(ctx, newDeviceBatchAllocationAuditParams(0, "", req, constants.AssetAuditResultDenied, appErr))
return nil, appErr
}
if req == nil || !constants.IsDeviceImportOperation(req.OperationType) || req.OperationType == constants.DeviceImportOperationCreate || req.TargetID == 0 {
return nil, errors.New(errors.CodeInvalidParam, "设备批量分配参数不合法")
}
if !strings.HasPrefix(req.FileKey, constants.DeviceBatchAllocationStoragePrefix+"/") || !strings.EqualFold(filepath.Ext(req.FileKey), ".csv") {
return nil, errors.New(errors.CodeInvalidParam, "设备批量分配文件必须是指定目录下的CSV文件")
}
taskNo := s.importTaskStore.GenerateTaskNo(ctx)
var operatorShopID *uint
if userType == constants.UserTypeAgent {
shopID := middleware.GetShopIDFromContext(ctx)
if shopID == 0 {
return nil, errors.New(errors.CodeForbidden, "代理账号缺少店铺归属")
}
operatorShopID = &shopID
}
targetID := req.TargetID
task := &model.DeviceImportTask{
TaskNo: taskNo, OperationType: req.OperationType, TargetID: &targetID,
OperatorType: userType, OperatorShopID: operatorShopID,
Status: model.ImportTaskStatusPending, StorageKey: req.FileKey, FileName: filepath.Base(req.FileKey),
CreatorName: middleware.GetUsernameFromContext(ctx),
}
task.Creator, task.Updater = userID, userID
if err := s.importTaskStore.Create(ctx, task); err != nil {
appErr := errors.Wrap(errors.CodeDatabaseError, err, "创建设备批量分配任务失败")
s.logDeviceImportAudit(ctx, newDeviceBatchAllocationAuditParams(0, taskNo, req, constants.AssetAuditResultFailed, appErr))
return nil, appErr
}
if err := s.queueClient.EnqueueTask(ctx, constants.TaskTypeDeviceImport, DeviceImportPayload{TaskID: task.ID},
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeDeviceImport)),
asynq.Timeout(constants.DeviceBatchAllocationTaskTimeout)); err != nil {
_ = s.importTaskStore.UpdateStatus(ctx, task.ID, model.ImportTaskStatusFailed, "任务入队失败")
appErr := errors.Wrap(errors.CodeInternalError, err, "设备批量分配任务入队失败")
s.logDeviceImportAudit(ctx, newDeviceBatchAllocationAuditParams(task.ID, taskNo, req, constants.AssetAuditResultFailed, appErr))
return nil, appErr
}
s.logDeviceImportAudit(ctx, newDeviceBatchAllocationAuditParams(task.ID, taskNo, req, constants.AssetAuditResultSuccess, nil))
return &dto.CreateDeviceBatchAllocationResponse{
TaskID: task.ID, TaskNo: task.TaskNo, Message: "设备批量分配任务已创建Worker 将异步处理CSV文件",
}, nil
}
func (s *Service) List(ctx context.Context, req *dto.ListDeviceImportTaskRequest) (*dto.ListDeviceImportTaskResponse, error) {
page := req.Page
pageSize := req.PageSize
@@ -113,6 +167,9 @@ func (s *Service) List(ctx context.Context, req *dto.ListDeviceImportTaskRequest
if req.Status != nil {
filters["status"] = *req.Status
}
if req.OperationType != "" {
filters["operation_type"] = req.OperationType
}
if req.BatchNo != "" {
filters["batch_no"] = req.BatchNo
}
@@ -156,25 +213,19 @@ func (s *Service) GetByID(ctx context.Context, id uint) (*dto.DeviceImportTaskDe
for _, item := range task.SkippedItems {
resp.SkippedItems = append(resp.SkippedItems, &dto.DeviceImportResultItemDTO{
Line: item.Line,
VirtualNo: item.ICCID,
Reason: item.Reason,
Line: item.Line, VirtualNo: item.ICCID, DeviceIdentifier: item.ICCID, Reason: item.Reason,
})
}
for _, item := range task.FailedItems {
resp.FailedItems = append(resp.FailedItems, &dto.DeviceImportResultItemDTO{
Line: item.Line,
VirtualNo: item.ICCID,
Reason: item.Reason,
Line: item.Line, VirtualNo: item.ICCID, DeviceIdentifier: item.ICCID, Reason: item.Reason,
})
}
for _, item := range task.WarningItems {
resp.WarningItems = append(resp.WarningItems, &dto.DeviceImportResultItemDTO{
Line: item.Line,
VirtualNo: item.ICCID,
Reason: item.Reason,
Line: item.Line, VirtualNo: item.ICCID, DeviceIdentifier: item.ICCID, Reason: item.Reason,
})
}
@@ -193,7 +244,11 @@ func (s *Service) toTaskResponse(task *model.DeviceImportTask) *dto.DeviceImport
return &dto.DeviceImportTaskResponse{
ID: task.ID,
TaskNo: task.TaskNo,
OperationType: task.OperationType,
OperationName: constants.GetDeviceImportOperationName(task.OperationType),
TargetID: task.TargetID,
Status: task.Status,
StatusName: getStatusText(task.Status),
StatusText: getStatusText(task.Status),
BatchNo: task.BatchNo,
RealnamePolicy: task.RealnamePolicy,