347 lines
7.8 KiB
Go
347 lines
7.8 KiB
Go
package utils
|
||
|
||
import (
|
||
"context"
|
||
|
||
"github.com/gogf/gf/v2/container/gmap"
|
||
"github.com/gogf/gf/v2/container/gvar"
|
||
"github.com/gogf/gf/v2/database/gdb"
|
||
"github.com/gogf/gf/v2/frame/g"
|
||
"github.com/gogf/gf/v2/os/gctx"
|
||
"github.com/gogf/gf/v2/os/glog"
|
||
"github.com/gogf/gf/v2/text/gstr"
|
||
"github.com/gogf/gf/v2/util/gconv"
|
||
)
|
||
|
||
type ctx = context.Context
|
||
|
||
type IDao interface {
|
||
DB() gdb.DB
|
||
Table() string
|
||
Group() string
|
||
Ctx(ctx context.Context) *gdb.Model
|
||
Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error)
|
||
}
|
||
|
||
type Curd[R any] struct {
|
||
Dao IDao
|
||
}
|
||
|
||
var pageInfo = []string{
|
||
"page",
|
||
"size",
|
||
"num",
|
||
"limit",
|
||
"pagesize",
|
||
"pageSize",
|
||
"page_size",
|
||
"pageNum",
|
||
"pagenum",
|
||
"page_num",
|
||
}
|
||
|
||
func (c Curd[R]) BuildWhere(req any, changeWhere any, subWhere any, removeFields []string, isSnake ...bool) map[string]any {
|
||
// 默认使用小写下划线方式
|
||
caseTypeValue := gstr.Snake
|
||
if len(isSnake) > 0 && isSnake[0] == false {
|
||
caseTypeValue = gstr.CamelLower
|
||
}
|
||
|
||
// 转换req为map
|
||
reqMap := gconv.Map(req)
|
||
|
||
// 清理空值和分页信息
|
||
ctx := gctx.New()
|
||
cleanedReq := make(map[string]any)
|
||
for k, v := range reqMap {
|
||
// 清理空值
|
||
if g.IsEmpty(v) {
|
||
glog.Debugf(ctx, "清理空值:%s", k)
|
||
continue
|
||
}
|
||
// 清理分页信息
|
||
if gstr.InArray(pageInfo, k) {
|
||
glog.Debugf(ctx, "清理分页信息:%s", k)
|
||
continue
|
||
}
|
||
if len(removeFields) > 0 && gstr.InArray(removeFields, k) {
|
||
glog.Debugf(ctx, "清理字段:%s", k)
|
||
continue
|
||
}
|
||
cleanedReq[gstr.CaseConvert(k, caseTypeValue)] = v
|
||
}
|
||
|
||
// 处理changeWhere
|
||
if changeWhere != nil {
|
||
changeMap := gconv.Map(changeWhere)
|
||
for k, v := range changeMap {
|
||
if _, hasKey := cleanedReq[k]; !hasKey {
|
||
glog.Debugf(ctx, "处理changeWhere:%s", k)
|
||
continue
|
||
}
|
||
if len(removeFields) > 0 && gstr.InArray(removeFields, k) {
|
||
glog.Debugf(ctx, "清理应删除字段:%s", k)
|
||
continue
|
||
}
|
||
// 转换v为map
|
||
vMap := gconv.Map(v)
|
||
value, hasValue := vMap["value"]
|
||
op, hasOp := vMap["op"]
|
||
|
||
if hasValue {
|
||
glog.Debugf(ctx, "变更字段存在value:%s", k)
|
||
// 构建新的键名
|
||
newKey := k
|
||
if hasOp && op != "" {
|
||
glog.Debugf(ctx, "变更字段存在op:%s", k)
|
||
newKey = k + " " + gconv.String(op)
|
||
delete(cleanedReq, k)
|
||
}
|
||
cleanedReq[newKey] = value
|
||
}
|
||
}
|
||
}
|
||
|
||
// 变量名切换
|
||
resultMap := make(map[string]any)
|
||
for k, v := range cleanedReq {
|
||
// 提取原始键名(去掉op部分)
|
||
originalKey := k
|
||
opStr := ""
|
||
if opIndex := gstr.Pos(k, " "); opIndex > 0 {
|
||
originalKey = k[:opIndex]
|
||
opStr = k[opIndex+1:]
|
||
}
|
||
|
||
// 转换键名
|
||
convertedKey := originalKey
|
||
convertedKey = gstr.CaseConvert(convertedKey, caseTypeValue)
|
||
|
||
// 如果有op,重新构建键名
|
||
if opStr != "" {
|
||
convertedKey = convertedKey + " " + opStr
|
||
}
|
||
|
||
resultMap[convertedKey] = v
|
||
}
|
||
// 合并subWhere
|
||
if subWhere != nil {
|
||
subMap := gconv.Map(subWhere)
|
||
resultM := gmap.NewStrAnyMapFrom(resultMap)
|
||
resultM.Merge(gmap.NewStrAnyMapFrom(subMap))
|
||
resultMap = resultM.Map()
|
||
}
|
||
return resultMap
|
||
}
|
||
func (c Curd[R]) BuildMap(op string, value any, field ...string) map[string]any {
|
||
if len(field) > 0 {
|
||
return map[string]any{
|
||
"op": op,
|
||
"field": field[0],
|
||
"value": value,
|
||
}
|
||
}
|
||
return map[string]any{
|
||
"op": op,
|
||
"field": "",
|
||
"value": value,
|
||
}
|
||
}
|
||
func (c Curd[R]) Builder(ctx context.Context) *gdb.WhereBuilder {
|
||
return c.Dao.Ctx(ctx).Builder()
|
||
}
|
||
func (c Curd[R]) ClearField(req any, delField []string, subField ...map[string]any) map[string]any {
|
||
m := gmap.NewStrAnyMapFrom(gconv.Map(req))
|
||
if delField != nil && len(delField) > 0 {
|
||
m.Iterator(func(k string, v any) bool {
|
||
if g.IsEmpty(v) {
|
||
m.Remove(k)
|
||
return true
|
||
}
|
||
if gstr.InArray(delField, k) {
|
||
m.Remove(k)
|
||
return true
|
||
}
|
||
if gstr.InArray(pageInfo, k) {
|
||
m.Remove(k)
|
||
return true
|
||
}
|
||
return true
|
||
})
|
||
}
|
||
if subField != nil && len(subField) > 0 {
|
||
m.Merge(gmap.NewStrAnyMapFrom(subField[0]))
|
||
}
|
||
return m.Map()
|
||
}
|
||
func (c Curd[R]) ClearFieldPage(ctx ctx, req any, delField []string, where any, page *Paginate, order any, with bool) (items []*R, total int, err error) {
|
||
db := c.Dao.Ctx(ctx)
|
||
m := c.ClearField(req, delField)
|
||
if with {
|
||
db = db.WithAll()
|
||
}
|
||
db = db.Where(m)
|
||
if !g.IsNil(where) {
|
||
db = db.Where(where)
|
||
}
|
||
if order != nil {
|
||
db = db.Order(order)
|
||
}
|
||
if !g.IsNil(page) {
|
||
db = db.Page(page.Page, page.Limit)
|
||
}
|
||
err = db.ScanAndCount(&items, &total, false)
|
||
return
|
||
}
|
||
func (c Curd[R]) ClearFieldList(ctx ctx, req any, delField []string, where any, order any, with bool) (items []*R, err error) {
|
||
db := c.Dao.Ctx(ctx)
|
||
m := c.ClearField(req, delField)
|
||
db = db.Where(m)
|
||
if !g.IsNil(where) {
|
||
db = db.Where(where)
|
||
}
|
||
if with {
|
||
db = db.WithAll()
|
||
}
|
||
if !g.IsNil(order) {
|
||
db = db.Order(order)
|
||
}
|
||
err = db.Scan(&items)
|
||
return
|
||
}
|
||
func (c Curd[R]) ClearFieldOne(ctx ctx, req any, delField []string, where any, order any, with bool) (items *R, err error) {
|
||
db := c.Dao.Ctx(ctx)
|
||
m := c.ClearField(req, delField)
|
||
db = db.Where(m)
|
||
if !g.IsNil(where) {
|
||
db = db.Where(where)
|
||
}
|
||
if with {
|
||
db = db.WithAll()
|
||
}
|
||
if !g.IsNil(order) {
|
||
db = db.Order(order)
|
||
}
|
||
err = db.Scan(&items)
|
||
return
|
||
}
|
||
func (c Curd[R]) Value(ctx ctx, where any, field any) (*gvar.Var, error) {
|
||
return c.Dao.Ctx(ctx).Where(where).Fields(field).Value()
|
||
}
|
||
func (c Curd[R]) DeletePri(ctx ctx, primaryKey any) error {
|
||
_, err := c.Dao.Ctx(ctx).WherePri(primaryKey).Delete()
|
||
return err
|
||
}
|
||
func (c Curd[R]) DeleteWhere(ctx ctx, where any) error {
|
||
_, err := c.Dao.Ctx(ctx).Where(where).Delete()
|
||
return err
|
||
}
|
||
|
||
func (c Curd[R]) Sum(ctx ctx, where any, field string) (float64, error) {
|
||
return c.Dao.Ctx(ctx).Where(where).Sum(field)
|
||
}
|
||
|
||
func (c Curd[R]) ArrayField(ctx ctx, where any, field any) ([]*gvar.Var, error) {
|
||
if field == nil {
|
||
field = "*"
|
||
}
|
||
return c.Dao.Ctx(ctx).Where(where).Fields(field).Array()
|
||
}
|
||
|
||
func (c Curd[R]) FindPri(ctx ctx, primaryKey any, with bool) (model *R, err error) {
|
||
db := c.Dao.Ctx(ctx).WherePri(primaryKey)
|
||
if with {
|
||
db = db.WithAll()
|
||
}
|
||
err = db.Scan(&model)
|
||
if err != nil {
|
||
return
|
||
}
|
||
return
|
||
}
|
||
|
||
func (c Curd[R]) First(ctx ctx, where any, order any, with bool) (model *R, err error) {
|
||
db := c.Dao.Ctx(ctx).Where(where)
|
||
if with {
|
||
db = db.WithAll()
|
||
}
|
||
if !g.IsNil(order) {
|
||
db = db.Order(order)
|
||
}
|
||
err = db.Scan(&model)
|
||
if err != nil {
|
||
return
|
||
}
|
||
return
|
||
}
|
||
|
||
func (c Curd[R]) Exists(ctx ctx, where any) (exists bool, err error) {
|
||
return c.Dao.Ctx(ctx).Where(where).Exist()
|
||
}
|
||
|
||
func (c Curd[R]) All(ctx ctx, where any, order any, with bool) (items []*R, err error) {
|
||
db := c.Dao.Ctx(ctx)
|
||
if with {
|
||
db = db.WithAll()
|
||
}
|
||
if !g.IsNil(order) {
|
||
db = db.Order(order)
|
||
}
|
||
err = db.Where(where).Scan(&items)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return
|
||
}
|
||
|
||
func (c Curd[R]) Count(ctx ctx, where any) (count int, err error) {
|
||
count, err = c.Dao.Ctx(ctx).Where(where).Count()
|
||
return
|
||
}
|
||
|
||
func (c Curd[R]) Save(ctx ctx, data any) (id int64, err error) {
|
||
result, err := c.Dao.Ctx(ctx).Save(data)
|
||
if err != nil {
|
||
return
|
||
}
|
||
id, err = result.LastInsertId()
|
||
return
|
||
}
|
||
|
||
func (c Curd[R]) Update(ctx ctx, where any, data any) (count int64, err error) {
|
||
result, err := c.Dao.Ctx(ctx).Where(where).Data(data).Update()
|
||
if err != nil {
|
||
return
|
||
}
|
||
count, err = result.RowsAffected()
|
||
return
|
||
}
|
||
|
||
func (c Curd[R]) UpdatePri(ctx ctx, primaryKey any, data any) (count int64, err error) {
|
||
result, err := c.Dao.Ctx(ctx).WherePri(primaryKey).Data(data).Update()
|
||
if err != nil {
|
||
return
|
||
}
|
||
count, err = result.RowsAffected()
|
||
return
|
||
}
|
||
|
||
func (c Curd[R]) Paginate(ctx context.Context, where any, p Paginate, with bool, order any) (items []*R, total int, err error) {
|
||
query := c.Dao.Ctx(ctx)
|
||
if where != nil {
|
||
query = query.Where(where)
|
||
}
|
||
query = query.Page(p.Page, p.Limit)
|
||
if order != nil {
|
||
query = query.Order(order)
|
||
}
|
||
if with == true {
|
||
query = query.WithAll()
|
||
}
|
||
err = query.Order(order).ScanAndCount(&items, &total, false)
|
||
if err != nil {
|
||
return
|
||
}
|
||
return
|
||
}
|