Files
2026-09-07 10:11:36 +08:00

205 lines
9.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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{}
// ---------- AppBearer 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{}