fix(phase2a): handleError 增强 + 代码格式化 + 测试报告归档

- auth/contact Controller handleError 增加 fallbackMsg 可变参数,未知错误可返回更有语义的降级提示
- import 排序、变量对齐等 gofmt 格式规范化
- 新增管理端测试报告和路由验证报告

Made-with: Cursor
This commit is contained in:
bujinyuan
2026-03-03 09:51:43 +08:00
parent 2c59500e27
commit c8ae70ef97
9 changed files with 616 additions and 59 deletions

View File

@@ -6,9 +6,9 @@ import (
"errors"
"math"
adminDAO "github.com/echochat/backend/app/admin/dao"
authDAO "github.com/echochat/backend/app/auth/dao"
"github.com/echochat/backend/app/auth/model"
adminDAO "github.com/echochat/backend/app/admin/dao"
"github.com/echochat/backend/app/constants"
"github.com/echochat/backend/app/dto"
"github.com/echochat/backend/pkg/logs"

View File

@@ -40,7 +40,7 @@ func (ctrl *AdminAuthController) AdminLogin(c *gin.Context) {
resp, err := ctrl.authService.AdminLogin(ctx, &req, c.ClientIP())
if err != nil {
handleAuthError(c, err)
handleAuthError(c, err, "管理员登录失败")
return
}

View File

@@ -43,7 +43,7 @@ func (ctrl *AuthController) Register(c *gin.Context) {
resp, err := ctrl.authService.Register(ctx, &req)
if err != nil {
handleAuthError(c, err)
handleAuthError(c, err, "注册失败")
return
}
@@ -70,7 +70,7 @@ func (ctrl *AuthController) Login(c *gin.Context) {
resp, err := ctrl.authService.Login(ctx, &req, c.ClientIP(), constants.ClientTypeFrontend)
if err != nil {
handleAuthError(c, err)
handleAuthError(c, err, "登录失败")
return
}
@@ -118,7 +118,7 @@ func (ctrl *AuthController) RefreshToken(c *gin.Context) {
resp, err := ctrl.authService.RefreshToken(ctx, req.RefreshToken)
if err != nil {
handleAuthError(c, err)
handleAuthError(c, err, "刷新 Token 失败")
return
}
@@ -141,7 +141,7 @@ func (ctrl *AuthController) GetProfile(c *gin.Context) {
userInfo, err := ctrl.authService.GetProfile(ctx, userID)
if err != nil {
handleAuthError(c, err)
handleAuthError(c, err, "获取个人信息失败")
return
}
@@ -171,7 +171,7 @@ func (ctrl *AuthController) UpdateProfile(c *gin.Context) {
userInfo, err := ctrl.authService.UpdateProfile(ctx, userID, &req)
if err != nil {
handleAuthError(c, err)
handleAuthError(c, err, "更新个人资料失败")
return
}
@@ -200,15 +200,17 @@ func (ctrl *AuthController) ChangePassword(c *gin.Context) {
logs.Info(ctx, funcName, "修改密码", zap.Int64("user_id", userID))
if err := ctrl.authService.ChangePassword(ctx, userID, &req); err != nil {
handleAuthError(c, err)
handleAuthError(c, err, "修改密码失败")
return
}
utils.ResponseOK(c, nil)
}
// handleAuthError 统一处理认证相关业务错误映射到对应的 HTTP 状态码
func handleAuthError(c *gin.Context, err error) {
// handleAuthError 统一认证业务错误映射
// 已知业务错误 → 返回 Service 层定义的具体提示(如"账号已被禁用"
// 未知错误 → 返回 fallbackMsg未传则默认"服务器内部错误"
func handleAuthError(c *gin.Context, err error, fallbackMsg ...string) {
switch err {
case service.ErrUserAlreadyExists:
utils.ResponseBadRequest(c, err.Error())
@@ -225,6 +227,10 @@ func handleAuthError(c *gin.Context, err error) {
case service.ErrRefreshTokenType:
utils.ResponseBadRequest(c, err.Error())
default:
utils.ResponseError(c, "服务器内部错误")
msg := "服务器内部错误"
if len(fallbackMsg) > 0 && fallbackMsg[0] != "" {
msg = fallbackMsg[0]
}
utils.ResponseError(c, msg)
}
}

View File

@@ -41,7 +41,7 @@ func (ctl *ContactController) GetFriendList(c *gin.Context) {
friends, err := ctl.contactService.GetFriendList(ctx, userID, groupID)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "获取好友列表失败")
return
}
utils.ResponseOK(c, friends)
@@ -65,7 +65,7 @@ func (ctl *ContactController) SendFriendRequest(c *gin.Context) {
err := ctl.contactService.SendFriendRequest(ctx, userID, req.TargetID, req.Message)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "发送好友申请失败")
return
}
utils.ResponseOK(c, nil)
@@ -89,7 +89,7 @@ func (ctl *ContactController) AcceptFriendRequest(c *gin.Context) {
err := ctl.contactService.AcceptFriendRequest(ctx, req.RequestID, userID)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "接受好友申请失败")
return
}
utils.ResponseOK(c, nil)
@@ -113,7 +113,7 @@ func (ctl *ContactController) RejectFriendRequest(c *gin.Context) {
err := ctl.contactService.RejectFriendRequest(ctx, req.RequestID, userID)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "拒绝好友申请失败")
return
}
utils.ResponseOK(c, nil)
@@ -131,7 +131,7 @@ func (ctl *ContactController) GetPendingRequests(c *gin.Context) {
requests, err := ctl.contactService.GetPendingRequests(ctx, userID)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "获取好友申请列表失败")
return
}
utils.ResponseOK(c, requests)
@@ -154,7 +154,7 @@ func (ctl *ContactController) DeleteFriend(c *gin.Context) {
}
if err := ctl.contactService.DeleteFriend(ctx, userID, friendID); err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "删除好友失败")
return
}
utils.ResponseOK(c, nil)
@@ -183,7 +183,7 @@ func (ctl *ContactController) UpdateRemark(c *gin.Context) {
}
if err := ctl.contactService.UpdateRemark(ctx, userID, friendID, req.Remark); err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "更新备注失败")
return
}
utils.ResponseOK(c, nil)
@@ -207,7 +207,7 @@ func (ctl *ContactController) BlockUser(c *gin.Context) {
err := ctl.contactService.BlockUser(ctx, userID, req.TargetID)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "拉黑用户失败")
return
}
utils.ResponseOK(c, nil)
@@ -230,7 +230,7 @@ func (ctl *ContactController) UnblockUser(c *gin.Context) {
}
if err := ctl.contactService.UnblockUser(ctx, userID, targetID); err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "取消拉黑失败")
return
}
utils.ResponseOK(c, nil)
@@ -248,7 +248,7 @@ func (ctl *ContactController) GetBlockList(c *gin.Context) {
blocked, err := ctl.contactService.GetBlockList(ctx, userID)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "获取黑名单失败")
return
}
utils.ResponseOK(c, blocked)
@@ -275,7 +275,7 @@ func (ctl *ContactController) SearchUsers(c *gin.Context) {
users, total, err := ctl.contactService.SearchUsers(ctx, userID, keyword, page, pageSize)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "搜索用户失败")
return
}
utils.ResponseOK(c, gin.H{
@@ -296,7 +296,7 @@ func (ctl *ContactController) GetRecommendFriends(c *gin.Context) {
friends, err := ctl.contactService.GetRecommendFriends(ctx, userID)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "获取好友推荐失败")
return
}
utils.ResponseOK(c, friends)
@@ -314,7 +314,7 @@ func (ctl *ContactController) GetGroups(c *gin.Context) {
groups, err := ctl.contactService.GetGroups(ctx, userID)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "获取分组列表失败")
return
}
utils.ResponseOK(c, groups)
@@ -338,7 +338,7 @@ func (ctl *ContactController) CreateGroup(c *gin.Context) {
group, err := ctl.contactService.CreateGroup(ctx, userID, req.Name)
if err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "创建分组失败")
return
}
utils.ResponseCreated(c, group)
@@ -367,7 +367,7 @@ func (ctl *ContactController) UpdateGroup(c *gin.Context) {
}
if err := ctl.contactService.UpdateGroup(ctx, userID, groupID, req.Name, req.SortOrder); err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "修改分组失败")
return
}
utils.ResponseOK(c, nil)
@@ -390,7 +390,7 @@ func (ctl *ContactController) DeleteGroup(c *gin.Context) {
}
if err := ctl.contactService.DeleteGroup(ctx, userID, groupID); err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "删除分组失败")
return
}
utils.ResponseOK(c, nil)
@@ -419,14 +419,16 @@ func (ctl *ContactController) MoveToGroup(c *gin.Context) {
}
if err := ctl.contactService.MoveToGroup(ctx, userID, friendID, req.GroupID); err != nil {
ctl.handleError(c, err)
ctl.handleError(c, err, "移动好友到分组失败")
return
}
utils.ResponseOK(c, nil)
}
// handleError 统一错误处理
func (ctl *ContactController) handleError(c *gin.Context, err error) {
// handleError 统一业务错误映射
// 已知业务错误 → 返回 Service 层定义的具体提示(如"对方已将你拉黑"
// 未知错误 → 返回 fallbackMsg未传则默认"服务器内部错误"
func (ctl *ContactController) handleError(c *gin.Context, err error, fallbackMsg ...string) {
switch err {
case service.ErrSelfRequest:
utils.ResponseBadRequest(c, err.Error())
@@ -443,6 +445,10 @@ func (ctl *ContactController) handleError(c *gin.Context, err error) {
case service.ErrGroupNotFound:
utils.ResponseNotFound(c, err.Error())
default:
utils.ResponseError(c, "服务内部错误")
msg := "服务内部错误"
if len(fallbackMsg) > 0 && fallbackMsg[0] != "" {
msg = fallbackMsg[0]
}
utils.ResponseError(c, msg)
}
}

View File

@@ -15,14 +15,14 @@ import (
)
var (
ErrSelfRequest = errors.New("不能添加自己为好友")
ErrAlreadyFriend = errors.New("已经是好友了")
ErrPendingExists = errors.New("已有待处理的好友申请")
ErrBlocked = errors.New("对方已将你拉黑")
ErrRequestNotFound = errors.New("好友申请不存在")
ErrFriendNotFound = errors.New("好友关系不存在")
ErrGroupNotFound = errors.New("分组不存在")
ErrUserNotFound = errors.New("用户不存在")
ErrSelfRequest = errors.New("不能添加自己为好友")
ErrAlreadyFriend = errors.New("已经是好友了")
ErrPendingExists = errors.New("已有待处理的好友申请")
ErrBlocked = errors.New("对方已将你拉黑")
ErrRequestNotFound = errors.New("好友申请不存在")
ErrFriendNotFound = errors.New("好友关系不存在")
ErrGroupNotFound = errors.New("分组不存在")
ErrUserNotFound = errors.New("用户不存在")
)
// ContactService 联系人业务服务

View File

@@ -3,35 +3,35 @@ package dto
// UserListRequest 管理端用户列表查询请求参数
type UserListRequest struct {
Page int `form:"page" binding:"required,min=1"` // 页码,从 1 开始
Page int `form:"page" binding:"required,min=1"` // 页码,从 1 开始
PageSize int `form:"page_size" binding:"required,min=1,max=100"` // 每页数量1-100
Keyword string `form:"keyword"` // 搜索关键词(匹配用户名或邮箱)
Status *int `form:"status"` // 状态筛选1=正常, 2=禁用, 3=注销;为空则不筛选
Keyword string `form:"keyword"` // 搜索关键词(匹配用户名或邮箱)
Status *int `form:"status"` // 状态筛选1=正常, 2=禁用, 3=注销;为空则不筛选
}
// UserListResponse 管理端用户列表响应
type UserListResponse struct {
Total int64 `json:"total"` // 符合条件的用户总数
List []AdminUserInfo `json:"list"` // 当前页的用户列表
Total int64 `json:"total"` // 符合条件的用户总数
List []AdminUserInfo `json:"list"` // 当前页的用户列表
}
// AdminUserInfo 管理端用户信息(比 UserInfo 更详细,包含管理字段)
type AdminUserInfo struct {
ID int64 `json:"id"` // 用户 ID
Username string `json:"username"` // 用户名
Email string `json:"email"` // 邮箱
Nickname string `json:"nickname"` // 昵称
Avatar string `json:"avatar"` // 头像 URL
Gender int `json:"gender"` // 性别0=未知, 1=男, 2=女
Phone string `json:"phone,omitempty"` // 手机号
Status int `json:"status"` // 账号状态
StatusText string `json:"status_text"` // 状态中文描述
Roles []RoleInfo `json:"roles"` // 角色详情列表(含 code/name/level
MaxLevel int `json:"max_level"` // 用户最高权限等级(最小 level 值)
ID int64 `json:"id"` // 用户 ID
Username string `json:"username"` // 用户名
Email string `json:"email"` // 邮箱
Nickname string `json:"nickname"` // 昵称
Avatar string `json:"avatar"` // 头像 URL
Gender int `json:"gender"` // 性别0=未知, 1=男, 2=女
Phone string `json:"phone,omitempty"` // 手机号
Status int `json:"status"` // 账号状态
StatusText string `json:"status_text"` // 状态中文描述
Roles []RoleInfo `json:"roles"` // 角色详情列表(含 code/name/level
MaxLevel int `json:"max_level"` // 用户最高权限等级(最小 level 值)
LastLoginAt string `json:"last_login_at,omitempty"` // 最后登录时间
LastLoginIP string `json:"last_login_ip,omitempty"` // 最后登录 IP
CreatedAt string `json:"created_at"` // 注册时间
UpdatedAt string `json:"updated_at"` // 更新时间
CreatedAt string `json:"created_at"` // 注册时间
UpdatedAt string `json:"updated_at"` // 更新时间
}
// RoleInfo 角色信息(用于前端角色列表展示和角色分配)