siteInfoManageRepo.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. package mongo
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "fwh-toolbox-server/database"
  7. "fwh-toolbox-server/domain"
  8. "fwh-toolbox-server/dto"
  9. "time"
  10. "go.mongodb.org/mongo-driver/bson"
  11. "go.mongodb.org/mongo-driver/bson/primitive"
  12. "go.mongodb.org/mongo-driver/mongo"
  13. "go.mongodb.org/mongo-driver/mongo/options"
  14. "go.uber.org/zap"
  15. )
  16. const (
  17. CollectionName_SiteInfoManageRecord = "SiteInfoManageRecord"
  18. CollectionName_SiteInfoManageData = "SiteInfoManageData"
  19. CollectionName_SiteInfoTags = "SiteInfoTags"
  20. )
  21. // 更新站点信息获取结果
  22. func CreateSiteInfoUpdateInfo() (*primitive.ObjectID, error) {
  23. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  24. defer cancel()
  25. collection := database.GetCollection(CollectionName_SiteInfoManageRecord)
  26. result, err := collection.InsertOne(ctx, domain.SiteInfoUpdateRecord{
  27. Progress: domain.ProgressPending,
  28. CreateTime: time.Now(),
  29. UpdateTime: time.Now(),
  30. Total: 0,
  31. })
  32. if err != nil {
  33. return nil, err
  34. }
  35. id := result.InsertedID.(primitive.ObjectID)
  36. return &id, nil
  37. }
  38. // 更新站点信息获取结果
  39. func UpdateSiteInfoUpdateResult(id primitive.ObjectID, progress domain.Progress, total uint64) error {
  40. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  41. defer cancel()
  42. collection := database.GetCollection(CollectionName_SiteInfoManageRecord)
  43. filter := bson.M{"_id": id}
  44. var update map[string]interface{}
  45. if progress == domain.ProgressComplete {
  46. update = bson.M{
  47. "$set": bson.M{
  48. "progress": progress,
  49. "updateTime": time.Now(),
  50. "total": total,
  51. },
  52. }
  53. } else {
  54. update = bson.M{
  55. "$set": bson.M{
  56. "progress": progress,
  57. },
  58. }
  59. }
  60. _, err := collection.UpdateOne(ctx, filter, update)
  61. if err != nil {
  62. return err
  63. }
  64. return nil
  65. }
  66. // 获取最新站点信息记录数据
  67. func GetSiteInfoUpdateNewRecord() (*domain.SiteInfoUpdateRecord, error) {
  68. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  69. defer cancel()
  70. collection := database.GetCollection(CollectionName_SiteInfoManageRecord)
  71. opts := options.FindOne().SetSort(bson.D{{Key: "_id", Value: -1}})
  72. var result domain.SiteInfoUpdateRecord
  73. err := collection.FindOne(ctx, bson.M{}, opts).Decode(&result)
  74. if err != nil {
  75. if errors.Is(err, mongo.ErrNoDocuments) {
  76. return nil, nil // 没有数据返回空指针
  77. }
  78. return nil, err
  79. }
  80. return &result, nil
  81. }
  82. // 从数据库获取站点信息列表
  83. func GetSiteInfoManageList(page, size uint, filter *domain.SiteInfoFilter, search string) (*dto.ResPage[domain.SiteInfoDomain], error) {
  84. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  85. defer cancel()
  86. collection := database.GetCollection(CollectionName_SiteInfoManageData)
  87. mainFilter := bson.M{}
  88. // 条件
  89. if filter != nil {
  90. subFilterConfig := bson.M{}
  91. mainFilterSet := []bson.M{}
  92. for _, subFilter := range filter.SubFilter {
  93. subFilterSet := []bson.M{}
  94. filterConfigItem := bson.M{}
  95. for _, filterItem := range subFilter.Config {
  96. switch filterItem.Type {
  97. case domain.FilterEqualInt:
  98. // 等于指定值(整数)
  99. if filterItem.Para1.Int != nil {
  100. filterConfigItem[filterItem.Key] = bson.M{"$eq": *filterItem.Para1.Int}
  101. }
  102. case domain.FilterEqualFloat:
  103. // 等于指定值(浮点数)
  104. if filterItem.Para1.Float != nil {
  105. filterConfigItem[filterItem.Key] = bson.M{"$eq": *filterItem.Para1.Float}
  106. }
  107. case domain.FilterEqualString:
  108. // 等于指定字符串
  109. filterConfigItem[filterItem.Key] = bson.M{"$eq": *filterItem.Para1.String}
  110. case domain.FilterIncludeString:
  111. // 包含指定字符串
  112. filterConfigItem[filterItem.Key] = bson.M{"$regex": *filterItem.Para1.String, "$options": "i"} // 选项 $options:大小写不敏感 (i)
  113. case domain.FilterRangeInt:
  114. // 数值范围检索(整数)
  115. if filterItem.Para2 != nil {
  116. if filterItem.Para1.Int != nil && filterItem.Para2 != nil && filterItem.Para2.Int != nil {
  117. filterConfigItem[filterItem.Key] = bson.M{"$gte": *filterItem.Para1.Int, "$lte": *filterItem.Para2.Int}
  118. }
  119. }
  120. case domain.FilterRangeFloat:
  121. // 数值范围检索(浮点数)
  122. if filterItem.Para2 != nil {
  123. if filterItem.Para1.Float != nil && filterItem.Para2 != nil && filterItem.Para2.Float != nil {
  124. filterConfigItem[filterItem.Key] = bson.M{"$gte": *filterItem.Para1.Float, "$lte": *filterItem.Para2.Float}
  125. }
  126. }
  127. case domain.FilterRangeTime:
  128. // 数值范围检索(时间)
  129. if filterItem.Para1.String != nil && filterItem.Para2 != nil && filterItem.Para2.String != nil {
  130. // start, e1 := time.Parse(time.DateTime, *filterItem.Para1.String)
  131. // end, e2 := time.Parse(time.DateTime, *filterItem.Para2.String)
  132. // if e1 == nil && e2 == nil {
  133. // filterConfigItem[filterItem.Key] = bson.M{"$gte": start, "$lte": end}
  134. // }
  135. start := *filterItem.Para1.String
  136. end := *filterItem.Para2.String
  137. filterConfigItem[filterItem.Key] = bson.M{"$gte": start, "$lte": end}
  138. }
  139. case domain.FilterExists:
  140. // 判断字段是否存在或不为空
  141. // filterConfigItem[filterItem.Key] = bson.M{"$exists": true}
  142. value := *filterItem.Para1.String
  143. switch value {
  144. case "yes":
  145. filterConfigItem[filterItem.Key] = bson.M{"$exists": true, "$ne": nil}
  146. case "no":
  147. filterConfigItem["$or"] = bson.M{
  148. filterItem.Key: bson.M{"$exists": false},
  149. filterItem.Key: bson.M{"$eq": nil},
  150. }
  151. }
  152. }
  153. subFilterSet = append(subFilterSet, filterConfigItem)
  154. }
  155. if len(subFilterSet) > 0 {
  156. switch subFilter.Logic {
  157. case "and":
  158. subFilterConfig["$and"] = subFilterSet
  159. case "or":
  160. subFilterConfig["$or"] = subFilterSet
  161. }
  162. }
  163. mainFilterSet = append(mainFilterSet, subFilterConfig)
  164. }
  165. if len(mainFilterSet) > 0 {
  166. switch filter.Logic {
  167. case "and":
  168. mainFilter["$and"] = mainFilterSet
  169. case "or":
  170. mainFilter["$or"] = mainFilterSet
  171. }
  172. }
  173. }
  174. dbFilter := bson.M{}
  175. if len(search) > 0 {
  176. dbFilter["$and"] = []bson.M{
  177. mainFilter,
  178. {
  179. "$or": []bson.M{
  180. {"_id": bson.M{"$regex": search, "$options": "i"}}, // 选项 $options:大小写不敏感 (i)
  181. {"name": bson.M{"$regex": search, "$options": "i"}},
  182. {"distributorName": bson.M{"$regex": search, "$options": "i"}},
  183. {"installerName": bson.M{"$regex": search, "$options": "i"}},
  184. {"maintName": bson.M{"$regex": search, "$options": "i"}},
  185. {"accountName": bson.M{"$regex": search, "$options": "i"}},
  186. {"iccId": bson.M{"$regex": search, "$options": "i"}},
  187. {"imei": bson.M{"$regex": search, "$options": "i"}},
  188. {"fhpSn": bson.M{"$regex": search, "$options": "i"}},
  189. {"version": bson.M{"$regex": search, "$options": "i"}},
  190. {"protocolVer": bson.M{"$regex": search, "$options": "i"}},
  191. {"realSysHdVersion": bson.M{"$regex": search, "$options": "i"}},
  192. {"financierName": bson.M{"$regex": search, "$options": "i"}},
  193. {"remark": bson.M{"$regex": search, "$options": "i"}},
  194. {"country": bson.M{"$regex": search, "$options": "i"}},
  195. {"province": bson.M{"$regex": search, "$options": "i"}},
  196. {"city": bson.M{"$regex": search, "$options": "i"}},
  197. {"site": bson.M{"$regex": search, "$options": "i"}},
  198. {"jobCode": bson.M{"$regex": search, "$options": "i"}},
  199. },
  200. },
  201. }
  202. } else {
  203. dbFilter = mainFilter
  204. }
  205. var findOptions *options.FindOptions
  206. findOptions = options.Find().
  207. SetSkip(int64((page - 1) * size)).
  208. SetLimit(int64(size))
  209. cursor, err := collection.Find(ctx, dbFilter, findOptions)
  210. if err != nil {
  211. return nil, err
  212. }
  213. defer cursor.Close(ctx)
  214. var infoList []domain.SiteInfoDomain
  215. for cursor.Next(ctx) {
  216. var info domain.SiteInfoDomain
  217. if err := cursor.Decode(&info); err != nil {
  218. return nil, err
  219. }
  220. infoList = append(infoList, info)
  221. }
  222. // 查询总数
  223. total, err := collection.CountDocuments(ctx, dbFilter)
  224. if err != nil {
  225. return nil, err
  226. }
  227. res := dto.ResPage[domain.SiteInfoDomain]{
  228. Data: infoList,
  229. PageSize: size,
  230. PageNum: page,
  231. Total: uint(total),
  232. }
  233. return &res, nil
  234. }
  235. // 从数据库获取站点信息列表(基于GICCID)
  236. func GetSiteInfoManageListFromGiccid(giccid string) ([]domain.SiteInfoDomain, error) {
  237. // 判断GICCID的有效性
  238. if len(giccid) != 19 {
  239. return nil, fmt.Errorf("giccid len is %s, not 19", giccid)
  240. }
  241. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  242. defer cancel()
  243. collection := database.GetCollection(CollectionName_SiteInfoManageData)
  244. // 条件
  245. filter := bson.M{
  246. "iccId": bson.M{
  247. "$regex": giccid, "$options": "i"},
  248. }
  249. cursor, err := collection.Find(ctx, filter, options.Find())
  250. if err != nil {
  251. return nil, err
  252. }
  253. defer cursor.Close(ctx)
  254. var infoList []domain.SiteInfoDomain
  255. for cursor.Next(ctx) {
  256. var info domain.SiteInfoDomain
  257. if err := cursor.Decode(&info); err != nil {
  258. return nil, err
  259. }
  260. infoList = append(infoList, info)
  261. }
  262. return infoList, nil
  263. }
  264. // 插入站点信息数据
  265. func InsertSiteInfoData(data domain.SiteInfoDomain) error {
  266. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  267. defer cancel()
  268. collection := database.GetCollection(CollectionName_SiteInfoManageData)
  269. filter := bson.M{"_id": data.Sn} // 按ID匹配
  270. opts := options.Replace().SetUpsert(true)
  271. _, err := collection.ReplaceOne(ctx, filter, data, opts)
  272. if err != nil {
  273. return err
  274. }
  275. return nil
  276. }
  277. // 查询站点信息标签列表
  278. func GetSiteInfoTags(page, size uint, search string) (*dto.ResPage[domain.SiteTagDomain], error) {
  279. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  280. defer cancel()
  281. collection := database.GetCollection(CollectionName_SiteInfoTags)
  282. // 查询条件
  283. filter := bson.M{}
  284. if search != "" {
  285. filter["name"] = bson.M{
  286. "$regex": primitive.Regex{
  287. Pattern: search,
  288. Options: "i", // 忽略大小写
  289. },
  290. }
  291. }
  292. // 总数
  293. total, err := collection.CountDocuments(ctx, filter)
  294. if err != nil {
  295. return nil, err
  296. }
  297. // 查询选项
  298. opts := options.Find().
  299. SetSkip(int64((page - 1) * size)).
  300. SetLimit(int64(size)).
  301. SetSort(bson.D{
  302. {Key: "name", Value: 1}, // 按名称升序
  303. })
  304. cursor, err := collection.Find(ctx, filter, opts)
  305. if err != nil {
  306. return nil, err
  307. }
  308. defer cursor.Close(ctx)
  309. list := make([]domain.SiteTagDomain, 0)
  310. if err := cursor.All(ctx, &list); err != nil {
  311. return nil, err
  312. }
  313. return &dto.ResPage[domain.SiteTagDomain]{
  314. Data: list,
  315. PageSize: size,
  316. PageNum: page,
  317. Total: uint(total),
  318. }, nil
  319. }
  320. // 查询站点信息标签列表(根据id列表)
  321. func GetSiteInfoTagsFromId(idList []string) (map[string]*dto.SiteTagDTO, error) {
  322. tagMap := make(map[string]*dto.SiteTagDTO)
  323. if len(idList) == 0 {
  324. return tagMap, nil
  325. }
  326. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  327. defer cancel()
  328. collection := database.GetCollection(CollectionName_SiteInfoTags)
  329. // 转换为 ObjectID
  330. objectIDs := make([]primitive.ObjectID, 0, len(idList))
  331. for _, id := range idList {
  332. objectID, err := primitive.ObjectIDFromHex(id)
  333. if err != nil {
  334. // 非法 ID
  335. zap.L().Warn("GetSiteInfoTagsFromId illegal ID", zap.String("err", err.Error()), zap.String("id", id))
  336. continue
  337. }
  338. objectIDs = append(objectIDs, objectID)
  339. }
  340. if len(objectIDs) == 0 {
  341. return tagMap, nil
  342. }
  343. filter := bson.M{
  344. "_id": bson.M{
  345. "$in": objectIDs,
  346. },
  347. }
  348. cursor, err := collection.Find(ctx, filter)
  349. if err != nil {
  350. return nil, err
  351. }
  352. defer cursor.Close(ctx)
  353. for cursor.Next(ctx) {
  354. var tag domain.SiteTagDomain
  355. if err := cursor.Decode(&tag); err != nil {
  356. return nil, err
  357. }
  358. tagMap[tag.Id.Hex()] = dto.SiteTagDomainToSiteTagDTO(&tag)
  359. }
  360. if err := cursor.Err(); err != nil {
  361. return nil, err
  362. }
  363. return tagMap, nil
  364. }
  365. // 创建或更新站点信息标签
  366. func UpdateSiteInfoTag(tag domain.SiteTagDomain) error {
  367. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  368. defer cancel()
  369. collection := database.GetCollection(CollectionName_SiteInfoTags)
  370. filter := bson.M{"_id": tag.Id}
  371. update := bson.M{
  372. "$set": bson.M{
  373. "name": tag.Name,
  374. "count": tag.Count,
  375. "color": tag.Color,
  376. "description": tag.Description,
  377. },
  378. }
  379. opts := options.Update().SetUpsert(true)
  380. _, err := collection.UpdateOne(ctx, filter, update, opts)
  381. if err != nil {
  382. return err
  383. }
  384. return nil
  385. }