862 lines
24 KiB
Go
862 lines
24 KiB
Go
package crud
|
||
|
||
//
|
||
//import (
|
||
// "context"
|
||
// "errors"
|
||
// "fmt"
|
||
// "reflect"
|
||
// "strings"
|
||
//
|
||
// "git.magicany.cc/black1552/gin-base/orm"
|
||
//)
|
||
//
|
||
//// 定义上下文别名,保持原代码风格
|
||
//type ctx = context.Context
|
||
//
|
||
//// Paginate -------------------------- 分页结构体定义 --------------------------
|
||
//// Paginate 分页参数结构体(补全原代码中缺失的定义,保持功能完整)
|
||
//type Paginate struct {
|
||
// Page int // 页码(从1开始)
|
||
// Limit int // 每页条数
|
||
//}
|
||
//
|
||
//// -------------------------- 全局常量 --------------------------
|
||
//// 分页相关字段,用于清理请求参数
|
||
//var pageInfo = []string{
|
||
// "page",
|
||
// "size",
|
||
// "num",
|
||
// "limit",
|
||
// "pagesize",
|
||
// "pageSize",
|
||
// "page_size",
|
||
// "pageNum",
|
||
// "pagenum",
|
||
// "page_num",
|
||
//}
|
||
//
|
||
//// Crud -------------------------- 泛型CURD核心结构体 --------------------------
|
||
//// Crud GORM 版本的泛型CURD封装,R为对应的模型结构体, C为对应模型结构体的字段结构体
|
||
//type Crud[R any] struct {
|
||
// Dao orm.IDao[R]
|
||
//}
|
||
//
|
||
//// -------------------------- 工具方法:字段名转换(保持原代码的命名风格转换) --------------------------
|
||
//// caseConvert 字段名风格转换(下划线 <-> 小驼峰)
|
||
//func caseConvert(key string, toSnake bool) string {
|
||
// if toSnake {
|
||
// // 驼峰转下划线
|
||
// return toSnakeCase(key)
|
||
// }
|
||
// // 下划线转小驼峰
|
||
// return toCamelCase(key)
|
||
//}
|
||
//
|
||
//// toSnakeCase 驼峰转下划线
|
||
//func toSnakeCase(s string) string {
|
||
// if s == "" {
|
||
// return ""
|
||
// }
|
||
//
|
||
// var result strings.Builder
|
||
// for i, r := range s {
|
||
// if r >= 'A' && r <= 'Z' {
|
||
// if i > 0 {
|
||
// result.WriteRune('_')
|
||
// }
|
||
// result.WriteRune(r + 'a' - 'A')
|
||
// } else {
|
||
// result.WriteRune(r)
|
||
// }
|
||
// }
|
||
// return result.String()
|
||
//}
|
||
//
|
||
//// toCamelCase 下划线转小驼峰
|
||
//func toCamelCase(s string) string {
|
||
// if s == "" {
|
||
// return ""
|
||
// }
|
||
//
|
||
// var result strings.Builder
|
||
// upperNext := false
|
||
// for i, r := range s {
|
||
// if r == '_' && i < len(s)-1 {
|
||
// upperNext = true
|
||
// continue
|
||
// }
|
||
// if upperNext {
|
||
// if r >= 'a' && r <= 'z' {
|
||
// result.WriteRune(r - 'a' + 'A')
|
||
// } else {
|
||
// result.WriteRune(r)
|
||
// }
|
||
// upperNext = false
|
||
// } else {
|
||
// result.WriteRune(r)
|
||
// }
|
||
// }
|
||
// return result.String()
|
||
//}
|
||
//
|
||
//// BuildWhere -------------------------- 原BuildWhere对应实现:构建查询条件map --------------------------
|
||
//func (c Crud[R]) BuildWhere(req any, changeWhere any, subWhere any, removeFields []string, isSnake ...bool) map[string]any {
|
||
// // 默认使用小写下划线方式
|
||
// toSnake := true
|
||
// if len(isSnake) > 0 && !isSnake[0] {
|
||
// toSnake = false
|
||
// }
|
||
//
|
||
// // 1. 转换req为map并清理无效数据
|
||
// reqMap := convToMap(req)
|
||
// cleanedReq := make(map[string]any)
|
||
//
|
||
// for k, v := range reqMap {
|
||
// // 清理空值
|
||
// if isEmpty(v) {
|
||
// continue
|
||
// }
|
||
// // 清理分页字段
|
||
// if strInArray(pageInfo, k) {
|
||
// continue
|
||
// }
|
||
// // 清理指定移除字段
|
||
// if len(removeFields) > 0 && strInArray(removeFields, k) {
|
||
// continue
|
||
// }
|
||
// // 转换字段名风格并存入
|
||
// cleanedReq[caseConvert(k, toSnake)] = v
|
||
// }
|
||
//
|
||
// // 2. 处理changeWhere(修改查询操作符,如:eq -> gt)
|
||
// if changeWhere != nil {
|
||
// changeMap := convToMap(changeWhere)
|
||
// for k, v := range changeMap {
|
||
// // 跳过不存在于cleanedReq的字段
|
||
// if _, exists := cleanedReq[k]; !exists {
|
||
// continue
|
||
// }
|
||
// // 跳过指定移除的字段
|
||
// if len(removeFields) > 0 && strInArray(removeFields, k) {
|
||
// continue
|
||
// }
|
||
//
|
||
// vMap := convToMap(v)
|
||
// value, hasValue := vMap["value"]
|
||
// op, hasOp := vMap["op"]
|
||
//
|
||
// if hasValue {
|
||
// // 存在操作符则重构字段名(GORM支持 "字段名 >" 这种格式作为where key)
|
||
// if hasOp && op != "" {
|
||
// newKey := fmt.Sprintf("%s %s", k, op)
|
||
// delete(cleanedReq, k)
|
||
// cleanedReq[newKey] = value
|
||
// } else {
|
||
// cleanedReq[k] = value
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
//
|
||
// // 3. 字段名风格最终转换(确保一致性)
|
||
// resultMap := make(map[string]any)
|
||
// for k, v := range cleanedReq {
|
||
// // 拆分字段名和操作符
|
||
// parts := strings.SplitN(k, " ", 2)
|
||
// fieldName := parts[0]
|
||
// opStr := ""
|
||
// if len(parts) == 2 {
|
||
// opStr = parts[1]
|
||
// }
|
||
//
|
||
// // 转换字段名风格
|
||
// convertedField := caseConvert(fieldName, toSnake)
|
||
//
|
||
// // 重构带操作符的key
|
||
// if opStr != "" {
|
||
// resultMap[fmt.Sprintf("%s %s", convertedField, opStr)] = v
|
||
// } else {
|
||
// resultMap[convertedField] = v
|
||
// }
|
||
// }
|
||
//
|
||
// // 4. 合并subWhere附加条件
|
||
// if subWhere != nil {
|
||
// subMap := convToMap(subWhere)
|
||
// for k, v := range subMap {
|
||
// resultMap[caseConvert(k, toSnake)] = v
|
||
// }
|
||
// }
|
||
//
|
||
// return resultMap
|
||
//}
|
||
//
|
||
//// BuildMap -------------------------- 原 BuildMap 对应实现:构建变更条件 map --------------------------
|
||
//func (c Crud[R]) BuildMap(op string, value any, field ...string) map[string]any {
|
||
// res := map[string]any{
|
||
// "op": op,
|
||
// "field": "",
|
||
// "value": value,
|
||
// }
|
||
// if len(field) > 0 {
|
||
// res["field"] = field[0]
|
||
// }
|
||
// return res
|
||
//}
|
||
//
|
||
//// WhereCondition -------------------------- AND/OR 查询条件结构体 --------------------------
|
||
//// WhereCondition 用于构建复杂的 AND/OR 查询条件
|
||
//type WhereCondition struct {
|
||
// AND []interface{} // AND 条件列表
|
||
// OR []interface{} // OR 条件列表
|
||
//}
|
||
//
|
||
//// BuildWhereAndOr -------------------------- 新增:支持 AND 和 OR 的查询条件构建 --------------------------
|
||
//// BuildWhereAndOr 构建支持 AND 和 OR 混合使用的查询条件
|
||
//// 用法示例:
|
||
////
|
||
//// where := crud.BuildWhereAndOr().
|
||
//// AND(map[string]any{"status": 1}).
|
||
//// OR(
|
||
//// map[string]any{"age": 18},
|
||
//// map[string]any{"name": "test"},
|
||
//// ).
|
||
//// AND(map[string]any{"deleted": 0}).
|
||
//// Build()
|
||
//func (c Crud[R]) BuildWhereAndOr() *WhereBuilder[R] {
|
||
// return &WhereBuilder[R]{
|
||
// conditions: make([]WhereCondition, 0),
|
||
// crud: Crud[R]{
|
||
// Dao: c.Dao,
|
||
// },
|
||
// }
|
||
//}
|
||
//
|
||
//// WhereBuilder -------------------------- WHERE 条件构建器 --------------------------
|
||
//// WhereBuilder 流式构建 WHERE 条件(R 为模型类型参数)
|
||
//type WhereBuilder[R any] struct {
|
||
// conditions []WhereCondition
|
||
// crud Crud[R]
|
||
//}
|
||
//
|
||
//// AND 添加 AND 条件
|
||
//func (wb *WhereBuilder[R]) AND(conditions ...interface{}) *WhereBuilder[R] {
|
||
// if len(conditions) > 0 {
|
||
// wb.conditions = append(wb.conditions, WhereCondition{
|
||
// AND: conditions,
|
||
// })
|
||
// }
|
||
// return wb
|
||
//}
|
||
//
|
||
//// OR 添加 OR 条件(OR 条件内部是或关系)
|
||
//func (wb *WhereBuilder[R]) OR(conditions ...interface{}) *WhereBuilder[R] {
|
||
// if len(conditions) > 0 {
|
||
// wb.conditions = append(wb.conditions, WhereCondition{
|
||
// OR: conditions,
|
||
// })
|
||
// }
|
||
// return wb
|
||
//}
|
||
//
|
||
//// Build 构建最终的查询条件
|
||
//// 返回格式:map[string]any 或者可以直接用于 GORM 的 Where 子句
|
||
//func (wb *WhereBuilder[R]) Build() interface{} {
|
||
// if len(wb.conditions) == 0 {
|
||
// return nil
|
||
// }
|
||
//
|
||
// // 如果只有一个条件组,直接返回
|
||
// if len(wb.conditions) == 1 {
|
||
// cond := wb.conditions[0]
|
||
// if len(cond.AND) == 1 && len(cond.OR) == 0 {
|
||
// return cond.AND[0]
|
||
// }
|
||
// if len(cond.OR) > 0 && len(cond.AND) == 0 {
|
||
// return wb.buildORCondition(cond.OR)
|
||
// }
|
||
// }
|
||
//
|
||
// // 构建复杂的 AND/OR 混合条件
|
||
// var andConditions []interface{}
|
||
//
|
||
// for _, cond := range wb.conditions {
|
||
// // 处理 AND 条件
|
||
// for _, andCond := range cond.AND {
|
||
// andConditions = append(andConditions, andCond)
|
||
// }
|
||
//
|
||
// // 处理 OR 条件(将 OR 条件作为一个整体添加到 AND 中)
|
||
// if len(cond.OR) > 0 {
|
||
// orCondition := wb.buildORCondition(cond.OR)
|
||
// andConditions = append(andConditions, orCondition)
|
||
// }
|
||
// }
|
||
//
|
||
// // 如果只有一个条件,直接返回
|
||
// if len(andConditions) == 1 {
|
||
// return andConditions[0]
|
||
// }
|
||
//
|
||
// // 返回 AND 条件数组
|
||
// return andConditions
|
||
//}
|
||
//
|
||
//// buildORCondition 构建 OR 条件
|
||
//func (wb *WhereBuilder[R]) buildORCondition(orConds []interface{}) map[string]interface{} {
|
||
// if len(orConds) == 0 {
|
||
// return nil
|
||
// }
|
||
//
|
||
// // 如果只有一个 OR 条件,直接返回
|
||
// if len(orConds) == 1 {
|
||
// return map[string]interface{}{
|
||
// "OR": orConds[0],
|
||
// }
|
||
// }
|
||
//
|
||
// // 多个 OR 条件
|
||
// return map[string]interface{}{
|
||
// "OR": orConds,
|
||
// }
|
||
//}
|
||
//
|
||
//// BuildWhereGORM -------------------------- 新增:GORM 原生语法构建 WHERE 条件(支持 AND/OR) --------------------------
|
||
//// BuildWhereGORM 使用 GORM 原生语法构建复杂的 AND/OR 查询条件
|
||
//// 用法示例 1 - 纯 AND 条件:
|
||
////
|
||
//// db.Where("age > ?", 18).Where("status = ?", 1)
|
||
////
|
||
//// 用法示例 2 - OR 条件:
|
||
////
|
||
//// db.Where(db.Where("name = ?", "john").Or("name = ?", "jane"))
|
||
////
|
||
//// 用法示例 3 - 混合使用:
|
||
////
|
||
//// db.Where("status = ?", 1).
|
||
//// Where(db.Where("age >= ?", 18).Or("age < ? AND vip = ?", 18, true)).
|
||
//// Find(&users)
|
||
//func (c Crud[R]) BuildWhereGORM(query interface{}, args ...interface{}) *GORMWhereBuilder[R] {
|
||
// return &GORMWhereBuilder[R]{
|
||
// Pool: c.Dao.DB(),
|
||
// crud: c,
|
||
// query: query,
|
||
// args: args,
|
||
// }
|
||
//}
|
||
//
|
||
//// GORMWhereBuilder -------------------------- GORM 原生 WHERE 构建器 --------------------------
|
||
//// GORMWhereBuilder 使用 GORM 原生 API 构建复杂查询(R 为模型类型参数)
|
||
//type GORMWhereBuilder[R any] struct {
|
||
// *orm.Pool
|
||
// crud Crud[R]
|
||
// query interface{}
|
||
// args []interface{}
|
||
//}
|
||
//
|
||
//// Where 添加 WHERE 条件(AND 关系)
|
||
//func (gwb *GORMWhereBuilder[R]) Where(query interface{}, args ...interface{}) *GORMWhereBuilder[R] {
|
||
// // 如果当前已经有查询条件,先应用
|
||
// if gwb.query != nil {
|
||
// gwb = gwb.Where(gwb.query, gwb.args...)
|
||
// gwb.query = nil
|
||
// gwb.args = nil
|
||
// }
|
||
// return gwb.Where(query, args...)
|
||
//}
|
||
//
|
||
//// Or 添加 OR 条件
|
||
//func (gwb *GORMWhereBuilder[R]) Or(query interface{}, args ...interface{}) *GORMWhereBuilder[R] {
|
||
// // 如果当前有未应用的查询条件,先应用
|
||
// if gwb.query != nil {
|
||
// gwb = gwb.Where(gwb.query, gwb.args...)
|
||
// gwb.query = nil
|
||
// gwb.args = nil
|
||
// }
|
||
// return gwb.Or(query, args...)
|
||
//}
|
||
//
|
||
//// Not 添加 NOT 条件
|
||
//func (gwb *GORMWhereBuilder[R]) Not(query interface{}, args ...interface{}) *GORMWhereBuilder[R] {
|
||
// if gwb.query != nil {
|
||
// gwb = gwb.Where(gwb.query, gwb.args...)
|
||
// gwb.query = nil
|
||
// gwb.args = nil
|
||
// }
|
||
// gwb = gwb.Not(query, args...)
|
||
// return gwb
|
||
//}
|
||
//
|
||
//// Find 执行查询并返回结果
|
||
//func (gwb *GORMWhereBuilder[R]) Find(items interface{}) error {
|
||
// // 应用剩余的查询条件
|
||
// if gwb.query != nil {
|
||
// gwb = gwb.Where(gwb.query, gwb.args...)
|
||
// }
|
||
// return gwb.Model(new(R)).Find(items).Error
|
||
//}
|
||
//
|
||
//// First 查询第一条记录
|
||
//func (gwb *GORMWhereBuilder[R]) First(result interface{}) error {
|
||
// if gwb.query != nil {
|
||
// gwb = gwb.Where(gwb.query, gwb.args...)
|
||
// }
|
||
//
|
||
// return gwb.Model(new(R)).First(result)
|
||
//}
|
||
//
|
||
//// Count 统计记录数
|
||
//func (gwb *GORMWhereBuilder[R]) Count(count *int64) error {
|
||
// if gwb.query != nil {
|
||
// gwb = gwb.Where(gwb.query, gwb.args...)
|
||
// }
|
||
// result := gwb.Model(new(R)).Count(count)
|
||
// return result.Error
|
||
//}
|
||
//
|
||
//// ClearField -------------------------- 原ClearField对应实现:清理请求参数并返回有效map --------------------------
|
||
//func (c Crud[R]) ClearField(req any, delField []string, subField ...map[string]any) map[string]any {
|
||
// reqMap := convToMap(req)
|
||
// resultMap := make(map[string]any)
|
||
//
|
||
// // 过滤无效数据和指定删除字段
|
||
// for k, v := range reqMap {
|
||
// if isEmpty(v) {
|
||
// continue
|
||
// }
|
||
// if strInArray(pageInfo, k) {
|
||
// continue
|
||
// }
|
||
// if len(delField) > 0 && strInArray(delField, k) {
|
||
// continue
|
||
// }
|
||
// resultMap[k] = v
|
||
// }
|
||
//
|
||
// // 合并附加字段
|
||
// if len(subField) > 0 && subField[0] != nil {
|
||
// for k, v := range subField[0] {
|
||
// resultMap[k] = v
|
||
// }
|
||
// }
|
||
//
|
||
// return resultMap
|
||
//}
|
||
//
|
||
//// ClearFieldPage -------------------------- 原 ClearFieldPage 对应实现:清理参数 + 分页查询 --------------------------
|
||
//func (c Crud[R]) ClearFieldPage(ctx ctx, req any, delField []string, where any, page *Paginate, order string, with map[string]interface{}) (items []*R, total int64, err error) {
|
||
// // 1. 清理请求参数
|
||
// filterMap := c.ClearField(req, delField)
|
||
//
|
||
// // 2. 初始化 ORM 查询
|
||
// db := c.Dao.Ctx(ctx)
|
||
//
|
||
// // 注意:orm 包不支持 Preload,如需关联查询需手动处理
|
||
// _ = with // 忽略 with 参数
|
||
//
|
||
// // 3. 构建查询条件
|
||
// db = db.Where(filterMap)
|
||
// if where != nil {
|
||
// db = db.Where(where)
|
||
// }
|
||
//
|
||
// // 4. 排序
|
||
// if order != "" {
|
||
// db = db.OrderBy(order)
|
||
// }
|
||
//
|
||
// // 5. 统计总数
|
||
// total, err = db.Count(&total)
|
||
// if err != nil {
|
||
// return nil, 0, err
|
||
// }
|
||
//
|
||
// // 6. 分页查询
|
||
// if page != nil && page.Limit > 0 {
|
||
// offset := (page.Page - 1) * page.Limit
|
||
// db = db.Offset(offset).Limit(page.Limit)
|
||
// }
|
||
//
|
||
// // 7. 执行查询
|
||
// results, err := db.Find(&items)
|
||
// if err != nil {
|
||
// return nil, 0, results.Error
|
||
// }
|
||
// return
|
||
//}
|
||
//
|
||
//// ClearFieldList -------------------------- 原 ClearFieldList 对应实现:清理参数 + 列表查询(不分页) --------------------------
|
||
//func (c Crud[R]) ClearFieldList(ctx ctx, req any, delField []string, where any, order any, with map[string]interface{}) (items []*R, err error) {
|
||
// filterMap := c.ClearField(req, delField)
|
||
// db := c.Dao.Ctx(ctx)
|
||
//
|
||
// // 注意:orm 包不支持 Preload
|
||
// _ = with
|
||
//
|
||
// if where != nil {
|
||
// db = db.Where(where)
|
||
// }
|
||
// if order != nil {
|
||
// db = db.OrderBy(order)
|
||
// }
|
||
//
|
||
// results, err := db.Where(filterMap).Find(&items)
|
||
// if err != nil {
|
||
// return nil, results.Error
|
||
// }
|
||
// return
|
||
//}
|
||
//
|
||
//// ClearFieldOne -------------------------- 原 ClearFieldOne 对应实现:清理参数 + 单条查询 --------------------------
|
||
//func (c Crud[R]) ClearFieldOne(ctx ctx, req any, delField []string, where any, order any, with map[string]interface{}) (item *R, err error) {
|
||
// item = new(R)
|
||
// filterMap := c.ClearField(req, delField)
|
||
// db := c.Dao.Ctx(ctx)
|
||
//
|
||
// // 注意:orm 包不支持 Preload
|
||
// _ = with
|
||
//
|
||
// if where != nil {
|
||
// db = db.Where(where)
|
||
// }
|
||
// if order != nil {
|
||
// db = db.OrderBy(order)
|
||
// }
|
||
//
|
||
// err = db.Where(filterMap).First(item)
|
||
// if err != nil {
|
||
// panic("未找到数据")
|
||
// }
|
||
// return
|
||
//}
|
||
//
|
||
//// Value -------------------------- 原Value对应实现:查询单个字段值 --------------------------
|
||
//func (c Crud[R]) Value(ctx ctx, where any, field any) (interface{}, error) {
|
||
// var result interface{}
|
||
// db := c.Dao.Ctx(ctx).Model(new(R)).Where(where)
|
||
//
|
||
// // 处理字段参数
|
||
// if field != nil {
|
||
// fieldStr, ok := field.(string)
|
||
// if !ok || fieldStr == "" {
|
||
// fieldStr = "*"
|
||
// }
|
||
// db = db.Select(fieldStr)
|
||
// } else {
|
||
// db = db.Select("*")
|
||
// }
|
||
//
|
||
// // 执行查询(取第一条记录的指定字段)
|
||
// err := db.First(&result).Error
|
||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
// panic("未找到数据")
|
||
// }
|
||
// return result, err
|
||
//}
|
||
//
|
||
//// DeletePri -------------------------- 原DeletePri对应实现:按主键删除 --------------------------
|
||
//func (c Crud[R]) DeletePri(ctx ctx, primaryKey any) error {
|
||
// db := c.Dao.Ctx(ctx).Model(new(R))
|
||
// // 按主键字段构建查询
|
||
// pk := c.Dao.PrimaryKey()
|
||
// if pk == "" {
|
||
// panic("主键字段未配置")
|
||
// }
|
||
// return db.Where(fmt.Sprintf("%s = ?", pk), primaryKey).Delete(new(R)).Error
|
||
//}
|
||
//
|
||
//// DeleteWhere -------------------------- 原DeleteWhere对应实现:按条件删除 --------------------------
|
||
//func (c Crud[R]) DeleteWhere(ctx ctx, where any) error {
|
||
// return c.Dao.Ctx(ctx).Model(new(R)).Where(where).Delete(new(R)).Error
|
||
//}
|
||
//
|
||
//// Sum -------------------------- 原Sum对应实现:字段求和 --------------------------
|
||
//func (c Crud[R]) Sum(ctx ctx, where any, field string) float64 {
|
||
// var sum float64
|
||
// if field == "" {
|
||
// panic("求和字段不能为空")
|
||
// }
|
||
//
|
||
// err := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Select(fmt.Sprintf("SUM(%s) as sum", field)).Scan(&sum).Error
|
||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
// panic("未找到数据")
|
||
// }
|
||
// return sum
|
||
//}
|
||
//
|
||
//// ArrayField -------------------------- 原ArrayField对应实现:查询指定字段数组 --------------------------
|
||
//func (c Crud[R]) ArrayField(ctx ctx, where any, field any) []interface{} {
|
||
// var result []interface{}
|
||
// db := c.Dao.Ctx(ctx).Model(new(R)).Where(where)
|
||
//
|
||
// // 处理字段参数
|
||
// if field != nil {
|
||
// fieldStr, ok := field.(string)
|
||
// if !ok || fieldStr == "" {
|
||
// fieldStr = "*"
|
||
// }
|
||
// db = db.Select(fieldStr)
|
||
// } else {
|
||
// db = db.Select("*")
|
||
// }
|
||
//
|
||
// // 执行查询
|
||
// err := db.Find(&result).Error
|
||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
// panic("未找到数据")
|
||
// }
|
||
// return result
|
||
//}
|
||
//
|
||
//// FindPri -------------------------- 原FindPri对应实现:按主键查询单条记录 --------------------------
|
||
//func (c Crud[R]) FindPri(ctx ctx, primaryKey any, with map[string]func(db *gorm.DB) *gorm.DB) (model *R) {
|
||
// model = new(R)
|
||
// db := c.Dao.Ctx(ctx).Model(model)
|
||
// pk := c.Dao.PrimaryKey()
|
||
//
|
||
// if pk == "" {
|
||
// panic("主键字段未配置")
|
||
// }
|
||
// if with != nil {
|
||
// for k, v := range with {
|
||
// db = db.Preload(k, v)
|
||
// }
|
||
// }
|
||
//
|
||
// // 按主键查询
|
||
// err := db.Where(fmt.Sprintf("%s = ?", pk), primaryKey).First(model).Error
|
||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
// panic("未找到数据")
|
||
// }
|
||
// return
|
||
//}
|
||
//
|
||
//// -------------------------- 原First对应实现:按条件查询第一条记录 --------------------------
|
||
//func (c Crud[R]) First(ctx ctx, where any, order any, with map[string]func(db *gorm.DB) *gorm.DB) (model *R) {
|
||
// model = new(R)
|
||
// db := c.Dao.Ctx(ctx).Model(model)
|
||
//
|
||
// if with != nil {
|
||
// for k, v := range with {
|
||
// db = db.Preload(k, v)
|
||
// }
|
||
// }
|
||
// if where != nil {
|
||
// db = db.Where(where)
|
||
// }
|
||
// if order != nil {
|
||
// db = db.Order(order)
|
||
// }
|
||
//
|
||
// err := db.First(model).Error
|
||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
// panic("未找到数据")
|
||
// }
|
||
// return
|
||
//}
|
||
//
|
||
//// -------------------------- 原Exists对应实现:判断记录是否存在 --------------------------
|
||
//func (c Crud[R]) Exists(ctx ctx, where any) (exists bool) {
|
||
// var count int64
|
||
// err := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Count(&count).Error
|
||
// if err != nil {
|
||
// panic(fmt.Sprintf("Exists查询错误: %v", err))
|
||
// }
|
||
// return count > 0
|
||
//}
|
||
//
|
||
//// -------------------------- 原All对应实现:查询所有符合条件的记录 --------------------------
|
||
//func (c Crud[R]) All(ctx ctx, where any, order any, with map[string]func(db *gorm.DB) *gorm.DB) (items []*R) {
|
||
// db := c.Dao.Ctx(ctx).Model(new(R))
|
||
//
|
||
// if with != nil {
|
||
// for k, v := range with {
|
||
// db = db.Preload(k, v)
|
||
// }
|
||
// }
|
||
// if where != nil {
|
||
// db = db.Where(where)
|
||
// }
|
||
// if order != nil {
|
||
// db = db.Order(order)
|
||
// }
|
||
//
|
||
// err := db.Find(&items).Error
|
||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
// panic(fmt.Sprintf("All查询错误: %v", err))
|
||
// }
|
||
// return
|
||
//}
|
||
//
|
||
//// -------------------------- 原Count对应实现:统计记录总数 --------------------------
|
||
//func (c Crud[R]) Count(ctx ctx, where any) (count int64) {
|
||
// err := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Count(&count).Error
|
||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
// panic(fmt.Sprintf("Count查询错误: %v", err))
|
||
// }
|
||
// return
|
||
//}
|
||
//
|
||
//// -------------------------- 原Save对应实现:新增/更新记录(对应GORM的Save) --------------------------
|
||
//func (c Crud[R]) Save(ctx ctx, data any) {
|
||
// err := c.Dao.Ctx(ctx).Model(new(R)).Create(data).Error
|
||
// if err != nil {
|
||
// panic(fmt.Sprintf("Save保存错误: %v", err))
|
||
// }
|
||
//}
|
||
//
|
||
//// -------------------------- 原Update对应实现:按条件更新记录 --------------------------
|
||
//func (c Crud[R]) Update(ctx ctx, where any, data any) (count int64) {
|
||
// result := c.Dao.Ctx(ctx).Model(new(R)).Where(where).Updates(data)
|
||
// if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||
// panic(fmt.Sprintf("Update更新错误: %v", result.Error.Error()))
|
||
// }
|
||
// return result.RowsAffected
|
||
//}
|
||
//
|
||
//// -------------------------- 原UpdatePri对应实现:按主键更新记录 --------------------------
|
||
//func (c Crud[R]) UpdatePri(ctx ctx, primaryKey any, data any) (count int64) {
|
||
// db := c.Dao.Ctx(ctx).Model(new(R))
|
||
// pk := c.Dao.PrimaryKey()
|
||
//
|
||
// if pk == "" {
|
||
// panic("主键字段未配置")
|
||
// }
|
||
//
|
||
// result := db.Where(fmt.Sprintf("%s = ?", pk), primaryKey).Updates(data)
|
||
// if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||
// panic(fmt.Sprintf("UpdatePri更新错误: %v", result.Error.Error()))
|
||
// }
|
||
// return result.RowsAffected
|
||
//}
|
||
//
|
||
//// -------------------------- 原Paginate对应实现:分页查询 --------------------------
|
||
//func (c Crud[R]) Paginate(ctx context.Context, where any, p Paginate, with map[string]func(db *gorm.DB) *gorm.DB, order any) (items []*R, total int64) {
|
||
// db := c.Dao.Ctx(ctx).Model(new(R))
|
||
//
|
||
// // 1. 构建查询条件
|
||
// if where != nil {
|
||
// db = db.Where(where)
|
||
// }
|
||
//
|
||
// // 2. 统计总数
|
||
// if err := db.Count(&total).Error; err != nil {
|
||
// panic(fmt.Sprintf("Paginate查询错误: %v", err))
|
||
// }
|
||
//
|
||
// // 3. 关联查询
|
||
// if with != nil {
|
||
// for k, v := range with {
|
||
// db = db.Preload(k, v)
|
||
// }
|
||
// }
|
||
//
|
||
// // 4. 排序
|
||
// if order != nil {
|
||
// db = db.Order(order)
|
||
// }
|
||
//
|
||
// // 5. 分页(offset = (页码-1)*每页条数)
|
||
// if p.Limit > 0 {
|
||
// offset := (p.Page - 1) * p.Limit
|
||
// db = db.Offset(offset).Limit(p.Limit)
|
||
// }
|
||
//
|
||
// // 6. 执行查询
|
||
// err := db.Find(&items).Error
|
||
// if err != nil || errors.Is(err, gorm.ErrRecordNotFound) {
|
||
// panic(fmt.Sprintf("Paginate查询错误: %v", err))
|
||
// }
|
||
// return
|
||
//}
|
||
//
|
||
//// -------------------------- 内部辅助工具函数 --------------------------
|
||
//// convToMap 将任意类型转换为map[string]any(简化版,适配常见场景)
|
||
//func convToMap(v any) map[string]any {
|
||
// if v == nil {
|
||
// return make(map[string]any)
|
||
// }
|
||
//
|
||
// val := reflect.ValueOf(v)
|
||
// // 处理指针类型
|
||
// if val.Kind() == reflect.Ptr {
|
||
// val = val.Elem()
|
||
// }
|
||
//
|
||
// // 只处理结构体和map类型
|
||
// if val.Kind() != reflect.Struct && val.Kind() != reflect.Map {
|
||
// return make(map[string]any)
|
||
// }
|
||
//
|
||
// result := make(map[string]any)
|
||
//
|
||
// if val.Kind() == reflect.Map {
|
||
// // 处理map类型
|
||
// for _, key := range val.MapKeys() {
|
||
// keyStr, ok := key.Interface().(string)
|
||
// if !ok {
|
||
// continue
|
||
// }
|
||
// result[keyStr] = val.MapIndex(key).Interface()
|
||
// }
|
||
// } else {
|
||
// // 处理结构体类型
|
||
// typ := val.Type()
|
||
// for i := 0; i < val.NumField(); i++ {
|
||
// field := typ.Field(i)
|
||
// fieldVal := val.Field(i)
|
||
//
|
||
// // 获取json标签作为key(优先),否则用字段名
|
||
// jsonTag := field.Tag.Get("json")
|
||
// if jsonTag == "" || jsonTag == "-" {
|
||
// jsonTag = field.Name
|
||
// } else {
|
||
// // 分割json标签(忽略omitempty等选项)
|
||
// jsonTag = strings.Split(jsonTag, ",")[0]
|
||
// }
|
||
//
|
||
// result[jsonTag] = fieldVal.Interface()
|
||
// }
|
||
// }
|
||
//
|
||
// return result
|
||
//}
|
||
//
|
||
//// isEmpty 判断值是否为空
|
||
//func isEmpty(v any) bool {
|
||
// if v == nil {
|
||
// return true
|
||
// }
|
||
//
|
||
// val := reflect.ValueOf(v)
|
||
// switch val.Kind() {
|
||
// case reflect.String:
|
||
// return val.String() == ""
|
||
// case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
// return val.Int() == 0
|
||
// case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
// return val.Uint() == 0
|
||
// case reflect.Float32, reflect.Float64:
|
||
// return val.Float() == 0
|
||
// case reflect.Bool:
|
||
// return !val.Bool()
|
||
// case reflect.Slice, reflect.Array, reflect.Map, reflect.Chan:
|
||
// return val.Len() == 0
|
||
// case reflect.Ptr, reflect.Interface:
|
||
// return val.IsNil()
|
||
// default:
|
||
// return false
|
||
// }
|
||
//}
|
||
//
|
||
//// strInArray 判断字符串是否在数组中
|
||
//func strInArray(arr []string, str string) bool {
|
||
// for _, v := range arr {
|
||
// if strings.EqualFold(v, str) { // 忽略大小写比较
|
||
// return true
|
||
// }
|
||
// }
|
||
// return false
|
||
//}
|