refactor: 重构后端架构为 go-zero 框架,优化项目结构
主要变更: - 采用 go-zero 框架替代 Gin,提升开发效率 - 重构项目结构,API 文件模块化组织 - 将 model 移至 api/internal/model 目录 - 移除 common 包,改为标准 pkg 目录结构 - 实现统一的仓储模式,支持配置驱动数据库切换 - 简化测试策略,专注 API 集成测试 - 更新 CLAUDE.md 文档,提供详细的开发指导 技术栈更新: - 框架: Gin → go-zero v1.6.0+ - 代码生成: 引入 goctl 工具 - 架构模式: 四层架构 → go-zero 三层架构 (Handler→Logic→Model) - 项目布局: 遵循 Go 社区标准和 go-zero 最佳实践
This commit is contained in:
@ -5,7 +5,8 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"photography-backend/internal/models"
|
||||
"photography-backend/internal/model/entity"
|
||||
"photography-backend/internal/model/dto"
|
||||
"photography-backend/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -31,8 +32,8 @@ func NewUserHandler(userService *service.UserService, logger *zap.Logger) *UserH
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} models.UserResponse
|
||||
// @Failure 401 {object} models.ErrorResponse
|
||||
// @Failure 500 {object} models.ErrorResponse
|
||||
// @Failure 401 {object} response.Error
|
||||
// @Failure 500 {object} response.Error
|
||||
// @Router /me [get]
|
||||
func (h *UserHandler) GetCurrentUser(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
@ -40,7 +41,7 @@ func (h *UserHandler) GetCurrentUser(c *gin.Context) {
|
||||
user, err := h.userService.GetUserByID(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get current user", zap.Error(err), zap.Uint("user_id", userID))
|
||||
c.JSON(http.StatusInternalServerError, models.ErrorResponse{
|
||||
c.JSON(http.StatusInternalServerError, response.Error{
|
||||
Error: "Failed to get user information",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -68,8 +69,8 @@ func (h *UserHandler) GetCurrentUser(c *gin.Context) {
|
||||
// @Produce json
|
||||
// @Param user body models.UpdateCurrentUserRequest true "用户信息"
|
||||
// @Success 200 {object} models.UserResponse
|
||||
// @Failure 400 {object} models.ErrorResponse
|
||||
// @Failure 500 {object} models.ErrorResponse
|
||||
// @Failure 400 {object} response.Error
|
||||
// @Failure 500 {object} response.Error
|
||||
// @Router /me [put]
|
||||
func (h *UserHandler) UpdateCurrentUser(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
@ -77,7 +78,7 @@ func (h *UserHandler) UpdateCurrentUser(c *gin.Context) {
|
||||
var req models.UpdateCurrentUserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
h.logger.Error("Failed to bind JSON", zap.Error(err))
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
c.JSON(http.StatusBadRequest, response.Error{
|
||||
Error: "Invalid request body",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -87,7 +88,7 @@ func (h *UserHandler) UpdateCurrentUser(c *gin.Context) {
|
||||
user, err := h.userService.UpdateCurrentUser(c.Request.Context(), userID, &req)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to update current user", zap.Error(err), zap.Uint("user_id", userID))
|
||||
c.JSON(http.StatusInternalServerError, models.ErrorResponse{
|
||||
c.JSON(http.StatusInternalServerError, response.Error{
|
||||
Error: "Failed to update user information",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -117,8 +118,8 @@ func (h *UserHandler) UpdateCurrentUser(c *gin.Context) {
|
||||
// @Param limit query int false "每页数量"
|
||||
// @Param search query string false "搜索关键词"
|
||||
// @Success 200 {object} service.UserListResponse
|
||||
// @Failure 403 {object} models.ErrorResponse
|
||||
// @Failure 500 {object} models.ErrorResponse
|
||||
// @Failure 403 {object} response.Error
|
||||
// @Failure 500 {object} response.Error
|
||||
// @Router /admin/users [get]
|
||||
func (h *UserHandler) GetUsers(c *gin.Context) {
|
||||
var params service.UserListParams
|
||||
@ -126,7 +127,7 @@ func (h *UserHandler) GetUsers(c *gin.Context) {
|
||||
// 解析查询参数
|
||||
if err := c.ShouldBindQuery(¶ms); err != nil {
|
||||
h.logger.Error("Failed to bind query params", zap.Error(err))
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
c.JSON(http.StatusBadRequest, response.Error{
|
||||
Error: "Invalid query parameters",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -136,7 +137,7 @@ func (h *UserHandler) GetUsers(c *gin.Context) {
|
||||
result, err := h.userService.GetUsers(c.Request.Context(), params)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get users", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, models.ErrorResponse{
|
||||
c.JSON(http.StatusInternalServerError, response.Error{
|
||||
Error: "Failed to get users",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -154,15 +155,15 @@ func (h *UserHandler) GetUsers(c *gin.Context) {
|
||||
// @Produce json
|
||||
// @Param id path int true "用户ID"
|
||||
// @Success 200 {object} models.UserResponse
|
||||
// @Failure 400 {object} models.ErrorResponse
|
||||
// @Failure 404 {object} models.ErrorResponse
|
||||
// @Failure 500 {object} models.ErrorResponse
|
||||
// @Failure 400 {object} response.Error
|
||||
// @Failure 404 {object} response.Error
|
||||
// @Failure 500 {object} response.Error
|
||||
// @Router /admin/users/{id} [get]
|
||||
func (h *UserHandler) GetUser(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
c.JSON(http.StatusBadRequest, response.Error{
|
||||
Error: "Invalid user ID",
|
||||
Message: "User ID must be a valid number",
|
||||
})
|
||||
@ -172,7 +173,7 @@ func (h *UserHandler) GetUser(c *gin.Context) {
|
||||
user, err := h.userService.GetUserByID(c.Request.Context(), uint(id))
|
||||
if err != nil {
|
||||
if err.Error() == "user not found" {
|
||||
c.JSON(http.StatusNotFound, models.ErrorResponse{
|
||||
c.JSON(http.StatusNotFound, response.Error{
|
||||
Error: "User not found",
|
||||
Message: "The requested user does not exist",
|
||||
})
|
||||
@ -180,7 +181,7 @@ func (h *UserHandler) GetUser(c *gin.Context) {
|
||||
}
|
||||
|
||||
h.logger.Error("Failed to get user", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, models.ErrorResponse{
|
||||
c.JSON(http.StatusInternalServerError, response.Error{
|
||||
Error: "Failed to get user",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -208,14 +209,14 @@ func (h *UserHandler) GetUser(c *gin.Context) {
|
||||
// @Produce json
|
||||
// @Param user body models.CreateUserRequest true "用户信息"
|
||||
// @Success 201 {object} models.UserResponse
|
||||
// @Failure 400 {object} models.ErrorResponse
|
||||
// @Failure 500 {object} models.ErrorResponse
|
||||
// @Failure 400 {object} response.Error
|
||||
// @Failure 500 {object} response.Error
|
||||
// @Router /admin/users [post]
|
||||
func (h *UserHandler) CreateUser(c *gin.Context) {
|
||||
var req models.CreateUserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
h.logger.Error("Failed to bind JSON", zap.Error(err))
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
c.JSON(http.StatusBadRequest, response.Error{
|
||||
Error: "Invalid request body",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -224,7 +225,7 @@ func (h *UserHandler) CreateUser(c *gin.Context) {
|
||||
|
||||
// 验证请求数据
|
||||
if err := h.validateCreateUserRequest(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
c.JSON(http.StatusBadRequest, response.Error{
|
||||
Error: "Invalid request data",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -234,7 +235,7 @@ func (h *UserHandler) CreateUser(c *gin.Context) {
|
||||
user, err := h.userService.CreateUser(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to create user", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, models.ErrorResponse{
|
||||
c.JSON(http.StatusInternalServerError, response.Error{
|
||||
Error: "Failed to create user",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -263,15 +264,15 @@ func (h *UserHandler) CreateUser(c *gin.Context) {
|
||||
// @Param id path int true "用户ID"
|
||||
// @Param user body models.UpdateUserRequest true "用户信息"
|
||||
// @Success 200 {object} models.UserResponse
|
||||
// @Failure 400 {object} models.ErrorResponse
|
||||
// @Failure 404 {object} models.ErrorResponse
|
||||
// @Failure 500 {object} models.ErrorResponse
|
||||
// @Failure 400 {object} response.Error
|
||||
// @Failure 404 {object} response.Error
|
||||
// @Failure 500 {object} response.Error
|
||||
// @Router /admin/users/{id} [put]
|
||||
func (h *UserHandler) UpdateUser(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
c.JSON(http.StatusBadRequest, response.Error{
|
||||
Error: "Invalid user ID",
|
||||
Message: "User ID must be a valid number",
|
||||
})
|
||||
@ -281,7 +282,7 @@ func (h *UserHandler) UpdateUser(c *gin.Context) {
|
||||
var req models.UpdateUserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
h.logger.Error("Failed to bind JSON", zap.Error(err))
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
c.JSON(http.StatusBadRequest, response.Error{
|
||||
Error: "Invalid request body",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -291,7 +292,7 @@ func (h *UserHandler) UpdateUser(c *gin.Context) {
|
||||
user, err := h.userService.UpdateUser(c.Request.Context(), uint(id), &req)
|
||||
if err != nil {
|
||||
if err.Error() == "user not found" {
|
||||
c.JSON(http.StatusNotFound, models.ErrorResponse{
|
||||
c.JSON(http.StatusNotFound, response.Error{
|
||||
Error: "User not found",
|
||||
Message: "The requested user does not exist",
|
||||
})
|
||||
@ -299,7 +300,7 @@ func (h *UserHandler) UpdateUser(c *gin.Context) {
|
||||
}
|
||||
|
||||
h.logger.Error("Failed to update user", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, models.ErrorResponse{
|
||||
c.JSON(http.StatusInternalServerError, response.Error{
|
||||
Error: "Failed to update user",
|
||||
Message: err.Error(),
|
||||
})
|
||||
@ -327,15 +328,15 @@ func (h *UserHandler) UpdateUser(c *gin.Context) {
|
||||
// @Produce json
|
||||
// @Param id path int true "用户ID"
|
||||
// @Success 204 "No Content"
|
||||
// @Failure 400 {object} models.ErrorResponse
|
||||
// @Failure 404 {object} models.ErrorResponse
|
||||
// @Failure 500 {object} models.ErrorResponse
|
||||
// @Failure 400 {object} response.Error
|
||||
// @Failure 404 {object} response.Error
|
||||
// @Failure 500 {object} response.Error
|
||||
// @Router /admin/users/{id} [delete]
|
||||
func (h *UserHandler) DeleteUser(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
c.JSON(http.StatusBadRequest, response.Error{
|
||||
Error: "Invalid user ID",
|
||||
Message: "User ID must be a valid number",
|
||||
})
|
||||
@ -345,7 +346,7 @@ func (h *UserHandler) DeleteUser(c *gin.Context) {
|
||||
// 防止删除自己
|
||||
currentUserID := c.GetUint("user_id")
|
||||
if uint(id) == currentUserID {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
c.JSON(http.StatusBadRequest, response.Error{
|
||||
Error: "Cannot delete yourself",
|
||||
Message: "You cannot delete your own account",
|
||||
})
|
||||
@ -355,7 +356,7 @@ func (h *UserHandler) DeleteUser(c *gin.Context) {
|
||||
err = h.userService.DeleteUser(c.Request.Context(), uint(id))
|
||||
if err != nil {
|
||||
if err.Error() == "user not found" {
|
||||
c.JSON(http.StatusNotFound, models.ErrorResponse{
|
||||
c.JSON(http.StatusNotFound, response.Error{
|
||||
Error: "User not found",
|
||||
Message: "The requested user does not exist",
|
||||
})
|
||||
@ -363,7 +364,7 @@ func (h *UserHandler) DeleteUser(c *gin.Context) {
|
||||
}
|
||||
|
||||
h.logger.Error("Failed to delete user", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, models.ErrorResponse{
|
||||
c.JSON(http.StatusInternalServerError, response.Error{
|
||||
Error: "Failed to delete user",
|
||||
Message: err.Error(),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user