Files
bl/common/cool/service.go
xinian d0cf39b439
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
style: 调整代码格式
2026-03-24 04:43:51 +08:00

507 lines
14 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cool
import (
"context"
"database/sql"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
)
type IService interface {
ServiceAdd(ctx context.Context, req *AddReq) (data interface{}, err error) // 新增
ServiceDelete(ctx context.Context, req *DeleteReq) (data sql.Result, err error) // 删除
ServiceUpdate(ctx context.Context, req *UpdateReq) (data sql.Result, err error) // 修改
ServiceInfo(ctx context.Context, req *InfoReq) (data interface{}, err error) // 详情
ServiceList(ctx context.Context, req *ListReq) (data interface{}, err error) // 列表
ServicePage(ctx context.Context, req *PageReq) (data interface{}, err error) // 分页
ModifyBefore(ctx context.Context, method string, param g.MapStrAny) (err error) // 新增|删除|修改前的操作
ModifyAfter(ctx context.Context, method string, param g.MapStrAny) (err error) // 新增|删除|修改后的操作
GetModel() IModel // 获取model
}
type Service struct {
Model IModel
ListQueryOp *QueryOp
PageQueryOp *QueryOp
Where func(ctx context.Context) []g.Array // 删除修改定义条件
InsertParam func(ctx context.Context) g.MapStrAny // Add时插入参数
Before func(ctx context.Context) (err error) // CRUD前的操作
InfoIgnoreProperty string // Info时忽略的字段,多个字段用逗号隔开
UniqueKey g.MapStrStr // 唯一键 key:字段名 value:错误信息
NotNullKey g.MapStrStr // 非空键 key:字段名 value:错误信息
//Cache *gcache.Cache
}
// List/Add接口条件配置
type QueryOp struct {
FieldEQ []string // 字段等于 多个字段选择以及高级搜索都是这个
DataFieldEQ []string // 新增JSONB data->>'xxx' 字段 = ? 多个字段选择以及高级搜索都是这个
KeyWordField []string // 模糊搜索匹配的数据库字段,对应普通搜索
AddOrderby g.MapStrStr // 添加排序
Where func(ctx context.Context) []g.Array // 自定义条件
Select string // 查询字段,多个字段用逗号隔开 如: id,name 或 a.id,a.name,b.name AS bname
Join []*JoinOp // 关联查询
Extend func(ctx g.Ctx, m *gdb.Model) *gdb.Model // 追加其他条件
ModifyResult func(ctx g.Ctx, data interface{}) interface{} // 修改结果
}
// JoinOp 关联查询
type JoinOp struct {
Model IModel // 关联的model
Alias string // 别名
Condition string // 关联条件
Type JoinType // 关联类型 LeftJoin RightJoin InnerJoin
}
// JoinType 关联类型
type JoinType string
// ServiceAdd 新增
func (s *Service) ServiceAdd(ctx context.Context, req *AddReq) (data interface{}, err error) {
r := g.RequestFromCtx(ctx)
rmap := r.GetMap()
// 非空键
if s.NotNullKey != nil {
for k, v := range s.NotNullKey {
if rmap[k] == nil {
return nil, gerror.New(v)
}
}
}
// 唯一键
if s.UniqueKey != nil {
for k, v := range s.UniqueKey {
if rmap[k] != nil {
m := DBM(s.Model)
count, err := m.Where(k, rmap[k]).Count()
if err != nil {
return nil, err
}
if count > 0 {
err = gerror.New(v)
return nil, err
}
}
}
}
if s.InsertParam != nil {
insertParams := s.InsertParam(ctx)
if len(insertParams) > 0 {
for k, v := range insertParams {
rmap[k] = v
}
}
}
m := DBM(s.Model)
lastInsertId, err := m.Data(rmap).InsertAndGetId()
if err != nil {
return
}
data = g.Map{"id": lastInsertId}
return
}
// ServiceDelete 删除
func (s *Service) ServiceDelete(ctx context.Context, req *DeleteReq) (data sql.Result, err error) {
ids := g.RequestFromCtx(ctx).Get("ids").Slice()
m := g.DB(s.Model.GroupName()).Model(s.Model.TableName())
if s.Where != nil {
where := s.Where(ctx)
if len(where) > 0 {
for _, v := range where {
if len(v) == 3 {
if gconv.Bool(v[2]) {
m.Where(v[0], v[1])
}
}
if len(v) == 2 {
m.Where(v[0], v[1])
}
}
}
}
data, err = m.WhereIn("id", ids).Delete()
return
}
// ServiceUpdate 修改
func (s *Service) ServiceUpdate(ctx context.Context, req *UpdateReq) (data sql.Result, err error) {
r := g.RequestFromCtx(ctx)
rmap := r.GetMap()
if rmap["id"] == nil {
err = gerror.New("id不能为空")
return
}
if s.UniqueKey != nil {
for k, v := range s.UniqueKey {
if rmap[k] != nil {
count, err := DBM(s.Model).Where(k, rmap[k]).WhereNot("id", rmap["id"]).Count()
if err != nil {
return nil, err
}
if count > 0 {
err = gerror.New(v)
return nil, err
}
}
}
}
m := DBM(s.Model)
rmap["updateTime"] = nil
if s.Where != nil {
where := s.Where(ctx)
if len(where) > 0 {
for _, v := range where {
if len(v) == 3 {
if gconv.Bool(v[2]) {
m.Where(v[0], v[1])
}
}
if len(v) == 2 {
m.Where(v[0], v[1])
}
}
}
}
//rmap["id"] = nil
data, err = m.Data(rmap).Where("id", rmap["id"]).Update()
return
}
func (s *Service) ServiceInfo(ctx context.Context, req *InfoReq) (data interface{}, err error) {
if s.Before != nil {
err = s.Before(ctx)
if err != nil {
return
}
}
m := g.DB(s.Model.GroupName()).Model(s.Model.TableName())
// 如果InfoIgnoreProperty不为空 则忽略相关字段
if len(s.InfoIgnoreProperty) > 0 {
m = m.FieldsEx(s.InfoIgnoreProperty)
}
data, err = m.Clone().Where("id", req.Id).One()
return
}
func (s *Service) ServiceList(ctx context.Context, req *ListReq) (data interface{}, err error) {
if s.Before != nil {
err = s.Before(ctx)
if err != nil {
return
}
}
r := g.RequestFromCtx(ctx)
m := g.DB(s.Model.GroupName()).Model(s.Model.TableName())
// 如果 req.Order 和 req.Sort 均不为空 则添加排序
if !r.Get("order").IsEmpty() && !r.Get("sort").IsEmpty() {
m.Order(r.Get("order").String() + " " + r.Get("sort").String())
// m.OrderDesc("ordernum")
}
// 如果 ListQueryOp 不为空 则使用 ListQueryOp 进行查询
if s.ListQueryOp != nil {
if Select := s.ListQueryOp.Select; Select != "" {
m.Fields(Select)
}
// 如果Join不为空 则添加Join
if len(s.ListQueryOp.Join) > 0 {
for _, join := range s.ListQueryOp.Join {
switch join.Type {
case LeftJoin:
m.LeftJoin(join.Model.TableName(), join.Condition).As(join.Alias)
case RightJoin:
m.RightJoin(join.Model.TableName(), join.Condition).As(join.Alias)
case InnerJoin:
m.InnerJoin(join.Model.TableName(), join.Condition).As(join.Alias)
}
}
}
// 如果fileldEQ不为空 则添加查询条件
if len(s.ListQueryOp.FieldEQ) > 0 {
for _, field := range s.ListQueryOp.FieldEQ {
if !r.Get(field).IsEmpty() {
m.Where(field, r.Get(field))
}
}
}
// 2. JSONB data->>'xxx' 字段查询(你要的 data 类查找)
if len(s.ListQueryOp.DataFieldEQ) > 0 {
for _, field := range s.ListQueryOp.DataFieldEQ {
if val := r.Get(field); val.String() != "" {
// 关键:拼接 data->>'字段名' = ?
// 错误写法m.Where("data->>::TEXT? = ?", field, val)
// 正确写法:
m.Where("(data->>?)::TEXT = ?", field, val)
}
}
}
// 如果KeyWordField不为空 则添加查询条件
if !r.Get("keyWord").IsEmpty() {
if len(s.ListQueryOp.KeyWordField) > 0 {
builder := m.Builder()
for _, field := range s.ListQueryOp.KeyWordField {
// g.DumpWithType(field)
// builder.WhereLike(field, "%"+r.Get("keyWord").String()+"%")
builder = builder.WhereOrf(field+"::text LIKE ?", "%"+r.Get("keyWord").String()+"%")
//builder = builder.WhereOrLike(field, "%"+r.Get("keyWord").String()+"%")
}
m.Where(builder)
}
}
if s.ListQueryOp.Where != nil {
where := s.ListQueryOp.Where(ctx)
if len(where) > 0 {
for _, v := range where {
if len(v) == 3 {
if gconv.Bool(v[2]) {
m.Where(v[0], v[1])
} else {
m.WhereNot(gconv.String(v[0]), v[1])
}
}
if len(v) == 2 {
m.Where(v[0], v[1])
}
}
}
}
// 如果ListQueryOp的Extend不为空 则执行Extend
if s.ListQueryOp.Extend != nil {
m = s.ListQueryOp.Extend(ctx, m)
}
// 如果 addOrderby 不为空 则添加排序
if len(s.ListQueryOp.AddOrderby) > 0 && r.Get("order").IsEmpty() && r.Get("sort").IsEmpty() {
for field, order := range s.ListQueryOp.AddOrderby {
m.Order(field, order)
}
}
}
// 增加默认数据限制,防止查询所有数据
m.Limit(10000)
result, err := m.All()
if err != nil {
Logger.Error(ctx, "ServiceList error:", err)
}
if result == nil {
data = garray.New()
} else {
data = result
}
if s.ListQueryOp != nil {
if s.ListQueryOp.ModifyResult != nil {
data = s.ListQueryOp.ModifyResult(ctx, data)
}
}
return
}
func (s *Service) ServicePage(ctx context.Context, req *PageReq) (data interface{}, err error) {
var (
r = g.RequestFromCtx(ctx)
total = 0
)
type pagination struct {
Page int `json:"page"`
Size int `json:"size"`
Total int `json:"total"`
}
if req.Size <= 0 {
req.Size = 10
}
if req.Page <= 0 {
req.Page = 1
}
m := g.DB(s.Model.GroupName()).Model(s.Model.TableName())
// 如果pageQueryOp不为空 则使用pageQueryOp进行查询
if s.PageQueryOp != nil {
// 如果Join不为空 则添加Join
if len(s.PageQueryOp.Join) > 0 {
for _, join := range s.PageQueryOp.Join {
switch join.Type {
case LeftJoin:
m.LeftJoin(join.Model.TableName(), join.Condition).As(join.Alias)
case RightJoin:
m.RightJoin(join.Model.TableName(), join.Condition).As(join.Alias)
case InnerJoin:
m.InnerJoin(join.Model.TableName(), join.Condition).As(join.Alias)
}
}
}
// 如果fileldEQ不为空 则添加查询条件
if len(s.PageQueryOp.FieldEQ) > 0 {
for _, field := range s.PageQueryOp.FieldEQ {
if !r.Get(field).IsEmpty() {
m.Where(field, r.Get(field))
}
}
}
// 2. JSONB data->>'xxx' 字段查询(你要的 data 类查找)
if len(s.PageQueryOp.DataFieldEQ) > 0 {
for _, field := range s.PageQueryOp.DataFieldEQ {
if val := r.Get(field); val.String() != "" {
// 关键:拼接 data->>'字段名' = ?
// 错误写法m.Where("data->>::TEXT? = ?", field, val)
// 正确写法:
m.Where("(data->>?)::TEXT = ?", field, val)
}
}
}
// 如果KeyWordField不为空 则添加查询条件
if !r.Get("keyWord").IsEmpty() {
if len(s.PageQueryOp.KeyWordField) > 0 {
builder := m.Builder()
for _, field := range s.PageQueryOp.KeyWordField {
// g.DumpWithType(field)
// builder.WhereLike(field, "%"+r.Get("keyWord").String()+"%")
builder = builder.WhereOrLike(field, "%"+r.Get("keyWord").String()+"%")
}
m.Where(builder)
}
}
// 加入where条件
if s.PageQueryOp.Where != nil {
where := s.PageQueryOp.Where(ctx)
if len(where) > 0 {
for _, v := range where {
if len(v) == 3 {
if gconv.Bool(v[2]) {
m.Where(v[0], v[1])
} else {
m.WhereNot(gconv.String(v[0]), v[1])
}
}
if len(v) == 2 {
m.Where(v[0], v[1])
}
}
}
}
// 如果PageQueryOp的Extend不为空 则执行Extend
if s.PageQueryOp.Extend != nil {
m = s.PageQueryOp.Extend(ctx, m)
}
// 如果 addOrderby 不为空 则添加排序
if len(s.PageQueryOp.AddOrderby) > 0 && r.Get("order").IsEmpty() && r.Get("sort").IsEmpty() {
for field, order := range s.PageQueryOp.AddOrderby {
m.Order(field, order)
}
}
}
// 统计总数
total, err = m.Clone().Count()
if err != nil {
return nil, err
}
if s.PageQueryOp != nil {
if Select := s.PageQueryOp.Select; Select != "" {
m.Fields(Select)
}
}
// 如果 req.Order 和 req.Sort 均不为空 则添加排序
if !r.Get("order").IsEmpty() && !r.Get("sort").IsEmpty() {
m.Order(r.Get("order").String() + " " + r.Get("sort").String())
}
// 如果req.IsExport为true 则导出数据
if req.IsExport {
// 如果req.MaxExportSize大于0 则限制导出数据的最大条数
if req.MaxExportLimit > 0 {
m.Limit(req.MaxExportLimit)
}
result, err := m.All()
if err != nil {
return nil, err
}
data = g.Map{
"list": result,
"total": total,
}
return data, nil
}
result, err := m.Offset((req.Page - 1) * req.Size).Limit(req.Size).All()
if err != nil {
return nil, err
}
if result != nil {
data = g.Map{
"list": result,
"pagination": pagination{
Page: req.Page,
Size: req.Size,
Total: total,
},
}
} else {
data = g.Map{
"list": garray.New(),
"pagination": pagination{
Page: req.Page,
Size: req.Size,
Total: total,
},
}
}
if s.PageQueryOp != nil {
if s.PageQueryOp.ModifyResult != nil {
data = s.PageQueryOp.ModifyResult(ctx, data)
}
}
return
}
// ModifyBefore 新增|删除|修改前的操作
func (s *Service) ModifyBefore(ctx context.Context, method string, param g.MapStrAny) (err error) {
// Loger.Debugf(ctx, "ModifyBefore: %s", method)
return
}
// ModifyAfter 新增|删除|修改后的操作
func (s *Service) ModifyAfter(ctx context.Context, method string, param g.MapStrAny) (err error) {
// if s.Cache != nil {
// s.Cache.Clear(context.Background())
// }
g.DB().GetCore().ClearCache(context.TODO(), s.Model.TableName())
// println(er1)
return
}
// GetModel 获取model
func (s *Service) GetModel() IModel {
return s.Model
}
// GetModel 获取model
// NewService 新建一个service
func NewService(model IModel) *Service {
return &Service{
Model: model,
}
}