a-service-img.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. package api
  2. import (
  3. "errors"
  4. "fmt"
  5. "sku3dweb/db/model"
  6. "sku3dweb/db/repo"
  7. "sku3dweb/log"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/gin-gonic/gin"
  12. "go.mongodb.org/mongo-driver/bson"
  13. "go.mongodb.org/mongo-driver/bson/primitive"
  14. "go.mongodb.org/mongo-driver/mongo/options"
  15. )
  16. func FassiApi(r *GinRouter) {
  17. r.POSTJWT("/image/create", createImg)
  18. r.GETJWT("/image/fassi/list", SearchByImg)
  19. r.GETJWT("/image/list", SearchByFields)
  20. r.POSTJWT("/image/delete/:id", DeleteImage)
  21. r.POSTJWT("/image/update", UpdateImage)
  22. r.GETJWT("/image/detail/:id", DetailImage)
  23. }
  24. func getSerialNum(img *model.MatImage, ctx *repo.RepoSession) (string, error) {
  25. catId1 := ""
  26. catId2 := ""
  27. catId3 := ""
  28. cat := &model.Category{
  29. CreateTime: time.Now(),
  30. }
  31. find, err := repo.RepoSeachDoc(ctx, &repo.DocSearchOptions{CollectName: repo.CollectionCategory, Query: repo.Map{}, Project: []string{"name", "type", "children", "createTime"}}, cat)
  32. if !find || err != nil {
  33. fmt.Println("find category error", err)
  34. return "", err
  35. }
  36. setMap := make(map[string]*model.Category, len(cat.Children)*200)
  37. for _, s := range cat.Children {
  38. for _, s1 := range s.Children {
  39. setMap[s1.IdStr] = s1
  40. for _, c := range s1.Children {
  41. setMap[c.IdStr] = c
  42. for _, cc := range c.Children {
  43. setMap[cc.IdStr] = cc
  44. }
  45. }
  46. }
  47. }
  48. setParentMap := make(map[string]*model.Category, len(cat.Children)*20)
  49. for _, s := range cat.Children {
  50. for _, s1 := range s.Children {
  51. setParentMap[s1.IdStr] = s
  52. for _, c := range s1.Children {
  53. setParentMap[c.IdStr] = s1
  54. for _, cc := range c.Children {
  55. setParentMap[cc.IdStr] = c
  56. }
  57. }
  58. }
  59. }
  60. fmt.Println("len of cate =", len(img.Categories))
  61. for _, v := range img.Categories {
  62. c, ok := setMap[v]
  63. if !ok {
  64. continue
  65. }
  66. p := setParentMap[v]
  67. fmt.Println("parent->", p.Name, c.Name)
  68. if p.Name == "商品分类" {
  69. catId1 = c.CusNum
  70. fmt.Println("p name", c.CusNum)
  71. continue
  72. }
  73. if p.Name == "产品系列" {
  74. catId2 = c.CusNum
  75. fmt.Println("产品系列 name", catId2)
  76. continue
  77. }
  78. if p.Name == "产品用途" {
  79. catId3 = c.CusNum
  80. fmt.Println("产品用途 name", c.CusNum)
  81. }
  82. }
  83. if len(catId1) < 1 || len(catId2) < 1 || len(catId3) < 1 {
  84. fmt.Println("cat err", catId1, catId2, catId3)
  85. return "", NewError("商品分类/产品系列/产品用途为空")
  86. }
  87. filter := bson.M{
  88. "catId1": catId1,
  89. "catId2": catId2,
  90. }
  91. update := bson.M{
  92. "$inc": bson.M{"next": 1},
  93. "$setOnInsert": bson.M{
  94. "catId1": catId1,
  95. "catId2": catId2,
  96. },
  97. }
  98. opts := options.FindOneAndUpdate().
  99. SetUpsert(true).
  100. SetReturnDocument(options.After)
  101. var result model.SerialNumer
  102. col := ctx.Client.GetCollection(repo.CollectionSerialNos)
  103. err = col.FindOneAndUpdate(ctx.Ctx, filter, update, opts).Decode(&result)
  104. if err != nil {
  105. fmt.Println("get SerialNumer error", err)
  106. return "", fmt.Errorf("failed to get next serial number: %v", err)
  107. }
  108. return fmt.Sprintf("%s%s%03d%s", catId1, catId2, result.Next, catId3), nil
  109. }
  110. func UpdateImage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  111. var matImage model.MatImage
  112. err := c.ShouldBindJSON(&matImage)
  113. if err != nil {
  114. log.Error(err)
  115. return nil, err
  116. }
  117. if matImage.Id.IsZero() {
  118. return nil, errors.New("id错误")
  119. }
  120. searchMat := &model.MatImage{}
  121. // 如果更新的是面料图
  122. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  123. CollectName: repo.CollectionMatImages,
  124. Query: repo.Map{"_id": matImage.Id},
  125. Project: []string{"rawImage"},
  126. }, &searchMat)
  127. if err != nil {
  128. return nil, err
  129. }
  130. // 没有找到面料数据
  131. if !found {
  132. return nil, NewError("未找到数据")
  133. }
  134. fmt.Println("updateing ==============")
  135. fmt.Println(matImage.RawImage, searchMat.RawImage)
  136. // 更新了面料原图 对应更新fassi 特征数据
  137. if matImage.RawImage != nil && (searchMat.RawImage == nil || searchMat.RawImage.Url != matImage.RawImage.Url) {
  138. // 先删除
  139. // 这里原本可能没有图片特征
  140. RomoveFassiImage(matImage.Id.Hex())
  141. // 再新增
  142. err = AddFassiImage(matImage.Id, matImage.RawImage.Url)
  143. if err != nil {
  144. fmt.Println("更新时添加fassi image 错误:", err)
  145. return nil, errors.New("更新图片搜索特征错误,请重试!")
  146. }
  147. fmt.Println("更新fassi image ", matImage.Id.Hex(), err)
  148. }
  149. fmt.Println("33333")
  150. return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionMatImages, matImage.Id.Hex(), &matImage)
  151. }
  152. func DeleteImage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  153. id := c.Param("id")
  154. _, err := RomoveFassiImage(id)
  155. if err != nil {
  156. log.Error("删除时删除fassi image 错误:", err)
  157. }
  158. return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionMatImages, id)
  159. }
  160. func DetailImage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  161. id := c.Param("id")
  162. searchMat := &model.MatImage{}
  163. _, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  164. CollectName: repo.CollectionMatImages,
  165. Query: repo.Map{"_id": id},
  166. }, searchMat)
  167. return searchMat, err
  168. }
  169. func SearchByFields(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  170. page, size, query := UtilQueryPageSize(c)
  171. // 查询所有分类
  172. cates := []*model.Category{}
  173. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{CollectName: repo.CollectionCategory}, &cates)
  174. err := parseCategories(query, cates[0])
  175. if err != nil {
  176. return nil, err
  177. }
  178. pageOption := &repo.PageSearchOptions{
  179. CollectName: repo.CollectionMatImages,
  180. Page: page,
  181. Size: size,
  182. Query: query,
  183. // Project: []string{"nameCn", "createTime", "thumbnail", "price", "from"},
  184. Sort: bson.M{"createTime": -1},
  185. }
  186. return repo.RepoPageSearch(apictx.CreateRepoCtx(), pageOption)
  187. }
  188. func createImg(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  189. data := &model.MatImage{}
  190. err := c.ShouldBindJSON(data)
  191. if err != nil {
  192. return nil, err
  193. }
  194. data.CreateTime = time.Now()
  195. data.UpdateTime = time.Now()
  196. data.UserId, _ = primitive.ObjectIDFromHex(apictx.User.ID)
  197. serial, err := getSerialNum(data, apictx.CreateRepoCtx())
  198. if err != nil {
  199. fmt.Println(err)
  200. return nil, NewError("编号生成失败")
  201. }
  202. data.CusNum = serial
  203. fmt.Println("CusNum=>", serial)
  204. idstr, err := repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionMatImages, data)
  205. if err != nil {
  206. return nil, err
  207. }
  208. imgId, _ := primitive.ObjectIDFromHex(idstr)
  209. return imgId, AddFassiImage(imgId, data.RawImage.Url)
  210. }
  211. func SearchByImg(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  212. url := c.Query("url")
  213. _limit := c.Query("limit")
  214. _min_score := c.Query("min_score")
  215. _max_score := c.Query("max_score")
  216. limit, _ := strconv.Atoi(_limit)
  217. min_score, _ := strconv.ParseFloat(_min_score, 64)
  218. max_score, _ := strconv.ParseFloat(_max_score, 64)
  219. fmt.Println("search url =>: ", url)
  220. if !strings.Contains(url, "http") {
  221. return nil, NewError("参数错误")
  222. }
  223. images, err := QueryFassiImage(url, limit, min_score, max_score)
  224. if err != nil {
  225. return nil, err
  226. }
  227. var list = []map[string]interface{}{}
  228. if len(images) < 1 {
  229. return list, nil
  230. }
  231. var ids = []primitive.ObjectID{}
  232. for _, item := range images {
  233. ids = append(ids, item.Id)
  234. }
  235. param := &repo.DocSearchOptions{
  236. CollectName: repo.CollectionMatImages,
  237. Query: repo.Map{"_id": bson.M{"$in": ids}},
  238. }
  239. err = repo.RepoSeachDocs(apictx.CreateRepoCtx(), param, &list)
  240. if err != nil {
  241. return nil, err
  242. }
  243. var ImageMap = map[primitive.ObjectID]map[string]interface{}{}
  244. for _, item := range list {
  245. ImageMap[item["_id"].(primitive.ObjectID)] = item
  246. }
  247. var out = []interface{}{}
  248. for _, item := range images {
  249. value := ImageMap[item.Id]
  250. value["score"] = item.Score
  251. out = append(out, value)
  252. }
  253. return out, nil
  254. }
  255. type IteChildren func(n *model.Category) []string
  256. type FindChild func(n *model.Category, id string) []string
  257. func FindCategoryIds(c *model.Category, parents []string) ([]string, [][]string) {
  258. out := []string{}
  259. andOut := [][]string{}
  260. var allChildren IteChildren
  261. allChildren = func(n *model.Category) []string {
  262. ids := []string{}
  263. if n == nil {
  264. return ids
  265. }
  266. ids = append(ids, n.IdStr)
  267. if n.Children != nil {
  268. for _, c := range n.Children {
  269. cids := allChildren(c)
  270. if len(cids) > 0 {
  271. ids = append(ids, cids...)
  272. }
  273. }
  274. }
  275. return ids
  276. }
  277. var findChildrens FindChild
  278. findChildrens = func(n *model.Category, id string) []string {
  279. ids := []string{}
  280. if n == nil {
  281. return ids
  282. }
  283. if n.IdStr == id {
  284. ids = allChildren(n)
  285. return ids
  286. }
  287. if n.Children == nil {
  288. return ids
  289. }
  290. //查找孩子节点
  291. for _, c := range n.Children {
  292. ids = findChildrens(c, id)
  293. if len(ids) > 0 {
  294. break
  295. }
  296. }
  297. return ids
  298. }
  299. for _, v := range parents {
  300. for _, catnode := range c.Children {
  301. extends := findChildrens(catnode, v)
  302. if len(extends) > 0 {
  303. andOut = append(andOut, extends)
  304. out = append(out, extends...)
  305. break
  306. }
  307. }
  308. }
  309. return out, andOut
  310. }
  311. func parseCategories(query map[string]interface{}, cateConf *model.Category) error {
  312. filters := []bson.M{}
  313. keyfilters := []bson.M{}
  314. //keyword
  315. if query["keyword"] != nil {
  316. keyword := query["keyword"].(string)
  317. if len(keyword) > 0 {
  318. keyfilters = append(keyfilters, bson.M{"nameCn": bson.M{"$regex": keyword, "$options": "$i"}})
  319. keyfilters = append(keyfilters, bson.M{"nameEn": bson.M{"$regex": keyword, "$options": "$i"}})
  320. keyfilters = append(keyfilters, bson.M{"from": bson.M{"$regex": keyword, "$options": "$i"}})
  321. keyfilters = append(keyfilters, bson.M{"cusNum": bson.M{"$regex": keyword, "$options": "$i"}})
  322. filters = append(filters, bson.M{"$or": keyfilters})
  323. }
  324. delete(query, "keyword")
  325. }
  326. if query["categories"] != nil {
  327. categories := query["categories"].([]interface{})
  328. delete(query, "categories")
  329. //查询所有子内容
  330. if len(categories) > 0 {
  331. filterCaties := []string{}
  332. for _, c := range categories {
  333. if c != nil {
  334. if str, ok := c.(string); ok {
  335. filterCaties = append(filterCaties, str)
  336. }
  337. }
  338. }
  339. oldextends, andExtends := FindCategoryIds(cateConf, filterCaties)
  340. fmt.Println("old =>: ", oldextends)
  341. fmt.Println("and =>: ", andExtends)
  342. andArrayCons := []bson.M{}
  343. if len(andExtends) > 0 {
  344. for _, cateCon := range andExtends {
  345. if len(cateCon) > 0 {
  346. andArrayCons = append(andArrayCons, bson.M{"categories": bson.M{"$elemMatch": bson.M{"$in": cateCon}}})
  347. }
  348. }
  349. }
  350. if len(andArrayCons) > 0 {
  351. filters = append(filters, bson.M{"$and": andArrayCons})
  352. }
  353. }
  354. }
  355. if len(filters) > 0 {
  356. query["$and"] = filters
  357. }
  358. fmt.Printf("分类条件 =>: %#v\n", query)
  359. return nil
  360. }