duidui_fiber/internal/camp/handler/task_handler.go
2026-03-27 10:34:03 +08:00

423 lines
10 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 handler
import (
"encoding/json"
"strconv"
"dd_fiber_api/internal/camp"
"dd_fiber_api/internal/camp/service"
"github.com/gofiber/fiber/v2"
)
// TaskHandler 任务处理器
type TaskHandler struct {
taskService *service.TaskService
}
// NewTaskHandler 创建任务处理器
func NewTaskHandler(taskService *service.TaskService) *TaskHandler {
return &TaskHandler{
taskService: taskService,
}
}
// CreateTask 创建任务
func (h *TaskHandler) CreateTask(c *fiber.Ctx) error {
// 先解析为 map 以处理 task_type 的数字到字符串转换
var rawReq map[string]interface{}
if err := c.BodyParser(&rawReq); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "请求参数解析失败: " + err.Error(),
})
}
// 转换 task_type如果前端传的是数字转换为字符串
if taskTypeVal, ok := rawReq["task_type"]; ok {
switch v := taskTypeVal.(type) {
case float64: // JSON 解析数字为 float64
switch int(v) {
case 0:
rawReq["task_type"] = "unknown"
case 1:
rawReq["task_type"] = "image_text"
case 2:
rawReq["task_type"] = "video"
case 3:
rawReq["task_type"] = "subjective"
case 4:
rawReq["task_type"] = "objective"
case 5:
rawReq["task_type"] = "essay"
default:
rawReq["task_type"] = "unknown"
}
case int:
switch v {
case 0:
rawReq["task_type"] = "unknown"
case 1:
rawReq["task_type"] = "image_text"
case 2:
rawReq["task_type"] = "video"
case 3:
rawReq["task_type"] = "subjective"
case 4:
rawReq["task_type"] = "objective"
case 5:
rawReq["task_type"] = "essay"
default:
rawReq["task_type"] = "unknown"
}
}
}
// 将转换后的 map 转换为 CreateTaskRequest
var req camp.CreateTaskRequest
if campID, ok := rawReq["camp_id"].(string); ok {
req.CampID = campID
}
if sectionID, ok := rawReq["section_id"].(string); ok {
req.SectionID = sectionID
}
if taskTypeStr, ok := rawReq["task_type"].(string); ok {
req.TaskType = camp.TaskType(taskTypeStr)
}
if title, ok := rawReq["title"].(string); ok {
req.Title = title
}
// Content 和 Condition 需要特殊处理,因为它们可能是 JSON 对象
if content, ok := rawReq["content"]; ok {
contentBytes, err := json.Marshal(content)
if err == nil {
req.Content = contentBytes
} else {
req.Content = []byte("{}")
}
}
if condition, ok := rawReq["condition"]; ok {
conditionBytes, err := json.Marshal(condition)
if err == nil {
req.Condition = conditionBytes
} else {
req.Condition = []byte("{}")
}
}
if pid, ok := rawReq["prerequisite_task_id"].(string); ok {
req.PrerequisiteTaskID = pid
}
// 验证必填字段
if req.CampID == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "打卡营ID不能为空",
})
}
if req.SectionID == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "小节ID不能为空",
})
}
if req.TaskType == "" || req.TaskType == camp.TaskTypeUnknown {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "任务类型不能为空",
})
}
// 验证 Content 和 Condition 是否为有效的 JSON
if len(req.Content) == 0 {
req.Content = []byte("{}")
}
if len(req.Condition) == 0 {
req.Condition = []byte("{}")
}
resp, err := h.taskService.CreateTask(&req)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"success": false,
"message": "创建任务失败: " + err.Error(),
})
}
if !resp.Success {
return c.Status(fiber.StatusBadRequest).JSON(resp)
}
return c.Status(fiber.StatusOK).JSON(resp)
}
// GetTask 获取任务
// 支持两种方式:
// 1. 路径参数GET /api/v1/camp/tasks/:id
// 2. 查询参数GET /api/v1/camp/tasks/detail?id=xxx
func (h *TaskHandler) GetTask(c *fiber.Ctx) error {
// 优先从查询参数获取,如果没有则从路径参数获取
id := c.Query("id")
if id == "" {
id = c.Params("id")
}
// 如果路径参数是 "detail",说明是查询参数方式,需要从查询参数获取
if id == "detail" {
id = c.Query("id")
}
if id == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "任务ID不能为空",
})
}
// 获取 user_id可选
userID := c.Query("user_id")
resp, err := h.taskService.GetTask(id, userID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"success": false,
"message": "获取任务失败: " + err.Error(),
})
}
if !resp.Success {
return c.Status(fiber.StatusNotFound).JSON(resp)
}
return c.Status(fiber.StatusOK).JSON(resp)
}
// UpdateTask 更新任务
func (h *TaskHandler) UpdateTask(c *fiber.Ctx) error {
// 先解析为 map 以处理 task_type 的数字到字符串转换
var rawReq map[string]interface{}
if err := c.BodyParser(&rawReq); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "请求参数解析失败: " + err.Error(),
})
}
// 转换 task_type如果前端传的是数字转换为字符串
if taskTypeVal, ok := rawReq["task_type"]; ok {
switch v := taskTypeVal.(type) {
case float64: // JSON 解析数字为 float64
switch int(v) {
case 0:
rawReq["task_type"] = "unknown"
case 1:
rawReq["task_type"] = "image_text"
case 2:
rawReq["task_type"] = "video"
case 3:
rawReq["task_type"] = "subjective"
case 4:
rawReq["task_type"] = "objective"
case 5:
rawReq["task_type"] = "essay"
default:
rawReq["task_type"] = "unknown"
}
case int:
switch v {
case 0:
rawReq["task_type"] = "unknown"
case 1:
rawReq["task_type"] = "image_text"
case 2:
rawReq["task_type"] = "video"
case 3:
rawReq["task_type"] = "subjective"
case 4:
rawReq["task_type"] = "objective"
case 5:
rawReq["task_type"] = "essay"
default:
rawReq["task_type"] = "unknown"
}
}
}
// 将转换后的 map 转换为 UpdateTaskRequest
var req camp.UpdateTaskRequest
if id, ok := rawReq["id"].(string); ok {
req.ID = id
}
if campID, ok := rawReq["camp_id"].(string); ok {
req.CampID = campID
}
if sectionID, ok := rawReq["section_id"].(string); ok {
req.SectionID = sectionID
}
if taskTypeStr, ok := rawReq["task_type"].(string); ok {
req.TaskType = camp.TaskType(taskTypeStr)
}
if title, ok := rawReq["title"].(string); ok {
req.Title = title
}
// Content 和 Condition 需要特殊处理,因为它们可能是 JSON 对象
if content, ok := rawReq["content"]; ok {
contentBytes, err := json.Marshal(content)
if err == nil {
req.Content = contentBytes
} else {
req.Content = []byte("{}")
}
}
if condition, ok := rawReq["condition"]; ok {
conditionBytes, err := json.Marshal(condition)
if err == nil {
req.Condition = conditionBytes
} else {
req.Condition = []byte("{}")
}
}
if pid, ok := rawReq["prerequisite_task_id"].(string); ok {
req.PrerequisiteTaskID = pid
}
// 从 URL 参数获取 ID如果请求体中没有
if req.ID == "" {
req.ID = c.Query("id")
if req.ID == "" {
req.ID = c.Params("id")
}
}
if req.ID == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "任务ID不能为空",
})
}
// 验证 Content 和 Condition 是否为有效的 JSON
if len(req.Content) == 0 {
req.Content = []byte("{}")
}
if len(req.Condition) == 0 {
req.Condition = []byte("{}")
}
resp, err := h.taskService.UpdateTask(&req)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"success": false,
"message": "更新任务失败: " + err.Error(),
})
}
if !resp.Success {
return c.Status(fiber.StatusBadRequest).JSON(resp)
}
return c.Status(fiber.StatusOK).JSON(resp)
}
// DeleteTask 删除任务
func (h *TaskHandler) DeleteTask(c *fiber.Ctx) error {
var id string
// 支持从 JSON body 获取(前端可能传 {"id":"xxx"} 或 {"params":{"id":"xxx"}}
if c.Get("Content-Type") != "" && len(c.Body()) > 0 {
var body struct {
ID string `json:"id"`
Params struct {
ID string `json:"id"`
} `json:"params"`
}
if err := c.BodyParser(&body); err == nil {
if body.ID != "" {
id = body.ID
} else if body.Params.ID != "" {
id = body.Params.ID
}
}
}
if id == "" {
id = c.Query("id")
}
if id == "" {
id = c.Params("id")
}
if id == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "任务ID不能为空",
})
}
resp, err := h.taskService.DeleteTask(id)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"success": false,
"message": "删除任务失败: " + err.Error(),
})
}
if !resp.Success {
return c.Status(fiber.StatusNotFound).JSON(resp)
}
return c.Status(fiber.StatusOK).JSON(resp)
}
// ListTasks 列出任务
func (h *TaskHandler) ListTasks(c *fiber.Ctx) error {
// 显式从 Query 读取所有参数,确保 GET 请求的 camp_id、section_id 等筛选被正确接收admin 与 client 通用)
page, _ := strconv.Atoi(c.Query("page", "1"))
pageSize, _ := strconv.Atoi(c.Query("page_size", "10"))
req := camp.ListTasksRequest{
Keyword: c.Query("keyword"),
CampID: c.Query("camp_id"),
SectionID: c.Query("section_id"),
Page: page,
PageSize: pageSize,
}
if req.Page < 1 {
req.Page = 1
}
if req.PageSize < 1 {
req.PageSize = 10
}
if req.PageSize > 100 {
req.PageSize = 100
}
if s := c.Query("task_type"); s != "" {
// 支持前端传数字0=unknown,1=image_text,2=video,3=subjective,4=objective,5=essay或字符串
switch s {
case "0":
req.TaskType = camp.TaskTypeUnknown
case "1":
req.TaskType = camp.TaskTypeImageText
case "2":
req.TaskType = camp.TaskTypeVideo
case "3":
req.TaskType = camp.TaskTypeSubjective
case "4":
req.TaskType = camp.TaskTypeObjective
case "5":
req.TaskType = camp.TaskTypeEssay
default:
req.TaskType = camp.TaskType(s)
}
}
if req.TaskType == "" {
req.TaskType = camp.TaskTypeUnknown
}
resp, err := h.taskService.ListTasks(&req)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"success": false,
"message": "获取任务列表失败: " + err.Error(),
})
}
return c.Status(fiber.StatusOK).JSON(resp)
}