Version:0.0.3.dev.260203
feat: ✨ 新增任务队列任务获取与创建接口 - 编写获取任务队列中任务的接口 - 编写新增任务接口 - 完成相关测试并验证通过 ✅
This commit is contained in:
@@ -2,4 +2,5 @@ package api
|
||||
|
||||
type ApiHandlers struct {
|
||||
UserHandler *UserHandler
|
||||
TaskHandler *TaskHandler
|
||||
}
|
||||
|
||||
68
backend/api/task.go
Normal file
68
backend/api/task.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/LoveLosita/smartflow/backend/model"
|
||||
"github.com/LoveLosita/smartflow/backend/respond"
|
||||
"github.com/LoveLosita/smartflow/backend/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type TaskHandler struct {
|
||||
// 伸出手:准备接住 Service
|
||||
svc *service.TaskService
|
||||
}
|
||||
|
||||
// NewTaskHandler 创建 TaskHandler 实例
|
||||
func NewTaskHandler(svc *service.TaskService) *TaskHandler {
|
||||
return &TaskHandler{
|
||||
svc: svc,
|
||||
}
|
||||
}
|
||||
|
||||
func (th *TaskHandler) AddTask(c *gin.Context) {
|
||||
//1. 绑定请求参数
|
||||
var req model.UserAddTaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, respond.WrongParamType)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
// 用户ID从上下文中获取
|
||||
userID := c.GetInt("user_id")
|
||||
//2. 调用 Service 层处理业务逻辑
|
||||
resp, err := th.svc.AddTask(&req, userID)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, respond.InvalidPriority): //如果是无效刷新令牌或者无效claims或者无效签名方法
|
||||
c.JSON(http.StatusBadRequest, err)
|
||||
return
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, respond.InternalError(err))
|
||||
}
|
||||
}
|
||||
//3. 返回响应
|
||||
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, resp))
|
||||
}
|
||||
|
||||
func (th *TaskHandler) GetUserTasks(c *gin.Context) {
|
||||
// 用户ID从上下文中获取
|
||||
userID := c.GetInt("user_id")
|
||||
//2. 调用 Service 层处理业务逻辑
|
||||
resp, err := th.svc.GetUserTasks(userID)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, respond.UserTasksEmpty): //如果任务列表为空
|
||||
c.JSON(http.StatusOK, respond.RespWithData(respond.UserTasksEmpty, []model.Task{})) //确实没错误,但是任务列表为空,返回自定义响应
|
||||
return
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, respond.InternalError(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
//3. 返回响应
|
||||
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, resp))
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func (api *UserHandler) UserRegister(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, respond.OKWithData(respond.Ok, retUser))
|
||||
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, retUser))
|
||||
}
|
||||
|
||||
func (api *UserHandler) UserLogin(c *gin.Context) {
|
||||
@@ -68,7 +68,7 @@ func (api *UserHandler) UserLogin(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, respond.OKWithData(respond.Ok, tokens))
|
||||
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, tokens))
|
||||
}
|
||||
|
||||
func (api *UserHandler) RefreshTokenHandler(c *gin.Context) {
|
||||
@@ -93,7 +93,7 @@ func (api *UserHandler) RefreshTokenHandler(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, respond.InternalError(err))
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, respond.OKWithData(respond.Ok, tokens))
|
||||
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, tokens))
|
||||
}
|
||||
|
||||
func (api *UserHandler) UserLogout(c *gin.Context) {
|
||||
|
||||
@@ -39,13 +39,20 @@ func Start() {
|
||||
log.Fatalf("Failed to connect to database: %v", err)
|
||||
}
|
||||
rdb := inits.InitRedis()
|
||||
|
||||
//dao 层
|
||||
userRepo := dao.NewUserDAO(db)
|
||||
cacheRepo := dao.NewCacheDAO(rdb)
|
||||
taskRepo := dao.NewTaskDAO(db)
|
||||
//service 层
|
||||
userService := service.NewUserService(userRepo, cacheRepo)
|
||||
taskSv := service.NewTaskService(taskRepo)
|
||||
//api 层
|
||||
userApi := api.NewUserHandler(userService)
|
||||
taskApi := api.NewTaskHandler(taskSv)
|
||||
|
||||
handlers := &api.ApiHandlers{
|
||||
UserHandler: userApi,
|
||||
TaskHandler: taskApi,
|
||||
}
|
||||
r := routers.RegisterRouters(handlers, cacheRepo)
|
||||
routers.StartEngine(r)
|
||||
|
||||
52
backend/conv/task.go
Normal file
52
backend/conv/task.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package conv
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/LoveLosita/smartflow/backend/model"
|
||||
)
|
||||
|
||||
func UserAddTaskRequestToModel(request *model.UserAddTaskRequest, userID int) *model.Task {
|
||||
return &model.Task{
|
||||
Title: request.Title,
|
||||
Priority: request.PriorityGroup,
|
||||
DeadlineAt: request.DeadlineAt,
|
||||
UserID: userID,
|
||||
}
|
||||
}
|
||||
|
||||
func ModelToUserAddTaskResponse(task *model.Task) *model.UserAddTaskResponse {
|
||||
status := "incomplete"
|
||||
if task.IsCompleted {
|
||||
status = "completed"
|
||||
}
|
||||
return &model.UserAddTaskResponse{
|
||||
ID: task.ID,
|
||||
Title: task.Title,
|
||||
PriorityGroup: task.Priority,
|
||||
DeadlineAt: task.DeadlineAt,
|
||||
Status: status,
|
||||
CreatedAt: time.Now(), // 创建时间为当前时间
|
||||
}
|
||||
}
|
||||
|
||||
func ModelToGetUserTasksResp(tasks []model.Task) []model.GetUserTaskResp {
|
||||
var resp []model.GetUserTaskResp
|
||||
for _, task := range tasks {
|
||||
status := "incomplete"
|
||||
if task.IsCompleted {
|
||||
status = "completed"
|
||||
}
|
||||
deadline := task.DeadlineAt.Format("2006-01-02 15:04:05")
|
||||
resp = append(resp, model.GetUserTaskResp{
|
||||
ID: task.ID,
|
||||
UserID: task.UserID,
|
||||
Title: task.Title,
|
||||
PriorityGroup: task.Priority,
|
||||
Status: status,
|
||||
Deadline: deadline,
|
||||
IsCompleted: task.IsCompleted,
|
||||
})
|
||||
}
|
||||
return resp
|
||||
}
|
||||
39
backend/dao/task.go
Normal file
39
backend/dao/task.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/LoveLosita/smartflow/backend/model"
|
||||
"github.com/LoveLosita/smartflow/backend/respond"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type TaskDAO struct {
|
||||
// 这是一个口袋,用来装数据库连接实例
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewTaskDAO 创建TaskDAO实例
|
||||
// NewTaskDAO 接收一个 *gorm.DB,并把它塞进结构体的口袋里
|
||||
func NewTaskDAO(db *gorm.DB) *TaskDAO {
|
||||
return &TaskDAO{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// AddTask 为指定用户添加任务
|
||||
func (dao *TaskDAO) AddTask(req *model.Task) (*model.Task, error) {
|
||||
if err := dao.db.Create(req).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (dao *TaskDAO) GetTasksByUserID(userID int) ([]model.Task, error) {
|
||||
var tasks []model.Task
|
||||
if err := dao.db.Where("user_id = ?", userID).Find(&tasks).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(tasks) == 0 { // 如果没有任务,返回自定义错误
|
||||
return nil, respond.UserTasksEmpty
|
||||
}
|
||||
return tasks, nil
|
||||
}
|
||||
36
backend/model/task.go
Normal file
36
backend/model/task.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type Task struct {
|
||||
ID int `gorm:"primaryKey;autoIncrement"`
|
||||
UserID int `gorm:"column:user_id;index"`
|
||||
Title string `gorm:"type:varchar(255)"`
|
||||
Priority int `gorm:"not null"`
|
||||
IsCompleted bool `gorm:"column:is_completed;default:false"`
|
||||
DeadlineAt time.Time `gorm:"column:deadline_at"`
|
||||
}
|
||||
|
||||
type UserAddTaskResponse struct {
|
||||
ID int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
PriorityGroup int `json:"priority_group"`
|
||||
DeadlineAt time.Time `json:"deadline_at"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type UserAddTaskRequest struct {
|
||||
Title string `json:"title"`
|
||||
PriorityGroup int `json:"priority_group"`
|
||||
DeadlineAt time.Time `json:"deadline_at"`
|
||||
}
|
||||
type GetUserTaskResp struct {
|
||||
ID int `json:"id"`
|
||||
UserID int `json:"user_id"`
|
||||
Title string `json:"title"`
|
||||
PriorityGroup int `json:"priority_group"`
|
||||
Status string `json:"status"`
|
||||
Deadline string `json:"deadline"`
|
||||
IsCompleted bool `json:"is_completed"`
|
||||
}
|
||||
@@ -18,7 +18,7 @@ func (r Response) Error() string { // 实现 error 接口
|
||||
return r.Info
|
||||
}
|
||||
|
||||
func OKWithData(response Response, data interface{}) FinalResponse { //传入一个响应结构体和数据,返回一个最终响应结构体
|
||||
func RespWithData(response Response, data interface{}) FinalResponse { //传入一个响应结构体和数据,返回一个最终响应结构体
|
||||
var finalResponse FinalResponse
|
||||
finalResponse.Status = response.Status
|
||||
finalResponse.Info = response.Info
|
||||
@@ -39,6 +39,11 @@ var ( //请求相关的响应
|
||||
Info: "success",
|
||||
}
|
||||
|
||||
UserTasksEmpty = Response{ //用户任务为空
|
||||
Status: "10001",
|
||||
Info: "user tasks empty",
|
||||
}
|
||||
|
||||
WrongName = Response{ //用户名错误
|
||||
Status: "40001",
|
||||
Info: "wrong username",
|
||||
@@ -123,4 +128,9 @@ var ( //请求相关的响应
|
||||
Status: "40017",
|
||||
Info: "user logged out",
|
||||
}
|
||||
|
||||
InvalidPriority = Response{ //无效优先级
|
||||
Status: "40018",
|
||||
Info: "invalid priority",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -48,6 +48,12 @@ func RegisterRouters(handlers *api.ApiHandlers, cache *dao.CacheDAO) *gin.Engine
|
||||
userGroup.POST("/refresh-token", handlers.UserHandler.RefreshTokenHandler)
|
||||
userGroup.POST("/logout", middleware.JWTTokenAuth(cache), handlers.UserHandler.UserLogout)
|
||||
}
|
||||
taskGroup := apiGroup.Group("/task")
|
||||
{
|
||||
taskGroup.Use(middleware.JWTTokenAuth(cache))
|
||||
taskGroup.POST("/create", handlers.TaskHandler.AddTask)
|
||||
taskGroup.GET("/get", handlers.TaskHandler.GetUserTasks)
|
||||
}
|
||||
}
|
||||
// 初始化Gin引擎
|
||||
log.Println("Routes setup completed")
|
||||
|
||||
48
backend/service/task.go
Normal file
48
backend/service/task.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/LoveLosita/smartflow/backend/conv"
|
||||
"github.com/LoveLosita/smartflow/backend/dao"
|
||||
"github.com/LoveLosita/smartflow/backend/model"
|
||||
"github.com/LoveLosita/smartflow/backend/respond"
|
||||
)
|
||||
|
||||
type TaskService struct {
|
||||
// 伸出手:准备接住 DAO
|
||||
dao *dao.TaskDAO
|
||||
}
|
||||
|
||||
// NewTaskService 创建 TaskService 实例
|
||||
func NewTaskService(dao *dao.TaskDAO) *TaskService {
|
||||
return &TaskService{
|
||||
dao: dao,
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TaskService) AddTask(req *model.UserAddTaskRequest, userID int) (*model.UserAddTaskResponse, error) {
|
||||
//1. 调用 conv 层进行转换
|
||||
taskModel := conv.UserAddTaskRequestToModel(req, userID)
|
||||
//2.检查优先级是否合法
|
||||
if taskModel.Priority < 1 || taskModel.Priority >= 5 {
|
||||
return nil, respond.InvalidPriority
|
||||
}
|
||||
//3. 调用 dao 层进行数据持久化
|
||||
createdTask, err := ts.dao.AddTask(taskModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//4. 调用 conv 层进行响应转换
|
||||
response := conv.ModelToUserAddTaskResponse(createdTask)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (ts *TaskService) GetUserTasks(userID int) ([]model.GetUserTaskResp, error) {
|
||||
//1. 调用 dao 层获取数据
|
||||
tasks, err := ts.dao.GetTasksByUserID(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//2. 调用 conv 层进行响应转换
|
||||
response := conv.ModelToGetUserTasksResp(tasks)
|
||||
return response, nil
|
||||
}
|
||||
Reference in New Issue
Block a user