package api import ( "box-cost/db/repo" "fmt" "github.com/gin-gonic/gin" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) type DetailHandler func(c *gin.Context, apictx *ApiSession, entity interface{}) (interface{}, error) type ArrayCRUDOption struct { Collection string ArrayFieldPath string NewModel CreateModel EmtyModel EmptyModel DocModel EmptyModel SearchProject []string Query repo.Map OnUpdate Update OnDetail DetailHandler NeedsUpdate bool NeedsRemove bool } func CreateArrayCRUD(router *GinRouter, prefix string, option *ArrayCRUDOption) { //创建 creatpath := fmt.Sprintf("%s/create/:id", prefix) if option.NewModel != nil { router.POSTJWT(creatpath, func(c *gin.Context, apictx *ApiSession) (interface{}, error) { id := c.Param("id") if len(id) < 1 { return nil, NewError("参数id不能为空") } var entity interface{} = nil entity, _ = option.NewModel(c, apictx) if entity == nil { return nil, NewError("数据已存在!") } ret, _ := repo.RepoDocArrayAppend(apictx.CreateRepoCtx(), option.Collection, id, option.ArrayFieldPath, entity) if ret.ModifiedCount == 1 { return entity, nil } return nil, NewError("创建失败!") }) } //更新 if option.NeedsUpdate { updatePath := fmt.Sprintf("%s/update/:id", prefix) router.POSTJWT(updatePath, func(c *gin.Context, apictx *ApiSession) (interface{}, error) { docId := c.Param("id") if len(docId) < 1 { return nil, NewError("id不能为空!") } m := option.EmtyModel(c, apictx) err := c.ShouldBindJSON(m) if err != nil { fmt.Println(err) return nil, NewError("参数解析错误") } if option.OnUpdate != nil { option.OnUpdate(c, apictx, m) } updateQuery := repo.Map{} for k, v := range option.Query { p := fmt.Sprintf("%s.%s", option.ArrayFieldPath, k) updateQuery[p] = v } updateSet := repo.Map{} spath := fmt.Sprintf("%s.$", option.ArrayFieldPath) updateSet[spath] = m updateOption := &repo.ArrayOneUpdateOption{CollectName: option.Collection, Id: docId, Query: updateQuery, Set: updateSet} return repo.RepoDocArrayOneUpdate(apictx.CreateRepoCtx(), updateOption) }) } //数组所有数据 SearchPath := fmt.Sprintf("%s/list/:id", prefix) pageSearchFn := func(c *gin.Context, apictx *ApiSession) (interface{}, error) { docId := c.Param("id") if len(docId) < 1 { return nil, NewError("id不能为空!") } query := UtilQueryMap(c) query["_id"], _ = primitive.ObjectIDFromHex(docId) _, list := repo.RepoSeachDocsMap(apictx.CreateRepoCtx(), &repo.DocsSearchOptions{ CollectName: option.Collection, Query: query, Project: option.SearchProject, }) out := map[string]interface{}{"list": []string{}} if list != nil { out["list"] = list } return out, nil } router.GETJWT(SearchPath, pageSearchFn) //删除 if option.NeedsRemove { removePath := fmt.Sprintf("%s/delete/:id", prefix) router.POSTJWT(removePath, func(c *gin.Context, apictx *ApiSession) (interface{}, error) { id := c.Param("id") if len(id) < 1 { return nil, NewError("参数不能为空") } body := map[string]interface{}{} c.ShouldBindJSON(&body) ArrayQuery := repo.Map{} if len(body) < 1 { return nil, NewError("body参数不能为空") } query := bson.M{} for k, v := range body { query[k] = v } ArrayQuery[option.ArrayFieldPath] = query options := &repo.ArrayOneRemoveOption{ CollectName: option.Collection, Id: id, ArrayQuery: ArrayQuery, } ret, err := repo.RepoDocArrayOneRemove(apictx.CreateRepoCtx(), options) if ret.ModifiedCount < 1 { return nil, NewError("删除失败!") } return ret, err }) } //详情 if option.OnDetail != nil && option.DocModel != nil { DetailPath := fmt.Sprintf("%s/detail/:id", prefix) router.GETJWT(DetailPath, func(c *gin.Context, apictx *ApiSession) (interface{}, error) { docId := c.Param("id") if len(docId) < 1 { return nil, NewError("id不能为空!") } query := UtilQueryMap(c) filter := repo.Map{} if len(query) > 0 { filter[option.ArrayFieldPath] = query } m := option.DocModel(c, apictx) err := repo.RepoDocArraySearch(apictx.CreateRepoCtx(), &repo.ArrayOneSearchOption{ CollectName: option.Collection, ArrayQuery: filter, Id: docId, Field: option.ArrayFieldPath, }, m) if err != nil { return nil, NewError("数据不存在!") } retOut, err := option.OnDetail(c, apictx, m) if err != nil { return nil, err } if retOut != nil { return retOut, nil } return m, nil }) } }