refactor: 新增base.Repo与base.App,重构repo与app层代码

This commit is contained in:
meilin.huang
2023-10-26 17:15:49 +08:00
parent 10f6b03fb5
commit a1303b52eb
115 changed files with 1867 additions and 1696 deletions

145
server/pkg/base/app.go Normal file
View File

@@ -0,0 +1,145 @@
package base
import (
"gorm.io/gorm"
)
// 基础application接口
type App[T any] interface {
// 新增一个实体
Insert(e T) error
// 批量新增实体
BatchInsert(models []T) error
// 根据实体id更新实体信息
UpdateById(e T) error
// 使用指定gorm db执行主要用于事务执行
UpdateByIdWithDb(db *gorm.DB, e T) error
// 根据实体主键删除实体
DeleteById(id uint64) error
// 使用指定gorm db执行主要用于事务执行
DeleteByIdWithDb(db *gorm.DB, id uint64) error
// 根据实体条件更新参数udpateFields指定字段
Updates(cond any, udpateFields map[string]any) error
// 根据实体条件删除实体
DeleteByCond(cond any) error
// 使用指定gorm db执行主要用于事务执行
DeleteByCondWithDb(db *gorm.DB, cond any) error
// 根据实体id查询
GetById(e T, id uint64, cols ...string) (T, error)
GetByIdIn(list any, ids []uint64, orderBy ...string) error
// 根据实体条件查询实体信息
GetBy(condModel T, cols ...string) error
// 根据条件查询数据映射至listModels
ListByCond(cond any, listModels any, cols ...string) error
// 获取满足model中不为空的字段值条件的所有数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体
// @param cond 条件
ListByCondOrder(cond any, list any, order ...string) error
// 根据指定条件统计model表的数量, cond为条件可以为map等
CountByCond(cond any) int64
}
// 基础application接口实现
type AppImpl[T any, R Repo[T]] struct {
Repo R // repo接口
}
// 获取repo
func (ai *AppImpl[T, R]) GetRepo() R {
return ai.Repo
}
// 新增一个实体 (单纯新增,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) Insert(e T) error {
return ai.GetRepo().Insert(e)
}
// 批量新增实体 (单纯新增,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) BatchInsert(es []T) error {
return ai.GetRepo().BatchInsert(es)
}
// 根据实体id更新实体信息 (单纯更新,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) UpdateById(e T) error {
return ai.GetRepo().UpdateById(e)
}
// 使用指定gorm db执行主要用于事务执行
func (ai *AppImpl[T, R]) UpdateByIdWithDb(db *gorm.DB, e T) error {
return ai.GetRepo().UpdateByIdWithDb(db, e)
}
// 根据实体条件更新参数udpateFields指定字段 (单纯更新,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) Updates(cond any, udpateFields map[string]any) error {
return ai.GetRepo().Updates(cond, udpateFields)
}
// 根据实体主键删除实体 (单纯删除实体,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) DeleteById(id uint64) error {
return ai.GetRepo().DeleteById(id)
}
func (ai *AppImpl[T, R]) DeleteByIdWithDb(db *gorm.DB, id uint64) error {
return ai.GetRepo().DeleteByCondWithDb(db, id)
}
// 根据指定条件删除实体 (单纯删除实体,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) DeleteByCond(cond any) error {
return ai.GetRepo().DeleteByCond(cond)
}
// 使用指定gorm db执行主要用于事务执行
func (ai *AppImpl[T, R]) DeleteByCondWithDb(db *gorm.DB, cond any) error {
return ai.GetRepo().DeleteByCondWithDb(db, cond)
}
// 根据实体id查询
func (ai *AppImpl[T, R]) GetById(e T, id uint64, cols ...string) (T, error) {
if err := ai.GetRepo().GetById(e, id, cols...); err != nil {
return e, err
}
return e, nil
}
func (ai *AppImpl[T, R]) GetByIdIn(list any, ids []uint64, orderBy ...string) error {
return ai.GetRepo().GetByIdIn(list, ids, orderBy...)
}
// 根据实体条件查询实体信息
func (ai *AppImpl[T, R]) GetBy(condModel T, cols ...string) error {
return ai.GetRepo().GetBy(condModel, cols...)
}
// 根据条件查询数据映射至listModels
func (ai *AppImpl[T, R]) ListByCond(cond any, listModels any, cols ...string) error {
return ai.GetRepo().ListByCond(cond, listModels, cols...)
}
// 获取满足model中不为空的字段值条件的所有数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体
// @param cond 条件
func (ai *AppImpl[T, R]) ListByCondOrder(cond any, list any, order ...string) error {
return ai.GetRepo().ListByCondOrder(cond, list, order...)
}
// 根据指定条件统计model表的数量, cond为条件可以为map等
func (ai *AppImpl[T, R]) CountByCond(cond any) int64 {
return ai.GetRepo().CountByCond(cond)
}

