507 lines
14 KiB
Go
507 lines
14 KiB
Go
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,
|
||
}
|
||
}
|