package handler import ( "carrotskin/internal/model" "carrotskin/internal/service" "carrotskin/internal/types" "carrotskin/pkg/database" "carrotskin/pkg/logger" "net/http" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // CreateProfile 创建档案 // @Summary 创建Minecraft档案 // @Description 创建新的Minecraft角色档案,UUID由后端自动生成 // @Tags profile // @Accept json // @Produce json // @Security BearerAuth // @Param request body types.CreateProfileRequest true "档案信息(仅需提供角色名)" // @Success 200 {object} model.Response{data=types.ProfileInfo} "创建成功,返回完整档案信息(含自动生成的UUID)" // @Failure 400 {object} model.ErrorResponse "请求参数错误或已达档案数量上限" // @Failure 401 {object} model.ErrorResponse "未授权" // @Failure 500 {object} model.ErrorResponse "服务器错误" // @Router /api/v1/profile [post] func CreateProfile(c *gin.Context) { loggerInstance := logger.MustGetLogger() // 获取用户ID userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, model.NewErrorResponse( model.CodeUnauthorized, "未授权", nil, )) return } // 解析请求 var req types.CreateProfileRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, model.NewErrorResponse( model.CodeBadRequest, "请求参数错误: "+err.Error(), nil, )) return } // TODO: 从配置或数据库读取限制 maxProfiles := 5 db := database.MustGetDB() // 检查档案数量限制 if err := service.CheckProfileLimit(db, userID.(int64), maxProfiles); err != nil { c.JSON(http.StatusBadRequest, model.NewErrorResponse( model.CodeBadRequest, err.Error(), nil, )) return } // 创建档案 profile, err := service.CreateProfile(db, userID.(int64), req.Name) if err != nil { loggerInstance.Error("创建档案失败", zap.Int64("user_id", userID.(int64)), zap.String("name", req.Name), zap.Error(err), ) c.JSON(http.StatusInternalServerError, model.NewErrorResponse( model.CodeServerError, err.Error(), nil, )) return } // 返回成功响应 c.JSON(http.StatusOK, model.NewSuccessResponse(&types.ProfileInfo{ UUID: profile.UUID, UserID: profile.UserID, Name: profile.Name, SkinID: profile.SkinID, CapeID: profile.CapeID, IsActive: profile.IsActive, LastUsedAt: profile.LastUsedAt, CreatedAt: profile.CreatedAt, UpdatedAt: profile.UpdatedAt, })) } // GetProfiles 获取档案列表 // @Summary 获取档案列表 // @Description 获取当前用户的所有档案 // @Tags profile // @Accept json // @Produce json // @Security BearerAuth // @Success 200 {object} model.Response "获取成功" // @Failure 401 {object} model.ErrorResponse "未授权" // @Failure 500 {object} model.ErrorResponse "服务器错误" // @Router /api/v1/profile [get] func GetProfiles(c *gin.Context) { loggerInstance := logger.MustGetLogger() // 获取用户ID userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, model.NewErrorResponse( model.CodeUnauthorized, "未授权", nil, )) return } // 查询档案列表 profiles, err := service.GetUserProfiles(database.MustGetDB(), userID.(int64)) if err != nil { loggerInstance.Error("获取档案列表失败", zap.Int64("user_id", userID.(int64)), zap.Error(err), ) c.JSON(http.StatusInternalServerError, model.NewErrorResponse( model.CodeServerError, err.Error(), nil, )) return } // 转换为响应格式 result := make([]*types.ProfileInfo, 0, len(profiles)) for _, profile := range profiles { result = append(result, &types.ProfileInfo{ UUID: profile.UUID, UserID: profile.UserID, Name: profile.Name, SkinID: profile.SkinID, CapeID: profile.CapeID, IsActive: profile.IsActive, LastUsedAt: profile.LastUsedAt, CreatedAt: profile.CreatedAt, UpdatedAt: profile.UpdatedAt, }) } c.JSON(http.StatusOK, model.NewSuccessResponse(result)) } // GetProfile 获取档案详情 // @Summary 获取档案详情 // @Description 根据UUID获取档案详细信息 // @Tags profile // @Accept json // @Produce json // @Param uuid path string true "档案UUID" // @Success 200 {object} model.Response "获取成功" // @Failure 404 {object} model.ErrorResponse "档案不存在" // @Failure 500 {object} model.ErrorResponse "服务器错误" // @Router /api/v1/profile/{uuid} [get] func GetProfile(c *gin.Context) { loggerInstance := logger.MustGetLogger() uuid := c.Param("uuid") // 查询档案 profile, err := service.GetProfileByUUID(database.MustGetDB(), uuid) if err != nil { loggerInstance.Error("获取档案失败", zap.String("uuid", uuid), zap.Error(err), ) c.JSON(http.StatusNotFound, model.NewErrorResponse( model.CodeNotFound, err.Error(), nil, )) return } // 返回成功响应 c.JSON(http.StatusOK, model.NewSuccessResponse(&types.ProfileInfo{ UUID: profile.UUID, UserID: profile.UserID, Name: profile.Name, SkinID: profile.SkinID, CapeID: profile.CapeID, IsActive: profile.IsActive, LastUsedAt: profile.LastUsedAt, CreatedAt: profile.CreatedAt, UpdatedAt: profile.UpdatedAt, })) } // UpdateProfile 更新档案 // @Summary 更新档案 // @Description 更新档案信息 // @Tags profile // @Accept json // @Produce json // @Security BearerAuth // @Param uuid path string true "档案UUID" // @Param request body types.UpdateProfileRequest true "更新信息" // @Success 200 {object} model.Response "更新成功" // @Failure 400 {object} model.ErrorResponse "请求参数错误" // @Failure 401 {object} model.ErrorResponse "未授权" // @Failure 403 {object} model.ErrorResponse "无权操作" // @Failure 404 {object} model.ErrorResponse "档案不存在" // @Failure 500 {object} model.ErrorResponse "服务器错误" // @Router /api/v1/profile/{uuid} [put] func UpdateProfile(c *gin.Context) { loggerInstance := logger.MustGetLogger() uuid := c.Param("uuid") // 获取用户ID userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, model.NewErrorResponse( model.CodeUnauthorized, "未授权", nil, )) return } // 解析请求 var req types.UpdateProfileRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, model.NewErrorResponse( model.CodeBadRequest, "请求参数错误: "+err.Error(), nil, )) return } // 更新档案 var namePtr *string if req.Name != "" { namePtr = &req.Name } profile, err := service.UpdateProfile(database.MustGetDB(), uuid, userID.(int64), namePtr, req.SkinID, req.CapeID) if err != nil { loggerInstance.Error("更新档案失败", zap.String("uuid", uuid), zap.Int64("user_id", userID.(int64)), zap.Error(err), ) statusCode := http.StatusInternalServerError if err.Error() == "档案不存在" { statusCode = http.StatusNotFound } else if err.Error() == "无权操作此档案" { statusCode = http.StatusForbidden } c.JSON(statusCode, model.NewErrorResponse( model.CodeServerError, err.Error(), nil, )) return } // 返回成功响应 c.JSON(http.StatusOK, model.NewSuccessResponse(&types.ProfileInfo{ UUID: profile.UUID, UserID: profile.UserID, Name: profile.Name, SkinID: profile.SkinID, CapeID: profile.CapeID, IsActive: profile.IsActive, LastUsedAt: profile.LastUsedAt, CreatedAt: profile.CreatedAt, UpdatedAt: profile.UpdatedAt, })) } // DeleteProfile 删除档案 // @Summary 删除档案 // @Description 删除指定的Minecraft档案 // @Tags profile // @Accept json // @Produce json // @Security BearerAuth // @Param uuid path string true "档案UUID" // @Success 200 {object} model.Response "删除成功" // @Failure 401 {object} model.ErrorResponse "未授权" // @Failure 403 {object} model.ErrorResponse "无权操作" // @Failure 404 {object} model.ErrorResponse "档案不存在" // @Failure 500 {object} model.ErrorResponse "服务器错误" // @Router /api/v1/profile/{uuid} [delete] func DeleteProfile(c *gin.Context) { loggerInstance := logger.MustGetLogger() uuid := c.Param("uuid") // 获取用户ID userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, model.NewErrorResponse( model.CodeUnauthorized, "未授权", nil, )) return } // 删除档案 err := service.DeleteProfile(database.MustGetDB(), uuid, userID.(int64)) if err != nil { loggerInstance.Error("删除档案失败", zap.String("uuid", uuid), zap.Int64("user_id", userID.(int64)), zap.Error(err), ) statusCode := http.StatusInternalServerError if err.Error() == "档案不存在" { statusCode = http.StatusNotFound } else if err.Error() == "无权操作此档案" { statusCode = http.StatusForbidden } c.JSON(statusCode, model.NewErrorResponse( model.CodeServerError, err.Error(), nil, )) return } // 返回成功响应 c.JSON(http.StatusOK, model.NewSuccessResponse(gin.H{ "message": "删除成功", })) } // SetActiveProfile 设置活跃档案 // @Summary 设置活跃档案 // @Description 将指定档案设置为活跃状态 // @Tags profile // @Accept json // @Produce json // @Security BearerAuth // @Param uuid path string true "档案UUID" // @Success 200 {object} model.Response "设置成功" // @Failure 401 {object} model.ErrorResponse "未授权" // @Failure 403 {object} model.ErrorResponse "无权操作" // @Failure 404 {object} model.ErrorResponse "档案不存在" // @Failure 500 {object} model.ErrorResponse "服务器错误" // @Router /api/v1/profile/{uuid}/activate [post] func SetActiveProfile(c *gin.Context) { loggerInstance := logger.MustGetLogger() uuid := c.Param("uuid") // 获取用户ID userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, model.NewErrorResponse( model.CodeUnauthorized, "未授权", nil, )) return } // 设置活跃状态 err := service.SetActiveProfile(database.MustGetDB(), uuid, userID.(int64)) if err != nil { loggerInstance.Error("设置活跃档案失败", zap.String("uuid", uuid), zap.Int64("user_id", userID.(int64)), zap.Error(err), ) statusCode := http.StatusInternalServerError if err.Error() == "档案不存在" { statusCode = http.StatusNotFound } else if err.Error() == "无权操作此档案" { statusCode = http.StatusForbidden } c.JSON(statusCode, model.NewErrorResponse( model.CodeServerError, err.Error(), nil, )) return } // 返回成功响应 c.JSON(http.StatusOK, model.NewSuccessResponse(gin.H{ "message": "设置成功", })) }