149
server/pkg/base/repo.go Normal file
View File

@@ -0,0 +1,149 @@
package base
import (
"mayfly-go/pkg/biz"
"mayfly-go/pkg/gormx"
"gorm.io/gorm"
)
// 基础repo接口
type Repo[T any] interface {
// 新增一个实体
Insert(e T) error
// 使用指定gorm db执行主要用于事务执行
InsertWithDb(db *gorm.DB, e T) error
// 批量新增实体
BatchInsert(models []T) error
// 使用指定gorm db执行主要用于事务执行
BatchInsertWithDb(db *gorm.DB, es []T) error
// 根据实体id更新实体信息
UpdateById(e T) error
// 使用指定gorm db执行主要用于事务执行
UpdateByIdWithDb(db *gorm.DB, e T) error
// 根据实体主键删除实体
DeleteById(id uint64) error
// 使用指定gorm db执行主要用于事务执行
DeleteByIdWithDb(db *gorm.DB, id uint64) error
// 根据实体条件更新参数udpateFields指定字段
Updates(cond any, udpateFields map[string]any) error
// 根据实体条件删除实体
DeleteByCond(cond any) error
// 使用指定gorm db执行主要用于事务执行
DeleteByCondWithDb(db *gorm.DB, cond any) error
// 根据实体id查询
GetById(e T, id uint64, cols ...string) error
// 根据实体id数组查询对应实体列表并将响应结果映射至list
GetByIdIn(list any, ids []uint64, orderBy ...string) error
// 根据实体条件查询实体信息
GetBy(cond T, cols ...string) error
// 根据实体条件查询数据映射至listModels
ListByCond(cond any, listModels any, cols ...string) error
// 获取满足model中不为空的字段值条件的所有数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体
// @param cond 条件
ListByCondOrder(cond any, list any, order ...string) error
// 根据指定条件统计model表的数量, cond为条件可以为map等
CountByCond(cond any) int64
}
// 基础repo接口
type RepoImpl[T any] struct {
M any // 模型实例
}
func (br *RepoImpl[T]) Insert(e T) error {
return gormx.Insert(e)
}
func (br *RepoImpl[T]) InsertWithDb(db *gorm.DB, e T) error {
return gormx.InsertWithDb(db, e)
}
func (br *RepoImpl[T]) BatchInsert(es []T) error {
return gormx.BatchInsert(es)
}
// 使用指定gorm db执行主要用于事务执行
func (br *RepoImpl[T]) BatchInsertWithDb(db *gorm.DB, es []T) error {
return gormx.BatchInsertWithDb(db, es)
}
func (br *RepoImpl[T]) UpdateById(e T) error {
return gormx.UpdateById(e)
}
func (br *RepoImpl[T]) UpdateByIdWithDb(db *gorm.DB, e T) error {
return gormx.UpdateByIdWithDb(db, e)
}
func (br *RepoImpl[T]) Updates(cond any, udpateFields map[string]any) error {
return gormx.Updates(cond, udpateFields)
}
func (br *RepoImpl[T]) DeleteById(id uint64) error {
return gormx.DeleteById(br.getModel(), id)
}
func (br *RepoImpl[T]) DeleteByIdWithDb(db *gorm.DB, id uint64) error {
return gormx.DeleteByCondWithDb(db, br.getModel(), id)
}
func (br *RepoImpl[T]) DeleteByCond(cond any) error {
return gormx.DeleteByCond(br.getModel(), cond)
}
func (br *RepoImpl[T]) DeleteByCondWithDb(db *gorm.DB, cond any) error {
return gormx.DeleteByCondWithDb(db, br.getModel(), cond)
}
func (br *RepoImpl[T]) GetById(e T, id uint64, cols ...string) error {
if err := gormx.GetById(e, id, cols...); err != nil {
return err
}
return nil
}
func (br *RepoImpl[T]) GetByIdIn(list any, ids []uint64, orderBy ...string) error {
return gormx.GetByIdIn(br.getModel(), list, ids, orderBy...)
}
func (br *RepoImpl[T]) GetBy(cond T, cols ...string) error {
return gormx.GetBy(cond, cols...)
}
func (br *RepoImpl[T]) ListByCond(cond any, listModels any, cols ...string) error {
return gormx.ListByCond(br.getModel(), cond, listModels, cols...)
}
func (br *RepoImpl[T]) ListByCondOrder(cond any, list any, order ...string) error {
return gormx.ListByCondOrder(br.getModel(), cond, list, order...)
}
func (br *RepoImpl[T]) CountByCond(cond any) int64 {
return gormx.CountByCond(br.getModel(), cond)
}
// 获取表的模型实例
func (br *RepoImpl[T]) getModel() any {
biz.IsTrue(br.M != nil, "base.RepoImpl的M字段不能为空")
return br.M
}

