Files
smartmate/backend/api/task-class.go
LoveLosita f4bea0576c feat: 🗓️ 新增任务块排期能力并完善课程与日程模型
Version: 0.1.1.dev.260207

- 新增并测试通过将任务块排进日程接口 
- 批量导入课程接口增加单双周功能,支持只在单双周上课的课程 📚
- 任务块时间定位逻辑调整为「第几周-周几」模式 🧭

refactor: 🔨 重构时间与日程数据结构

- 完成绝对日期与相对时间的转换逻辑 🔄
  - 后续可根据需求灵活决定时间的传入与输出类型
- 再次重构 schedule 表单结构
  - 拆分为 schedule_event(单)与 schedule(多)
  - 建立前者对后者的一对多关系 🧩

fix: 🐛 大幅调整表结构与业务逻辑,修复大量历史遗留 bug 🔥
2026-02-07 16:33:30 +08:00

152 lines
4.7 KiB
Go
Raw 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 api
import (
"context"
"errors"
"net/http"
"strconv"
"time"
"github.com/LoveLosita/smartflow/backend/model"
"github.com/LoveLosita/smartflow/backend/respond"
"github.com/LoveLosita/smartflow/backend/service"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type TaskClassHandler struct {
svc *service.TaskClassService
}
// NewTaskClassHandler组装 Handler 的“工厂”
func NewTaskClassHandler(svc *service.TaskClassService) *TaskClassHandler {
return &TaskClassHandler{
svc: svc, // 把传进来的 Service 揣进口袋里
}
}
const (
create = 0
update = 1
)
func (api *TaskClassHandler) UserAddTaskClass(c *gin.Context) {
var req model.UserAddTaskClassRequest
err := c.ShouldBindJSON(&req)
if err != nil {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
userIDInterface := c.GetInt("user_id")
// 创建一个带 1 秒超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Second)
defer cancel() // 记得释放资源
err = api.svc.AddOrUpdateTaskClass(ctx, &req, userIDInterface, create, 0)
if err != nil {
if errors.Is(err, respond.WrongParamType) {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
c.JSON(http.StatusInternalServerError, respond.InternalError(err))
}
c.JSON(http.StatusOK, respond.Ok)
}
func (api *TaskClassHandler) UserGetTaskClassInfos(c *gin.Context) {
userIDInterface := c.GetInt("user_id")
// 创建一个带 1 秒超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Second)
defer cancel() // 记得释放资源
resp, err := api.svc.GetUserTaskClassInfos(ctx, userIDInterface)
if err != nil {
c.JSON(http.StatusInternalServerError, respond.InternalError(err))
return
}
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, resp))
}
func (api *TaskClassHandler) UserGetCompleteTaskClass(c *gin.Context) {
taskClassID := c.Query("task_class_id")
//将taskClassID转换为int
intTaskClassID, err := strconv.Atoi(taskClassID)
if err != nil {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
if taskClassID == "" {
c.JSON(http.StatusBadRequest, respond.MissingParam)
return
}
userIDInterface := c.GetInt("user_id")
// 创建一个带 1 秒超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Second)
defer cancel() // 记得释放资源
resp, err := api.svc.GetUserCompleteTaskClass(ctx, userIDInterface, intTaskClassID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, respond.UserTaskClassNotFound)
return
}
c.JSON(http.StatusInternalServerError, respond.InternalError(err))
return
}
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, resp))
}
func (api *TaskClassHandler) UserUpdateTaskClass(c *gin.Context) {
var req model.UserAddTaskClassRequest
err := c.ShouldBindJSON(&req)
if err != nil {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
taskClassID := c.Query("task_class_id")
//将taskClassID转换为int
intTaskClassID, err := strconv.Atoi(taskClassID)
userIDInterface := c.GetInt("user_id")
// 创建一个带 1 秒超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Second)
defer cancel() // 记得释放资源
err = api.svc.AddOrUpdateTaskClass(ctx, &req, userIDInterface, update, intTaskClassID)
if err != nil {
if errors.Is(err, respond.WrongParamType) || errors.Is(err, respond.UserTaskClassForbidden) {
c.JSON(http.StatusBadRequest, err)
return
}
c.JSON(http.StatusInternalServerError, respond.InternalError(err))
}
c.JSON(http.StatusOK, respond.Ok)
}
func (api *TaskClassHandler) UserAddTaskClassItemIntoSchedule(c *gin.Context) {
var req model.UserInsertTaskClassItemToScheduleRequest
err := c.ShouldBindJSON(&req)
if err != nil {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
taskID := c.Query("task_item_id")
//将taskID转换为int
intTaskID, err := strconv.Atoi(taskID)
if err != nil {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
userIDInterface := c.GetInt("user_id")
// 创建一个带 1 秒超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Second)
defer cancel() // 记得释放资源
err = api.svc.AddTaskClassItemIntoSchedule(ctx, &req, userIDInterface, intTaskID)
if err != nil {
if errors.Is(err, respond.TaskClassItemNotBelongToUser) || errors.Is(err, respond.CourseNotBelongToUser) ||
errors.Is(err, respond.CourseAlreadyEmbeddedByOtherTaskBlock) || errors.Is(err, respond.CourseTimeNotMatch) ||
errors.Is(err, respond.ScheduleConflict) || errors.Is(err, respond.WrongCourseID) {
c.JSON(http.StatusBadRequest, err)
return
}
c.JSON(http.StatusInternalServerError, respond.InternalError(err))
return
}
c.JSON(http.StatusOK, respond.Ok)
}