Files
smartmate/backend/api/user.go
LoveLosita d07234e183 Version: 0.2.0.dev.260210
feat: 🗑️ 新增删除单个课程与解除安排日程接口

- 逻辑复杂,初版接口写完后才发现需求需要传切片
- 针对需求修改,通过大 for 循环和事务处理来解决问题 🔄

refactor: 🔧 移除部分冗余的用户 ID 验证逻辑

- sv/schedule.go 中,进来的 ID 已通过 redis 黑名单与 JWT 保护验证
- 去除重复的数据库查验,优化了代码流程 🛠️

refactor: 🔄 重构 API 层业务错误判断逻辑

- 抛弃了原有的手动比对方式,封装进 `respond` 包,简化判断流程
- 未来不再手动遍历数据链路,提升了开发效率 🧹

undo: ⚠️ 修复任务块添加到日程的接口问题(待修复)

- 接口允许直接修改已经安排的任务时间,且重复执行时未被禁止
- 此逻辑存在问题,计划在下个版本修复 🔧

undo: ⚠️ 重测接口的幂等性与其他特性

- 当前接口幂等性等特性尚未专门测试,后续计划重测所有接口
- 测试不充分,待进一步完善 🔄

undo: ⚠️ 修复刷新 token 接口错误处理问题

- 当前接口将 token 本身的错误以 500 错误返回,需修复此问题 🛠️
2026-02-10 19:51:05 +08:00

104 lines
2.9 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 定义API接口层
// 包含所有对外暴露的HTTP接口定义
package api
import (
"context"
"net/http"
"time"
"github.com/LoveLosita/smartflow/backend/model"
"github.com/LoveLosita/smartflow/backend/respond"
"github.com/LoveLosita/smartflow/backend/service"
"github.com/gin-gonic/gin"
)
type UserHandler struct {
// 伸出手:准备接住 Service
svc *service.UserService
}
// NewUserHandler组装 Handler 的“工厂”
func NewUserHandler(svc *service.UserService) *UserHandler {
return &UserHandler{
svc: svc, // 把传进来的 Service 揣进口袋里
}
}
// UserRegister 用户注册API
// 处理用户注册请求
func (api *UserHandler) UserRegister(c *gin.Context) {
var user model.UserRegisterRequest
err := c.ShouldBindJSON(&user)
if err != nil {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
// 创建一个带 1 秒超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Second)
defer cancel() // 记得释放资源
retUser, err := api.svc.UserRegister(ctx, user)
if err != nil {
respond.DealWithError(c, err)
return
}
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, retUser))
}
func (api *UserHandler) UserLogin(c *gin.Context) {
var req model.UserLoginRequest
err := c.ShouldBindJSON(&req)
if err != nil {
c.JSON(http.StatusOK, respond.WrongParamType)
return
}
// 创建一个带 1 秒超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Second)
defer cancel() // 记得释放资源
tokens, err := api.svc.UserLogin(ctx, &req)
if err != nil {
respond.DealWithError(c, err)
return
}
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, tokens))
}
func (api *UserHandler) RefreshTokenHandler(c *gin.Context) {
var requestBody struct {
RefreshToken string `json:"old_refresh_token"`
}
if err := c.ShouldBindJSON(&requestBody); err != nil {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
if requestBody.RefreshToken == "" {
c.JSON(http.StatusBadRequest, respond.MissingParam)
}
// 创建一个带 1 秒超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Second)
defer cancel() // 记得释放资源
tokens, err := api.svc.RefreshTokenHandler(ctx, requestBody.RefreshToken)
if err != nil {
respond.DealWithError(c, err)
return
}
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, tokens))
}
func (api *UserHandler) UserLogout(c *gin.Context) {
//1.从上下文中获取 jti 和 expireTime
claims, _ := c.Get("claims")
cl := claims.(*model.MyCustomClaims)
//2.调用 Service 层的 UserLogout 方法
// 创建一个带 1 秒超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Second)
defer cancel() // 记得释放资源
err := api.svc.UserLogout(ctx, cl.Jti, cl.ExpiresAt.Time)
if err != nil {
respond.DealWithError(c, err)
return
}
c.JSON(http.StatusOK, respond.Ok)
}