|
|
package websocket |
|
|
|
|
|
import ( |
|
|
"fmt" |
|
|
"mime/multipart" |
|
|
"net/http" |
|
|
"regexp" |
|
|
"strings" |
|
|
|
|
|
"github.com/Tencent/AI-Infra-Guard/pkg/database" |
|
|
|
|
|
"github.com/gin-gonic/gin" |
|
|
"trpc.group/trpc-go/trpc-go/log" |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type TaskCreateRequest struct { |
|
|
ID string `json:"id" validate:"required"` |
|
|
SessionID string `json:"sessionId" validate:"required"` |
|
|
Username string `json:"username,omitempty"` |
|
|
Task string `json:"taskType" validate:"required"` |
|
|
Timestamp int64 `json:"timestamp" validate:"required"` |
|
|
Content string `json:"content" validate:"required"` |
|
|
Params map[string]interface{} `json:"params,omitempty"` |
|
|
Attachments []string `json:"attachments,omitempty"` |
|
|
CountryIsoCode string `json:"countryIsoCode,omitempty"` |
|
|
} |
|
|
|
|
|
|
|
|
type TaskEventMessage struct { |
|
|
ID string `json:"id" validate:"required"` |
|
|
Type string `json:"type" validate:"required"` |
|
|
SessionID string `json:"sessionId" validate:"required"` |
|
|
Timestamp int64 `json:"timestamp" validate:"required"` |
|
|
Event interface{} `json:"event" validate:"required"` |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type LiveStatusEvent struct { |
|
|
ID string `json:"id" validate:"required"` |
|
|
Type string `json:"type" validate:"required"` |
|
|
Timestamp int64 `json:"timestamp" validate:"required"` |
|
|
Text string `json:"text" validate:"required"` |
|
|
} |
|
|
|
|
|
|
|
|
type PlanUpdateEvent struct { |
|
|
ID string `json:"id" validate:"required"` |
|
|
Type string `json:"type" validate:"required"` |
|
|
Timestamp int64 `json:"timestamp" validate:"required"` |
|
|
Tasks []PlanTaskItem `json:"tasks" validate:"required"` |
|
|
} |
|
|
|
|
|
type PlanTaskItem struct { |
|
|
StepID string `json:"stepId" validate:"required"` |
|
|
Status string `json:"status" validate:"required"` |
|
|
Title string `json:"title" validate:"required"` |
|
|
StartedAt int64 `json:"startedAt" validate:"required"` |
|
|
} |
|
|
|
|
|
|
|
|
type NewPlanStepEvent struct { |
|
|
ID string `json:"id" validate:"required"` |
|
|
Type string `json:"type" validate:"required"` |
|
|
Timestamp int64 `json:"timestamp" validate:"required"` |
|
|
StepID string `json:"stepId" validate:"required"` |
|
|
Title string `json:"title" validate:"required"` |
|
|
} |
|
|
|
|
|
|
|
|
type StatusUpdateEvent struct { |
|
|
ID string `json:"id" validate:"required"` |
|
|
Type string `json:"type" validate:"required"` |
|
|
Timestamp int64 `json:"timestamp" validate:"required"` |
|
|
AgentStatus string `json:"agentStatus" validate:"required"` |
|
|
Brief string `json:"brief,omitempty"` |
|
|
Description string `json:"description,omitempty"` |
|
|
NoRender bool `json:"noRender,omitempty"` |
|
|
PlanStepID string `json:"planStepId,omitempty"` |
|
|
} |
|
|
|
|
|
|
|
|
type ToolUsedEvent struct { |
|
|
ID string `json:"id" validate:"required"` |
|
|
Type string `json:"type" validate:"required"` |
|
|
Timestamp int64 `json:"timestamp" validate:"required"` |
|
|
Description string `json:"description" validate:"required"` |
|
|
PlanStepID string `json:"planStepId,omitempty"` |
|
|
StatusID string `json:"statusId,omitempty"` |
|
|
Tools []ToolInfo `json:"tools" validate:"required"` |
|
|
Detail interface{} `json:"detail,omitempty"` |
|
|
} |
|
|
|
|
|
|
|
|
type ToolInfo struct { |
|
|
ToolID string `json:"toolId" validate:"required"` |
|
|
Tool string `json:"tool" validate:"required"` |
|
|
Status string `json:"status" validate:"required"` |
|
|
Brief string `json:"brief,omitempty"` |
|
|
Message interface{} `json:"message,omitempty"` |
|
|
Result string `json:"result,omitempty"` |
|
|
} |
|
|
|
|
|
|
|
|
type ActionLogEvent struct { |
|
|
ID string `json:"id" validate:"required"` |
|
|
Type string `json:"type" validate:"required"` |
|
|
Timestamp int64 `json:"timestamp" validate:"required"` |
|
|
ActionID string `json:"actionId" validate:"required"` |
|
|
Tool string `json:"tool" validate:"required"` |
|
|
PlanStepID string `json:"planStepId,omitempty"` |
|
|
ActionLog string `json:"actionLog" validate:"required"` |
|
|
} |
|
|
|
|
|
|
|
|
type ResultUpdateEvent struct { |
|
|
ID string `json:"id" validate:"required"` |
|
|
Type string `json:"type" validate:"required"` |
|
|
Timestamp int64 `json:"timestamp" validate:"required"` |
|
|
Result interface{} `json:"result" validate:"required"` |
|
|
} |
|
|
|
|
|
|
|
|
type TaskAssignMessage struct { |
|
|
Type string `json:"type" validate:"required"` |
|
|
Content TaskContent `json:"content" validate:"required"` |
|
|
} |
|
|
|
|
|
|
|
|
type TaskContent struct { |
|
|
SessionID string `json:"sessionId" validate:"required"` |
|
|
TaskType string `json:"taskType" validate:"required"` |
|
|
Content string `json:"content" validate:"required"` |
|
|
Params map[string]interface{} `json:"params,omitempty"` |
|
|
Attachments []string `json:"attachments,omitempty"` |
|
|
Timeout int `json:"timeout,omitempty"` |
|
|
CountryIsoCode string `json:"countryIsoCode,omitempty"` |
|
|
} |
|
|
|
|
|
|
|
|
type TaskUpdateRequest struct { |
|
|
Title string `json:"title" validate:"required"` |
|
|
} |
|
|
|
|
|
|
|
|
func getTraceID(c *gin.Context) string { |
|
|
if traceID, exists := c.Get("trace_id"); exists { |
|
|
if id, ok := traceID.(string); ok { |
|
|
return id |
|
|
} |
|
|
} |
|
|
return "unknown" |
|
|
} |
|
|
|
|
|
|
|
|
func isValidSessionID(sessionId string) bool { |
|
|
|
|
|
matched, _ := regexp.MatchString(`^[a-zA-Z0-9_-]+$`, sessionId) |
|
|
return matched && len(sessionId) > 0 && len(sessionId) <= 50 |
|
|
} |
|
|
|
|
|
|
|
|
func validateFileUpload(header *multipart.FileHeader) error { |
|
|
|
|
|
originalName := header.Filename |
|
|
if originalName == "" { |
|
|
return fmt.Errorf("文件名不能为空") |
|
|
} |
|
|
|
|
|
|
|
|
if strings.Contains(originalName, "..") || strings.Contains(originalName, "/") || strings.Contains(originalName, "\\") { |
|
|
return fmt.Errorf("文件名包含非法字符") |
|
|
} |
|
|
return nil |
|
|
} |
|
|
|
|
|
|
|
|
func validateTaskUpdateRequest(req *TaskUpdateRequest) error { |
|
|
if req.Title != "" { |
|
|
|
|
|
req.Title = strings.TrimSpace(req.Title) |
|
|
if len(req.Title) > 100 { |
|
|
return fmt.Errorf("标题长度超过限制") |
|
|
} |
|
|
} |
|
|
return nil |
|
|
} |
|
|
|
|
|
|
|
|
func HandleTaskSSE(c *gin.Context, tm *TaskManager) { |
|
|
traceID := getTraceID(c) |
|
|
sessionId := c.Param("sessionId") |
|
|
if sessionId == "" { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "sessionId不能为空", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if !isValidSessionID(sessionId) { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "无效的sessionId格式", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
_, err := tm.taskStore.GetSession(sessionId) |
|
|
if err != nil { |
|
|
c.JSON(http.StatusNotFound, gin.H{ |
|
|
"status": 1, |
|
|
"message": "任务不存在", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
username := c.GetString("username") |
|
|
|
|
|
|
|
|
err = tm.EstablishSSEConnection(c.Writer, sessionId, username, traceID) |
|
|
if err != nil { |
|
|
log.Errorf("建立SSE连接失败: trace_id=%s, sessionId=%s, username=%s, error=%v", traceID, sessionId, username, err) |
|
|
c.JSON(http.StatusInternalServerError, gin.H{ |
|
|
"status": 1, |
|
|
"message": "建立SSE连接失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Infof("SSE连接建立成功: trace_id=%s, sessionId=%s, username=%s", traceID, sessionId, username) |
|
|
|
|
|
|
|
|
<-c.Request.Context().Done() |
|
|
|
|
|
|
|
|
tm.CloseSSESession(sessionId) |
|
|
log.Infof("SSE连接已断开: trace_id=%s, sessionId=%s", traceID, sessionId) |
|
|
} |
|
|
|
|
|
|
|
|
func HandleTaskCreate(c *gin.Context, tm *TaskManager) { |
|
|
traceID := getTraceID(c) |
|
|
var req TaskCreateRequest |
|
|
log.Infof("开始创建任务: trace_id=%s, req=%+v", traceID, req) |
|
|
if err := c.ShouldBindJSON(&req); err != nil { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "参数错误", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if !isValidSessionID(req.SessionID) { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "无效的会话ID格式", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
username := c.GetString("username") |
|
|
|
|
|
|
|
|
req.Username = username |
|
|
|
|
|
log.Infof("开始创建任务: trace_id=%s, sessionId=%s, username=%s, taskType=%s", traceID, req.SessionID, username, req.Task) |
|
|
|
|
|
|
|
|
err := tm.AddTask(&req, traceID) |
|
|
if err != nil { |
|
|
log.Errorf("任务创建失败: trace_id=%s, sessionId=%s, username=%s, error=%v", traceID, req.SessionID, username, err) |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "任务创建失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Infof("任务创建成功: trace_id=%s, sessionId=%s, username=%s", traceID, req.SessionID, username) |
|
|
|
|
|
|
|
|
title := tm.generateTaskTitle(&req) |
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 0, |
|
|
"message": "任务创建成功", |
|
|
"data": gin.H{ |
|
|
"sessionId": req.SessionID, |
|
|
"title": title, |
|
|
}, |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
func HandleTerminateTask(c *gin.Context, tm *TaskManager) { |
|
|
traceID := getTraceID(c) |
|
|
sessionId := c.Param("sessionId") |
|
|
if sessionId == "" { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "会话ID不能为空", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if !isValidSessionID(sessionId) { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "无效的会话ID格式", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
username := c.GetString("username") |
|
|
|
|
|
log.Infof("用户请求终止任务: trace_id=%s, sessionId=%s, username=%s", traceID, sessionId, username) |
|
|
|
|
|
|
|
|
err := tm.TerminateTask(sessionId, username, traceID) |
|
|
if err != nil { |
|
|
log.Errorf("任务终止失败: trace_id=%s, sessionId=%s, username=%s, error=%v", traceID, sessionId, username, err) |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "任务终止失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Infof("任务终止成功: trace_id=%s, sessionId=%s, username=%s", traceID, sessionId, username) |
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 0, |
|
|
"message": "任务终止成功", |
|
|
"data": nil, |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
func HandleUpdateTask(c *gin.Context, tm *TaskManager) { |
|
|
traceID := getTraceID(c) |
|
|
sessionId := c.Param("sessionId") |
|
|
if sessionId == "" { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "会话ID不能为空", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if !isValidSessionID(sessionId) { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "无效的会话ID格式", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
var req TaskUpdateRequest |
|
|
if err := c.ShouldBindJSON(&req); err != nil { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "参数错误: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if err := validateTaskUpdateRequest(&req); err != nil { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "请求参数验证失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
username := c.GetString("username") |
|
|
|
|
|
log.Infof("开始更新任务: trace_id=%s, sessionId=%s, username=%s", traceID, sessionId, username) |
|
|
|
|
|
|
|
|
err := tm.UpdateTask(sessionId, &req, username, traceID) |
|
|
if err != nil { |
|
|
log.Errorf("任务信息更新失败: trace_id=%s, sessionId=%s, username=%s, error=%v", traceID, sessionId, username, err) |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "任务信息更新失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Infof("任务信息更新成功: trace_id=%s, sessionId=%s, username=%s", traceID, sessionId, username) |
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 0, |
|
|
"message": "任务信息更新成功", |
|
|
"data": nil, |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
func HandleDeleteTask(c *gin.Context, tm *TaskManager) { |
|
|
traceID := getTraceID(c) |
|
|
sessionId := c.Param("sessionId") |
|
|
if sessionId == "" { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "会话ID不能为空", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if !isValidSessionID(sessionId) { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "无效的会话ID格式", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
username := c.GetString("username") |
|
|
|
|
|
log.Infof("开始删除任务: trace_id=%s, sessionId=%s, username=%s", traceID, sessionId, username) |
|
|
|
|
|
|
|
|
err := tm.DeleteTask(sessionId, username, traceID) |
|
|
if err != nil { |
|
|
log.Errorf("任务删除失败: trace_id=%s, sessionId=%s, username=%s, error=%v", traceID, sessionId, username, err) |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "任务删除失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Infof("任务删除成功: trace_id=%s, sessionId=%s, username=%s", traceID, sessionId, username) |
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 0, |
|
|
"message": "任务删除成功", |
|
|
"data": nil, |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func HandleUploadFile(c *gin.Context, tm *TaskManager) { |
|
|
traceID := getTraceID(c) |
|
|
|
|
|
file, err := c.FormFile("file") |
|
|
if err != nil { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "获取上传文件失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if err := validateFileUpload(file); err != nil { |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "文件验证失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
username := c.GetString("username") |
|
|
log.Infof("开始文件上传: trace_id=%s, filename=%s, size=%d, username=%s", traceID, file.Filename, file.Size, username) |
|
|
|
|
|
|
|
|
uploadResult, err := tm.UploadFile(file, traceID) |
|
|
if err != nil { |
|
|
log.Errorf("文件上传失败: trace_id=%s, filename=%s, username=%s, error=%v", traceID, file.Filename, username, err) |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "文件上传失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Infof("文件上传成功: trace_id=%s, filename=%s, fileUrl=%s, username=%s", traceID, file.Filename, uploadResult.FileURL, username) |
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 0, |
|
|
"message": "文件上传成功", |
|
|
"data": uploadResult, |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
func HandleGetTaskList(c *gin.Context, tm *TaskManager) { |
|
|
traceID := getTraceID(c) |
|
|
|
|
|
username := c.GetString("username") |
|
|
query := c.Query("q") |
|
|
taskType := c.DefaultQuery("taskType", "") |
|
|
var err error |
|
|
|
|
|
log.Debugf("开始获取任务列表: trace_id=%s, username=%s, taskType=%s", traceID, username, taskType) |
|
|
var results []map[string]interface{} |
|
|
if query != "" { |
|
|
log.Debugf("搜索参数: trace_id=%s, username=%s, query=%s, taskType=%s", traceID, username, query, taskType) |
|
|
var searchParams database.SimpleSearchParams |
|
|
|
|
|
|
|
|
searchParams.Query = query |
|
|
searchParams.TaskType = taskType |
|
|
searchParams.Page = 1 |
|
|
searchParams.PageSize = 999 |
|
|
|
|
|
results, err = tm.SearchUserTasksSimple(username, searchParams, traceID) |
|
|
if err != nil { |
|
|
log.Errorf("搜索任务失败: trace_id=%s, username=%s, error=%v", traceID, username, err) |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "搜索任务失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
results, err = tm.GetUserTasksByType(username, taskType, traceID) |
|
|
if err != nil { |
|
|
log.Errorf("获取任务列表失败: trace_id=%s, username=%s, error=%v", traceID, username, err) |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 1, |
|
|
"message": "获取任务列表失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
log.Debugf("获取任务列表成功: trace_id=%s, username=%s, taskCount=%d", traceID, username, len(results)) |
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 0, |
|
|
"message": "获取任务列表成功", |
|
|
"data": gin.H{ |
|
|
"tasks": results, |
|
|
}, |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
func HandleShare(c *gin.Context, tm *TaskManager) { |
|
|
var params struct { |
|
|
Session string `json:"sessionId" binding:"required"` |
|
|
} |
|
|
if err := c.ShouldBindJSON(¶ms); err != nil { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "参数错误: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
if params.Session == "" { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "sessionId不能为空", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if !isValidSessionID(params.Session) { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "无效的sessionId格式", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
username := c.GetString("username") |
|
|
session, err := tm.taskStore.GetSession(params.Session) |
|
|
if err != nil { |
|
|
c.JSON(http.StatusInternalServerError, gin.H{ |
|
|
"status": 1, |
|
|
"message": "获取任务详情失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
if username != session.Username { |
|
|
c.JSON(http.StatusForbidden, gin.H{ |
|
|
"status": 1, |
|
|
"message": "无权限访问", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
err = tm.taskStore.SetShare(params.Session, true) |
|
|
if err != nil { |
|
|
c.JSON(http.StatusInternalServerError, gin.H{ |
|
|
"status": 1, |
|
|
"message": "设置分享失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 0, |
|
|
"message": "设置分享成功", |
|
|
"data": nil, |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
func HandleGetTaskDetail(c *gin.Context, tm *TaskManager) { |
|
|
traceID := getTraceID(c) |
|
|
sessionId := c.Param("sessionId") |
|
|
if sessionId == "" { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "sessionId不能为空", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if !isValidSessionID(sessionId) { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "无效的sessionId格式", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
username := c.GetString("username") |
|
|
|
|
|
log.Infof("开始获取任务详情: trace_id=%s, sessionId=%s, username=%s", traceID, sessionId, username) |
|
|
|
|
|
|
|
|
detail, err := tm.GetTaskDetail(sessionId, username, traceID) |
|
|
if err != nil { |
|
|
log.Errorf("获取任务详情失败: trace_id=%s, sessionId=%s, username=%s, error=%v", traceID, sessionId, username, err) |
|
|
c.JSON(http.StatusInternalServerError, gin.H{ |
|
|
"status": 1, |
|
|
"message": "获取任务详情失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Infof("获取任务详情成功: trace_id=%s, sessionId=%s, username=%s", traceID, sessionId, username) |
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{ |
|
|
"status": 0, |
|
|
"message": "获取任务详情成功", |
|
|
"data": detail, |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
func HandleDownloadFile(c *gin.Context, tm *TaskManager) { |
|
|
traceID := getTraceID(c) |
|
|
sessionId := c.Param("sessionId") |
|
|
if sessionId == "" { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "sessionId不能为空", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if !isValidSessionID(sessionId) { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "无效的会话ID格式", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
var req struct { |
|
|
FileURL string `json:"fileUrl" binding:"required"` |
|
|
} |
|
|
if err := c.ShouldBindJSON(&req); err != nil { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "参数错误: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if req.FileURL == "" { |
|
|
c.JSON(http.StatusBadRequest, gin.H{ |
|
|
"status": 1, |
|
|
"message": "文件URL不能为空", |
|
|
"data": nil, |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
username := c.GetString("username") |
|
|
|
|
|
log.Infof("开始文件下载: trace_id=%s, sessionId=%s, fileUrl=%s, username=%s", traceID, sessionId, req.FileURL, username) |
|
|
|
|
|
|
|
|
err := tm.DownloadFile(sessionId, req.FileURL, username, c, traceID) |
|
|
if err != nil { |
|
|
log.Errorf("文件下载失败: trace_id=%s, sessionId=%s, fileUrl=%s, username=%s, error=%v", traceID, sessionId, req.FileURL, username, err) |
|
|
|
|
|
switch err.Error() { |
|
|
case "任务不存在": |
|
|
c.JSON(http.StatusNotFound, gin.H{ |
|
|
"status": 1, |
|
|
"message": "任务不存在", |
|
|
"data": nil, |
|
|
}) |
|
|
case "文件不存在于此任务中": |
|
|
c.JSON(http.StatusNotFound, gin.H{ |
|
|
"status": 1, |
|
|
"message": "文件不存在于此任务中", |
|
|
"data": nil, |
|
|
}) |
|
|
case "文件不存在": |
|
|
c.JSON(http.StatusNotFound, gin.H{ |
|
|
"status": 1, |
|
|
"message": "文件不存在", |
|
|
"data": nil, |
|
|
}) |
|
|
default: |
|
|
c.JSON(http.StatusInternalServerError, gin.H{ |
|
|
"status": 1, |
|
|
"message": "文件下载失败: " + err.Error(), |
|
|
"data": nil, |
|
|
}) |
|
|
} |
|
|
return |
|
|
} |
|
|
|
|
|
log.Infof("文件下载成功: trace_id=%s, sessionId=%s, fileUrl=%s, username=%s", traceID, sessionId, req.FileURL, username) |
|
|
|
|
|
|
|
|
} |
|
|
|