package dto import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" ) // 标注众包与时长激励(技术设计.md「App 标注众包与时长激励」): // 管理端 = 下发/停用任务、批量审核、用户标注记录、手动解冻;App = 任务列表/领取/提交/我的统计。 // ---------- 管理端 ---------- // AdminAnnotateTaskCreateReq 下发标注任务(2026-09-07 图片粒度:勾选的具体未标注图集合即任务图集, // 下发即占用(annotate_task_id 写任务 id)从未标注 tab 消失,停用任务释放未领取图) type AdminAnnotateTaskCreateReq struct { g.Meta `path:"/annotate-tasks" method:"post" summary:"下发标注任务" tags:"管理端"` DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集"` Name string `json:"name" v:"required|length:1,50" dc:"任务名"` ImageIds []int64 `json:"imageIds" v:"required|min-length:1" dc:"勾选的未标注图片 id 列表"` } type AdminAnnotateTaskCreateRes struct { Id int64 `json:"id"` } // AdminAnnotateTaskListReq 标注任务列表(datasetId 缺省=全部;详情页 tab 内嵌时按数据集过滤) type AdminAnnotateTaskListReq struct { g.Meta `path:"/annotate-tasks" method:"get" summary:"标注任务列表" tags:"管理端"` DatasetId int64 `json:"datasetId" v:"integer|min:0" dc:"数据集过滤,0=全部"` Page int `json:"page" v:"integer|min:1" dc:"页码,默认 1"` Size int `json:"size" v:"integer|min:1|max:100" dc:"每页条数,默认 20"` } // AdminAnnotateTaskItem 任务条目:池余量 + 各状态记录数 type AdminAnnotateTaskItem struct { Id int64 `json:"id"` DatasetId int64 `json:"datasetId"` DatasetName string `json:"datasetName"` Name string `json:"name"` Status string `json:"status"` PoolRemain int64 `json:"poolRemain"` Pending int64 `json:"pending"` Submitted int64 `json:"submitted"` Approved int64 `json:"approved"` Rejected int64 `json:"rejected"` CreatedAt *gtime.Time `json:"createdAt"` } type AdminAnnotateTaskListRes struct { Total int64 `json:"total"` List []*AdminAnnotateTaskItem `json:"list"` } // AdminAnnotateTaskStopReq 停用任务 type AdminAnnotateTaskStopReq struct { g.Meta `path:"/annotate-tasks/stop" method:"post" summary:"停用标注任务" tags:"管理端"` Id int64 `json:"id" v:"required|min:1" dc:"任务 id"` } type AdminAnnotateTaskStopRes struct{} // AdminAnnotateReviewReq 批量审核:通过 → review_status=2;拒绝 → 清标注回未标注池 + // 对应 submitted 记录置 rejected(触发低质统计/冻结判定) type AdminAnnotateReviewReq struct { g.Meta `path:"/annotate-review" method:"post" summary:"批量审核标注" tags:"管理端"` ImageIds []int64 `json:"imageIds" v:"required" dc:"图片 id 列表"` Approve bool `json:"approve" dc:"true=通过 false=拒绝"` } type AdminAnnotateReviewRes struct { Affected int64 `json:"affected"` // 实际变更的图片数(过滤掉不存在/非待审核) FrozenPhones []string `json:"frozenPhones"` // 本次触发冻结的用户(空=无) } // AdminAnnotateRecordListReq 用户标注记录分页(每用户每张图的处理明细;datasetId 缺省=全部) type AdminAnnotateRecordListReq struct { g.Meta `path:"/annotate-records" method:"get" summary:"用户标注记录列表" tags:"管理端"` DatasetId int64 `json:"datasetId" v:"integer|min:0" dc:"数据集过滤,0=全部"` Phone string `json:"phone" v:"length:0,20" dc:"手机号精确过滤"` TaskId int64 `json:"taskId" v:"integer|min:0" dc:"任务过滤,0=全部"` Status string `json:"status" v:"in:,pending,submitted,approved,rejected" dc:"状态过滤,空=全部"` Page int `json:"page" v:"integer|min:1" dc:"页码,默认 1"` Size int `json:"size" v:"integer|min:1|max:100" dc:"每页条数,默认 20"` } // AdminAnnotateRecordItem 记录条目(附图片文件名与数据集名,内存组装) type AdminAnnotateRecordItem struct { Id int64 `json:"id"` PhoneNum string `json:"phoneNum"` TaskId int64 `json:"taskId"` DatasetName string `json:"datasetName"` ImageId int64 `json:"imageId"` Filename string `json:"filename"` ImageUrl string `json:"imageUrl"` Status string `json:"status"` Boxes []*AdminLabelBox `json:"boxes"` CreatedAt *gtime.Time `json:"createdAt"` SubmittedAt *gtime.Time `json:"submittedAt"` ReviewedAt *gtime.Time `json:"reviewedAt"` } type AdminAnnotateRecordListRes struct { Total int64 `json:"total"` List []*AdminAnnotateRecordItem `json:"list"` } // AdminAnnotateUnfreezeReq 手动解冻 type AdminAnnotateUnfreezeReq struct { g.Meta `path:"/annotate-unfreeze" method:"post" summary:"手动解冻标注资格" tags:"管理端"` Phone string `json:"phone" v:"required|length:6,20" dc:"手机号"` } type AdminAnnotateUnfreezeRes struct{} // ---------- App(Bearer token,手机号取登录态) ---------- // AnnotateStats 我的标注统计(任务列表/我的页共用) type AnnotateStats struct { SubmittedTotal int64 `json:"submittedTotal"` // 累计有效提交 Approved int64 `json:"approved"` // 审核通过 Rejected int64 `json:"rejected"` // 审核拒绝 ApproveRatio float64 `json:"approveRatio"` // 当前统计基线内通过比例(0~1,无样本=1) ProgressDone int64 `json:"progressDone"` // 距下次奖励进度(累计提交 mod perImages) RewardPerImages int `json:"rewardPerImages"` // 每次奖励所需提交数 RewardMinutes int `json:"rewardMinutes"` // 每次奖励分钟数 TotalEarnedMinutes int `json:"totalEarnedMinutes"` // 累计获得分钟数 TodayEarnedMinutes int `json:"todayEarnedMinutes"` // 今日已得(自然日) DailyCapMinutes int `json:"dailyCapMinutes"` // 每日上限 FrozenUntil *gtime.Time `json:"frozenUntil"` // 冻结到期(nil=未冻结) ExpiresAt *gtime.Time `json:"expiresAt"` // 当前授权到期 } // AnnotateTaskListReq App 可领任务列表 type AnnotateTaskListReq struct { g.Meta `path:"/annotate/tasks" method:"get" summary:"可领标注任务列表" tags:"标注众包"` } // AnnotateTaskItem 任务条目(含池余量;冻结中仍展示但不可领取) type AnnotateTaskItem struct { Id int64 `json:"id"` Name string `json:"name"` DatasetId int64 `json:"datasetId"` DatasetName string `json:"datasetName"` Species string `json:"species"` PoolRemain int64 `json:"poolRemain"` } type AnnotateTaskListRes struct { List []*AnnotateTaskItem `json:"list"` Stats *AnnotateStats `json:"stats"` } // AnnotateClaimReq 领取:分配 ≤ClaimSize 张未处理过的池内图(pending 锁定) type AnnotateClaimReq struct { g.Meta `path:"/annotate/claim" method:"post" summary:"领取标注图片" tags:"标注众包"` TaskId int64 `json:"taskId" v:"required|min:1" dc:"任务 id"` } // AnnotateClaimImage 分配的单张图(宽高供 App 端 canvas 画框) type AnnotateClaimImage struct { ImageId int64 `json:"imageId"` Url string `json:"url"` Width int `json:"width"` Height int `json:"height"` } type AnnotateClaimRes struct { Images []*AnnotateClaimImage `json:"images"` Species string `json:"species"` } // AnnotateSubmitReq 提交标注:写 labels_json + review_status=1 待审核,每累计 RewardPerImages // 张发 RewardMinutes 分钟(当日超 DailyCapMinutes 不再发);boxes 可为空数组(画面无目标主张) type AnnotateSubmitReq struct { g.Meta `path:"/annotate/submit" method:"post" summary:"提交标注" tags:"标注众包"` ImageId int64 `json:"imageId" v:"required|min:1" dc:"图片 id"` Boxes []*AdminLabelBox `json:"boxes" dc:"标注框(空数组=画面无目标)"` } type AnnotateSubmitRes struct { Granted bool `json:"granted"` // 本次是否触发发放 Minutes int `json:"minutes"` // 本次发放分钟数(granted 时有效) TodayEarnedMinutes int `json:"todayEarnedMinutes"` // 今日已得 ExpiresAt *gtime.Time `json:"expiresAt"` // 发放后的授权到期 ProgressDone int64 `json:"progressDone"` // 距下次奖励进度 } // AnnotateMeReq 我的标注统计 type AnnotateMeReq struct { g.Meta `path:"/annotate/me" method:"get" summary:"我的标注统计" tags:"标注众包"` } type AnnotateMeRes struct { Stats *AnnotateStats `json:"stats"` } // AnnotateImageReq 标注图片访问(登录态;controller 直写响应体,服务端校验图片归属) type AnnotateImageReq struct { g.Meta `path:"/annotate/image" method:"get" summary:"标注图片访问" tags:"标注众包"` DatasetId int64 `json:"datasetId" v:"required|min:1" dc:"数据集"` Filename string `json:"filename" v:"required" dc:"文件名"` } type AnnotateImageRes struct{}