Files
x_admin/server/core/response/response.go
T
2025-07-24 02:05:23 +08:00

226 lines
5.9 KiB
Go

package response
import (
"errors"
"net/http"
"strconv"
"x_admin/core"
"github.com/gin-gonic/gin"
"github.com/go-sql-driver/mysql"
"go.uber.org/zap"
"gorm.io/gorm"
)
// RespType 响应类型
type RespType struct {
code int
message string
data interface{}
}
// Response 响应格式结构
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
var (
// code 200成功
Success = RespType{code: 200, message: "成功"}
// code 300失败
Failed = RespType{code: 300, message: "失败"}
// code 310参数校验错误
ParamsValidError = RespType{code: 310, message: "参数校验错误"}
// code 311参数类型错误
ParamsTypeError = RespType{code: 311, message: "参数类型错误"}
RequestMethodError = RespType{code: 312, message: "请求方法错误"}
AssertArgumentError = RespType{code: 313, message: "断言参数错误"}
// code 330登录账号或密码错误
LoginAccountError = RespType{code: 330, message: "登录账号或密码错误"}
// code 331登录账号已被禁用了
LoginDisableError = RespType{code: 331, message: "登录账号已被禁用了"}
// code 332 token参数为空
TokenEmpty = RespType{code: 332, message: "token参数为空"}
// code 333 登录失效
TokenInvalid = RespType{code: 333, message: "登录失效"}
// 无相关权限
NoPermission = RespType{code: 403, message: "无相关权限"}
Request404Error = RespType{code: 404, message: "请求接口不存在"}
Request405Error = RespType{code: 405, message: "请求方法不允许"}
// code 500系统错误
SystemError = RespType{code: 500, message: "系统错误"}
)
// Error 实现error方法
func (rt RespType) Error() string {
return strconv.Itoa(rt.code) + ":" + rt.message
}
// SetMessage 以响应类型生成信息
func (rt RespType) SetMessage(message string) RespType {
rt.message = message
return rt
}
// SetData 以响应类型生成数据
func (rt RespType) SetData(data interface{}) RespType {
rt.data = data
return rt
}
// Code 获取code
func (rt RespType) Code() int {
return rt.code
}
// Msg 获取msg
func (rt RespType) Msg() string {
return rt.message
}
// Data 获取data
func (rt RespType) Data() interface{} {
return rt.data
}
// Result 统一响应
func Result(c *gin.Context, resp RespType, data interface{}) {
if data == nil {
data = resp.data
}
if resp != Success {
c.Error(resp)
}
c.JSON(http.StatusOK, Response{
Code: resp.code,
Message: resp.message,
Data: data,
})
}
// Ok 正常响应
func Ok(c *gin.Context) {
Result(c, Success, nil)
}
// // OkWithMsg 正常响应附带msg
// func OkWithMsg(c *gin.Context, message string) {
// resp := Success
// resp.message = message
// Result(c, resp, nil)
// }
// OkWithData 正常响应附带data
func OkWithData(c *gin.Context, data interface{}) {
Result(c, Success, data)
}
// respLogger 打印日志
func respLogger(resp RespType, template string, args ...interface{}) {
loggerFunc := core.Logger.WithOptions(zap.AddCallerSkip(2)).Warnf
if resp.code >= 500 {
loggerFunc = core.Logger.WithOptions(zap.AddCallerSkip(1)).Errorf
}
loggerFunc(template, args...)
}
// Fail 错误响应
func Fail(c *gin.Context, resp RespType) {
respLogger(resp, "Request Fail: url=[%s], resp=[%+v]", c.Request.URL.Path, resp)
Result(c, resp, nil)
}
// FailWithMsg 错误响应附带msg
func FailWithMsg(c *gin.Context, resp RespType, message string) {
resp.message = message
respLogger(resp, "Request FailWithMsg: url=[%s], resp=[%+v]", c.Request.URL.Path, resp)
Result(c, resp, nil)
}
// FailWithData 错误响应附带data
func FailWithData(c *gin.Context, resp RespType, data interface{}) {
respLogger(resp, "Request FailWithData: url=[%s], resp=[%+v], data=[%+v]", c.Request.URL.Path, resp, data)
Result(c, resp, data)
}
// IsFailWithResp 判断是否出现错误,并追加错误返回信息
func IsFailWithResp(c *gin.Context, err error) bool {
if err == nil {
return false
}
switch v := err.(type) {
// 自定义类型
case RespType:
data := v.Data()
if data == nil {
data = nil
}
FailWithData(c, v, data)
// 其他类型
default:
Fail(c, SystemError.SetMessage(err.Error()))
}
return true
}
// CheckAndResp 判断是否出现错误,并返回对应响应
func CheckAndResp(c *gin.Context, err error) {
if IsFailWithResp(c, err) {
return
}
Ok(c)
}
// CheckAndRespWithData 判断是否出现错误,并返回对应响应(带data数据)
func CheckAndRespWithData(c *gin.Context, data interface{}, err error) {
if IsFailWithResp(c, err) {
return
}
OkWithData(c, data)
}
// CheckErr 校验未知错误并抛出
func CheckErr(err error, template string, args ...interface{}) (e error) {
prefix := ": "
if len(args) > 0 {
prefix = " ,"
}
args = append(args, err)
if err != nil {
core.Logger.WithOptions(zap.AddCallerSkip(1)).Errorf(template+prefix+"err=[%+v]", args...)
return SystemError.SetMessage(template)
}
return
}
// 插入操作违反唯一约束时,会发生此错误:
func CheckMysqlErr(err error) (e error) {
if mysqlErr, ok := err.(*mysql.MySQLError); ok {
switch mysqlErr.Number {
case 404:
core.Logger.WithOptions(zap.AddCallerSkip(1)).Errorf("record not found: err=[%+v]", err)
return SystemError.SetMessage("数据不存在")
case 1062: // MySQL中表示重复条目的代码
core.Logger.WithOptions(zap.AddCallerSkip(1)).Infof("数据已存在: err=[%+v]", err)
return SystemError.SetMessage("数据已存在")
default:
// 处理其他错误
core.Logger.WithOptions(zap.AddCallerSkip(1)).Errorf("未知错误: err=[%+v]", err)
return err
}
}
return
}
// CheckErrDBNotRecord 校验数据库记录不存在的错误
func CheckErrDBNotRecord(err error, message string) (e error) {
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
core.Logger.WithOptions(zap.AddCallerSkip(1)).Infof("记录不存在: err=[%+v]", err)
return SystemError.SetMessage(message)
}
return
}