package dao import ( "fmt" "micro-bundle/internal/model" "micro-bundle/pkg/app" commonErr "micro-bundle/pkg/err" "micro-bundle/pkg/msg" "time" "github.com/google/uuid" "gorm.io/gorm" ) // ===== 聚合和扣减的辅助函数 ===== // aggregatePendingVideo 汇总所有视频分类的待发数量 func aggregatePendingVideo(t *model.TaskManagement) int { return t.PendingBundleLimitVideoExpiredCount + t.PendingBundleLimitVideoCount + t.PendingIncreaseLimitVideoExpiredCount + t.PendingIncreaseLimitVideoCount + t.PendingBundleVideoCount + t.PendingIncreaseVideoCount } // aggregatePendingImage 汇总所有图文分类的待发数量 func aggregatePendingImage(t *model.TaskManagement) int { return t.PendingBundleLimitImageExpiredCount + t.PendingBundleLimitImageCount + t.PendingIncreaseLimitImageExpiredCount + t.PendingIncreaseLimitImageCount + t.PendingBundleImageCount + t.PendingIncreaseImageCount } // aggregatePendingData 汇总所有数据分析分类的待发数量 func aggregatePendingData(t *model.TaskManagement) int { return t.PendingBundleLimitDataAnalysisExpiredCount + t.PendingBundleLimitDataAnalysisCount + t.PendingIncreaseLimitDataAnalysisExpiredCount + t.PendingIncreaseLimitDataAnalysisCount + t.PendingBundleDataAnalysisCount + t.PendingIncreaseDataAnalysisCount } // deductCount 按顺序从各个桶中扣减数量,剩余未扣减数量应为0(正常情况) func deductCount(count *int, buckets ...*int) { if count == nil { return } for _, b := range buckets { if *count <= 0 { break } if b == nil || *b <= 0 { continue } if *b >= *count { *b = *b - *count *count = 0 } else { *count = *count - *b *b = 0 } } } // deductVideo 视频扣减优先级:受限 > 非受限;同类型中:打包 > 增量;受限类型中:过期优先 func deductVideo(t *model.TaskManagement, n int) { c := n deductCount(&c, &t.PendingBundleLimitVideoExpiredCount, &t.PendingBundleLimitVideoCount, &t.PendingIncreaseLimitVideoExpiredCount, &t.PendingIncreaseLimitVideoCount, &t.PendingBundleVideoCount, &t.PendingIncreaseVideoCount, ) } // deductImage 图文扣减优先级:受限 > 非受限;同类型中:打包 > 增量;受限类型中:过期优先 func deductImage(t *model.TaskManagement, n int) { c := n deductCount(&c, &t.PendingBundleLimitImageExpiredCount, &t.PendingBundleLimitImageCount, &t.PendingIncreaseLimitImageExpiredCount, &t.PendingIncreaseLimitImageCount, &t.PendingBundleImageCount, &t.PendingIncreaseImageCount, ) } // deductData 数据分析扣减优先级:受限 > 非受限;同类型中:打包 > 增量;受限类型中:过期优先 func deductData(t *model.TaskManagement, n int) { c := n deductCount(&c, &t.PendingBundleLimitDataAnalysisExpiredCount, &t.PendingBundleLimitDataAnalysisCount, &t.PendingIncreaseLimitDataAnalysisExpiredCount, &t.PendingIncreaseLimitDataAnalysisCount, &t.PendingBundleDataAnalysisCount, &t.PendingIncreaseDataAnalysisCount, ) } // TaskQueryRequest 查询待指派任务记录请求参数 type TaskQueryRequest struct { Keyword string `json:"keyword"` // 艺人姓名、编号、手机号搜索关键词 Page int `json:"page"` // 页码 PageSize int `json:"pageSize"` // 每页数量 SortBy string `json:"sortBy"` // 排序字段 SortType string `json:"sortType"` // 排序类型 asc/desc } // TaskAssignRequest 指派任务请求参数 type TaskAssignRequest struct { SubNum string `json:"subNum"` // 艺人编号 TelNum string `json:"telNum"` // 艺人手机号 ArtistName string `json:"artistName"` // 艺人姓名 TaskAssignee string `json:"taskAssignee"` // 任务指派人 TaskAssigneeNum string `json:"taskAssigneeNum"` // 任务指派人账号 Operator string `json:"operator"` // 操作人 OperatorNum string `json:"operatorNum"` // 操作人账号 AssignVideoCount int `json:"assignVideoCount"` // 指派视频数 AssignPostCount int `json:"assignPostCount"` // 指派图文数 AssignDataCount int `json:"assignDataCount"` // 指派数据数 } // UpdatePendingCountRequest 修改待发数量请求参数 type UpdatePendingCountRequest struct { SubNum string `json:"subNum"` // 艺人编号 TelNum string `json:"telNum"` // 艺人手机号 ArtistName string `json:"artistName"` // 艺人姓名 PendingVideoCount int `json:"pendingVideoCount"` // 待发视频数量 PendingPostCount int `json:"pendingPostCount"` // 待发图文数量 PendingDataCount int `json:"pendingDataCount"` // 待发数据数量 Operator string `json:"operator"` // 操作人 OperatorNum string `json:"operatorNum"` // 操作人账号 } // EmployeeTaskQueryRequest 员工任务查询请求参数 type EmployeeTaskQueryRequest struct { TaskAssigneeNum string `json:"taskAssigneeNum"` // 被指派人账号 Keyword string `json:"keyword"` // 艺人姓名、编号、手机号搜索关键词 Operator string `json:"operator"` // 操作人 SortBy string `json:"sortBy"` // 排序字段 StartTime string `json:"startTime"` // 指派开始时间 EndTime string `json:"endTime"` // 指派结束时间 StartCompleteTime string `json:"startCompleteTime"` // 开始完成时间 EndCompleteTime string `json:"endCompleteTime"` // 结束完成时间 Status int `json:"status"` // 反馈完成状态 Page int `json:"page"` // 页码 PageSize int `json:"pageSize"` // 每页数量 } // CompleteTaskRequest 完成任务请求参数 type CompleteTaskRequest struct { AssignRecordsUUID string `json:"assignRecordsUUID,omitempty"` // 指派记录UUID(可选) EmployeeName string `json:"employeeName"` // 员工姓名(必要) EmployeeNum string `json:"employeeNum"` // 员工工号(必要) TaskType string `json:"taskType"` // 任务类型: video/post/data CompleteCount int `json:"completeCount"` // 完成数量 } // TaskAssignRecordsQueryRequest 多条件查询操作记录表请求参数 type TaskAssignRecordsQueryRequest struct { Keyword string `json:"keyword"` // 艺人姓名、编号、手机号搜索关键词 TaskAssignee string `json:"taskAssignee"` // 指派人姓名 Operator string `json:"operator"` // 操作人姓名 OperatorNum string `json:"operatorNum"` // 操作人手机号 StartTime string `json:"startTime"` // 操作开始时间 EndTime string `json:"endTime"` // 操作结束时间 Status int `json:"status"` // 反馈完成状态 0:全部 1:未完成 2:完成 ActualStatus int `json:"actualStatus"` // 实际完成状态 0:全部 1:未完成 2:完成 Page int `json:"page"` // 页码 PageSize int `json:"pageSize"` // 每页数量 } // 待指派任务 response type TaskQueryResponse struct { SubNum string `json:"subNum"` TelNum string `json:"telNum"` ArtistName string `json:"artistName"` PendingVideoCount int `gorm:"column:pending_video_count;comment:待发视频数量" json:"pendingVideoCount"` PendingPostCount int `gorm:"column:pending_post_count;comment:待发图文数量" json:"pendingPostCount"` PendingDataCount int `gorm:"column:pending_data_count;comment:待发数据数量" json:"pendingDataCount"` ProgressTaskCount int `gorm:"column:progress_task_count;comment:进行中的任务数量" json:"progressTaskCount"` CompleteTaskCount int `gorm:"column:complete_task_count;comment:已完成任务数量" json:"completeTaskCount"` LastTaskAssignee string `gorm:"column:last_task_assignee;comment:最后一次的任务指派人" json:"lastTaskAssignee"` TaskAssigneeNum string `gorm:"column:task_assignee_num;comment:最后一次指派人账号" json:"taskAssigneeNum"` } // 任务记录表返回结构体 type TaskAssignRecordsResponse struct { AssignRecordsUUID string `gorm:"column:assign_records_uuid;comment:指派记录UUID" json:"assignRecordsUUID"` SubNum string `gorm:"column:sub_num;comment:艺人编号" json:"subNum"` TelNum string `gorm:"column:tel_num;comment:艺人手机号" json:"telNum"` ArtistName string `gorm:"column:artist_name;comment:艺人名称" json:"artistName"` Status int `gorm:"column:status;comment:反馈完成状态 1:未完成 2:完成" json:"status"` ActualStatus int `gorm:"column:actual_status;comment:实际完成状态 1:未完成 2:完成" json:"actualStatus"` CompleteTime *time.Time `gorm:"column:complete_time;comment:反馈完成时间" json:"completeTime"` OperatorType int `gorm:"column:operator_type;comment:操作类型 1:修改待发数量 2:指派" json:"operatorType"` Operator string `gorm:"column:operator;comment:操作人" json:"operator"` OperatorNum string `gorm:"column:operator_num;comment:操作人账号" json:"operatorNum"` OperatorTime time.Time `gorm:"column:operator_time;comment:操作时间" json:"operatorTime"` TaskAssignee string `gorm:"column:task_assignee;comment:任务指派人" json:"taskAssignee"` TaskAssigneeNum string `gorm:"column:task_assignee_num;comment:任务指派人账号" json:"taskAssigneeNum"` PendingVideoCount int `gorm:"column:pending_video_count;comment:待发视频数量" json:"pendingVideoCount"` PendingPostCount int `gorm:"column:pending_post_count;comment:待发图文数量" json:"pendingPostCount"` PendingDataCount int `gorm:"column:pending_data_count;comment:待发数据数量" json:"pendingDataCount"` UpdatedAt time.Time `gorm:"column:updated_at;comment:更新时间" json:"updatedAt"` } // 任务指派记录数量结构体 type TaskAssignRecords struct { TaskAssigneeNum string `json:"taskAssigneeNum"` // 任务指派人工号 ProgressTaskCount int `json:"progressTaskCount"` // 进行中任务数量 CompleteTaskCount int `json:"completeTaskCount"` // 已完成任务数量 } // ValidArtistInfo 有效艺人信息结构体 type ValidArtistInfo struct { UserID int `json:"userId"` // 用户ID CustomerNum string `json:"customerNum"` // 艺人编号 UserName string `json:"userName"` // 艺人姓名 UserPhoneNumber string `json:"userPhoneNumber"` // 艺人手机号 BundleName string `json:"bundleName"` // 套餐名称 ExpirationTime string `json:"expirationTime"` // 过期时间 Status int `json:"status"` // 套餐状态 OrderUUID string `json:"orderUUID"` // 订单UUID AccountNumber int `json:"accountNumber"` // 账号数量 AccountConsumptionNumber int `json:"accountConsumptionNumber"` // 账号消耗数量 VideoNumber int `json:"videoNumber"` // 视频数量 VideoConsumptionNumber int `json:"videoConsumptionNumber"` // 视频消耗数量 ImageNumber int `json:"imageNumber"` // 图片数量 ImageConsumptionNumber int `json:"imageConsumptionNumber"` // 图片消耗数量 DataAnalysisNumber int `json:"dataAnalysisNumber"` // 数据分析数量 DataAnalysisConsumptionNumber int `json:"dataAnalysisConsumptionNumber"` // 数据分析消耗数量 ExpansionPacksNumber int `json:"expansionPacksNumber"` // 扩展套餐数量 } // ArtistBundleBalanceRequest 查询艺人套餐剩余数量请求参数 type ArtistBundleBalanceRequest struct { CustomerNum string `json:"customerNum"` // 艺人编号(推荐使用) TelNum string `json:"telNum"` // 艺人手机号(备选) } // ArtistBundleBalanceResponse 艺人套餐剩余数量响应结构体 type ArtistBundleBalanceResponse struct { RemainingVideoCount int `json:"remainingVideoCount"` // 剩余视频数量 (video_number - video_consumption_number) RemainingImageCount int `json:"remainingImageCount"` // 剩余图片数量 (image_number - image_consumption_number) RemainingDataAnalysisCount int `json:"remainingDataAnalysisCount"` // 剩余数据分析数量 (data_analysis_number - data_analysis_consumption_number) } // PendingAndBalanceRequest 查询待发与任务余额请求参数 // 优先使用艺人编号查询,如果为空则使用手机号查询 type PendingAndBalanceRequest struct { SubNum string `json:"subNum"` // 艺人编号(推荐使用) TelNum string `json:"telNum"` // 艺人手机号(备选) } // PendingAndBalanceResponse 查询待发与任务余额响应结构 // 待发数量为细分待发字段求和;余额为对应总数减已使用数后再按类别(套餐/增值)聚合 type PendingAndBalanceResponse struct { // 待发(按类别聚合) PendingBundleVideoCount int `json:"pendingBundleVideoCount"` // 待发套餐视频数量(非限制+限制非过期+限制会过期) PendingBundleImageCount int `json:"pendingBundleImageCount"` // 待发套餐图文数量(非限制+限制非过期+限制会过期) PendingBundleDataAnalysisCount int `json:"pendingBundleDataAnalysisCount"` // 待发套餐数据分析数量(非限制+限制非过期+限制会过期) PendingIncreaseVideoCount int `json:"pendingIncreaseVideoCount"` // 待发增值视频数量(非限制+限制非过期+限制会过期) PendingIncreaseImageCount int `json:"pendingIncreaseImageCount"` // 待发增值图文数量(非限制+限制非过期+限制会过期) PendingIncreaseDataAnalysisCount int `json:"pendingIncreaseDataAnalysisCount"` // 待发增值数据分析数量(非限制+限制非过期+限制会过期) // 任务余额(套餐/增值按类别聚合) BundleVideoBalance int `json:"bundleVideoBalance"` // 套餐视频余额 BundleImageBalance int `json:"bundleImageBalance"` // 套餐图文余额 BundleDataAnalysisBalance int `json:"bundleDataAnalysisBalance"` // 套餐数据分析余额 IncreaseVideoBalance int `json:"increaseVideoBalance"` // 增值视频余额 IncreaseImageBalance int `json:"increaseImageBalance"` // 增值图文余额 IncreaseDataAnalysisBalance int `json:"increaseDataAnalysisBalance"` // 增值数据分析余额 } // calculateBundleBalances 计算套餐类别下的三类余额(视频/图文/数据分析) // 余额=对应类别总数-对应类别已使用数;再将非限制、限制非过期、限制会过期三类相加 func calculateBundleBalances(tb *model.TaskBalance) (video int, image int, data int) { // 视频套餐余额 video = (tb.TaskBundleVideoNumber - tb.TaskBundleVideoConsumptionNumber) + (tb.TaskBundleLimitVideoNumber - tb.TaskBundleLimitVideoConsumptionNumber) + (tb.TaskBundleLimitVideoExpiredNumber - tb.TaskBundleLimitVideoExpiredConsumptionNumber) // 图文套餐余额 image = (tb.TaskBundleImageNumber - tb.TaskBundleImageConsumptionNumber) + (tb.TaskBundleLimitImageNumber - tb.TaskBundleLimitImageConsumptionNumber) + (tb.TaskBundleLimitImageExpiredNumber - tb.TaskBundleLimitImageExpiredConsumptionNumber) // 数据分析套餐余额 data = (tb.TaskBundleDataAnalysisNumber - tb.TaskBundleDataAnalysisConsumptionNumber) + (tb.TaskBundleLimitDataAnalysisNumber - tb.TaskBundleLimitDataAnalysisConsumptionNumber) + (tb.TaskBundleLimitDataAnalysisExpiredNumber - tb.TaskBundleLimitDataAnalysisExpiredConsumptionNumber) return } // calculateIncreaseBalances 计算增值类别下的三类余额(视频/图文/数据分析) // 余额=对应类别总数-对应类别已使用数;再将非限制、限制非过期、限制会过期三类相加 func calculateIncreaseBalances(tb *model.TaskBalance) (video int, image int, data int) { // 视频增值余额 video = (tb.TaskIncreaseVideoNumber - tb.TaskIncreaseVideoConsumptionNumber) + (tb.TaskIncreaseLimitVideoNumber - tb.TaskIncreaseLimitVideoConsumptionNumber) + (tb.TaskIncreaseLimitVideoExpiredNumber - tb.TaskIncreaseLimitVideoExpiredConsumptionNumber) // 图文增值余额 image = (tb.TaskIncreaseImageNumber - tb.TaskIncreaseImageConsumptionNumber) + (tb.TaskIncreaseLimitImageNumber - tb.TaskIncreaseLimitImageConsumptionNumber) + (tb.TaskIncreaseLimitImageExpiredNumber - tb.TaskIncreaseLimitImageExpiredConsumptionNumber) // 数据分析增值余额 data = (tb.TaskIncreaseDataAnalysisNumber - tb.TaskIncreaseDataAnalysisConsumptionNumber) + (tb.TaskIncreaseLimitDataAnalysisNumber - tb.TaskIncreaseLimitDataAnalysisConsumptionNumber) + (tb.TaskIncreaseLimitDataAnalysisExpiredNumber - tb.TaskIncreaseLimitDataAnalysisExpiredConsumptionNumber) return } // GetUserPendingAndTaskBalances 查询用户待发套餐/增值数量与任务余额(套餐/增值) // 待发数量来自 task_management,余额来自 task_balance;均按视频/图文/数据分析三类返回 // 待发聚合口径:将该类别下(套餐或增值)的非限制、限制非过期、限制会过期三类相加 // 余额聚合口径:对应类别总数减已使用数后,再将三类相加 func GetUserPendingAndTaskBalances(req *PendingAndBalanceRequest) (*PendingAndBalanceResponse, error) { // 校验查询条件 if req.SubNum == "" && req.TelNum == "" { return nil, commonErr.ReturnError(nil, "查询参数错误", "艺人编号和手机号不能同时为空") } // 查询任务管理表(待发) var tm model.TaskManagement tmQuery := app.ModuleClients.TaskBenchDB.Model(&model.TaskManagement{}) if req.SubNum != "" { tmQuery = tmQuery.Where("sub_num = ?", req.SubNum) } else { tmQuery = tmQuery.Where("tel_num = ?", req.TelNum) } // 若不存在,待发视为 0 _ = tmQuery.Take(&tm).Error // 聚合待发(套餐与增值分开统计) pendingBundleVideo := tm.PendingBundleVideoCount + tm.PendingBundleLimitVideoCount + tm.PendingBundleLimitVideoExpiredCount pendingBundleImage := tm.PendingBundleImageCount + tm.PendingBundleLimitImageCount + tm.PendingBundleLimitImageExpiredCount pendingBundleData := tm.PendingBundleDataAnalysisCount + tm.PendingBundleLimitDataAnalysisCount + tm.PendingBundleLimitDataAnalysisExpiredCount pendingIncreaseVideo := tm.PendingIncreaseVideoCount + tm.PendingIncreaseLimitVideoCount + tm.PendingIncreaseLimitVideoExpiredCount pendingIncreaseImage := tm.PendingIncreaseImageCount + tm.PendingIncreaseLimitImageCount + tm.PendingIncreaseLimitImageExpiredCount pendingIncreaseData := tm.PendingIncreaseDataAnalysisCount + tm.PendingIncreaseLimitDataAnalysisCount + tm.PendingIncreaseLimitDataAnalysisExpiredCount // 查询任务余额表(当前有效月份优先) var tb model.TaskBalance now := time.Now() tbQuery := app.ModuleClients.TaskBenchDB.Model(&model.TaskBalance{}) if req.SubNum != "" { tbQuery = tbQuery.Where("sub_num = ?", req.SubNum) } else { tbQuery = tbQuery.Where("tel_num = ?", req.TelNum) } // 选择当前有效区间的记录,若无则回退到最近一条 err := tbQuery.Where("start_at <= ? AND expired_at >= ?", now, now).Order("start_at DESC").Take(&tb).Error if err != nil { // 回退:取最近一条记录(可能没有有效期覆盖 now) _ = tbQuery.Order("start_at DESC").Take(&tb).Error } // 计算套餐与增值余额 bundleVideo, bundleImage, bundleData := calculateBundleBalances(&tb) increaseVideo, increaseImage, increaseData := calculateIncreaseBalances(&tb) resp := &PendingAndBalanceResponse{ PendingBundleVideoCount: pendingBundleVideo, PendingBundleImageCount: pendingBundleImage, PendingBundleDataAnalysisCount: pendingBundleData, PendingIncreaseVideoCount: pendingIncreaseVideo, PendingIncreaseImageCount: pendingIncreaseImage, PendingIncreaseDataAnalysisCount: pendingIncreaseData, BundleVideoBalance: bundleVideo, BundleImageBalance: bundleImage, BundleDataAnalysisBalance: bundleData, IncreaseVideoBalance: increaseVideo, IncreaseImageBalance: increaseImage, IncreaseDataAnalysisBalance: increaseData, } return resp, nil } // GetPendingTaskList 查询待指派任务记录 // 根据套餐没有过期的艺人查询TaskManagement表中的记录,如果不存在则构建默认值 func GetPendingTaskList(req *TaskQueryRequest, validArtist []ValidArtistInfo) ([]*model.TaskManagement, int64, error) { // 构建有效艺人ID列表 var validArtistIDs []string for _, artist := range validArtist { if artist.CustomerNum != "" { validArtistIDs = append(validArtistIDs, artist.CustomerNum) } } // 如果没有有效艺人,直接返回空结果 if len(validArtistIDs) == 0 { return []*model.TaskManagement{}, 0, nil } // 第一步:查询所有有效艺人在数据库中的存在情况(不应用关键词过滤) var existingTasks []*model.TaskManagement existQuery := app.ModuleClients.TaskBenchDB.Model(&model.TaskManagement{}).Where("sub_num IN (?)", validArtistIDs) err := existQuery.Find(&existingTasks).Error if err != nil { return nil, 0, commonErr.ReturnError(err, msg.ErrorGetBundleList, "查询现有任务记录失败: ") } // 创建已存在艺人编号的映射 existingSubNums := make(map[string]bool) for _, task := range existingTasks { existingSubNums[task.SubNum] = true } // 创建艺人编号到艺人信息的映射,便于快速查找 artistMap := make(map[string]ValidArtistInfo) for _, artist := range validArtist { artistMap[artist.CustomerNum] = artist } // 为不存在的艺人创建默认记录 var newTasksToCreate []*model.TaskManagement for _, subNum := range validArtistIDs { if !existingSubNums[subNum] { artist := artistMap[subNum] // 构建默认任务记录 // 默认将剩余数量分配到“非限制-套餐权益”类别,其它类别置零 remainingVideo := artist.VideoNumber - artist.VideoConsumptionNumber remainingImage := artist.ImageNumber - artist.ImageConsumptionNumber remainingData := artist.DataAnalysisNumber - artist.DataAnalysisConsumptionNumber if remainingVideo < 0 { remainingVideo = 0 } if remainingImage < 0 { remainingImage = 0 } if remainingData < 0 { remainingData = 0 } defaultTask := &model.TaskManagement{ SubNum: subNum, TelNum: artist.UserPhoneNumber, ArtistName: artist.UserName, // 视频 PendingBundleVideoCount: remainingVideo, PendingIncreaseVideoCount: 0, PendingBundleLimitVideoCount: 0, PendingIncreaseLimitVideoCount: 0, PendingBundleLimitVideoExpiredCount: 0, PendingIncreaseLimitVideoExpiredCount: 0, // 图片 PendingBundleImageCount: remainingImage, PendingIncreaseImageCount: 0, PendingBundleLimitImageCount: 0, PendingIncreaseLimitImageCount: 0, PendingBundleLimitImageExpiredCount: 0, PendingIncreaseLimitImageExpiredCount: 0, // 数据分析 PendingBundleDataAnalysisCount: remainingData, PendingIncreaseDataAnalysisCount: 0, PendingBundleLimitDataAnalysisCount: 0, PendingIncreaseLimitDataAnalysisCount: 0, PendingBundleLimitDataAnalysisExpiredCount: 0, PendingIncreaseLimitDataAnalysisExpiredCount: 0, ProgressCount: 0, CompleteCount: 0, CreatedAt: time.Now(), UpdatedAt: time.Now(), } newTasksToCreate = append(newTasksToCreate, defaultTask) } } // 批量创建新的任务记录 if len(newTasksToCreate) > 0 { if err := app.ModuleClients.TaskBenchDB.Create(&newTasksToCreate).Error; err != nil { return nil, 0, commonErr.ReturnError(err, msg.ErrorGetBundleList, "创建默认任务记录失败: ") } } // 第二步:应用完整的查询条件进行最终查询 var tasks []*model.TaskManagement var total int64 // 构建最终查询条件 query := app.ModuleClients.TaskBenchDB.Model(&model.TaskManagement{}) // 限制在有效艺人范围内 query = query.Where("sub_num IN (?)", validArtistIDs) // 关键词搜索(艺人姓名、编号、手机号) if req.Keyword != "" { query = query.Where("sub_num LIKE ? OR tel_num LIKE ? OR artist_name LIKE ?", "%"+req.Keyword+"%", "%"+req.Keyword+"%", "%"+req.Keyword+"%") } // 计算总数 query.Count(&total) // 排序 if req.SortBy != "" && req.SortType != "" { sortBy := req.SortBy sortType := req.SortType if sortType != "asc" && sortType != "desc" && sortType != "ASC" && sortType != "DESC" { sortType = "DESC" } // 将常用聚合字段映射为详细字段总和表达式 switch sortBy { case "pending_video_count", "pendingVideoCount": sortBy = "(pending_bundle_limit_video_expired_count + pending_bundle_limit_video_count + pending_increase_limit_video_expired_count + pending_increase_limit_video_count + pending_bundle_video_count + pending_increase_video_count)" case "pending_post_count", "pendingPostCount": sortBy = "(pending_bundle_limit_image_expired_count + pending_bundle_limit_image_count + pending_increase_limit_image_expired_count + pending_increase_limit_image_count + pending_bundle_image_count + pending_increase_image_count)" case "pending_data_count", "pendingDataCount": sortBy = "(pending_bundle_limit_data_analysis_expired_count + pending_bundle_limit_data_analysis_count + pending_increase_limit_data_analysis_expired_count + pending_increase_limit_data_analysis_count + pending_bundle_data_analysis_count + pending_increase_data_analysis_count)" } orderClause := fmt.Sprintf("%s %s", sortBy, sortType) query = query.Order(orderClause) } else { // 默认按待发视频总和降序 query = query.Order("(pending_bundle_limit_video_expired_count + pending_bundle_limit_video_count + pending_increase_limit_video_expired_count + pending_increase_limit_video_count + pending_bundle_video_count + pending_increase_video_count) DESC") } // 分页 if req.PageSize > 0 && req.Page > 0 { offset := (req.Page - 1) * req.PageSize query = query.Limit(req.PageSize).Offset(offset) } err = query.Find(&tasks).Error if err != nil { return nil, 0, commonErr.ReturnError(err, msg.ErrorGetBundleList, "查询待指派任务记录失败: ") } return tasks, total, nil } // AssignTask 指派某位员工完成某个艺人的任务 func AssignTask(req *TaskAssignRequest, progressTaskCount int, completeTaskCount int) error { // 开启事务 tx := app.ModuleClients.TaskBenchDB.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() // 1. 查询当前艺人的任务记录 var taskManagement model.TaskManagement err := tx.Where("sub_num = ? AND tel_num = ?", req.SubNum, req.TelNum).First(&taskManagement).Error if err != nil { if err == gorm.ErrRecordNotFound { // 如果不存在,创建新记录 taskManagement = model.TaskManagement{ SubNum: req.SubNum, TelNum: req.TelNum, ArtistName: req.ArtistName, // 待发视频 PendingBundleVideoCount: 0, PendingIncreaseVideoCount: 0, PendingBundleLimitVideoCount: 0, PendingIncreaseLimitVideoCount: 0, PendingBundleLimitVideoExpiredCount: 0, PendingIncreaseLimitVideoExpiredCount: 0, // 待发图片 PendingBundleImageCount: 0, PendingIncreaseImageCount: 0, PendingBundleLimitImageCount: 0, PendingIncreaseLimitImageCount: 0, PendingBundleLimitImageExpiredCount: 0, PendingIncreaseLimitImageExpiredCount: 0, // 待发数据分析 PendingBundleDataAnalysisCount: 0, PendingIncreaseDataAnalysisCount: 0, PendingBundleLimitDataAnalysisCount: 0, PendingIncreaseLimitDataAnalysisCount: 0, PendingBundleLimitDataAnalysisExpiredCount: 0, PendingIncreaseLimitDataAnalysisExpiredCount: 0, // 其他字段 ProgressCount: 0, CompleteCount: 0, CreatedAt: time.Now(), UpdatedAt: time.Now(), } if err = tx.Create(&taskManagement).Error; err != nil { tx.Rollback() return commonErr.ReturnError(err, "创建任务记录失败", "创建任务记录失败: ") } } else { tx.Rollback() return commonErr.ReturnError(err, "查询任务记录失败", "查询任务记录失败: ") } } // 2. 检查待发数量是否大于0(聚合总和) if aggregatePendingVideo(&taskManagement) <= 0 && aggregatePendingImage(&taskManagement) <= 0 && aggregatePendingData(&taskManagement) <= 0 { tx.Rollback() return commonErr.ReturnError(nil, "无可指派任务", "当前艺人待发视频数、图文数、数据数均为0,无法指派任务") } // 3. 检查指派数量是否合理(增强验证) if req.AssignVideoCount < 0 || req.AssignPostCount < 0 || req.AssignDataCount < 0 { tx.Rollback() return commonErr.ReturnError(nil, "指派数量不能为负数", "指派数量必须大于等于0") } if req.AssignVideoCount > aggregatePendingVideo(&taskManagement) || req.AssignPostCount > aggregatePendingImage(&taskManagement) || req.AssignDataCount > aggregatePendingData(&taskManagement) { tx.Rollback() return commonErr.ReturnError(nil, "指派数量超出限制", fmt.Sprintf("指派数量不能超过待发数量。当前待发:视频%d,图文%d,数据%d", aggregatePendingVideo(&taskManagement), aggregatePendingImage(&taskManagement), aggregatePendingData(&taskManagement))) } if req.AssignVideoCount == 0 && req.AssignPostCount == 0 && req.AssignDataCount == 0 { tx.Rollback() return commonErr.ReturnError(nil, "指派数量不能全为0", "至少需要指派一种类型的任务") } // 4. 按优先级扣减详细待发数量 if req.AssignVideoCount > 0 { deductVideo(&taskManagement, req.AssignVideoCount) } if req.AssignPostCount > 0 { deductImage(&taskManagement, req.AssignPostCount) } if req.AssignDataCount > 0 { deductData(&taskManagement, req.AssignDataCount) } // 汇总更新字段 updateData := map[string]interface{}{ // 视频 "pending_bundle_limit_video_expired_count": taskManagement.PendingBundleLimitVideoExpiredCount, "pending_bundle_limit_video_count": taskManagement.PendingBundleLimitVideoCount, "pending_increase_limit_video_expired_count": taskManagement.PendingIncreaseLimitVideoExpiredCount, "pending_increase_limit_video_count": taskManagement.PendingIncreaseLimitVideoCount, "pending_bundle_video_count": taskManagement.PendingBundleVideoCount, "pending_increase_video_count": taskManagement.PendingIncreaseVideoCount, // 图片 "pending_bundle_limit_image_expired_count": taskManagement.PendingBundleLimitImageExpiredCount, "pending_bundle_limit_image_count": taskManagement.PendingBundleLimitImageCount, "pending_increase_limit_image_expired_count": taskManagement.PendingIncreaseLimitImageExpiredCount, "pending_increase_limit_image_count": taskManagement.PendingIncreaseLimitImageCount, "pending_bundle_image_count": taskManagement.PendingBundleImageCount, "pending_increase_image_count": taskManagement.PendingIncreaseImageCount, // 数据分析 "pending_bundle_limit_data_analysis_expired_count": taskManagement.PendingBundleLimitDataAnalysisExpiredCount, "pending_bundle_limit_data_analysis_count": taskManagement.PendingBundleLimitDataAnalysisCount, "pending_increase_limit_data_analysis_expired_count": taskManagement.PendingIncreaseLimitDataAnalysisExpiredCount, "pending_increase_limit_data_analysis_count": taskManagement.PendingIncreaseLimitDataAnalysisCount, "pending_bundle_data_analysis_count": taskManagement.PendingBundleDataAnalysisCount, "pending_increase_data_analysis_count": taskManagement.PendingIncreaseDataAnalysisCount, // 其他字段 "last_task_assignee": req.TaskAssignee, "task_assignee_num": req.TaskAssigneeNum, "progress_count": progressTaskCount, "complete_count": completeTaskCount, "updated_at": time.Now(), } if err = tx.Model(&taskManagement).Updates(updateData).Error; err != nil { tx.Rollback() return commonErr.ReturnError(err, "更新任务记录失败", "更新任务记录失败: ") } // 5. 创建指派记录 assignRecord := &model.TaskAssignRecords{ AssignRecordsUUID: uuid.New().String(), // 使用Google UUID SubNum: req.SubNum, TelNum: req.TelNum, ArtistName: req.ArtistName, Status: 1, // 1:未完成 ActualStatus: 1, // 1:未完成 OperatorType: 2, // 2:指派 Operator: req.Operator, // 当前操作人名字 OperatorNum: req.OperatorNum, // 当前操作人账号 OperatorTime: time.Now(), TaskAssignee: req.TaskAssignee, // 指派员工姓名 TaskAssigneeNum: req.TaskAssigneeNum, // 指派员工账号 PendingVideoCount: aggregatePendingVideo(&taskManagement), PendingPostCount: aggregatePendingImage(&taskManagement), PendingDataCount: aggregatePendingData(&taskManagement), AssignVideoCount: req.AssignVideoCount, AssignPostCount: req.AssignPostCount, AssignDataCount: req.AssignDataCount, CompleteVideoCount: 0, CompletePostCount: 0, CompleteDataCount: 0, CreatedAt: time.Now(), UpdatedAt: time.Now(), } if err = tx.Create(assignRecord).Error; err != nil { tx.Rollback() return commonErr.ReturnError(err, "创建指派记录失败", "创建指派记录失败: ") } // 提交事务 if err = tx.Commit().Error; err != nil { return commonErr.ReturnError(err, "提交事务失败", "提交事务失败: ") } return nil } // UpdatePendingCount 修改待发数量 func UpdatePendingCount(req *UpdatePendingCountRequest) error { // 开启事务 tx := app.ModuleClients.TaskBenchDB.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() // 1. 查询或创建TaskManagement记录 var taskManagement model.TaskManagement // 与查询余额保持一致:优先使用 sub_num,否则使用 tel_num tmQuery := tx.Model(&model.TaskManagement{}) if req.SubNum != "" { tmQuery = tmQuery.Where("sub_num = ?", req.SubNum) } else { tmQuery = tmQuery.Where("tel_num = ?", req.TelNum) } err := tmQuery.First(&taskManagement).Error if err != nil { if err == gorm.ErrRecordNotFound { return commonErr.ReturnError(err, "无该艺人任务记录", "无该艺人任务记录") } else { tx.Rollback() return commonErr.ReturnError(err, "查询任务记录失败", "查询任务记录失败: ") } } // 2. 查询任务余额记录(当前有效月份优先,若无则回退到最近一条) var taskBalance model.TaskBalance now := time.Now() tbQuery := tx.Model(&model.TaskBalance{}) if req.SubNum != "" { tbQuery = tbQuery.Where("sub_num = ?", req.SubNum) } else { tbQuery = tbQuery.Where("tel_num = ?", req.TelNum) } tbErr := tbQuery.Where("start_at <= ? AND expired_at >= ?", now, now).Order("start_at DESC").Take(&taskBalance).Error if tbErr != nil { // 回退:取最近一条记录 _ = tbQuery.Order("start_at DESC").Take(&taskBalance).Error } // 若余额记录不存在,且本次需要“扣返余额”(目标小于当前)或“占用余额”(目标大于当前),直接报错 // 说明:此处不创建余额记录,避免无源数据导致余额错账 hasBalanceRecord := taskBalance.ID != 0 // 3. 计算当前聚合待发与目标值的差异(目标为绝对值,不是增减) curVideo := aggregatePendingVideo(&taskManagement) curImage := aggregatePendingImage(&taskManagement) curData := aggregatePendingData(&taskManagement) diffVideo := req.PendingVideoCount - curVideo diffImage := req.PendingPostCount - curImage diffData := req.PendingDataCount - curData // 4. 若需要增加目标(diff>0),从艺人余额中按优先级占用并分配到待发分类 // 优先级:受限>非受限;同类型:打包>增量;受限内:过期优先 if diffVideo > 0 || diffImage > 0 || diffData > 0 { if !hasBalanceRecord { tx.Rollback() return commonErr.ReturnError(nil, "无可用任务余额记录", "该艺人没有任务余额记录,无法占用余额用于增加待发") } // 视频占用 if diffVideo > 0 { need := diffVideo // 可用余额按分类拆分 availBLE := taskBalance.TaskBundleLimitVideoExpiredNumber - taskBalance.TaskBundleLimitVideoExpiredConsumptionNumber availILE := taskBalance.TaskIncreaseLimitVideoExpiredNumber - taskBalance.TaskIncreaseLimitVideoExpiredConsumptionNumber availBL := taskBalance.TaskBundleLimitVideoNumber - taskBalance.TaskBundleLimitVideoConsumptionNumber availIL := taskBalance.TaskIncreaseLimitVideoNumber - taskBalance.TaskIncreaseLimitVideoConsumptionNumber availB := taskBalance.TaskBundleVideoNumber - taskBalance.TaskBundleVideoConsumptionNumber availI := taskBalance.TaskIncreaseVideoNumber - taskBalance.TaskIncreaseVideoConsumptionNumber // 逐类占用并写入待发分类与消费数 if need > 0 && availBLE > 0 { take := minInt(need, availBLE) taskManagement.PendingBundleLimitVideoExpiredCount += take taskBalance.TaskBundleLimitVideoExpiredConsumptionNumber += take need -= take } if need > 0 && availILE > 0 { take := minInt(need, availILE) taskManagement.PendingIncreaseLimitVideoExpiredCount += take taskBalance.TaskIncreaseLimitVideoExpiredConsumptionNumber += take need -= take } if need > 0 && availBL > 0 { take := minInt(need, availBL) taskManagement.PendingBundleLimitVideoCount += take taskBalance.TaskBundleLimitVideoConsumptionNumber += take need -= take } if need > 0 && availIL > 0 { take := minInt(need, availIL) taskManagement.PendingIncreaseLimitVideoCount += take taskBalance.TaskIncreaseLimitVideoConsumptionNumber += take need -= take } if need > 0 && availB > 0 { take := minInt(need, availB) taskManagement.PendingBundleVideoCount += take taskBalance.TaskBundleVideoConsumptionNumber += take need -= take } if need > 0 && availI > 0 { take := minInt(need, availI) taskManagement.PendingIncreaseVideoCount += take taskBalance.TaskIncreaseVideoConsumptionNumber += take need -= take } if need > 0 { tx.Rollback() return commonErr.ReturnError(nil, "视频任务余额不足", "可用余额不足以达到目标待发视频数量") } } // 图片占用 if diffImage > 0 { need := diffImage availBLE := taskBalance.TaskBundleLimitImageExpiredNumber - taskBalance.TaskBundleLimitImageExpiredConsumptionNumber availILE := taskBalance.TaskIncreaseLimitImageExpiredNumber - taskBalance.TaskIncreaseLimitImageExpiredConsumptionNumber availBL := taskBalance.TaskBundleLimitImageNumber - taskBalance.TaskBundleLimitImageConsumptionNumber availIL := taskBalance.TaskIncreaseLimitImageNumber - taskBalance.TaskIncreaseLimitImageConsumptionNumber availB := taskBalance.TaskBundleImageNumber - taskBalance.TaskBundleImageConsumptionNumber availI := taskBalance.TaskIncreaseImageNumber - taskBalance.TaskIncreaseImageConsumptionNumber if need > 0 && availBLE > 0 { take := minInt(need, availBLE) taskManagement.PendingBundleLimitImageExpiredCount += take taskBalance.TaskBundleLimitImageExpiredConsumptionNumber += take need -= take } if need > 0 && availILE > 0 { take := minInt(need, availILE) taskManagement.PendingIncreaseLimitImageExpiredCount += take taskBalance.TaskIncreaseLimitImageExpiredConsumptionNumber += take need -= take } if need > 0 && availBL > 0 { take := minInt(need, availBL) taskManagement.PendingBundleLimitImageCount += take taskBalance.TaskBundleLimitImageConsumptionNumber += take need -= take } if need > 0 && availIL > 0 { take := minInt(need, availIL) taskManagement.PendingIncreaseLimitImageCount += take taskBalance.TaskIncreaseLimitImageConsumptionNumber += take need -= take } if need > 0 && availB > 0 { take := minInt(need, availB) taskManagement.PendingBundleImageCount += take taskBalance.TaskBundleImageConsumptionNumber += take need -= take } if need > 0 && availI > 0 { take := minInt(need, availI) taskManagement.PendingIncreaseImageCount += take taskBalance.TaskIncreaseImageConsumptionNumber += take need -= take } if need > 0 { tx.Rollback() return commonErr.ReturnError(nil, "图文任务余额不足", "可用余额不足以达到目标待发图文数量") } } // 数据分析占用 if diffData > 0 { need := diffData availBLE := taskBalance.TaskBundleLimitDataAnalysisExpiredNumber - taskBalance.TaskBundleLimitDataAnalysisExpiredConsumptionNumber availILE := taskBalance.TaskIncreaseLimitDataAnalysisExpiredNumber - taskBalance.TaskIncreaseLimitDataAnalysisExpiredConsumptionNumber availBL := taskBalance.TaskBundleLimitDataAnalysisNumber - taskBalance.TaskBundleLimitDataAnalysisConsumptionNumber availIL := taskBalance.TaskIncreaseLimitDataAnalysisNumber - taskBalance.TaskIncreaseLimitDataAnalysisConsumptionNumber availB := taskBalance.TaskBundleDataAnalysisNumber - taskBalance.TaskBundleDataAnalysisConsumptionNumber availI := taskBalance.TaskIncreaseDataAnalysisNumber - taskBalance.TaskIncreaseDataAnalysisConsumptionNumber if need > 0 && availBLE > 0 { take := minInt(need, availBLE) taskManagement.PendingBundleLimitDataAnalysisExpiredCount += take taskBalance.TaskBundleLimitDataAnalysisExpiredConsumptionNumber += take need -= take } if need > 0 && availILE > 0 { take := minInt(need, availILE) taskManagement.PendingIncreaseLimitDataAnalysisExpiredCount += take taskBalance.TaskIncreaseLimitDataAnalysisExpiredConsumptionNumber += take need -= take } if need > 0 && availBL > 0 { take := minInt(need, availBL) taskManagement.PendingBundleLimitDataAnalysisCount += take taskBalance.TaskBundleLimitDataAnalysisConsumptionNumber += take need -= take } if need > 0 && availIL > 0 { take := minInt(need, availIL) taskManagement.PendingIncreaseLimitDataAnalysisCount += take taskBalance.TaskIncreaseLimitDataAnalysisConsumptionNumber += take need -= take } if need > 0 && availB > 0 { take := minInt(need, availB) taskManagement.PendingBundleDataAnalysisCount += take taskBalance.TaskBundleDataAnalysisConsumptionNumber += take need -= take } if need > 0 && availI > 0 { take := minInt(need, availI) taskManagement.PendingIncreaseDataAnalysisCount += take taskBalance.TaskIncreaseDataAnalysisConsumptionNumber += take need -= take } if need > 0 { tx.Rollback() return commonErr.ReturnError(nil, "数据分析任务余额不足", "可用余额不足以达到目标待发数据分析数量") } } } // 5. 若需要减少目标(diff<0),先按优先级从待发分类扣减,并将扣减的数量按对应分类冲回余额(减少消费数) if diffVideo < 0 || diffImage < 0 || diffData < 0 { if !hasBalanceRecord { tx.Rollback() return commonErr.ReturnError(nil, "无可用任务余额记录", "该艺人没有任务余额记录,无法将多余待发冲回余额") } // 视频冲回 if diffVideo < 0 { refund := -diffVideo // 记录扣减前的各分类待发值 prevBLE := taskManagement.PendingBundleLimitVideoExpiredCount prevILE := taskManagement.PendingIncreaseLimitVideoExpiredCount prevBL := taskManagement.PendingBundleLimitVideoCount prevIL := taskManagement.PendingIncreaseLimitVideoCount prevB := taskManagement.PendingBundleVideoCount prevI := taskManagement.PendingIncreaseVideoCount deductVideo(&taskManagement, refund) // 计算各分类被扣减的数量,并减少对应消费数(不可小于0) removedBLE := prevBLE - taskManagement.PendingBundleLimitVideoExpiredCount removedILE := prevILE - taskManagement.PendingIncreaseLimitVideoExpiredCount removedBL := prevBL - taskManagement.PendingBundleLimitVideoCount removedIL := prevIL - taskManagement.PendingIncreaseLimitVideoCount removedB := prevB - taskManagement.PendingBundleVideoCount removedI := prevI - taskManagement.PendingIncreaseVideoCount taskBalance.TaskBundleLimitVideoExpiredConsumptionNumber = maxInt(0, taskBalance.TaskBundleLimitVideoExpiredConsumptionNumber-removedBLE) taskBalance.TaskIncreaseLimitVideoExpiredConsumptionNumber = maxInt(0, taskBalance.TaskIncreaseLimitVideoExpiredConsumptionNumber-removedILE) taskBalance.TaskBundleLimitVideoConsumptionNumber = maxInt(0, taskBalance.TaskBundleLimitVideoConsumptionNumber-removedBL) taskBalance.TaskIncreaseLimitVideoConsumptionNumber = maxInt(0, taskBalance.TaskIncreaseLimitVideoConsumptionNumber-removedIL) taskBalance.TaskBundleVideoConsumptionNumber = maxInt(0, taskBalance.TaskBundleVideoConsumptionNumber-removedB) taskBalance.TaskIncreaseVideoConsumptionNumber = maxInt(0, taskBalance.TaskIncreaseVideoConsumptionNumber-removedI) } // 图片冲回 if diffImage < 0 { refund := -diffImage prevBLE := taskManagement.PendingBundleLimitImageExpiredCount prevILE := taskManagement.PendingIncreaseLimitImageExpiredCount prevBL := taskManagement.PendingBundleLimitImageCount prevIL := taskManagement.PendingIncreaseLimitImageCount prevB := taskManagement.PendingBundleImageCount prevI := taskManagement.PendingIncreaseImageCount deductImage(&taskManagement, refund) removedBLE := prevBLE - taskManagement.PendingBundleLimitImageExpiredCount removedILE := prevILE - taskManagement.PendingIncreaseLimitImageExpiredCount removedBL := prevBL - taskManagement.PendingBundleLimitImageCount removedIL := prevIL - taskManagement.PendingIncreaseLimitImageCount removedB := prevB - taskManagement.PendingBundleImageCount removedI := prevI - taskManagement.PendingIncreaseImageCount taskBalance.TaskBundleLimitImageExpiredConsumptionNumber = maxInt(0, taskBalance.TaskBundleLimitImageExpiredConsumptionNumber-removedBLE) taskBalance.TaskIncreaseLimitImageExpiredConsumptionNumber = maxInt(0, taskBalance.TaskIncreaseLimitImageExpiredConsumptionNumber-removedILE) taskBalance.TaskBundleLimitImageConsumptionNumber = maxInt(0, taskBalance.TaskBundleLimitImageConsumptionNumber-removedBL) taskBalance.TaskIncreaseLimitImageConsumptionNumber = maxInt(0, taskBalance.TaskIncreaseLimitImageConsumptionNumber-removedIL) taskBalance.TaskBundleImageConsumptionNumber = maxInt(0, taskBalance.TaskBundleImageConsumptionNumber-removedB) taskBalance.TaskIncreaseImageConsumptionNumber = maxInt(0, taskBalance.TaskIncreaseImageConsumptionNumber-removedI) } // 数据分析冲回 if diffData < 0 { refund := -diffData prevBLE := taskManagement.PendingBundleLimitDataAnalysisExpiredCount prevILE := taskManagement.PendingIncreaseLimitDataAnalysisExpiredCount prevBL := taskManagement.PendingBundleLimitDataAnalysisCount prevIL := taskManagement.PendingIncreaseLimitDataAnalysisCount prevB := taskManagement.PendingBundleDataAnalysisCount prevI := taskManagement.PendingIncreaseDataAnalysisCount deductData(&taskManagement, refund) removedBLE := prevBLE - taskManagement.PendingBundleLimitDataAnalysisExpiredCount removedILE := prevILE - taskManagement.PendingIncreaseLimitDataAnalysisExpiredCount removedBL := prevBL - taskManagement.PendingBundleLimitDataAnalysisCount removedIL := prevIL - taskManagement.PendingIncreaseLimitDataAnalysisCount removedB := prevB - taskManagement.PendingBundleDataAnalysisCount removedI := prevI - taskManagement.PendingIncreaseDataAnalysisCount taskBalance.TaskBundleLimitDataAnalysisExpiredConsumptionNumber = maxInt(0, taskBalance.TaskBundleLimitDataAnalysisExpiredConsumptionNumber-removedBLE) taskBalance.TaskIncreaseLimitDataAnalysisExpiredConsumptionNumber = maxInt(0, taskBalance.TaskIncreaseLimitDataAnalysisExpiredConsumptionNumber-removedILE) taskBalance.TaskBundleLimitDataAnalysisConsumptionNumber = maxInt(0, taskBalance.TaskBundleLimitDataAnalysisConsumptionNumber-removedBL) taskBalance.TaskIncreaseLimitDataAnalysisConsumptionNumber = maxInt(0, taskBalance.TaskIncreaseLimitDataAnalysisConsumptionNumber-removedIL) taskBalance.TaskBundleDataAnalysisConsumptionNumber = maxInt(0, taskBalance.TaskBundleDataAnalysisConsumptionNumber-removedB) taskBalance.TaskIncreaseDataAnalysisConsumptionNumber = maxInt(0, taskBalance.TaskIncreaseDataAnalysisConsumptionNumber-removedI) } } // 6. 更新TaskManagement表 updateData := map[string]interface{}{ // 视频 "pending_bundle_limit_video_expired_count": taskManagement.PendingBundleLimitVideoExpiredCount, "pending_bundle_limit_video_count": taskManagement.PendingBundleLimitVideoCount, "pending_increase_limit_video_expired_count": taskManagement.PendingIncreaseLimitVideoExpiredCount, "pending_increase_limit_video_count": taskManagement.PendingIncreaseLimitVideoCount, "pending_bundle_video_count": taskManagement.PendingBundleVideoCount, "pending_increase_video_count": taskManagement.PendingIncreaseVideoCount, // 图片 "pending_bundle_limit_image_expired_count": taskManagement.PendingBundleLimitImageExpiredCount, "pending_bundle_limit_image_count": taskManagement.PendingBundleLimitImageCount, "pending_increase_limit_image_expired_count": taskManagement.PendingIncreaseLimitImageExpiredCount, "pending_increase_limit_image_count": taskManagement.PendingIncreaseLimitImageCount, "pending_bundle_image_count": taskManagement.PendingBundleImageCount, "pending_increase_image_count": taskManagement.PendingIncreaseImageCount, // 数据分析 "pending_bundle_limit_data_analysis_expired_count": taskManagement.PendingBundleLimitDataAnalysisExpiredCount, "pending_bundle_limit_data_analysis_count": taskManagement.PendingBundleLimitDataAnalysisCount, "pending_increase_limit_data_analysis_expired_count": taskManagement.PendingIncreaseLimitDataAnalysisExpiredCount, "pending_increase_limit_data_analysis_count": taskManagement.PendingIncreaseLimitDataAnalysisCount, "pending_bundle_data_analysis_count": taskManagement.PendingBundleDataAnalysisCount, "pending_increase_data_analysis_count": taskManagement.PendingIncreaseDataAnalysisCount, // 通用 "updated_at": time.Now(), } if err = tx.Model(&taskManagement).Updates(updateData).Error; err != nil { tx.Rollback() return commonErr.ReturnError(err, "更新任务记录失败", "更新任务记录失败: ") } // 7. 更新TaskBalance(消费数发生变化时) if hasBalanceRecord { updateBal := map[string]interface{}{ // 视频消费数 "task_bundle_limit_video_expired_consumption_number": taskBalance.TaskBundleLimitVideoExpiredConsumptionNumber, "task_increase_limit_video_expired_consumption_number": taskBalance.TaskIncreaseLimitVideoExpiredConsumptionNumber, "task_bundle_limit_video_consumption_number": taskBalance.TaskBundleLimitVideoConsumptionNumber, "task_increase_limit_video_consumption_number": taskBalance.TaskIncreaseLimitVideoConsumptionNumber, "task_bundle_video_consumption_number": taskBalance.TaskBundleVideoConsumptionNumber, "task_increase_video_consumption_number": taskBalance.TaskIncreaseVideoConsumptionNumber, // 图片消费数 "task_bundle_limit_image_expired_consumption_number": taskBalance.TaskBundleLimitImageExpiredConsumptionNumber, "task_increase_limit_image_expired_consumption_number": taskBalance.TaskIncreaseLimitImageExpiredConsumptionNumber, "task_bundle_limit_image_consumption_number": taskBalance.TaskBundleLimitImageConsumptionNumber, "task_increase_limit_image_consumption_number": taskBalance.TaskIncreaseLimitImageConsumptionNumber, "task_bundle_image_consumption_number": taskBalance.TaskBundleImageConsumptionNumber, "task_increase_image_consumption_number": taskBalance.TaskIncreaseImageConsumptionNumber, // 数据分析消费数 "task_bundle_limit_data_analysis_expired_consumption_number": taskBalance.TaskBundleLimitDataAnalysisExpiredConsumptionNumber, "task_increase_limit_data_analysis_expired_consumption_number": taskBalance.TaskIncreaseLimitDataAnalysisExpiredConsumptionNumber, "task_bundle_limit_data_analysis_consumption_number": taskBalance.TaskBundleLimitDataAnalysisConsumptionNumber, "task_increase_limit_data_analysis_consumption_number": taskBalance.TaskIncreaseLimitDataAnalysisConsumptionNumber, "task_bundle_data_analysis_consumption_number": taskBalance.TaskBundleDataAnalysisConsumptionNumber, "task_increase_data_analysis_consumption_number": taskBalance.TaskIncreaseDataAnalysisConsumptionNumber, // 通用 "updated_at": time.Now(), } if err = tx.Model(&taskBalance).Updates(updateBal).Error; err != nil { tx.Rollback() return commonErr.ReturnError(err, "更新任务余额失败", "更新任务余额失败: ") } } // 提交事务 if err = tx.Commit().Error; err != nil { return commonErr.ReturnError(err, "提交事务失败", "提交事务失败: ") } return nil } // minInt 返回两个整数的较小值 func minInt(a, b int) int { if a < b { return a } return b } // maxInt 返回两个整数的较大值 func maxInt(a, b int) int { if a > b { return a } return b } // GetRecentAssignRecords 查询最近被指派记录 // 查询操作类型为"指派"的最近n条不同员工的记录 func GetRecentAssignRecords(limit int) ([]*model.TaskAssignRecords, error) { var records []*model.TaskAssignRecords // 查询操作类型为指派(2)的记录,按操作时间倒序,去重员工 err := app.ModuleClients.TaskBenchDB.Model(&model.TaskAssignRecords{}). Where("operator_type = ?", 2). // 2:指派 Group("task_assignee_num"). // 按指派人账号分组去重 Order("operator_time DESC"). // 按操作时间倒序 Limit(limit). Find(&records).Error if err != nil { return nil, commonErr.ReturnError(err, "查询最近指派记录失败", "查询最近指派记录失败: ") } return records, nil } // GetEmployeeAssignedTasks 根据登录人信息查询被指派给该员工的艺人任务 func GetEmployeeAssignedTasks(req *EmployeeTaskQueryRequest) ([]*model.TaskAssignRecords, int64, error) { var records []*model.TaskAssignRecords var total int64 // 构建查询条件 query := app.ModuleClients.TaskBenchDB.Model(&model.TaskAssignRecords{}). Where("task_assignee_num = ?", req.TaskAssigneeNum) // 关键词搜索(艺人姓名、编号、手机号) if req.Keyword != "" { query = query.Where("sub_num LIKE ? OR tel_num LIKE ?", "%"+req.Keyword+"%", "%"+req.Keyword+"%") } // 被指派人姓名 if req.Operator != "" { query = query.Where("task_assignee LIKE ?", "%"+req.Operator+"%") } // 指派时间区间 if req.StartTime != "" && req.EndTime != "" { query = query.Where("operator_time BETWEEN ? AND ?", req.StartTime, req.EndTime) } else if req.StartTime != "" { query = query.Where("operator_time >= ?", req.StartTime) } else if req.EndTime != "" { query = query.Where("operator_time <= ?", req.EndTime) } // 完成时间区间 if req.StartCompleteTime != "" && req.EndCompleteTime != "" { query = query.Where("complete_time BETWEEN ? AND ?", req.StartCompleteTime, req.EndCompleteTime) } else if req.StartCompleteTime != "" { query = query.Where("complete_time >= ?", req.StartCompleteTime) } else if req.EndCompleteTime != "" { query = query.Where("complete_time <= ?", req.EndCompleteTime) } // 反馈完成状态 if req.Status != 0 { query = query.Where("status = ?", req.Status) } // 根据排序字段倒序 if req.SortBy != "" { query = query.Order(req.SortBy + " DESC") } // 计算总数 query.Count(&total) // 分页 if req.PageSize > 0 && req.Page > 0 { offset := (req.Page - 1) * req.PageSize query = query.Limit(req.PageSize).Offset(offset) } // 按操作时间倒序 err := query.Order("operator_time DESC").Find(&records).Error if err != nil { return nil, 0, commonErr.ReturnError(err, "查询员工指派任务失败", "查询员工指派任务失败: ") } return records, total, nil } // CompleteTaskManually 员工手动点击完成任务 func CompleteTaskManually(assignRecordsUUID string) error { now := time.Now() updateData := map[string]interface{}{ "status": 2, // 2:完成 "complete_time": &now, "updated_at": now, } err := app.ModuleClients.TaskBenchDB.Model(&model.TaskAssignRecords{}). Where("assign_records_uuid = ?", assignRecordsUUID). Updates(updateData).Error if err != nil { return commonErr.ReturnError(err, "更新任务完成状态失败", "更新任务完成状态失败: ") } return nil } // UpdateTaskProgress 员工实际完成任务状态更新 // 员工调用视频、图文、数据时,对应的待完成数据减一,已完成数据加一 func UpdateTaskProgress(req *CompleteTaskRequest) error { // 开启事务 tx := app.ModuleClients.TaskBenchDB.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() // 1. 查询指派记录 var assignRecord model.TaskAssignRecords var err error if req.AssignRecordsUUID != "" { // 如果提供了UUID,直接根据UUID查询 err = tx.Where("assign_records_uuid = ?", req.AssignRecordsUUID).First(&assignRecord).Error if err != nil { tx.Rollback() return commonErr.ReturnError(err, "查询指派记录失败", "查询指派记录失败: ") } } else { // 如果没有提供UUID,根据员工信息查询最早的未完成任务 if req.EmployeeName == "" || req.EmployeeNum == "" { tx.Rollback() return commonErr.ReturnError(nil, "参数错误", "员工姓名和手机号不能为空") } err = tx.Where("task_assignee = ? AND task_assignee_num = ? AND actual_status = 1", req.EmployeeName, req.EmployeeNum). Order("operator_time ASC"). First(&assignRecord).Error if err != nil { if err == gorm.ErrRecordNotFound { tx.Rollback() return commonErr.ReturnError(nil, "未找到任务记录", "该员工没有未完成的任务记录") } tx.Rollback() return commonErr.ReturnError(err, "查询指派记录失败", "查询指派记录失败: ") } } // 2. 根据任务类型更新完成数量 updateData := map[string]interface{}{ "updated_at": time.Now(), } switch req.TaskType { case "video": newCompleteCount := assignRecord.CompleteVideoCount + req.CompleteCount if newCompleteCount > assignRecord.AssignVideoCount { tx.Rollback() return commonErr.ReturnError(nil, "完成数量超出限制", "视频完成数量不能超过指派数量") } updateData["complete_video_count"] = newCompleteCount case "post": newCompleteCount := assignRecord.CompletePostCount + req.CompleteCount if newCompleteCount > assignRecord.AssignPostCount { tx.Rollback() return commonErr.ReturnError(nil, "完成数量超出限制", "图文完成数量不能超过指派数量") } updateData["complete_post_count"] = newCompleteCount case "data": newCompleteCount := assignRecord.CompleteDataCount + req.CompleteCount if newCompleteCount > assignRecord.AssignDataCount { tx.Rollback() return commonErr.ReturnError(nil, "完成数量超出限制", "数据完成数量不能超过指派数量") } updateData["complete_data_count"] = newCompleteCount default: tx.Rollback() return commonErr.ReturnError(nil, "无效的任务类型", "任务类型必须是video、post或data") } // 3. 更新指派记录 if err = tx.Model(&assignRecord).Updates(updateData).Error; err != nil { tx.Rollback() return commonErr.ReturnError(err, "更新完成数量失败", "更新完成数量失败: ") } // 4. 重新查询更新后的记录,检查是否全部完成 if err = tx.Where("assign_records_uuid = ?", assignRecord.AssignRecordsUUID).First(&assignRecord).Error; err != nil { tx.Rollback() return commonErr.ReturnError(err, "查询更新后记录失败", "查询更新后记录失败: ") } // 5. 检查是否所有任务都已完成 if assignRecord.CompleteVideoCount == assignRecord.AssignVideoCount && assignRecord.CompletePostCount == assignRecord.AssignPostCount && assignRecord.CompleteDataCount == assignRecord.AssignDataCount { // 更新实际完成状态 if err = tx.Model(&assignRecord).Update("actual_status", 2).Error; err != nil { tx.Rollback() return commonErr.ReturnError(err, "更新实际完成状态失败", "更新实际完成状态失败: ") } } // 提交事务 if err = tx.Commit().Error; err != nil { return commonErr.ReturnError(err, "提交事务失败", "提交事务失败: ") } return nil } // GetTaskManagementBySubNum 根据艺人编号查询任务管理记录 func GetTaskManagementBySubNum(subNum string) (*model.TaskManagement, error) { var task model.TaskManagement err := app.ModuleClients.TaskBenchDB.Where("sub_num = ?", subNum).First(&task).Error if err != nil { if err == gorm.ErrRecordNotFound { return nil, nil // 记录不存在 } return nil, commonErr.ReturnError(err, "查询任务管理记录失败", "查询任务管理记录失败: ") } return &task, nil } // GetAssignRecordByUUID 根据UUID查询指派记录 func GetAssignRecordByUUID(uuid string) (*model.TaskAssignRecords, error) { var record model.TaskAssignRecords err := app.ModuleClients.TaskBenchDB.Where("assign_records_uuid = ?", uuid).First(&record).Error if err != nil { if err == gorm.ErrRecordNotFound { return nil, nil // 记录不存在 } return nil, commonErr.ReturnError(err, "查询指派记录失败", "查询指派记录失败: ") } return &record, nil } // GetTaskAssignRecordsList 多条件查询操作记录表 // 支持通过艺人信息、指派人、操作人、操作时间、完成状态等多条件查询TaskAssignRecords表 func GetTaskAssignRecordsList(req *TaskAssignRecordsQueryRequest) ([]*model.TaskAssignRecords, int64, error) { var records []*model.TaskAssignRecords var total int64 // 构建查询条件 query := app.ModuleClients.TaskBenchDB.Model(&model.TaskAssignRecords{}) // 关键词搜索(艺人姓名、编号、手机号) if req.Keyword != "" { query = query.Where("sub_num LIKE ? OR tel_num LIKE ? OR artist_name LIKE ?", "%"+req.Keyword+"%", "%"+req.Keyword+"%", "%"+req.Keyword+"%") } // 指派人姓名 if req.TaskAssignee != "" { query = query.Where("task_assignee LIKE ?", "%"+req.TaskAssignee+"%") } // 操作人姓名 if req.Operator != "" { query = query.Where("operator LIKE ?", "%"+req.Operator+"%") } // 操作人手机号 if req.OperatorNum != "" { query = query.Where("operator_num LIKE ?", "%"+req.OperatorNum+"%") } // 操作时间区间 if req.StartTime != "" && req.EndTime != "" { query = query.Where("operator_time BETWEEN ? AND ?", req.StartTime, req.EndTime) } else if req.StartTime != "" { query = query.Where("operator_time >= ?", req.StartTime) } else if req.EndTime != "" { query = query.Where("operator_time <= ?", req.EndTime) } // 反馈完成状态 if req.Status != 0 { query = query.Where("status = ?", req.Status) } // 实际完成状态 if req.ActualStatus != 0 { query = query.Where("actual_status = ?", req.ActualStatus) } // 计算总数 query.Count(&total) // 分页 if req.PageSize > 0 && req.Page > 0 { offset := (req.Page - 1) * req.PageSize query = query.Limit(req.PageSize).Offset(offset) } // 按更新时间倒序排序 err := query.Order("updated_at DESC").Find(&records).Error if err != nil { return nil, 0, commonErr.ReturnError(err, "查询操作记录失败", "查询操作记录失败: ") } return records, total, nil } // GetValidArtistList 查询套餐状态为有效中的艺人数据列表 // 根据BundleOrderRecords表查询过期时间大于当前时间且状态为已支付的艺人详细信息 func GetValidArtistList() ([]ValidArtistInfo, error) { // 构建子查询,获取每个用户的最新订单记录 subQuery := app.ModuleClients.BundleDB.Table("bundle_order_records as bor1"). Select("bor1.*"). Joins(`INNER JOIN ( SELECT customer_id, MAX(created_at) AS max_created_time FROM bundle_order_records GROUP BY customer_id ) bor2 ON bor1.customer_id = bor2.customer_id AND bor1.created_at = bor2.max_created_time`) // 主查询,关联用户表和实名信息表 session := app.ModuleClients.BundleDB.Table("`micro-account`.`user` AS u"). Select(`u.id as user_id, bor.customer_num, rn.name as user_name, u.tel_num as user_phone_number, bor.bundle_name, bor.expiration_time, bor.status, bor.uuid as order_uuid, (bb.bundle_account_number + bb.increase_account_number + bb.manual_account_number) as account_number, (bb.bundle_account_consumption_number + bb.increase_account_consumption_number + bb.manual_account_consumption_number) as account_consumption_number, (bb.bundle_video_number + bb.increase_video_number) as video_number, (bb.bundle_video_consumption_number + bb.increase_video_consumption_number) as video_consumption_number, (bb.bundle_image_number + bb.increase_image_number + bb.manual_image_number) as image_number, (bb.bundle_image_consumption_number + bb.increase_image_consumption_number + bb.manual_image_consumption_number) as image_consumption_number, (bb.bundle_data_analysis_number + bb.increase_data_analysis_number + bb.manual_data_analysis_number) as data_analysis_number, (bb.bundle_data_analysis_consumption_number + bb.increase_data_analysis_consumption_number + bb.manual_data_analysis_consumption_number) as data_analysis_consumption_number, bb.expansion_packs_number`). Joins("LEFT JOIN `micro-account`.real_name rn ON u.real_name_id = rn.id"). Joins("LEFT JOIN (?) as bor ON bor.customer_id = u.id", subQuery). Joins("LEFT JOIN bundle_balance bb ON u.id = bb.user_id AND bb.order_uuid = bor.uuid"). Where("rn.name IS NOT NULL"). Where("u.deleted_at = 0"). Where("bor.expiration_time > ?", time.Now().Format("2006-01-02 15:04:05")). Where("bor.status = ?", 2). // 2:已签已支付 Order("bor.expiration_time desc") var data []ValidArtistInfo err := session.Find(&data).Error if err != nil { return nil, commonErr.ReturnError(err, "查询有效艺人失败", "查询有效艺人失败: ") } return data, nil } // 根据员工的工号从指派任务记录表中查询这名员工,进行中任务数量和已经完成的任务数量 func GetTaskAssigneeInfo(taskAssigneeNum string) (int, int, error) { // 如果taskAssigneeNum为空,直接返回默认值 if taskAssigneeNum == "" { return 0, 0, nil } var taskAssignRecords TaskAssignRecords err := app.ModuleClients.TaskBenchDB.Table("task_assign_records"). Select("task_assignee_num, count(*) as progress_task_count, sum(status = 2) as complete_task_count"). Where("task_assignee_num = ?", taskAssigneeNum). Group("task_assignee_num"). First(&taskAssignRecords).Error // 如果查询不到记录,返回默认值而不是错误 if err != nil { if err == gorm.ErrRecordNotFound { return 0, 0, nil } return 0, 0, commonErr.ReturnError(err, "查询任务指派记录失败", "查询任务指派记录失败: ") } return taskAssignRecords.ProgressTaskCount, taskAssignRecords.CompleteTaskCount, nil } // 更新被指派员工为 taskAssigneeNum 的记录中的ProgressCount + 1 和CompleteCount - 1 func UpdateTaskRecordsByAssigneeNum(taskAssigneeNum string) error { err := app.ModuleClients.TaskBenchDB.Table("task_management"). Where("task_assignee_num = ?", taskAssigneeNum). Update("progress_count", gorm.Expr("progress_count + ?", 1)). Update("complete_count", gorm.Expr("complete_count - ?", 1)).Error if err != nil { return commonErr.ReturnError(err, "更新员工任务进度失败", "更新员工任务进度失败: ") } return nil } // GetArtistBundleBalance 根据艺人编号或手机号查询套餐剩余数量 // 优先使用艺人编号查询,如果为空则使用手机号查询 func GetArtistBundleBalance(req *ArtistBundleBalanceRequest) (*ArtistBundleBalanceResponse, error) { // 构建子查询,获取用户的最新订单记录 subQuery := app.ModuleClients.BundleDB.Table("bundle_order_records as bor1"). Select("bor1.*"). Joins(`INNER JOIN ( SELECT customer_id, MAX(created_at) AS max_created_time FROM bundle_order_records GROUP BY customer_id ) bor2 ON bor1.customer_id = bor2.customer_id AND bor1.created_at = bor2.max_created_time`) // 主查询,关联用户表和实名信息表 session := app.ModuleClients.BundleDB.Table("`micro-account`.`user` AS u"). Select(`u.id, bor.customer_num, rn.name as user_name, u.tel_num as user_phone_number, bor.bundle_name, bor.expiration_time, bor.status, bor.uuid as order_uuid, bb.account_number, bb.account_consumption_number, bb.video_number, bb.video_consumption_number, bb.image_number, bb.image_consumption_number, bb.data_analysis_number, bb.data_analysis_consumption_number, bb.expansion_packs_number`). Joins("LEFT JOIN `micro-account`.real_name rn ON u.real_name_id = rn.id"). Joins("LEFT JOIN (?) as bor ON bor.customer_id = u.id", subQuery). Joins("LEFT JOIN bundle_balance bb ON u.id = bb.user_id AND bb.order_uuid = bor.uuid"). Where("rn.name IS NOT NULL"). Where("u.deleted_at = 0"). Where("bor.expiration_time > ?", time.Now().Format("2006-01-02 15:04:05")). Where("bor.status = ?", 2) // 2:已签已支付 // 根据查询条件添加WHERE子句 if req.CustomerNum != "" { session = session.Where("bor.customer_num = ?", req.CustomerNum) } else if req.TelNum != "" { session = session.Where("u.tel_num = ?", req.TelNum) } else { return nil, commonErr.ReturnError(nil, "查询参数错误", "艺人编号和手机号不能同时为空") } var data ValidArtistInfo err := session.Take(&data).Error // 使用Take()替代First(),避免自动排序 if err != nil { if err == gorm.ErrRecordNotFound { return nil, commonErr.ReturnError(err, "艺人不存在或套餐已过期", "未找到有效的艺人套餐信息") } return nil, commonErr.ReturnError(err, "查询艺人套餐信息失败", "查询艺人套餐信息失败: ") } // 计算剩余数量 response := &ArtistBundleBalanceResponse{ RemainingVideoCount: data.VideoNumber - data.VideoConsumptionNumber, RemainingImageCount: data.ImageNumber - data.ImageConsumptionNumber, RemainingDataAnalysisCount: data.DataAnalysisNumber - data.DataAnalysisConsumptionNumber, } return response, nil } // AdjustPendingCountRequest 调整待发数量请求参数 type AdjustPendingCountRequest struct { SubNum string `json:"subNum"` // 艺人编号 TelNum string `json:"telNum"` // 艺人手机号 ArtistName string `json:"artistName"` // 艺人姓名 AdjustVideoCount int `json:"adjustVideoCount"` // 调整视频数量(正数为增加,负数为减少) AdjustPostCount int `json:"adjustPostCount"` // 调整图文数量(正数为增加,负数为减少) AdjustDataCount int `json:"adjustDataCount"` // 调整数据数量(正数为增加,负数为减少) CreateIfNotExists bool `json:"createIfNotExists"` // 如果记录不存在是否创建 } // AdjustPendingCount 调整待发数量(增加或减少) // 支持正数增加和负数减少,可用于套餐扩展时同步增加待发任务数量 func AdjustPendingCount(req *AdjustPendingCountRequest) error { // 开启事务 tx := app.ModuleClients.TaskBenchDB.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() // 1. 查询现有任务记录 var taskManagement model.TaskManagement err := tx.Where("sub_num = ? AND tel_num = ?", req.SubNum, req.TelNum).First(&taskManagement).Error if err != nil { if err == gorm.ErrRecordNotFound { if req.CreateIfNotExists { // 创建新记录,正数增加分配到“非限制-套餐权益”,负数忽略(置0) video := req.AdjustVideoCount post := req.AdjustPostCount data := req.AdjustDataCount if video < 0 { video = 0 } if post < 0 { post = 0 } if data < 0 { data = 0 } taskManagement = model.TaskManagement{ SubNum: req.SubNum, TelNum: req.TelNum, ArtistName: req.ArtistName, // 视频 PendingBundleVideoCount: video, PendingIncreaseVideoCount: 0, PendingBundleLimitVideoCount: 0, PendingIncreaseLimitVideoCount: 0, PendingBundleLimitVideoExpiredCount: 0, PendingIncreaseLimitVideoExpiredCount: 0, // 图片 PendingBundleImageCount: post, PendingIncreaseImageCount: 0, PendingBundleLimitImageCount: 0, PendingIncreaseLimitImageCount: 0, PendingBundleLimitImageExpiredCount: 0, PendingIncreaseLimitImageExpiredCount: 0, // 数据分析 PendingBundleDataAnalysisCount: data, PendingIncreaseDataAnalysisCount: 0, PendingBundleLimitDataAnalysisCount: 0, PendingIncreaseLimitDataAnalysisCount: 0, PendingBundleLimitDataAnalysisExpiredCount: 0, PendingIncreaseLimitDataAnalysisExpiredCount: 0, ProgressCount: 0, CompleteCount: 0, CreatedAt: time.Now(), UpdatedAt: time.Now(), } if err = tx.Create(&taskManagement).Error; err != nil { tx.Rollback() return commonErr.ReturnError(err, "创建任务记录失败", "创建任务记录失败: ") } } else { tx.Rollback() return commonErr.ReturnError(err, "任务记录不存在", "找不到对应的任务记录") } } else { tx.Rollback() return commonErr.ReturnError(err, "查询任务记录失败", "查询任务记录失败: ") } } else { // 2. 计算调整:正数增加分配到“非限制-套餐权益”;负数按优先级扣减 if req.AdjustVideoCount > 0 { taskManagement.PendingBundleVideoCount += req.AdjustVideoCount } else if req.AdjustVideoCount < 0 { deductVideo(&taskManagement, -req.AdjustVideoCount) } if req.AdjustPostCount > 0 { taskManagement.PendingBundleImageCount += req.AdjustPostCount } else if req.AdjustPostCount < 0 { deductImage(&taskManagement, -req.AdjustPostCount) } if req.AdjustDataCount > 0 { taskManagement.PendingBundleDataAnalysisCount += req.AdjustDataCount } else if req.AdjustDataCount < 0 { deductData(&taskManagement, -req.AdjustDataCount) } // 4. 更新TaskManagement表 updateData := map[string]interface{}{ // 视频 "pending_bundle_limit_video_expired_count": taskManagement.PendingBundleLimitVideoExpiredCount, "pending_bundle_limit_video_count": taskManagement.PendingBundleLimitVideoCount, "pending_increase_limit_video_expired_count": taskManagement.PendingIncreaseLimitVideoExpiredCount, "pending_increase_limit_video_count": taskManagement.PendingIncreaseLimitVideoCount, "pending_bundle_video_count": taskManagement.PendingBundleVideoCount, "pending_increase_video_count": taskManagement.PendingIncreaseVideoCount, // 图片 "pending_bundle_limit_image_expired_count": taskManagement.PendingBundleLimitImageExpiredCount, "pending_bundle_limit_image_count": taskManagement.PendingBundleLimitImageCount, "pending_increase_limit_image_expired_count": taskManagement.PendingIncreaseLimitImageExpiredCount, "pending_increase_limit_image_count": taskManagement.PendingIncreaseLimitImageCount, "pending_bundle_image_count": taskManagement.PendingBundleImageCount, "pending_increase_image_count": taskManagement.PendingIncreaseImageCount, // 数据分析 "pending_bundle_limit_data_analysis_expired_count": taskManagement.PendingBundleLimitDataAnalysisExpiredCount, "pending_bundle_limit_data_analysis_count": taskManagement.PendingBundleLimitDataAnalysisCount, "pending_increase_limit_data_analysis_expired_count": taskManagement.PendingIncreaseLimitDataAnalysisExpiredCount, "pending_increase_limit_data_analysis_count": taskManagement.PendingIncreaseLimitDataAnalysisCount, "pending_bundle_data_analysis_count": taskManagement.PendingBundleDataAnalysisCount, "pending_increase_data_analysis_count": taskManagement.PendingIncreaseDataAnalysisCount, // 通用 "updated_at": time.Now(), } if err = tx.Model(&taskManagement).Updates(updateData).Error; err != nil { tx.Rollback() return commonErr.ReturnError(err, "更新任务记录失败", "更新任务记录失败: ") } } // 提交事务 if err = tx.Commit().Error; err != nil { return commonErr.ReturnError(err, "提交事务失败", "提交事务失败: ") } return nil }