package services import ( "context" "os" "path/filepath" "sync" "time" "qr-scanner/models" ) type TaskStatus string const ( TaskUploaded TaskStatus = "uploaded" // 上传完成 TaskProcessing TaskStatus = "processing" // 处理中 TaskCompleted TaskStatus = "completed" // 处理完成 TaskCanceled TaskStatus = "canceled" // 已取消 TaskFailed TaskStatus = "failed" // 处理失败 TaskExpired TaskStatus = "expired" // 已过期 ) type TaskFile struct { Index int // 文件索引 RelPath string // 相对路径 AbsPath string // 绝对路径 } type Task struct { ID string // 任务 ID TempDir string // 临时目录 CreatedAt time.Time // 创建时间 UpdatedAt time.Time // 更新时间 EndedAt time.Time // 结束时间 Status TaskStatus // 任务状态 Files []TaskFile // 任务文件列表 Concurrency int // 并发数 TimeoutS int // 超时时间(秒) Progress *Progress // 进度信息 ExcelPath string // 导出 Excel 路径 cancelMu sync.Mutex // 取消锁 cancel context.CancelFunc // 取消函数 } func (t *Task) SetCancel(cancel context.CancelFunc) { t.cancelMu.Lock() t.cancel = cancel t.cancelMu.Unlock() } func (t *Task) Cancel() { t.cancelMu.Lock() cancel := t.cancel t.cancelMu.Unlock() if cancel != nil { cancel() } } func (t *Task) Cleanup() error { if t.TempDir == "" { return nil } return os.RemoveAll(t.TempDir) } func (t *Task) ExportFilename() string { return filepath.Join(t.TempDir, "export", ExportFilename(time.Now())) } func (t *Task) Results() map[int]models.ScanResult { if t.Progress == nil { return map[int]models.ScanResult{} } return t.Progress.ResultsSnapshot() }