View File

@@ -2,43 +2,41 @@ package biz
import (
"fmt"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/utils/anyx"
"reflect"
)
func ErrIsNil(err error, msg string, params ...any) {
// 断言错误为ni
// @param msgAndParams 消息与参数占位符,第一位为错误消息可包含%s等格式化标识。其余为Sprintf格式化值内容
//
// ErrIsNil(err)
// ErrIsNil(err, "xxxx")
// ErrIsNil(err, "xxxx: %s", "yyyy")
func ErrIsNil(err error, msgAndParams ...any) {
if err != nil {
// logx.ErrorTrace(msg, err)
panic(NewBizErr(fmt.Sprintf(msg, params...)))
if len(msgAndParams) == 0 {
panic(err)
}
panic(errorx.NewBiz(fmt.Sprintf(msgAndParams[0].(string), msgAndParams[1:]...)))
}
}
func ErrIsNilAppendErr(err error, msg string) {
if err != nil {
// logx.ErrorTrace(msg, err)
panic(NewBizErr(fmt.Sprintf(msg, err.Error())))
}
}
func IsNil(err error) {
switch t := err.(type) {
case *BizError:
panic(t)
case error:
logx.Error("非业务异常: " + err.Error())
panic(NewBizErr(fmt.Sprintf("非业务异常: %s", err.Error())))
panic(errorx.NewBiz(fmt.Sprintf(msg, err.Error())))
}
}
func IsTrue(exp bool, msg string, params ...any) {
if !exp {
panic(NewBizErr(fmt.Sprintf(msg, params...)))
panic(errorx.NewBiz(fmt.Sprintf(msg, params...)))
}
}
func IsTrueBy(exp bool, err BizError) {
func IsTrueBy(exp bool, err errorx.BizError) {
if !exp {
panic(err)
}
@@ -46,30 +44,30 @@ func IsTrueBy(exp bool, err BizError) {
func NotEmpty(str string, msg string, params ...any) {
if str == "" {
panic(NewBizErr(fmt.Sprintf(msg, params...)))
panic(errorx.NewBiz(fmt.Sprintf(msg, params...)))
}
}
func NotNil(data any, msg string, params ...any) {
if reflect.ValueOf(data).IsNil() {
panic(NewBizErr(fmt.Sprintf(msg, params...)))
panic(errorx.NewBiz(fmt.Sprintf(msg, params...)))
}
}
func NotBlank(data any, msg string, params ...any) {
if anyx.IsBlank(data) {
panic(NewBizErr(fmt.Sprintf(msg, params...)))
panic(errorx.NewBiz(fmt.Sprintf(msg, params...)))
}
}
func IsEquals(data any, data1 any, msg string) {
if data != data1 {
panic(NewBizErr(msg))
panic(errorx.NewBiz(msg))
}
}
func Nil(data any, msg string) {
if !reflect.ValueOf(data).IsNil() {
panic(NewBizErr(msg))
panic(errorx.NewBiz(msg))
}
}

View File

@@ -0,0 +1,11 @@
package biz
import (
"testing"
)
func TestErrIsNil(t *testing.T) {
// ErrIsNil(NewBizErr("xxx is error"))
// ErrIsNil(NewBizErr("xxx is error"), "格式错误")
// ErrIsNil(NewBizErr("xxx is error"), "格式错误: %s, %d", "xxx", 12)
}

View File

@@ -1,40 +0,0 @@
package biz
import "fmt"
// 业务错误
type BizError struct {
code int16
err string
}
var (
Success BizError = NewBizErrCode(200, "success")
BizErr BizError = NewBizErrCode(400, "biz error")
ServerError BizError = NewBizErrCode(500, "server error")
PermissionErr BizError = NewBizErrCode(501, "token error")
)
// 错误消息
func (e BizError) Error() string {
return e.err
}
// 错误码
func (e BizError) Code() int16 {
return e.code
}
func (e BizError) String() string {
return fmt.Sprintf("errCode: %d, errMsg: %s", e.Code(), e.Error())
}
// 创建业务逻辑错误结构体,默认为业务逻辑错误
func NewBizErr(msg string) BizError {
return BizError{code: BizErr.code, err: msg}
}
// 创建业务逻辑错误结构体可设置指定错误code
func NewBizErrCode(code int16, msg string) BizError {
return BizError{code: code, err: msg}
}

View File

@@ -1,7 +1,6 @@
package cache
import (
"mayfly-go/pkg/biz"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/rediscli"
"strconv"
@@ -41,13 +40,12 @@ func GetInt(key string) int {
}
// 如果系统有设置redis信息则使用redis存否则存于本机内存。duration == -1则为永久缓存
func SetStr(key, value string, duration time.Duration) {
func SetStr(key, value string, duration time.Duration) error {
if !useRedisCache() {
checkCache()
tm.Add(key, value, duration)
return
return tm.Add(key, value, duration)
}
biz.ErrIsNilAppendErr(rediscli.Set(key, value, duration), "redis set err: %s")
return rediscli.Set(key, value, duration)
}
// 删除指定key

View File

@@ -1,7 +1,6 @@
package captcha
import (
"mayfly-go/pkg/biz"
"mayfly-go/pkg/rediscli"
"time"
@@ -12,7 +11,7 @@ var store base64Captcha.Store
var driver base64Captcha.Driver = base64Captcha.DefaultDriverDigit
// 生成验证码
func Generate() (string, string) {
func Generate() (string, string, error) {
if store == nil {
if rediscli.GetCli() != nil {
store = new(RedisStore)
@@ -23,9 +22,7 @@ func Generate() (string, string) {
c := base64Captcha.NewCaptcha(driver, store)
// 获取
id, b64s, err := c.Generate()
biz.ErrIsNilAppendErr(err, "获取验证码错误: %s")
return id, b64s
return c.Generate()
}
// 验证验证码

View File

@@ -0,0 +1,42 @@
package errorx
import (
"fmt"
)
// 业务错误
type BizError struct {
code int16
err string
}
var (
Success BizError = NewBizCode(200, "success")
BizErr BizError = NewBizCode(400, "biz error")
ServerError BizError = NewBizCode(500, "server error")
PermissionErr BizError = NewBizCode(501, "token error")
)
// 错误消息
func (e BizError) Error() string {
return e.err
}
// 错误码
func (e BizError) Code() int16 {
return e.code
}
func (e BizError) String() string {
return fmt.Sprintf("errCode: %d, errMsg: %s", e.Code(), e.Error())
}
// 创建业务逻辑错误结构体,默认为业务逻辑错误
func NewBiz(msg string, formats ...any) BizError {
return BizError{code: BizErr.code, err: fmt.Sprintf(msg, formats...)}
}
// 创建业务逻辑错误结构体可设置指定错误code
func NewBizCode(code int16, msg string, formats ...any) BizError {
return BizError{code: code, err: fmt.Sprintf(msg, formats...)}
}

View File

@@ -3,6 +3,7 @@ package ginx
import (
"io"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/structx"
@@ -100,21 +101,21 @@ func SuccessRes(g *gin.Context, data any) {
// 返回失败结果集
func ErrorRes(g *gin.Context, err any) {
switch t := err.(type) {
case biz.BizError:
case errorx.BizError:
g.JSON(http.StatusOK, model.Error(t))
case error:
g.JSON(http.StatusOK, model.ServerError())
case string:
g.JSON(http.StatusOK, model.ServerError())
default:
logx.Error("未知错误", "errInfo", t)
logx.Errorf("未知错误: %v", t)
}
}
// 转换参数校验错误为业务异常错误
func ConvBindValidationError(data any, err error) error {
if e, ok := err.(validator.ValidationErrors); ok {
return biz.NewBizErrCode(403, validatorx.Translate2Str(data, e))
return errorx.NewBizCode(403, validatorx.Translate2Str(data, e))
}
return err
}

View File

@@ -2,7 +2,6 @@ package gormx
import (
"fmt"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/global"
"mayfly-go/pkg/model"
"strings"
@@ -26,8 +25,8 @@ func GetById(model any, id uint64, cols ...string) error {
// 根据id列表查询实体信息
// @param model 数据库映射实体模型
func GetByIdIn(model any, list any, ids []uint64, orderBy ...string) {
NewQuery(model).In("id", ids).Undeleted().GenGdb().Find(list)
func GetByIdIn(model any, list any, ids []uint64, orderBy ...string) error {
return NewQuery(model).In("id", ids).Undeleted().GenGdb().Find(list).Error
}
// 获取满足model中不为空的字段值条件的单个对象。model需为指针类型需要将查询出来的值赋值给model
@@ -40,80 +39,102 @@ func GetBy(model any, cols ...string) error {
// 根据model指定条件统计数量
func CountBy(model any) int64 {
var count int64
NewQuery(model).WithCondModel(model).Undeleted().GenGdb().Count(&count)
return count
return CountByCond(model, model)
}
// 根据条件model指定条件统计数量
func CountByCond(model any, condModel any) int64 {
// 根据条件cond获取指定model统计数量
func CountByCond(model any, cond any) int64 {
var count int64
NewQuery(model).WithCondModel(condModel).Undeleted().GenGdb().Count(&count)
NewQuery(model).WithCondModel(cond).Undeleted().GenGdb().Count(&count)
return count
}
// 根据查询条件分页查询数据
// 若未指定查询列则查询列以toModels字段为准
func PageQuery[T any](q *QueryCond, pageParam *model.PageParam, toModels T) *model.PageResult[T] {
func PageQuery[T any](q *QueryCond, pageParam *model.PageParam, toModels T) (*model.PageResult[T], error) {
q.Undeleted()
gdb := q.GenGdb()
var count int64
err := gdb.Count(&count).Error
biz.ErrIsNilAppendErr(err, "查询错误: %s")
if err != nil {
return nil, err
}
if count == 0 {
return model.EmptyPageResult[T]()
return model.EmptyPageResult[T](), nil
}
page := pageParam.PageNum
pageSize := pageParam.PageSize
err = gdb.Limit(pageSize).Offset((page - 1) * pageSize).Find(toModels).Error
biz.ErrIsNilAppendErr(err, "查询失败: %s")
return &model.PageResult[T]{Total: count, List: toModels}
if err != nil {
return nil, err
}
return &model.PageResult[T]{Total: count, List: toModels}, nil
}
// 获取满足model中不为空的字段值条件的所有数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体即只包含需要返回的字段结构体
func ListBy(model any, list any, cols ...string) {
global.Db.Model(model).Select(cols).Where(model).Scopes(UndeleteScope).Order("id desc").Find(list)
func ListBy(model any, list any, cols ...string) error {
return ListByCond(model, model, list, cols...)
}
// 获取满足cond中不为空的字段值条件的所有model表数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体即只包含需要返回的字段结构体
func ListByCond(model any, cond any, list any, cols ...string) error {
return global.Db.Model(model).Select(cols).Where(cond).Scopes(UndeleteScope).Order("id desc").Find(list).Error
}
// 获取满足model中不为空的字段值条件的所有数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体
// @param model 数据库映射实体模型
func ListByOrder(model any, list any, order ...string) {
func ListByOrder(model any, list any, order ...string) error {
return ListByCondOrder(model, model, list, order...)
}
// 获取满足cond中不为空的字段值条件的所有model表数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体
// @param model 数据库映射实体模型
func ListByCondOrder(model any, cond any, list any, order ...string) error {
var orderByStr string
if order == nil {
orderByStr = "id desc"
} else {
orderByStr = strings.Join(order, ",")
}
global.Db.Model(model).Where(model).Scopes(UndeleteScope).Order(orderByStr).Find(list)
return global.Db.Model(model).Where(cond).Scopes(UndeleteScope).Order(orderByStr).Find(list).Error
}
func GetListBySql2Model(sql string, toEntity any, params ...any) error {
return global.Db.Raw(sql, params...).Find(toEntity).Error
}
func ExecSql(sql string, params ...any) {
global.Db.Exec(sql, params...)
func ExecSql(sql string, params ...any) error {
return global.Db.Exec(sql, params...).Error
}
// 插入model
// @param model 数据库映射实体模型
func Insert(model any) error {
return InsertWithDb(*global.Db, model)
return InsertWithDb(global.Db, model)
}
// 使用指定gormDb插入model
func InsertWithDb(db gorm.DB, model any) error {
func InsertWithDb(db *gorm.DB, model any) error {
return db.Create(model).Error
}
// 批量插入
func BatchInsert[T any](models []T) {
global.Db.CreateInBatches(models, len(models))
func BatchInsert[T any](models []T) error {
return BatchInsertWithDb[T](global.Db, models)
}
// 批量插入
func BatchInsertWithDb[T any](db *gorm.DB, models []T) error {
return db.CreateInBatches(models, len(models)).Error
}
// 根据id更新model更新字段为model中不为空的值即int类型不为0ptr类型不为nil这类字段值
@@ -142,16 +163,32 @@ func DeleteByIdWithDb(db *gorm.DB, model_ any, id uint64) error {
return db.Model(model_).Where("id = ?", id).Updates(getDeleteColumnValue()).Error
}
// 根据条件删除
// 根据model条件删除
// @param model 数据库映射实体模型
func DeleteByCondition(model_ any) error {
return DeleteByConditionWithDb(global.Db, model_)
func DeleteBy(model_ any) error {
return DeleteByCond(model_, model_)
}
// 根据条件使用指定gromDb删除
// 根据cond条件删除指定model表数据
//
// @param model_ 数据库映射实体模型
// @param cond 条件
func DeleteByCond(model_ any, cond any) error {
return DeleteByCondWithDb(global.Db, model_, cond)
}
// 根据model条件删除
// @param model 数据库映射实体模型
func DeleteByConditionWithDb(db *gorm.DB, model_ any) error {
return db.Model(model_).Where(model_).Updates(getDeleteColumnValue()).Error
func DeleteByWithDb(db *gorm.DB, model_ any) error {
return DeleteByCondWithDb(db, model_, model_)
}
// 根据cond条件删除指定model表数据
//
// @param model 数据库映射实体模型
// @param cond 条件
func DeleteByCondWithDb(db *gorm.DB, model_ any, cond any) error {
return db.Model(model_).Where(cond).Updates(getDeleteColumnValue()).Error
}
func getDeleteColumnValue() map[string]any {

View File

@@ -3,7 +3,7 @@ package model
import (
"encoding/json"
"fmt"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
)
const (
@@ -44,17 +44,17 @@ func SuccessNoData() *Result {
return &Result{Code: SuccessCode, Msg: SuccessMsg}
}
func Error(bizerr biz.BizError) *Result {
func Error(bizerr errorx.BizError) *Result {
return &Result{Code: bizerr.Code(), Msg: bizerr.Error()}
}
// 返回服务器错误Result
func ServerError() *Result {
return Error(biz.ServerError)
return Error(errorx.ServerError)
}
func TokenError() *Result {
return Error(biz.PermissionErr)
return Error(errorx.PermissionErr)
}
func ErrorBy(code int16, msg string) *Result {

View File

@@ -2,7 +2,7 @@ package req
import (
"fmt"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/runtimex"
@@ -76,7 +76,7 @@ func LogHandler(rc *Ctx) error {
if rc.Err != nil {
nFrames := DefaultLogFrames
if _, ok := rc.Err.(biz.BizError); ok {
if _, ok := rc.Err.(errorx.BizError); ok {
nFrames = nFrames / 2
}
attrMap["error"] = rc.Err
@@ -123,7 +123,7 @@ func getErrMsg(rc *Ctx, err any) string {
nFrames := DefaultLogFrames
var errMsg string
switch t := err.(type) {
case biz.BizError:
case errorx.BizError:
errMsg = fmt.Sprintf("\n<-e %s", t.String())
nFrames = nFrames / 2
case error:

View File

@@ -3,9 +3,9 @@ package req
import (
"encoding/json"
"fmt"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/config"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/rediscli"
"mayfly-go/pkg/utils/anyx"
@@ -48,16 +48,16 @@ func PermissionHandler(rc *Ctx) error {
tokenStr = rc.GinCtx.Query("token")
}
if tokenStr == "" {
return biz.PermissionErr
return errorx.PermissionErr
}
userId, userName, err := ParseToken(tokenStr)
if err != nil || userId == 0 {
return biz.PermissionErr
return errorx.PermissionErr
}
// 权限不为nil并且permission code不为空则校验是否有权限code
if permission != nil && permission.Code != "" {
if !permissionCodeRegistry.HasCode(userId, permission.Code) {
return biz.PermissionErr
return errorx.PermissionErr
}
}
if rc.LoginAccount == nil {

View File

@@ -2,7 +2,6 @@ package req
import (
"errors"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/config"
"time"
@@ -10,7 +9,7 @@ import (
)
// 创建用户token
func CreateToken(userId uint64, username string) string {
func CreateToken(userId uint64, username string) (string, error) {
// 带权限创建令牌
// 设置有效期过期需要重新登录获取token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
@@ -21,8 +20,10 @@ func CreateToken(userId uint64, username string) string {
// 使用自定义字符串加密 and get the complete encoded token as a string
tokenString, err := token.SignedString([]byte(config.Conf.Jwt.Key))
biz.ErrIsNilAppendErr(err, "token创建失败: %s")
return tokenString
if err != nil {
return "", err
}
return tokenString, nil
}
// 解析token并返回登录者账号信息
@@ -38,6 +39,9 @@ func ParseToken(tokenStr string) (uint64, string, error) {
if err != nil || token == nil {
return 0, "", err
}
if !token.Valid {
return 0, "", errors.New("token invalid")
}
i := token.Claims.(jwt.MapClaims)
return uint64(i["id"].(float64)), i["username"].(string), nil
}

View File

@@ -114,7 +114,7 @@ func ToString(value any) string {
case uint64:
return strconv.FormatUint(it, 10)
case []byte:
return string(value.([]byte))
return string(it)
default:
newValue, _ := json.Marshal(value)
return string(newValue)

View File

@@ -129,7 +129,9 @@ func (manager *ClientManager) WriteMessage() {
if cid != "" {
cli := manager.GetByUidAndCid(uid, cid)
if cli != nil {
cli.WriteMsg(msg)
if err := cli.WriteMsg(msg); err != nil {
logx.Warnf("ws消息发送失败[uid=%d, cid=%s]: %s", uid, cid, err.Error())
}
} else {
logx.Warnf("[uid=%v, cid=%s]的ws连接不存在", uid, cid)
}
@@ -138,7 +140,9 @@ func (manager *ClientManager) WriteMessage() {
// cid为空则向该用户所有客户端发送该消息
for _, cli := range manager.GetByUid(uid) {
cli.WriteMsg(msg)
if err := cli.WriteMsg(msg); err != nil {
logx.Warnf("ws消息发送失败[uid=%d, cid=%s]: %s", uid, cli.ClientId, err.Error())
}
}
}
}()