117 lines
2.8 KiB
Go
117 lines
2.8 KiB
Go
package response
|
|
|
|
import (
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
"github.com/gogf/gf/v2/net/ghttp"
|
|
|
|
"easygoadmin/internal/consts"
|
|
)
|
|
|
|
// ============================== 统一响应 ==============================
|
|
|
|
// Res 统一响应结构
|
|
//
|
|
// 前端按此结构解析:
|
|
// - 成功:code=0,前端仅在 code 为 0 时返回 data
|
|
// - 失败:code=1,前端弹出 msg 提示
|
|
// - 登录过期:code=401,前端跳转登录页
|
|
type Res struct {
|
|
Code int `json:"code"` // 业务状态码
|
|
Ok bool `json:"ok"` // code 为 0 时为 true
|
|
Msg string `json:"msg"` // 提示信息
|
|
Data any `json:"data"` // 响应数据
|
|
}
|
|
|
|
// PageData 分页数据结构
|
|
//
|
|
// 对应前端分页列表契约
|
|
type PageData struct {
|
|
List any `json:"list"` // 记录列表
|
|
Total int `json:"total"` // 总记录数
|
|
}
|
|
|
|
// Ok 构造成功响应
|
|
//
|
|
// data 为 nil 时输出空对象,避免前端判空逻辑失败
|
|
func Ok(data any) *Res {
|
|
if data == nil {
|
|
data = map[string]any{}
|
|
}
|
|
return &Res{Code: 0, Msg: "操作成功", Data: data}
|
|
}
|
|
|
|
// OkMsg 构造带自定义提示语的成功响应
|
|
func OkMsg(msg string, data any) *Res {
|
|
if data == nil {
|
|
data = map[string]any{}
|
|
}
|
|
return &Res{Code: 0, Msg: msg, Data: data}
|
|
}
|
|
|
|
// Page 构造分页响应
|
|
func Page(list any, total int) *Res {
|
|
return Ok(PageData{List: list, Total: total})
|
|
}
|
|
|
|
// Fail 构造错误响应
|
|
//
|
|
// 状态码 401 保持原样,其余错误码统一映射为 1,供前端弹出 msg
|
|
func Fail(err error) *Res {
|
|
intCode := gerror.Code(err).Code()
|
|
msg := err.Error()
|
|
if msg == "" {
|
|
msg = consts.CodeFailed.Message()
|
|
}
|
|
if intCode == 401 {
|
|
return &Res{Code: 401, Msg: msg, Data: map[string]any{}}
|
|
}
|
|
return &Res{Code: 1, Msg: msg, Data: map[string]any{}}
|
|
}
|
|
|
|
// Write 输出 JSON 响应
|
|
//
|
|
// 响应码记入上下文,供操作日志判断正常或异常
|
|
func Write(r *ghttp.Request, res *Res) {
|
|
WriteWithCode(r, res, res.Code)
|
|
}
|
|
|
|
// respCodeKey 与 respBodyKey 为请求上下文中的响应码与响应体键
|
|
//
|
|
// 供操作日志读取
|
|
var (
|
|
respCodeKey = struct{ name string }{"respCode"}
|
|
respBodyKey = struct{ name string }{"respBody"}
|
|
)
|
|
|
|
// WriteWithCode 输出 JSON 响应并记录指定状态码
|
|
func WriteWithCode(r *ghttp.Request, res *Res, code int) {
|
|
res.Ok = code == 0
|
|
r.SetCtxVar(respCodeKey, code)
|
|
r.SetCtxVar(respBodyKey, res)
|
|
r.Response.WriteJson(res)
|
|
}
|
|
|
|
// GetCode 读取响应码
|
|
//
|
|
// 第二个返回值表示是否已写出响应
|
|
func GetCode(r *ghttp.Request) (int, bool) {
|
|
v := r.Context().Value(respCodeKey)
|
|
if v == nil {
|
|
return 0, false
|
|
}
|
|
code, _ := v.(int)
|
|
return code, true
|
|
}
|
|
|
|
// GetBody 读取已写出的响应信封
|
|
//
|
|
// 供操作日志记录响应内容使用
|
|
func GetBody(r *ghttp.Request) (*Res, bool) {
|
|
v := r.Context().Value(respBodyKey)
|
|
if v == nil {
|
|
return nil, false
|
|
}
|
|
res, ok := v.(*Res)
|
|
return res, ok
|
|
}
|