Version:0.0.3.dev.260203
feat: ✨ 新增任务队列任务获取与创建接口 - 编写获取任务队列中任务的接口 - 编写新增任务接口 - 完成相关测试并验证通过 ✅
This commit is contained in:
@@ -2,4 +2,5 @@ package api
|
|||||||
|
|
||||||
type ApiHandlers struct {
|
type ApiHandlers struct {
|
||||||
UserHandler *UserHandler
|
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) {
|
func (api *UserHandler) UserLogin(c *gin.Context) {
|
||||||
@@ -68,7 +68,7 @@ func (api *UserHandler) UserLogin(c *gin.Context) {
|
|||||||
return
|
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) {
|
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.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) {
|
func (api *UserHandler) UserLogout(c *gin.Context) {
|
||||||
|
|||||||
@@ -39,13 +39,20 @@ func Start() {
|
|||||||
log.Fatalf("Failed to connect to database: %v", err)
|
log.Fatalf("Failed to connect to database: %v", err)
|
||||||
}
|
}
|
||||||
rdb := inits.InitRedis()
|
rdb := inits.InitRedis()
|
||||||
|
//dao 层
|
||||||
userRepo := dao.NewUserDAO(db)
|
userRepo := dao.NewUserDAO(db)
|
||||||
cacheRepo := dao.NewCacheDAO(rdb)
|
cacheRepo := dao.NewCacheDAO(rdb)
|
||||||
|
taskRepo := dao.NewTaskDAO(db)
|
||||||
|
//service 层
|
||||||
userService := service.NewUserService(userRepo, cacheRepo)
|
userService := service.NewUserService(userRepo, cacheRepo)
|
||||||
|
taskSv := service.NewTaskService(taskRepo)
|
||||||
|
//api 层
|
||||||
userApi := api.NewUserHandler(userService)
|
userApi := api.NewUserHandler(userService)
|
||||||
|
taskApi := api.NewTaskHandler(taskSv)
|
||||||
|
|
||||||
handlers := &api.ApiHandlers{
|
handlers := &api.ApiHandlers{
|
||||||
UserHandler: userApi,
|
UserHandler: userApi,
|
||||||
|
TaskHandler: taskApi,
|
||||||
}
|
}
|
||||||
r := routers.RegisterRouters(handlers, cacheRepo)
|
r := routers.RegisterRouters(handlers, cacheRepo)
|
||||||
routers.StartEngine(r)
|
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
|
return r.Info
|
||||||
}
|
}
|
||||||
|
|
||||||
func OKWithData(response Response, data interface{}) FinalResponse { //传入一个响应结构体和数据,返回一个最终响应结构体
|
func RespWithData(response Response, data interface{}) FinalResponse { //传入一个响应结构体和数据,返回一个最终响应结构体
|
||||||
var finalResponse FinalResponse
|
var finalResponse FinalResponse
|
||||||
finalResponse.Status = response.Status
|
finalResponse.Status = response.Status
|
||||||
finalResponse.Info = response.Info
|
finalResponse.Info = response.Info
|
||||||
@@ -39,6 +39,11 @@ var ( //请求相关的响应
|
|||||||
Info: "success",
|
Info: "success",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserTasksEmpty = Response{ //用户任务为空
|
||||||
|
Status: "10001",
|
||||||
|
Info: "user tasks empty",
|
||||||
|
}
|
||||||
|
|
||||||
WrongName = Response{ //用户名错误
|
WrongName = Response{ //用户名错误
|
||||||
Status: "40001",
|
Status: "40001",
|
||||||
Info: "wrong username",
|
Info: "wrong username",
|
||||||
@@ -123,4 +128,9 @@ var ( //请求相关的响应
|
|||||||
Status: "40017",
|
Status: "40017",
|
||||||
Info: "user logged out",
|
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("/refresh-token", handlers.UserHandler.RefreshTokenHandler)
|
||||||
userGroup.POST("/logout", middleware.JWTTokenAuth(cache), handlers.UserHandler.UserLogout)
|
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引擎
|
// 初始化Gin引擎
|
||||||
log.Println("Routes setup completed")
|
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