dashboard.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. package backend
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "kpt-pasture/model"
  7. "net/http"
  8. "regexp"
  9. "strconv"
  10. "strings"
  11. "time"
  12. "github.com/nicksnyder/go-i18n/v2/i18n"
  13. "gorm.io/gorm"
  14. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  15. "gitee.com/xuyiping_admin/pkg/xerr"
  16. "go.uber.org/zap"
  17. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  18. )
  19. func (s *StoreEntry) DataWarningSet(ctx context.Context, req *pasturePb.IndexDataWarningSetRequest) error {
  20. userModel, err := s.GetUserModel(ctx)
  21. if err != nil {
  22. return xerr.WithStack(err)
  23. }
  24. pastureId := userModel.AppPasture.Id
  25. if len(req.WarningDataSet) <= 0 {
  26. messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
  27. MessageID: "dataWarning.selectData",
  28. })
  29. return xerr.Custom(messageId)
  30. }
  31. defaultDataWarning, _ := s.FindDataWarning(ctx, pastureId, model.DefaultUserId)
  32. if len(defaultDataWarning) <= 0 {
  33. messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
  34. MessageID: "dataWarning.defaultDataNotExist",
  35. })
  36. return xerr.Custom(messageId)
  37. }
  38. userDataWarningList, err := s.FindDataWarning(ctx, pastureId, userModel.SystemUser.Id)
  39. if err != nil {
  40. return xerr.WithStack(err)
  41. }
  42. if len(userDataWarningList) <= 0 { // 新增
  43. return s.addUserDataWarning(userModel, defaultDataWarning, req.WarningDataSet)
  44. }
  45. return s.updateUserDataWarning(userModel, userDataWarningList, req.WarningDataSet)
  46. }
  47. func (s *StoreEntry) DataWarningList(ctx context.Context) (*pasturePb.IndexDataWarningResponse, error) {
  48. userModel, err := s.GetUserModel(ctx)
  49. if err != nil {
  50. return nil, xerr.WithStack(err)
  51. }
  52. pastureId := userModel.AppPasture.Id
  53. defaultDataWarning, _ := s.FindDataWarning(ctx, pastureId, model.DefaultUserId)
  54. if len(defaultDataWarning) <= 0 {
  55. messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
  56. MessageID: "dataWarning.defaultDataError",
  57. })
  58. return nil, xerr.Custom(messageId)
  59. }
  60. var isExist bool // 判断是否存在自己的设置的数据
  61. userDataWarning, _ := s.FindDataWarning(ctx, pastureId, userModel.SystemUser.Id)
  62. if len(userDataWarning) == 0 {
  63. // 如果用户没有配置自己的预警数据,则使用默认数据
  64. isExist = true
  65. userDataWarning = defaultDataWarning
  66. }
  67. //newTime := time.Now().Local().Unix()
  68. needUpdateWarningIds := make([]int64, 0)
  69. for _, warningData := range userDataWarning {
  70. // 如果预警数据更新时间大于预警条件更新时间,并且更新时间距离当前时间小于2小时,则跳过
  71. /*if warningData.DataUpdateAt > warningData.ConditionUpdateAt && newTime-warningData.DataUpdateAt < int64(2*time.Hour) {
  72. continue
  73. }*/
  74. needUpdateWarningIds = append(needUpdateWarningIds, warningData.Id)
  75. }
  76. // 需要重新计算更新的warningId
  77. if len(needUpdateWarningIds) > 0 {
  78. s.UpdateWarningData(userModel, needUpdateWarningIds)
  79. }
  80. userDataWarningItems := make([]*model.DataWarningItems, 0)
  81. // 计算过后重新获取数据
  82. if isExist {
  83. userDataWarning, _ = s.FindDataWarning(ctx, pastureId, model.DefaultUserId)
  84. userDataWarningItems, _ = s.FindDataWarningItems(pastureId, model.DefaultUserId)
  85. } else {
  86. userDataWarning, _ = s.FindDataWarning(ctx, pastureId, userModel.SystemUser.Id)
  87. userDataWarningItems, _ = s.FindDataWarningItems(pastureId, userModel.SystemUser.Id)
  88. }
  89. return &pasturePb.IndexDataWarningResponse{
  90. Code: http.StatusOK,
  91. Msg: "ok",
  92. Data: &pasturePb.DataWarning{
  93. DataSet: model.DataWarningItemsSlice(userDataWarningItems).ToPB(userDataWarning),
  94. DataShow: model.DataWarningSlice(userDataWarning).ToPB(),
  95. },
  96. }, nil
  97. }
  98. func (s *StoreEntry) DataWarningPop(ctx context.Context, req *pasturePb.WarningDataListRequest, pagination *pasturePb.PaginationModel) (*model.WarningDataPopResponse, error) {
  99. userModel, err := s.GetUserModel(ctx)
  100. if err != nil {
  101. return nil, xerr.WithStack(err)
  102. }
  103. if req.Kind <= pasturePb.DataWarningType_Invalid {
  104. messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
  105. MessageID: "dataWarning.selectData",
  106. })
  107. return nil, xerr.Custom(messageId)
  108. }
  109. pastureId := userModel.AppPasture.Id
  110. dataWaringItem := &model.DataWarning{}
  111. if err = s.DB.Model(new(model.DataWarning)).
  112. Where("pasture_id = ?", pastureId).
  113. Where("user_id = ?", userModel.SystemUser.Id).
  114. Where("kind = ?", req.Kind).
  115. First(dataWaringItem).Error; err != nil {
  116. if errors.Is(err, gorm.ErrRecordNotFound) {
  117. if err = s.DB.Model(new(model.DataWarning)).
  118. Where("pasture_id = ?", pastureId).
  119. Where("user_id = ?", model.DefaultUserId).
  120. Where("kind = ?", req.Kind).
  121. First(dataWaringItem).Error; err != nil {
  122. return nil, xerr.WithStack(err)
  123. }
  124. } else {
  125. messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
  126. MessageID: "dataWarning.dataNotExist",
  127. })
  128. return nil, xerr.Custom(messageId)
  129. }
  130. }
  131. headers, headerSort, err := dataWaringItem.GetWarningColumn(userModel.LanguageContent)
  132. if err != nil {
  133. return nil, xerr.WithStack(err)
  134. }
  135. resp := &model.WarningDataPopResponse{
  136. Code: http.StatusOK,
  137. Msg: "ok",
  138. Data: &model.WarningPop{
  139. DataList: make([]interface{}, 0),
  140. Title: dataWaringItem.Name,
  141. Kind: dataWaringItem.Kind,
  142. HeaderSort: headerSort,
  143. Headers: headers,
  144. Page: pagination.Page,
  145. PageSize: pagination.PageSize,
  146. Total: 0,
  147. },
  148. }
  149. query, params, err := s.BuildQuery(userModel, dataWaringItem.Id)
  150. if err != nil {
  151. zaplog.Error("UpdateWarningData", zap.Any("BuildQuery", err), zap.Any("warningId", dataWaringItem.Id))
  152. return resp, nil
  153. }
  154. if len(query) == 0 || len(params) == 0 {
  155. return resp, nil
  156. }
  157. var count int64
  158. cowList := make([]*model.Cow, 0)
  159. if err = s.DB.Model(new(model.Cow)).
  160. Where("pasture_id = ?", pastureId).
  161. Where(query, params...).
  162. Count(&count).
  163. Limit(int(pagination.PageSize)).
  164. Offset(int(pagination.PageOffset)).
  165. Find(&cowList).
  166. Error; err != nil {
  167. zaplog.Error("UpdateWarningData", zap.Any("err", err), zap.Any("query", query), zap.Any("params", params))
  168. }
  169. cowTypeMap := s.CowTypeMap()
  170. breedStatusMap := s.CowBreedStatusMap()
  171. cowKindMap := s.CowKindMap()
  172. cowSourceMap := s.CowSourceMap()
  173. admissionStatusMap := s.AdmissionStatusMap()
  174. healthStatusMap := s.HealthStatusMap()
  175. purposeMap := s.PurposeMap()
  176. resp.Data.Total = int32(count)
  177. systemBasic, err := s.GetSystemBasicByName(ctx, userModel.AppPasture.Id, model.PregnancyAge)
  178. if err != nil {
  179. messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
  180. MessageID: "auth.pregnancyDays",
  181. })
  182. return nil, xerr.Custom(messageId)
  183. }
  184. resp.Data.DataList = model.CowSlice(cowList).ToPB(
  185. cowTypeMap, breedStatusMap, cowKindMap,
  186. cowSourceMap, admissionStatusMap, healthStatusMap,
  187. purposeMap, systemBasic.MinValue,
  188. )
  189. return resp, nil
  190. }
  191. func (s *StoreEntry) FindDataWarning(ctx context.Context, pastureId, userId int64) ([]*model.DataWarning, error) {
  192. dataWarningList := make([]*model.DataWarning, 0)
  193. if err := s.DB.Model(new(model.DataWarning)).
  194. Where("user_id = ?", userId).
  195. Where("pasture_id = ?", pastureId).
  196. Find(&dataWarningList).Error; err != nil {
  197. return nil, xerr.WithStack(err)
  198. }
  199. return dataWarningList, nil
  200. }
  201. func (s *StoreEntry) FindDataWarningItems(pastureId, userId int64) ([]*model.DataWarningItems, error) {
  202. dataWarningItemsList := make([]*model.DataWarningItems, 0)
  203. if err := s.DB.Model(new(model.DataWarningItems)).
  204. Where("pasture_id = ?", pastureId).
  205. Where("user_id = ?", userId).
  206. Find(&dataWarningItemsList).Error; err != nil {
  207. return nil, xerr.WithStack(err)
  208. }
  209. return dataWarningItemsList, nil
  210. }
  211. /*func (s *StoreEntry) FindDataWarningMap(ctx context.Context, pastureId, userId int64) (map[int64]*model.DataWarning, error) {
  212. dataWarning, err := s.FindDataWarning(ctx, pastureId, userId)
  213. if err != nil {
  214. return nil, xerr.Custom("默认预警数据有误,请联系管理员!")
  215. }
  216. dataWarningMap := make(map[int64]*model.DataWarning)
  217. for _, v := range dataWarning {
  218. dataWarningMap[v.Id] = v
  219. }
  220. return dataWarningMap, nil
  221. }
  222. func (s *StoreEntry) FindDataWarningItemsMap(ctx context.Context, userId int64) (map[int64]*model.DataWarningItems, error) {
  223. dataWarningItemsList := make([]*model.DataWarningItems, 0)
  224. if err := s.DB.Model(new(model.DataWarningItems)).
  225. Where("user_id = ?", userId).
  226. Find(&dataWarningItemsList).Error; err != nil {
  227. return nil, xerr.WithStack(err)
  228. }
  229. dataWarningItemsMap := make(map[int64]*model.DataWarningItems)
  230. for _, v := range dataWarningItemsList {
  231. dataWarningItemsMap[v.Id] = v
  232. }
  233. return dataWarningItemsMap, nil
  234. }*/
  235. // UpdateWarningData 更新计算数据
  236. func (s *StoreEntry) UpdateWarningData(userModel *model.UserModel, needUpdateWarningIds []int64) {
  237. if len(needUpdateWarningIds) <= 0 {
  238. return
  239. }
  240. for _, warningId := range needUpdateWarningIds {
  241. query, params, err := s.BuildQuery(userModel, warningId)
  242. if err != nil {
  243. zaplog.Error("UpdateWarningData", zap.Any("BuildQuery", err), zap.Any("warningId", warningId))
  244. }
  245. if len(query) == 0 || len(params) == 0 {
  246. continue
  247. }
  248. zaplog.Info("UpdateWarningData", zap.Any("query", query), zap.Any("params", params))
  249. var count int64
  250. if err = s.DB.Model(new(model.Cow)).
  251. Where("pasture_id = ?", userModel.AppPasture.Id).
  252. Where(query, params...).
  253. Count(&count).Error; err != nil {
  254. zaplog.Error("UpdateWarningData", zap.Any("err", err), zap.Any("query", query), zap.Any("params", params))
  255. }
  256. if err = s.DB.Model(new(model.DataWarning)).
  257. Where("id = ?", warningId).
  258. Updates(map[string]interface{}{
  259. "data_value": count,
  260. "data_update_at": time.Now().Local().Unix(),
  261. }).Error; err != nil {
  262. zaplog.Error("UpdateWarningData", zap.Any("update", err))
  263. }
  264. }
  265. }
  266. // 新增用户预警数据
  267. func (s *StoreEntry) addUserDataWarning(userModel *model.UserModel, defaultDataWarning []*model.DataWarning, warningDataSet []*pasturePb.WarningDataSet) error {
  268. // 将默认预警数据按 Kind 映射
  269. defaultDataWarningMap := make(map[pasturePb.DataWarningType_Kind]*model.DataWarning)
  270. for _, v := range defaultDataWarning {
  271. defaultDataWarningMap[v.Kind] = v
  272. }
  273. pastureId := userModel.AppPasture.Id
  274. userId := userModel.SystemUser.Id
  275. // 在事务中执行新增操作
  276. return s.DB.Transaction(func(tx *gorm.DB) error {
  277. addedKinds := make(map[pasturePb.DataWarningType_Kind]bool) // 记录已添加的 Kind
  278. for _, set := range warningDataSet {
  279. dataWarning := model.NewDataWarning(pastureId, userId, set.Kind, pasturePb.IsShow_Ok, defaultDataWarningMap[set.Kind])
  280. // 如果该 Kind 已添加,跳过
  281. if !addedKinds[set.Kind] {
  282. // 创建新的预警数据
  283. if err := tx.Model(new(model.DataWarning)).
  284. Create(dataWarning).Error; err != nil {
  285. return xerr.WithStack(err)
  286. }
  287. } else {
  288. oldDataWarning := &model.DataWarning{}
  289. if err := tx.Model(new(model.DataWarning)).
  290. Where("user_id = ?", userId).
  291. Where("kind = ?", set.Kind).
  292. First(oldDataWarning).Error; err != nil {
  293. return xerr.WithStack(err)
  294. }
  295. dataWarning.Id = oldDataWarning.Id
  296. }
  297. // 创建预警项数据
  298. if err := tx.Model(new(model.DataWarningItems)).
  299. Create(model.NewDataWarningItems(pastureId, userId, dataWarning, set)).Error; err != nil {
  300. return xerr.WithStack(err)
  301. }
  302. addedKinds[set.Kind] = true
  303. }
  304. return nil
  305. })
  306. }
  307. // 更新用户预警数据
  308. func (s *StoreEntry) updateUserDataWarning(userModel *model.UserModel, userDataWarningList []*model.DataWarning, warningDataSet []*pasturePb.WarningDataSet) error {
  309. // 将请求数据按 WarningId 和 Id 映射
  310. warningIsShowMap := make(map[int32]*pasturePb.WarningDataSet)
  311. warningItemDataMap := make(map[int32]*pasturePb.WarningDataSet)
  312. for _, set := range warningDataSet {
  313. warningIsShowMap[set.WarningId] = set
  314. warningItemDataMap[set.Id] = set
  315. }
  316. pastureId := userModel.AppPasture.Id
  317. userId := userModel.SystemUser.Id
  318. // 获取用户预警项数据
  319. userDataWarningItems, err := s.FindDataWarningItems(pastureId, userId)
  320. if err != nil {
  321. return xerr.WithStack(err)
  322. }
  323. if len(userDataWarningItems) == 0 {
  324. messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
  325. MessageID: "dataWarning.dataError",
  326. })
  327. return xerr.Custom(messageId)
  328. }
  329. // 在事务中执行更新操作
  330. return s.DB.Transaction(func(tx *gorm.DB) error {
  331. // 更新预警数据的 IsShow 字段
  332. for _, warning := range userDataWarningList {
  333. if data, ok := warningIsShowMap[int32(warning.Id)]; ok {
  334. if strings.ContainsAny(warning.Name, "0123456789") {
  335. re := regexp.MustCompile(`\d+`)
  336. warning.Name = re.ReplaceAllString(warning.Name, data.Value)
  337. warning.Description = re.ReplaceAllString(warning.Description, data.Value)
  338. }
  339. if err = tx.Model(&model.DataWarning{}).
  340. Where("id = ?", warning.Id).
  341. Updates(map[string]interface{}{
  342. "is_show": data.IsShow,
  343. "name": warning.Name,
  344. "description": warning.Description,
  345. }).Error; err != nil {
  346. return xerr.WithStack(err)
  347. }
  348. }
  349. }
  350. // 更新预警项数据的 IsShow 和 Value 字段
  351. for _, item := range userDataWarningItems {
  352. if set, ok := warningItemDataMap[int32(item.Id)]; ok {
  353. value := set.Value
  354. if set.FieldName == model.FieldName {
  355. v1, _ := strconv.ParseInt(set.Value, 10, 64)
  356. value = fmt.Sprintf("%d", v1*30)
  357. }
  358. if err = tx.Model(&model.DataWarningItems{}).
  359. Where("id = ?", item.Id).
  360. Updates(map[string]interface{}{
  361. "is_show": set.IsShow,
  362. "value": value,
  363. }).Error; err != nil {
  364. return xerr.WithStack(err)
  365. }
  366. }
  367. }
  368. return nil
  369. })
  370. }