Эх сурвалжийг харах

Merge branch 'develop' of xuyiping/kpt-tmr-group into master

xuyiping 4 сар өмнө
parent
commit
e63fad38fb
100 өөрчлөгдсөн 5265 нэмэгдсэн , 4602 устгасан
  1. 90 15
      .drone.yml
  2. 1 0
      .gitignore
  3. 5 8
      Dockerfile
  4. 6 3
      README.md
  5. 0 116
      backend/common/errors.proto
  6. 0 83
      backend/operation/enum.proto
  7. 0 92
      backend/operation/feed_formula.proto
  8. 0 35
      backend/operation/mobile.proto
  9. 0 12
      backend/operation/pagination.proto
  10. 0 289
      backend/operation/pasture.proto
  11. 0 262
      backend/operation/statistic.proto
  12. 0 220
      backend/operation/system.proto
  13. 1 1
      cmd/http.go
  14. 1 0
      config/app.develop.yaml
  15. 11 2
      config/app.go
  16. 1 0
      config/app.test.yaml
  17. 39 1
      config/load_config.go
  18. 27 0
      config/private.key
  19. 9 0
      config/public.key
  20. 1 1
      dep/dep.go
  21. 1 1
      dep/di.go
  22. 34 36
      go.mod
  23. 72 59
      go.sum
  24. 69 0
      http/debug/debug.go
  25. 4 4
      http/handler/dashboard/dashboard.go
  26. 0 24
      http/handler/default.go
  27. 289 13
      http/handler/feed/feed_formula.go
  28. 35 0
      http/handler/feed/feed_formula_detail.go
  29. 3 3
      http/handler/mobile/mobile_list.go
  30. 4 4
      http/handler/pasture/cattle_forage_category.go
  31. 6 9
      http/handler/pasture/forage_list.go
  32. 4 4
      http/handler/pasture/pasture.go
  33. 4 4
      http/handler/pasture/pasture_list.go
  34. 124 5
      http/handler/statistic/analysis.go
  35. 4 4
      http/handler/system/menu.go
  36. 4 4
      http/handler/system/role.go
  37. 8 6
      http/handler/system/user.go
  38. 4 3
      http/middleware/cors.go
  39. 107 0
      http/middleware/log.go
  40. 2 2
      http/middleware/sentry.go
  41. 12 6
      http/middleware/sso.go
  42. 3 0
      http/route/api_debug_route.go
  43. 19 1
      http/route/ops_api.go
  44. 1 1
      http/route/root.go
  45. 1 1
      http/util/httptt/http.go
  46. 1 1
      http/util/httptt/query_encoder.go
  47. 1 1
      main.go
  48. 36 1
      model/analysis_accuracy.go
  49. 12 9
      model/cattle_category.go
  50. 12 0
      model/feed.go
  51. 48 7
      model/feed_formula.go
  52. 55 0
      model/feed_formula_detail.go
  53. 4 9
      model/feed_formula_distribute_log.go
  54. 39 0
      model/feed_formula_edit_record.go
  55. 56 4
      model/forage.go
  56. 12 9
      model/forage_category.go
  57. 182 3
      model/formula_estimate.go
  58. 59 45
      model/group_pasture.go
  59. 152 4
      model/pasture_data.go
  60. 1 1
      model/system_group_pasture_permissions.go
  61. 1 1
      model/system_menu.go
  62. 1 1
      model/system_menu_permissions.go
  63. 1 1
      model/system_mobile.go
  64. 1 1
      model/system_mobile_permissions.go
  65. 1 1
      model/system_role.go
  66. 1 1
      model/system_user.go
  67. 328 165
      module/backend/dashboard_service.go
  68. 15 0
      module/backend/edit_record_service.go
  69. 780 56
      module/backend/feed_service.go
  70. 32 6
      module/backend/interface.go
  71. 725 0
      module/backend/mock/PastureService.go
  72. 106 0
      module/backend/mock/PastureSyncService.go
  73. 353 0
      module/backend/mock/StatisticService.go
  74. 354 0
      module/backend/mock/SystemService.go
  75. 51 0
      module/backend/mock/WxAppletService.go
  76. 328 24
      module/backend/mock/kptservice.go
  77. 36 19
      module/backend/pasture_service.go
  78. 244 2
      module/backend/pasture_sync_service.go
  79. 188 223
      module/backend/statistic_service.go
  80. 3 3
      module/backend/system_permissions.go
  81. 37 32
      module/backend/system_service.go
  82. 3 3
      module/backend/wx_applet_service.go
  83. 0 207
      pkg/apierr/apierr.go
  84. 0 761
      pkg/apierr/apierr_gen.go
  85. 0 47
      pkg/apierr/config.go
  86. 0 23
      pkg/apiok/common.go
  87. 0 133
      pkg/cleanup/entry.go
  88. 0 53
      pkg/cleanup/entry_test.go
  89. 0 19
      pkg/cputil/cp.go
  90. 0 59
      pkg/cputil/cp_test.go
  91. 0 26
      pkg/di/annotation.go
  92. 0 153
      pkg/di/hub.go
  93. 0 187
      pkg/di/hub_test.go
  94. 0 180
      pkg/di/option.go
  95. 0 157
      pkg/di/xreflect/reflect.go
  96. 0 143
      pkg/di/xreflect/reflect_test.go
  97. 0 149
      pkg/di/xreflect/stack.go
  98. 0 236
      pkg/di/xreflect/stack_test.go
  99. 0 68
      pkg/ginutil/bind.go
  100. 0 34
      pkg/ginutil/bind_proto.go

+ 90 - 15
.drone.yml

@@ -1,18 +1,8 @@
 kind: pipeline
 type: docker
-name: kptTmrGroup
-
-#clone:
-#  depth: 1
-#  disable: true
+name: test
 
 steps:
-  #- name: clone
-  #  image: alpine/git
-  #  commands:
-  #    - git clone -b develop http://kpt.kptyun.cn:3000/xuyiping/kpt-tmr-group.git
-  #    - ls -l
-  #    - pwd
   - name: build
     image: plugins/docker:20.14.2
     volumes:
@@ -23,23 +13,108 @@ steps:
       - name: docker-sock
         path: /var/run/docker.sock
     settings:
-      #dockerfile: /drone/src/kpt-tmr-group/Dockerfile
+      dockerfile: /drone/src/Dockerfile
       username:
         from_secret: aliyuncs_username
       password:
         from_secret: aliyuncs_password
       repo: registry.cn-hangzhou.aliyuncs.com/kpt-event/kpt-tmr-group
       registry: registry.cn-hangzhou.aliyuncs.com
-      tags: [ 1.0.3,latest ]
-
+      tags: [ test ]
+  - name: ssh commands
+    image: appleboy/drone-ssh
+    settings:
+      host: 192.168.1.70
+      username: tmrwatch
+      password:
+        from_secret: ssh_password
+      port: 22
+      script:
+        - cd /data/docker-compose/kpt-tmr-group/
+        - echo "123456" | ./restart.sh
 trigger:
   branch:
     include:
-    - develop
+    - feature/*
   event:
     include:
     - push
+volumes:
+  - name: docker-ca
+    host:
+      path: /etc/docker
+  - name: docker-sock
+    host:
+      path: /var/run/docker.sock
+---
+kind: pipeline
+type: docker
+name: product
+steps:
+  - name: build
+    image: plugins/docker:20.14.2
+    volumes:
+      - name: hosts
+        path: /etc/hosts
+      - name: docker-ca
+        path: /etc/docker
+      - name: docker-sock
+        path: /var/run/docker.sock
+    settings:
+      username:
+        from_secret: aliyuncs_username
+      password:
+        from_secret: aliyuncs_password
+      repo: registry.cn-hangzhou.aliyuncs.com/kpt-event/kpt-tmr-group
+      registry: registry.cn-hangzhou.aliyuncs.com
+      tag:
+        - latest
+        - ${DRONE_BRANCH##release/}
+trigger:
+  branch:
+    include:
+      - release/*
+  event:
+    include:
+      - push
+volumes:
+  - name: docker-ca
+    host:
+      path: /etc/docker
+  - name: docker-sock
+    host:
+      path: /var/run/docker.sock
+---
+kind: pipeline
+type: docker
+name: fix
 
+steps:
+  - name: build
+    image: plugins/docker:20.14.2
+    volumes:
+      - name: hosts
+        path: /etc/hosts
+      - name: docker-ca
+        path: /etc/docker
+      - name: docker-sock
+        path: /var/run/docker.sock
+    settings:
+      username:
+        from_secret: aliyuncs_username
+      password:
+        from_secret: aliyuncs_password
+      repo: registry.cn-hangzhou.aliyuncs.com/kpt-event/kpt-tmr-group
+      registry: registry.cn-hangzhou.aliyuncs.com
+      tag:
+        - latest
+trigger:
+  branch:
+    include:
+      - fix/*
+  event:
+    include:
+      - push
 volumes:
   - name: docker-ca
     host:

+ 1 - 0
.gitignore

@@ -47,3 +47,4 @@ _testmain.go
 bin/
 .vscode/
 logger/
+config/private.key

+ 5 - 8
Dockerfile

@@ -3,14 +3,12 @@ WORKDIR /app/kpt-tmr-group
 
 COPY . .
 
-RUN mkdir -p ./bin
-
 RUN go env -w GO111MODULE=on && \
     go env -w GOPROXY=https://goproxy.cn,direct && \
     go env -w CGO_ENABLED=0 && \
     go env -w GOARCH=amd64 && \
     go env -w GOOS=linux && \
-    go build -o ./bin/kptTmrGroup -ldflags "-X kpt.kptyun.cn:3000/kpt-event/kpt-tmr-group/pod.appVersion=tmrGroup" main.go
+    go build -o ./kptTmrGroup -ldflags "-X kpt.kptyun.cn:3000/kpt-event/kpt-tmr-group/pod.appVersion=tmrGroup" main.go
 
 
 FROM alpine:latest
@@ -20,11 +18,10 @@ owner="yiping.xu"
 
 WORKDIR /app/kpt-tmr-group
 
-
-COPY --from=0 /app/kpt-tmr-group/config/*.yaml /app/kpt-tmr-group/bin/config/
-COPY --from=0  /app/kpt-tmr-group/bin/kptTmrGroup /app/kpt-tmr-group/bin/kptTmrGroup
+COPY --from=0 /app/kpt-tmr-group/config/ /app/kpt-tmr-group/config/
+COPY --from=0  /app/kpt-tmr-group/kptTmrGroup /app/kpt-tmr-group/kptTmrGroup
 
 EXPOSE 8090
-VOLUME /app/kpt-tmr-group/logger
+VOLUME ["/app/kpt-tmr-group/logger","/app/kpt-tmr-group/config"]
 
-CMD ["/app/kpt-tmr-group/bin/kptTmrGroup","http"]
+CMD ["/app/kpt-tmr-group/kptTmrGroup","http"]

+ 6 - 3
README.md

@@ -25,14 +25,17 @@ kpt-tmr-group - 科湃腾TMR集团版
 - make test
 
 lint:
-在开发完后请记得跑下make lint做代码检查(🤔: 你可能会有疑问,为啥不配置JOB跑呢?-->  因为golangci-lint跑本项目需要6G+的内存,会触发OOM😂)
+在开发完后请记得跑下make lint做代码检查(🤔: 你可能会有疑问,为啥不配置JOB跑呢?-->  因为golang-ci-lint跑本项目需要6G+的内存,会触发OOM😂)
 
-需要更新 gomock:
+需要更新 go-mock:
 - 生成 mock 前,请确保你能够编译 & 编译完成
 - make generate
 
+备注
+- GetDataByName(公共接口,目前只兼容startTime和endTime字段)
+
 TODO 列表
-- proto3 int64 jsonpb处理后自动转成string
+- proto3 int64 jsonPb处理后自动转成string
   * ~~现在处理的方式是把int64类型改成int32类型~~
 - 用户登出没有用redis做缓存,所以后端没有提供登出接口,有以下弊端
   * 用户的token没有过期,如被人劫持,会被使用到直到token过期

+ 0 - 116
backend/common/errors.proto

@@ -1,116 +0,0 @@
-syntax = "proto3";
-
-package backend.common;
-
-option go_package = ".;commonPb";
-
-message Error {
-  enum Code {
-    OK = 0;
-
-    reserved 1 to 9999;
-
-    // ========= Common =========
-
-    // 鉴权
-    UNAUTHORIZED = 10000;
-    reserved 10001 to 10999;
-
-    // 通用请求错误
-    BAD_REQUEST = 11000;
-    INVALID_CONTENT_TYPE = 11001;
-    INVALID_CONTENT_ENCODING = 11002;
-    TOO_MANY_REQUESTS = 11003;
-    reserved 11004 to 11099;
-
-    // ========= Biz =========
-
-    // Config
-    INVALID_STORAGE_TYPE = 11100;
-    reserved 11101 to 11199;
-
-    // DataEvent
-    INVALID_DE_DATA = 11200;
-    reserved 11201 to 19999;
-
-    // Checkin
-    CHECKIN_REPEATED = 20000;
-    reserved 20001 to 20999;
-
-    // Course
-    COURSE_NOT_FOUND = 21000;
-    // 课程没有权益
-    COURSE_NOT_INTEREST = 21001;
-    reserved 21002 to 21999;
-
-    // Recommend
-    MODULE_NOT_FOUND = 22000;
-    reserved 22001 to 22999;
-
-    // User Course
-    USER_COURSE_ALREADY_ADDED = 23000;
-    USER_COURSE_NOT_FOUND = 23001;
-    reserved 23002 to 23999;
-
-    // PT
-    PT_LIMITED = 24000;
-    reserved 24001 to 24099;
-
-    // Payment 24100 - 24299
-
-    // 无效的价格
-    INVALID_PRICE = 24100;
-    // 无效的 product ID
-    INVALID_PRODUCT_ID = 24101;
-    // 无效的订单号
-    INVALID_ORDER_NUMBER = 24102;
-    // 无效的用户 ID
-    INVALID_USER_ID = 24103;
-    // 无效的收据
-    INVALID_RECEIPT = 24104;
-    // 异常的 iOS 收据,需要客户端 check 和重试
-    EMPTY_IOS_RECEIPT = 24105;
-
-    reserved 24106 to 24299;
-
-    // UserPlan 相关
-    // 免费用户限制 plan 课程数量
-    USER_PLAN_LIMITED_COURSE_COUNT = 24300;
-
-
-    // 保留业务段 24400 to 89999
-    reserved 24400 to 89999;
-
-    // ========= SYSTEM =========
-    // 服务自身错误
-    INTERNAL_ERROR = 90000;
-    reserved 90001 to 90099;
-
-    // encoding/decoding error
-
-    // JSONPB encoding/decoding with error
-    JSONPB_ERROR = 90100;
-
-    // JSON encoding/decoding with error
-    JSON_ERROR = 90101;
-
-    // PB encoding/decoding with error
-    PB_ERROR = 90102;
-    reserved 90103 to 90999;
-
-    // 依赖服务错误
-    EXTERNAL_ERROR = 91000;
-
-    reserved 91001 to max;
-  }
-
-  // 业务错误码
-  Code code = 1;
-
-  // 错误信息
-  string msg = 2;
-
-  // 补充错误信息
-  // @optional
-  repeated string errors = 3;
-}

+ 0 - 83
backend/operation/enum.proto

@@ -1,83 +0,0 @@
-syntax = "proto3";
-
-package backend.operation;
-
-option go_package = ".;operationPb";
-
-// 字段类型
-message IsShow {
-  enum Kind {
-    INVALID = 0;  // 无效
-    OK = 1;       // 是
-    NO = 2;       // 否
-  }
-}
-
-message CattleCategoryParent {
-  enum Kind {
-    INVALID = 0;           // 所有
-    LACTATION_CAW = 1;     // 泌乳牛
-    FATTEN_CAW = 2;        // 育肥牛
-    RESERVE_CAW  = 3;      // 后备牛
-    DRY_CAW = 4;           // 干奶牛
-    PERINATAL_CAW  = 5;    // 围产牛
-    OTHER_CAW = 6;         // 其他
-  }
-}
-
-// 饲料类别
-message ForageCategoryParent {
-  enum Kind {
-    INVALID = 0;           // 无效
-    ROUGHAGE = 1;          // 粗料
-    CONCENTRATE  = 2;      // 精料(浓缩料)
-    HALF_ROUGHAGE_HALF_CONCENTRATE = 3;   // 粗料精料各半
-    OTHER = 4;        // 其他
-  }
-}
-
-// 饲料来源
-message ForageSource {
-  enum Kind {
-    INVALID = 0;           // 无效
-    SYSTEM_BUILT_IN = 1;   // 系统内置
-    USER_DEFINED = 2;      // 用户自定义
-  }
-}
-
-// 跳转延迟
-message JumpDelaType {
-  enum Kind {
-    INVALID = 0;           // 禁用
-    THREE = 1;             // 3秒
-    SIX = 2;               // 6秒
-    NINE = 3;              // 9秒
-  }
-}
-
-// 计划类型
-message ForagePlanType {
-  enum Kind {
-    INVALID = 0;           // 无
-    FORKLIFT = 1;          // 铲车
-    CONCENTRATE = 2;       // 精料
-  }
-}
-
-message DataSource {
-  enum Kind {
-    INVALID = 0;           // 无
-    BACKGROUND_ADD = 1;    // 后台手动添加
-    EXCEL_IMPORT = 2;     // excel报表导入
-    FROM_PASTURE = 3;     // 来自牧场
-  }
-}
-
-message FormulaType {
-  enum Kind {
-    INVALID = 0;                    // 无
-    FEED_FORMULA = 1;              // 饲喂配方
-    PREMIXED_FORMULA = 2;          // 预混配方
-    SUPPLEMENTARY_FORMULA = 3;     // 补料配方
-  }
-}

+ 0 - 92
backend/operation/feed_formula.proto

@@ -1,92 +0,0 @@
-syntax = "proto3";
-package backend.operation;
-
-option go_package = ".;operationPb";
-
-import "backend/operation/pagination.proto";
-import "backend/operation/enum.proto";
-
-message AddFeedFormulaRequest {
-  int32 id = 1;
-  string name = 2;                   // 名称
-  string  encode_number = 3;         // 编码
-  string colour = 4;                 // 颜色
-  CattleCategoryParent.Kind cattle_category_id = 5;      // 畜牧类别id
-  string cattle_category_name = 6;   // 畜牧类型名称
-  int32 formula_type_id = 7;         // 配方类型id
-  string formula_type_name = 8;      // 配方类型名称
-  DataSource.Kind data_source_id = 9;   // 数据来源
-  string data_source_name = 10;   // 数据来源
-  string remarks = 11;               // 备注
-  int32 version = 12;                // 版本号
-  IsShow.Kind is_show = 13;          // 是否启用
-  IsShow.Kind is_modify = 14;        // 是否可修改
-  int32 created_at = 15;             // 创建时间
-  string created_at_format = 16;     // 创建时间格式化
-  string pasture_name = 17;          // 牧场名称
-}
-
-message SearchFeedFormulaRequest {
-  int32 cattle_category_id = 1;    // 分类id
-  int32 formula_type_id = 2;       // 配方类型id
-  int32 data_source = 3;           // 饲料来源
-  IsShow.Kind is_show = 4;         // 是否启用
-  string name = 5;                 // 配方名称
-  string remarks = 6;              // 备注
-  PaginationModel pagination = 7;  // 分页
-}
-
-message SearchFeedFormulaListResponse {
-  int32 code = 1;
-  string msg = 2;
-  SearchFeedFormulaListData data = 3;
-}
-
-message SearchFeedFormulaListData {
-  int32 page = 1;
-  int32 page_size = 2;
-  int32 total = 3;
-  repeated AddFeedFormulaRequest list = 4;
-}
-
-// 是否启用
-message IsShowModifyFeedFormula {
-  int32 feed_formula_id = 1;
-  IsShow.Kind is_show = 2;
-  int32 edit_type = 3;      // 1 更新是否启用 2 更新 modify
-}
-
-// 配方编码
-message UniqueID {
-  int32 code = 1;
-  string msg = 2;
-  message UniqueData {
-    string encode_number = 1;
-  }
-  UniqueData data = 3;
-}
-
-// DistributeFeedFormulaRequest 饲料配方下发
-message DistributeFeedFormulaRequest {
-  repeated int32 pasture_ids = 1;          // 牧场ids集合
-  repeated int32 feed_formula_ids = 2;     // 配方ids集合
-}
-
-// 配方使用概况
-message FeedFormulaUsageRequest {
-    int32 feed_formula_id = 1;        // 饲料配方id
-    string start_time = 2;            // 开始时间
-    string end_time = 3;              // 结束时间
-}
-
-// 配方使用概况
-message FeedFormulaUsageResponse {
-  repeated FeedFormulaUsageList list = 1;
-}
-
-// 配方使用概况
-message FeedFormulaUsageList {
-  int32 pasture_id = 1;
-  string pasture_name = 2;
-
-}

+ 0 - 35
backend/operation/mobile.proto

@@ -1,35 +0,0 @@
-syntax = "proto3";
-package backend.operation;
-
-option go_package = ".;operationPb";
-
-import "backend/operation/pagination.proto";
-import "backend/operation/system.proto";
-
-message SearchMobileRequest {
-  string name = 1;       // 名称
-  PaginationModel pagination = 2; // 分页
-}
-
-message SearchMobileResponse {
-  int32 code = 1;
-  string msg = 2;
-  SearchMobileData data = 3;
-}
-
-message SearchMobileData {
-  int32 page = 1;
-  int32 total = 2;
-  int32 page_size = 3;
-  repeated  MobileData list = 4;
-}
-
-message MobileData {
-  uint32 id = 1;
-  string name = 2;
-  uint32 created_at = 3;
-  string created_at_format = 4;
-  repeated AddMenuRequest children = 15;   // 子分类
-}
-
-

+ 0 - 12
backend/operation/pagination.proto

@@ -1,12 +0,0 @@
-syntax = "proto3";
-
-package backend.operation;
-
-option go_package = ".;operationPb";
-
-
-message PaginationModel {
-  int32 Page       = 1;
-  int32 PageSize   = 2;
-  int32 PageOffset = 3;
-}

+ 0 - 289
backend/operation/pasture.proto

@@ -1,289 +0,0 @@
-syntax = "proto3";
-package backend.operation;
-
-option go_package = ".;operationPb";
-
-import "backend/operation/enum.proto";
-import "backend/operation/pagination.proto";
-
-message AddPastureRequest {
-  int32 id = 1;
-  string name = 2; // 牧场名称
-  string account = 3;   // 登录账号名称
-  string manager_user = 4; // 牧场负责人名称
-  string manager_phone = 5;   // 牧场负责人手机号
-  string address = 6;   // 牧场地址
-  IsShow.Kind is_show = 7;    // 是否启用
-  int32 created_at = 8;    // 创建时间
-  string created_at_format = 9;    // 创建时间格式化
-  string domain = 10;    // 牧场端域名或者ip
-  int32 pasture_id = 11;  // 牧场端id (兼容历史数据)
-}
-
-message SearchPastureRequest {
-  string name = 1;       // 牧场名称
-  string manager_user = 2; // 牧场负责人名称
-  string manager_phone = 3;   // 牧场负责人手机号
-  uint32 start_time = 4;       // 开始时间
-  uint32 end_time = 5;    // 结束时间
-  PaginationModel pagination = 6; // 分页
-}
-
-message SearchPastureResponse {
-  int32 code = 1;
-  string msg = 2;
-  SearchPastureData data = 3;
-}
-
-message SearchPastureData {
-  int32 page = 1;
-  int32 total = 2;
-  int32 page_size = 3;
-  repeated AddPastureRequest list = 4;
-}
-
-message UserPasture {
-  int32 id = 1;
-  string name = 2;
-}
-
-message IsShowGroupPasture {
-  int32 pasture_id = 1;    // 牧场id
-  IsShow.Kind is_show = 2;     // 是否开启
-}
-
-// 添加牧畜分类
-message AddCattleCategoryRequest {
-  uint32 id = 1;
-  CattleCategoryParent.Kind parent_id = 2;  // 父类id
-  string parent_name = 3;        // 父类名称
-  string name = 4;               // 牧畜分类名称
-  string number = 5;            // 畜牧类别编号
-  IsShow.Kind is_show = 6;      // 是否启用
-  uint32 created_at = 7;         // 创建时间
-  string created_at_format = 8;   // 创建时间格式
-}
-
-// 是否启用
-message IsShowCattleCategory {
-  int32 cattle_category_id = 1;
-  IsShow.Kind is_show = 2;
-}
-
-// 畜牧分类查询列表
-message SearchCattleCategoryRequest {
-  int32 parent_id = 1;
-  IsShow.Kind is_show = 2;
-  string name = 3;
-  PaginationModel pagination = 4; // 分页
-}
-
-message SearchCattleCategoryResponse {
-  int32 code = 1;
-  string msg = 2;
-  SearchCattleCategoryData data = 3;
-}
-
-message SearchCattleCategoryData {
-  int32 page = 1;
-  int32 total = 2;
-  int32 page_size = 3;
-  repeated AddCattleCategoryRequest list = 4;
-}
-
-// 添加饲料分类
-message AddForageCategoryRequest {
-  uint32 id = 1;
-  ForageCategoryParent.Kind parent_id = 2;  // 父类id
-  string parent_name = 3;        // 父类名称
-  string name = 4;               // 牧畜分类名称
-  string number = 5;            // 畜牧类别编号
-  IsShow.Kind is_show = 6;      // 是否启用
-  uint32 created_at = 7;         // 创建时间
-  string created_at_format = 8;   // 创建时间格式
-}
-
-// 是否启用
-message IsShowForageCategory {
-  int32 forage_category_id = 1;
-  IsShow.Kind is_show = 2;
-}
-
-// 饲料分类查询列表
-message SearchForageCategoryRequest {
-  int32 parent_id = 1;
-  IsShow.Kind is_show = 2;
-  string name = 3;
-  string number = 4;
-  PaginationModel pagination = 5; // 分页
-}
-
-message SearchForageCategoryResponse {
-  int32 code = 1;
-  string msg = 2;
-  SearchForageCategoryData data = 3;
-}
-
-message SearchForageCategoryData {
-  int32 page = 1;
-  int32 total = 2;
-  int32 page_size = 3;
-  repeated AddForageCategoryRequest list = 4;
-}
-
-// 饲料列表
-message AddForageRequest {
-  int32 id = 1;
-  string name = 2;                // 饲料名称
-  int32 category_id = 3;          // 饲料分类id
-  string category_name = 4;       // 饲料分类名称
-  int32 material_type = 5;        // 物料类型
-  string unique_encode = 7;       // 唯一编码
-  ForageSource.Kind forage_source_id = 8;       // 饲料来源id
-  string forage_source_name = 9;                // 饲料来源名称
-  ForagePlanType.Kind plan_type_id = 10;       // 计划类型id
-  string plan_type_name = 11;                  // 计划类型名称
-  string  small_material_scale = 12;           // 小料称
-  int32 allow_error = 13;                     // 允许误差 (单位kg)
-  int32 package_weight = 14;                  // 包装重量 (单位kg)
-  int32 price = 15;                          // 单价(单位分)
-  int32 jump_weight = 16;                    // 跳转重量域(单位kg)
-  JumpDelaType.Kind jump_delay = 17;         // 跳转延迟
-  IsShow.Kind confirm_start = 18;            // 确认开始
-  int32  relay_locations = 19;               // 继电器位置
-  IsShow.Kind jmp = 20;                     // 无上域
-  string backup1 = 21;                      // 备用字段1
-  string backup2 = 22;                      // 备用字段2
-  string backup3 = 23;                      // 备用字段3
-  int32 created_at = 24;                    // 创建时间
-  string created_at_format = 25;            // 创建时间格式化
-  IsShow.Kind is_show = 26;                  // 是否启用
-}
-
-message SearchForageListRequest {
-  string name = 1;   // 饲料名称
-  int32 category_id = 2;   // 饲料分类id
-  uint32 forage_source_id = 3;   // 饲料来源
-  IsShow.Kind is_show = 4;    // 是否启用
-  uint32 allow_error = 5;      // 允许误差
-  uint32 jump_weight = 6;      // 跳转重量域
-  JumpDelaType.Kind  jump_delay = 7;   // 跳转延迟
-  PaginationModel pagination = 8; // 分页
-}
-
-message ForageListSortRequest {
-  repeated ForageListSort list = 1;
-}
-
-message ForageListSort {
-  int64 id = 1;
-  int64 sort = 2;
-}
-
-message SmallMaterialRequest {
-  string api_name = 1;        // 牧场端接口标识名称
-  int32 pasture_id = 2;       // 牧场id
-  string info_name = 3;       //
-}
-
-message SearchForageListResponse {
- int32 code = 1;
- string msg = 2;
- SearchForageList data = 3;
-}
-
-message SearchForageList {
-  int32 page = 1;
-  int32 page_size = 2;
-  int32 total = 3;
-  repeated AddForageRequest list = 4;
-}
-
-// 是否启用
-message IsShowForage {
-  int32 forage_id = 1;
-  IsShow.Kind is_show = 2;
-}
-
-message ForageEnumListResponse {
-  int32 code = 1;
-  string msg = 2;
-  ForageEnumList data = 3;
-}
-
-message ForageEnumList {
-  repeated ForageSourceEnum forage_source = 1;                    // 饲料来源
-  repeated ForagePlanTypeEnum forage_plan_type = 2;               // 饲料计划类型
-  repeated JumpDelaTypeEnum jump_dela_type = 3;                   // 跳转延迟类型
-  repeated CattleParentCategoryEnum cattle_parent_category = 4;   // 畜牧分类
-  repeated ForageParentCategoryEnum forage_parent_category = 5;   // 饲料分类
-  repeated IsShowEnum is_show = 6;
-  repeated FormulaTypeEnum formula_type = 7;                      // 配方类型
-  repeated FormulaOptionEnum formula_list = 8;                    // 所有配方列表
-  repeated IsShowEnum confirm_start = 9;                          // 确认开始
-  repeated FormulaOptionEnum formulation_evaluation = 10;         // 配方评估查询方式
-  repeated FormulaOptionEnum use_materials_list = 11;             // 用料分析-列表显示
-  repeated FormulaOptionEnum use_materials_type = 12;             // 用料分析-统计类型
-  repeated FormulaOptionEnum price_materials_type = 13;           // 价格分析-统计类型
-  repeated FormulaOptionEnum jump_type = 14;                      // 准确性-跳转方式
-  repeated FormulaOptionEnum statistics_type = 15;                // 准确性-统计类型
-}
-
-message ForageSourceEnum {
-  ForageSource.Kind value = 1;
-  string label = 2;
-}
-
-message ForagePlanTypeEnum {
-  ForagePlanType.Kind value = 1;
-  string label = 2;
-}
-
-message JumpDelaTypeEnum {
-  JumpDelaType.Kind value = 1;
-  string label = 2;
-}
-
-message CattleParentCategoryEnum {
-  CattleCategoryParent.Kind value = 1;
-  string label = 2;
-}
-
-message ForageParentCategoryEnum {
-  ForageCategoryParent.Kind value = 1;
-  string label = 2;
-}
-
-message IsShowEnum {
-  IsShow.Kind value = 1;
-  string label = 2;
-}
-
-message FormulaTypeEnum {
-  FormulaType.Kind value = 1;
-  string label = 2;
-}
-
-message FormulaOptionEnum {
-  int32 value = 1;
-  string label = 2;
-}
-// 牧场端分类数据同步
-message CategorySyncRequest {
-  string key_word = 1;         // 关键字
-  int32 pasture_id = 2;        // 牧场id
-  int32 parent_id = 3;         // 一类id
-  string parent_name = 4;      // 一类名称
-  string name = 5;             // 分类名称
-  string number = 6;           // 分类编号
-  IsShow.Kind is_show = 7;     // 是否展示
-  IsShow.Kind is_delete = 8;   // 是否删除
-  int32 id = 9;                // 牧场端数据id
-}
-
-// 牧场端分类数据删除
-message CategoryDeleteRequest {
-  string key_word = 1;    // 关键字
-  int32 pasture_id = 2;   // 牧场id
-  int32 data_id = 3;
-}

+ 0 - 262
backend/operation/statistic.proto

@@ -1,262 +0,0 @@
-syntax = "proto3";
-package backend.operation;
-
-option go_package = ".;operationPb";
-
-
-import "backend/operation/pagination.proto";
-import "backend/operation/enum.proto";
-import "backend/operation/pasture.proto";
-
-// SearchFormulaEstimateRequest 配方评估
-message SearchFormulaEstimateRequest {
-  string start_time  = 1;     // 开始时间
-  string end_time    = 2;     // 结束时间
-  int32 search_type = 3;      // 查询方式  0 安照配方 1 按照栏舍
-  string api_name = 4;        // 牧场端接口标识名称
-  int32 pasture_id = 5;       // 牧场id
-  int32 template_id = 6;     // 配方模板id
-  int32 barn_id = 7;          // 栏舍id
-  PaginationModel pagination = 8; // 分页
-}
-
-// SearchInventoryStatisticsRequest 库存管理-库存统计
-message SearchInventoryStatisticsRequest {
-  string start_time  = 1;     // 开始时间
-  string end_time    = 2;     // 结束时间
-  string api_name = 3;        // 牧场端接口标识名称
-  string feed_name = 4;       // 饲料名称
-  int32 pasture_id = 5;       // 牧场id
-  PaginationModel pagination = 6; // 分页
-}
-
-// SearchUserMaterialsStatisticsRequest 库存管理-用料分析
-message SearchUserMaterialsStatisticsRequest {
-  string start_time  = 1;     // 开始时间
-  string end_time    = 2;     // 结束时间
-  string api_name = 3;        // 牧场端接口标识名称
-  int32 pasture_id = 4;       // 牧场id
-  int32 error_check = 5;       // 误差是否选中 0 未选中 1 选中
-  int32 type_check = 6;        // 返回实际或理论 1 理论 2 实际
-  string feed_name = 7;        // 名称
-  PaginationModel pagination = 8; // 分页
-}
-
-// SearchPriceStatisticsRequest 库存管理-价格分析
-message SearchPriceStatisticsRequest {
-  string start_time  = 1;     // 开始时间
-  string end_time    = 2;     // 结束时间
-  string api_name = 3;        // 牧场端接口标识名称
-  int32 pasture_id = 4;       // 牧场id
-  string feed_name = 5;        // 名称
-  PaginationModel pagination = 6; // 分页
-}
-
-// SearchFeedStatisticsRequest 饲喂效率-效率统计
-message SearchFeedStatisticsRequest {
-  string start_time  = 1;            // 开始时间
-  string api_name = 2;               // 牧场端接口标识名称
-  repeated int32 pasture_id = 3;              // 牧场id
-  string formula_template = 4;       // 配方模板名称
-  string barn_name = 5;               // 栏舍名称
-  string cattle_category_name = 6;   // 畜牧类别名称
-  int32 cattle_category_id = 7;     // 畜牧类别id
-  int32 class_number = 8;            // 班次
-  PaginationModel pagination = 9;   // 分页
-}
-
-// FeedChartStatisticsRequest 饲喂效率chart图表
-message FeedChartStatisticsRequest {
-  string start_time = 1;     // 开始时间
-  string end_time = 2;       // 结束时间
-  int32 pasture_id = 3;      // 牧场id
-  int32 status = 4;
-  string api_type = 5;       // mr 泌乳牛干物质采食量 sl 牛栏剩料率 hl 混料时间统计 zh 转化率 cbft 成本分析
-}
-
-// CowsAnalysisRequest 饲喂效率-牛群评估
-message CowsAnalysisRequest {
-  string start_time = 1;     // 开始时间
-  string api_name = 2;       // 牧场端接口标识名称
-  int32 pasture_id = 3;      // 牧场id
-  PaginationModel pagination = 4;   // 分页
-}
-
-// AccuracyAggStatisticsRequest 准确性分析-汇总统计
-message AccuracyAggStatisticsRequest {
-  string start_time = 1;     // 开始时间
-  string end_time = 2;       // 结束时间
-  int32 pasture_id = 3;      // 牧场id
-  string fname = 4;         // 查询名称
-  string sort = 5;
-  string status = 6;
-  int32 genre = 7;
-  int32 isdate = 8;
-  int32 hlwc1 = 9;
-  int32 hlwc2 = 10;
-  int32 hlzq1 = 11;
-  int32 hlzq2 = 12;
-  int32 hlzql1 = 13;
-  int32 hlzql2 = 14;
-  int32 slwc1 = 15;
-  int32 slwc2 = 16;
-  int32 slzq1 = 17;
-  int32 slzq2 = 18;
-  int32 slzql1 = 19;
-  int32 slzql2 = 20;
-  string projname = 21;
-  string Times = 22;
-  bool is_error = 23;
-}
-
-// MixFeedStatisticsRequest 准确性分析-混料统计
-message MixFeedStatisticsRequest {
-  string start_time  = 1;            // 开始时间
-  string end_time = 2;               // 结束时间
-  string api_name = 3;               // 牧场端接口标识名称
-  int32 pasture_id = 4;              // 牧场id
-  string equipment_name = 5;         // 设备名称
-  string train_number = 6;           // 车次
-  int32 class_number = 7;            // 班次
-  string formulation_name = 8;       // 配方名称
-  int32 jump_type = 9;               // 跳转方式 0 手动跳转 1 自动跳转
-  int32 hlwc1 = 10;                  // 混料误差值1
-  int32 hlwc2 = 11;                  // 混料误差值2
-  int32 hlzq1 = 12;                  // 混料准确率1
-  int32 hlzq2 = 13;                  // 混料准确率2
-  int32 hlzql1 = 14;                 // 混料正确率1
-  int32 hlzql2 = 15;                 // 混料正确率2
-  bool is_error = 16;                // 只看超出预设值数据
-  string button_type = 17;
-  string is_use = 18;
-  PaginationModel pagination = 19;   // 分页
-}
-
-// SprinkleStatisticsRequest 准确性分析-撒料统计
-message SprinkleStatisticsRequest {
-  string start_time  = 1;            // 开始时间
-  string end_time = 2;               // 结束时间
-  string api_name = 3;               // 牧场端接口标识名称
-  int32 pasture_id = 4;              // 牧场id
-  string equipment_name = 5;         // tmr设备名称
-  string train_number = 6;           // 车次
-  int32 class_number = 7;            // 班次
-  string formulation_name = 8;       // 配方名称
-  string barn_name = 9;              // 栏舍名称
-  int32 jump_type = 10;               // 跳转方式 0 手动跳转 1 自动跳转
-  int32 slwc1 = 11;                  // 撒料误差值1
-  int32 slwc2 = 12;                  // 撒料误差值2
-  int32 slzq1 = 13;                  // 撒料准确率1
-  int32 slzq2 = 14;                  // 撒料准确率2
-  int32 slzql1 = 15;                 // 撒料正确率1
-  int32 slzql2 = 16;                 // 撒料正确率2
-  bool is_error = 17;                // 只看超出预设值数据
-  string button_type = 18;
-  string is_use = 19;
-  PaginationModel pagination = 20;   // 分页
-}
-
-// GetDataByNameRequest
-message GetDataByNameRequest {
-  string start_time  = 1;            // 开始时间
-  string end_time = 2;               // 结束时间
-  string api_name = 3;               // 牧场端接口标识名称
-  int32 pasture_id = 4;              // 牧场id
-}
-
-// ProcessAnalysisRequest 过程分析
-message ProcessAnalysisRequest {
-  string start_time  = 1;            // 开始时间
-  string end_time = 2;               // 结束时间
-  string api_name = 3;               // 牧场端接口标识名称
-  int32 pasture_id = 4;              // 牧场id
-  int32 plan_type = 5;               // 计划类型
-  repeated string tmr_name = 6;      // TMR名称
-  string error_range = 7;            // 误差筛选范围
-  string work_status = 8;            // 工作状态
-  string mix_feed_type = 9;          // 混料类别
-  int32 hlwc1 = 10;                  // 混料误差值1
-  int32 hlwc2 = 11;                  // 混料误差值2
-  int32 hlzq1 = 12;                  // 混料准确率1
-  int32 hlzq2 = 13;                  // 混料准确率2
-  int32 slwc1 = 14;                  // 撒料误差值1
-  int32 slwc2 = 15;                  // 撒料误差值2
-  int32 slzq1 = 16;                  // 撒料准确率1
-  int32 slzq2 = 17;                  // 撒料准确率2
-  PaginationModel pagination = 18;   // 分页
-}
-
-message TrainNumberRequest {
-  string api_name = 1;               // 牧场端接口标识名称
-  int32 pasture_id = 2;              // 牧场id
-  string info_name = 3;
-  PaginationModel pagination = 4;   // 分页
-}
-
-message TrainNumberResponse {
-  int32 code = 1;
-  string msg = 2;
-  TrainNumberData data = 3;
-}
-
-message TrainNumberData {
-  repeated FormulaOptionEnum list = 1;
-}
-
-
-// 首页 dashboard 准确性分析
-message SearchAnalysisAccuracyRequest {
-  CattleCategoryParent.Kind cattle_parent_category_id = 1;   // 牧畜分类id 泌乳牛
-  int32 feed_formula_id = 2;    // 配方id
-  string start_date = 3;       // 开始时间
-  string end_date = 4;         // 结束时间
-  repeated int32 pasture_ids = 5;   //牧场ids
-}
-
-message SearchAnalysisAccuracyResponse {
-  int32 code = 1;
-  string msg = 2;
-  AnalysisAccuracy data = 3;
-}
-
-message AnalysisAccuracy {
-  Chart chart = 1;
-  Table table = 2;
-}
-
-message Chart {
-  CommonValueRatio mixed_fodder_accurate_ratio = 4;              // 混料准确率
-  CommonValueRatio mixed_fodder_correct_ratio = 5;               // 混料正确率
-  CommonValueRatio sprinkle_fodder_accurate_ratio = 6;           // 撒料准确率
-  CommonValueRatio sprinkle_fodder_correct_ratio = 7;            // 撒料正确率
-}
-
-message Table {
-  message TableList {
-    int32 id = 1;
-    string name = 2;
-  }
-
-  repeated TableList table_list = 1;
-}
-
-message CommonValueRatio {
-  string max_value = 1;                  // 最高值
-  string middle_value = 2;               // 中位值
-  string min_value = 3;                  // 最低值
-  repeated ValueRatio data_list = 4;     // 数据集合
-  repeated string pasture_name = 5;      // 牧场名称集合
-  repeated string date_day = 6;          // 日期集合
-}
-
-message ValueRatio {
-  repeated string value_ratio = 1;
-}
-
-// 首页 dashboard 撒料时间统计分析
-message SprinkleFeedTimeRequest {
-  int32 feed_formula_id = 1;    // 配方id
-  string start_date = 2;       // 开始时间
-  string end_date = 3;         // 结束时间
-  repeated int32 pasture_ids = 4;   //牧场ids
-}

+ 0 - 220
backend/operation/system.proto

@@ -1,220 +0,0 @@
-syntax = "proto3";
-package backend.operation;
-
-option go_package = ".;operationPb";
-
-import "backend/operation/enum.proto";
-import "backend/operation/pagination.proto";
-import "backend/operation/pasture.proto";
-
-message CommonOK {
-  int32 code = 1;
-  string msg = 2;
-  Success data = 3;
-}
-
-message Success {
-  bool success = 1;
-}
-
-message WxOpenId {
-  string openid = 1;
-}
-
-// 用户角色
-message AddRoleRequest {
-  uint32 id = 1;
-  string name = 2;        // 角色名称
-  string remarks = 3;     // 角色备注
-  IsShow.Kind is_show = 4;     // 是否启用
-  repeated uint32 pasture_id = 5;    // 牧场id
-  repeated uint32 menu_id = 6;       // 菜单id
-  repeated uint32 mobile_id = 7;     // 移动端id
-  string create_user = 8;          // 创建用户
-  uint32 created_at = 9;             // 创建时间
-  string created_at_format = 10;     // 创建时间格式化
-
-  repeated string pasture_list = 11;   // 负责的牧场
-  repeated string menu_list = 12; // 权限列表
-}
-
-message SearchRoleRequest {
-  string name = 3;       // 角色名称
-  PaginationModel pagination = 2;  // 分页
-}
-
-message SearchRoleResponse {
-  uint32 code = 1;
-  string msg = 2;
-  SearchRoleData data = 3;
-}
-
-message SearchRoleData {
-  int32 page = 1;
-  int32 total = 2;
-  int32 page_size = 3;
-  repeated AddRoleRequest list = 4;
-}
-
-// 角色对应权限列表
-message RolePermissionsList {
-  int32 code = 1;
-  string msg = 2;
-  RolePermissionsData data = 3;
-}
-
-message RolePermissionsData {
-  repeated uint32 mobile_list = 1;    // 移动端权限id
-  repeated uint32 pasture_list = 2;    // 牧场端列表
-  repeated uint32 menu_list = 3;      // 后端权限列表
-}
-
-// 用户token
-message SystemToken {
-  int32 code =  1;
-  string msg = 2;
-  TokenData data = 3;
-}
-
-message TokenData {
-  string token = 1;
-}
-
-// 用户登录
-message UserAuth {
-  int32 code = 1;
-  string msg = 2;
-  UserAuthData data = 3;
-}
-
-message UserAuthData {
-  string user_name = 1;   // 用户名称
-  string password = 2;    // 用户密码
-  string phone = 3;       // 用户手机号
-  repeated UserRole roles  = 4;    // 用户角色
-  string employee_name = 5;    // 员工名称
-  repeated UserPasture pastures = 6; // 用户角色牧场牧场
-}
-
-message UserRole {
-  int32 id = 1;      // 角色id
-  string name = 2;   // 角色名称
-}
-
-// 用户详情
-message UserDetails {
-  int32 code = 1;
-  string msg = 2;
-  AddSystemUser data = 3;
-}
-
-
-message AddSystemUser {
-  int32 id = 1;                    // 用户id
-  string name = 2;                 // 用户名称
-  string phone = 3;                // 用户手机号
-  repeated UserRole roles = 4;      // 角色
-  IsShow.Kind is_show = 5;         // 是否开启
-  string employee_name = 6;        // 员工姓名
-  string create_user = 7;          // 创建人
-  int32 created_at = 8;            // 创建时间
-  string created_at_format = 9;      // 创建时间格式化
-  string role_name = 10;            // 角色名称
-  repeated int32 role_ids = 11;     // 角色ids
-}
-
-// 查询用户
-message SearchUserRequest {
-  string name = 1;               // 用户名称
-  string employee_name = 2;       // 员工姓名
-  IsShow.Kind is_show = 3;        // 是否启用
-  uint32 created_start_time = 4;   // 开始时间
-  uint32 created_end_time = 5;     // 结束时间
-  PaginationModel pagination = 6; // 分页
-}
-
-message SearchUserResponse {
-    int32 code = 1;
-    string msg = 2;
-    SearchUserData data = 3;
-}
-
-message SearchUserData  {
-  int32 page = 1;
-  int32 total = 2;
-  int32 page_size = 3;
-  repeated AddSystemUser list = 4;
-}
-
-message IsShowSystemUserRequest {
-  int32 user_id = 1;  // 用户id
-  IsShow.Kind is_show = 2;   // is_show
-}
-// 系统菜单权限
-message AddMenuRequest {
-  int32 id = 1;
-  string name = 2;           // 名称
-  int32 parent_id = 3;       // 父id
-  int32 menu_type = 4;       // 菜单类型 1 菜单 2 按钮
-  string title = 5;          // 标题
-  string path = 6;           // 路径 path
-  IsShow.Kind is_show = 7;   // 是否显示
-  string component = 8;      // 组件
-  string icon = 9;           // 图标
-  int32 sort = 10;           // 排序
-  string redirect = 11;      // 重定向
-  int32 created_at = 12;     // 创建时间
-  string created_at_format = 13;      // 创建时间格式化
-  int32 level = 14;                   // 菜单等级
-  repeated AddMenuRequest children = 15;   // 子分类
-  bool affix = 16;
-  bool keepAlive = 17;
-}
-
-message IsShowSystemMenuRequest {
-  int32 menu_id = 1;  // 角色id
-  IsShow.Kind is_show = 2;   // is_show
-}
-
-// 查询菜单权限
-message SearchMenuRequest {
-  string name = 1;               // 菜单名称
-  PaginationModel pagination = 2; // 分页
-}
-
-message SearchMenuResponse {
-  int32 code = 1;
-  string msg = 2;
-  SearchMenuData data = 3;
-}
-
-message SearchMenuData {
-  int32 page = 1;
-  int32 total = 2;
-  repeated AddMenuRequest list = 3;
-}
-
-// 系统用户权限相关
-message SystemUserMenuPermissions {
-  int32 code = 1;
-  string msg = 2;
-  SystemUserMenuData data = 3;
-}
-
-message SystemUserMenuData {
-  repeated AddPastureRequest pasture_list = 1;    // 牧场列表
-  repeated AddMenuRequest menu_list = 2;          // 菜单列表
-  repeated AddMobileRequest mobile_list = 3;      // 移动端权限
-  repeated MenuButtonsPath menu_buttons_path = 4;  // 按钮级别权限path,前端需要特别处理
-}
-
-message MenuButtonsPath {
-  string path = 1;
-  int32 menu_id = 2;
-}
-
-// 移动端
-message AddMobileRequest {
-  uint32 id = 1;     // id
-  string name = 2;  // 名称
-}

+ 1 - 1
cmd/http.go

@@ -2,10 +2,10 @@ package cmd
 
 import (
 	"fmt"
+	"gitee.com/xuyiping_admin/pkg/logger/logrus"
 	"kpt-tmr-group/config"
 	"kpt-tmr-group/dep"
 	"kpt-tmr-group/http"
-	"kpt-tmr-group/pkg/logger/logrus"
 
 	"github.com/spf13/cobra"
 )

+ 1 - 0
config/app.develop.yaml

@@ -3,6 +3,7 @@ app_environment: test
 debug: true
 http_server_addr: ':8090'
 http_metrics_addr: ':23332'
+jwt_expire_time: 7200
 
 store:
   show_sql: true

+ 11 - 2
config/app.go

@@ -1,7 +1,8 @@
 package config
 
 import (
-	"kpt-tmr-group/pkg/di"
+	"crypto/rsa"
+	"gitee.com/xuyiping_admin/pkg/di"
 	"os"
 	"strings"
 	"sync"
@@ -29,7 +30,14 @@ type AppConfig struct {
 
 	ExcelSetting ExcelSetting `json:"excelSetting" yaml:"excel_setting"`
 
-	WechatSetting WechatSetting `json:"wechatSetting" yaml:"wechat_setting"`
+	WechatSetting     WechatSetting     `json:"wechatSetting" yaml:"wechat_setting"`
+	JwtTokenKeyConfig JwtTokenKeyConfig `json:"jwtTokenKeyConfig"`
+	JwtExpireTime     int               `json:"jwtExpireTime" yaml:"jwt_expire_time"`
+}
+
+type JwtTokenKeyConfig struct {
+	PrivateKey *rsa.PrivateKey `json:"privateKey"`
+	PublicKey  *rsa.PublicKey  `json:"publicKey"`
 }
 
 type WechatSetting struct {
@@ -83,6 +91,7 @@ func init() {
 		if err != nil {
 			panic(err)
 		}
+		cfg.JwtTokenKeyConfig = openPrivateKey()
 		options = cfg
 	})
 }

+ 1 - 0
config/app.test.yaml

@@ -3,6 +3,7 @@ app_environment: test
 debug: true
 http_server_addr: ':8090'
 http_metrics_addr: ':23332'
+jwt_expire_time: 7200
 
 store:
   show_sql: true

+ 39 - 1
config/load_config.go

@@ -2,14 +2,18 @@ package config
 
 import (
 	"fmt"
+	"io/ioutil"
 	"os"
 
+	"github.com/dgrijalva/jwt-go"
+
 	"github.com/mitchellh/mapstructure"
 	"github.com/spf13/viper"
 )
 
+var workDir = os.Getenv("GO_WORK_DIR_TMR_GROUP")
+
 func Initialize(path string, cfgStruct interface{}) error {
-	workDir := os.Getenv("GO_WORK_DIR_TMR_GROUP")
 	if workDir == "" {
 		workDir = "."
 	}
@@ -26,3 +30,37 @@ func Initialize(path string, cfgStruct interface{}) error {
 	}
 	return nil
 }
+
+func openPrivateKey() JwtTokenKeyConfig {
+	pathList := []string{fmt.Sprintf("%s/config/private.key", workDir), fmt.Sprintf("%s/config/public.key", workDir)}
+	res := JwtTokenKeyConfig{PublicKey: nil, PrivateKey: nil}
+	for i, path := range pathList {
+		keyConfig, err := os.Open(path)
+		if err != nil {
+			panic(err)
+		}
+
+		b, err := ioutil.ReadAll(keyConfig)
+		if err != nil {
+			panic(err)
+		}
+
+		if i == 0 {
+			parivateKey, err := jwt.ParseRSAPrivateKeyFromPEM(b)
+			if err != nil {
+				panic(err)
+			}
+			res.PrivateKey = parivateKey
+		}
+
+		if i == 1 {
+			publicKey, err := jwt.ParseRSAPublicKeyFromPEM(b)
+			if err != nil {
+				panic(err)
+			}
+			res.PublicKey = publicKey
+		}
+	}
+
+	return res
+}

+ 27 - 0
config/private.key

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAg5bDPoPigNdHslKHuR6bHk5K1SOqoMJLgCqmoLHdrKZp1T81
+2lAq1uECIcWyrPNnCDu47vmkn3zwLbM7Qn61udkhNqfKQVYMBGAmqeuqS06osVGo
+XKcbcxMmTSJFGjjy6hMCNd5DQDaV6AabXQRxSYyOxz5HDtYYjEUKd/RypAn+co9m
+gBWF4oqWmmt89RwHVqK+TACqnB9bA1yISq/71YbquMiTquyoY8KNlBDAmaFFvnYw
+8pzXG1KfLcKlpSibB4xkD5bEHfpzxOvU4zZu2rw4n2ju//Q8upQAJOQy7tefQ34I
+VjQ8ImrBwz3LOyHKQ3MRFDkBpq52j3yhOOlqVwIDAQABAoIBAG4sUUZLN9514KKN
+9PLqjCeAl6kClr7ITlx92UscAKSoJF4V8WnayzNj6twJ4YJqvG4pSrpTLCEYgyNQ
+OCKBYne7MtLHA1FW0PLs6hJErS0mK5li7Bq/Ev1zIBNeyQqeecu/pI8ji5z81uAQ
+gA4ORSe2Vmi9XNMwMBdpSs2KTl3GhjAG7G9Z6fhI8sv3yYsHK5hRUznSTdszmEtQ
+8z/EccOp8Dsu9lxxs6S41whcON6lIzZRQ8QhTjsg9wcE6ZhKWoixIEewuHn4jRAs
+aHwF3RI9RRy04IGPG/nHwh/O+Ln5i++vWPj7lzRUTwWApiAXKaPZkfuzI4nGH4Hm
+QyVp6YkCgYEA0gH25WFcO/+4HEa0dR93ILI3etDgYHn6QoNttFtyLq3FbLjK+c6J
+dS8aJSi0QFm14xDDhloigFEzUkz41FrOigrdWrNcpWzJaGGaSAco7DY8mOCiZRQ6
+vKpst4rqKh18XNaUyfd3t/Ws9BST0Uze0Vt+wwJ90yMIQKHnZVQr+V0CgYEAoGhE
+bhyNff+kKvZ48wEGcuAO7Sedt9NzM/dEAMfQltM/HspwcuSQ2MSUy5oggtSP2DbK
+guUnpD1BmttsXp8B4U9p7BI5Gh8VFYSdK4kVs9XChCFbe8Sx5v+PPr/+zNHjF0Xz
+9QqB+Q9DMVobswVrdLuUctiWdDBmXebgAx7mU0MCgYBbEccDicj5q9cnS/INqGt8
+nkw40kO7EqpYFa6JO+60F1852pkK42nwi1CHNLOWBFE/+pEPvh6gDpZ25jIxxH80
+lamQH5/ZjOd6gHjrK0+vv4Vftmo18yPVlQI4ReFuCgNYLyWuv8YG3F74KcRAS1mE
+6Gx8HKR73wFBJfS2mF3JcQKBgFRy8GvkHl3SY9S2lDCjPojmCxWyAKfR69nU+PlM
+OTXem2GThKYITXXB8PBMAYe/bseO+Qj2qese0NY9ZQ1fuzaqf4JoiaWF7ay5d6F+
+920JQfIcObSsdli9/OU1YWjlqyAKlQhR8uFztpVZ8jFKzirTwrC/9F3RSWNwdElQ
+UERPAoGBAMZGDFa9KlXjim6bxcJR05o4X2pGET8pi2rcEvxP+ipVwRieCWOlqliM
+K1qbud0a3X4c9GSmHBngWyrPQW33FgEJ5xkpKMQurR1uRqWlpY1+X4RruDMP5BMK
+M8gTREftbg88VhcvShxXMzGKKbS2NBkoHIUnvCOw4yXmKj4ZmeD6
+-----END RSA PRIVATE KEY-----

+ 9 - 0
config/public.key

@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAg5bDPoPigNdHslKHuR6b
+Hk5K1SOqoMJLgCqmoLHdrKZp1T812lAq1uECIcWyrPNnCDu47vmkn3zwLbM7Qn61
+udkhNqfKQVYMBGAmqeuqS06osVGoXKcbcxMmTSJFGjjy6hMCNd5DQDaV6AabXQRx
+SYyOxz5HDtYYjEUKd/RypAn+co9mgBWF4oqWmmt89RwHVqK+TACqnB9bA1yISq/7
+1YbquMiTquyoY8KNlBDAmaFFvnYw8pzXG1KfLcKlpSibB4xkD5bEHfpzxOvU4zZu
+2rw4n2ju//Q8upQAJOQy7tefQ34IVjQ8ImrBwz3LOyHKQ3MRFDkBpq52j3yhOOlq
+VwIDAQAB
+-----END PUBLIC KEY-----

+ 1 - 1
dep/dep.go

@@ -1,9 +1,9 @@
 package dep
 
 import (
+	"gitee.com/xuyiping_admin/pkg/di"
 	"kpt-tmr-group/config"
 	"kpt-tmr-group/module/backend"
-	"kpt-tmr-group/pkg/di"
 	"kpt-tmr-group/service/sso"
 	"kpt-tmr-group/service/wechat"
 	"kpt-tmr-group/store/kptstore"

+ 1 - 1
dep/di.go

@@ -1,6 +1,6 @@
 package dep
 
-import "kpt-tmr-group/pkg/di"
+import "gitee.com/xuyiping_admin/pkg/di"
 
 func DI(opts ...di.HubOption) *di.Hub {
 	var hubOpts []di.HubOption

+ 34 - 36
go.mod

@@ -3,9 +3,10 @@ module kpt-tmr-group
 go 1.17
 
 require (
-	github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20231129062310-bbb6722ac3a0
+	gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
-	github.com/getsentry/sentry-go v0.20.0
+	github.com/getsentry/sentry-go v0.23.0
 	github.com/gin-contrib/cors v1.4.0
 	github.com/gin-contrib/gzip v0.0.6
 	github.com/gin-contrib/requestid v0.0.6
@@ -14,84 +15,81 @@ require (
 	github.com/go-redis/redis/v7 v7.4.1
 	github.com/golang/mock v1.4.4
 	github.com/golang/protobuf v1.5.3
-	github.com/google/go-cmp v0.5.9
-	github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
-	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
-	github.com/huandu/xstrings v1.4.0
-	github.com/jinzhu/copier v0.3.5
-	github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
-	github.com/magiconair/properties v1.8.7
 	github.com/mitchellh/mapstructure v1.5.0
-	github.com/nyaruka/phonenumbers v1.1.7
-	github.com/sirupsen/logrus v1.9.0
 	github.com/spf13/cobra v1.7.0
 	github.com/spf13/viper v1.15.0
-	github.com/stretchr/testify v1.8.2
+	github.com/stretchr/testify v1.8.4
 	github.com/xuri/excelize/v2 v2.7.1
 	go.uber.org/dig v1.15.0
-	go.uber.org/zap v1.21.0
-	golang.org/x/sync v0.1.0
-	google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef
-	google.golang.org/grpc v1.52.0
-	google.golang.org/protobuf v1.30.0
-	gopkg.in/natefinch/lumberjack.v2 v2.2.1
-	gorm.io/driver/mysql v1.5.0
-	gorm.io/gorm v1.25.0
+	go.uber.org/multierr v1.8.0
+	go.uber.org/zap v1.24.0
+	golang.org/x/sync v0.2.0
+	gorm.io/driver/mysql v1.5.1
+	gorm.io/gorm v1.25.2
 )
 
 require (
 	github.com/beorn7/perks v1.0.1 // indirect
-	github.com/bytedance/sonic v1.8.0 // indirect
+	github.com/bytedance/sonic v1.9.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/fsnotify/fsnotify v1.6.0 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.2 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
 	github.com/go-playground/locales v0.14.1 // indirect
 	github.com/go-playground/universal-translator v0.18.1 // indirect
-	github.com/go-playground/validator/v10 v10.11.2 // indirect
+	github.com/go-playground/validator/v10 v10.14.0 // indirect
 	github.com/go-sql-driver/mysql v1.7.0 // indirect
-	github.com/goccy/go-json v0.10.0 // indirect
+	github.com/goccy/go-json v0.10.2 // indirect
 	github.com/google/uuid v1.3.0 // indirect
+	github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
+	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
+	github.com/huandu/xstrings v1.4.0 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
 	github.com/jinzhu/now v1.1.5 // indirect
-	github.com/jonboulle/clockwork v0.4.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
-	github.com/klauspost/cpuid/v2 v2.0.9 // indirect
-	github.com/leodido/go-urn v1.2.1 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.4 // indirect
+	github.com/leodido/go-urn v1.2.4 // indirect
+	github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect
 	github.com/lestrrat-go/strftime v1.0.6 // indirect
-	github.com/mattn/go-isatty v0.0.17 // indirect
+	github.com/magiconair/properties v1.8.7 // indirect
+	github.com/mattn/go-isatty v0.0.19 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
-	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
+	github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
+	github.com/pelletier/go-toml/v2 v2.0.8 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	github.com/prometheus/client_golang v1.14.0 // indirect
+	github.com/prometheus/client_golang v1.16.0 // indirect
 	github.com/prometheus/client_model v0.3.0 // indirect
 	github.com/prometheus/common v0.42.0 // indirect
-	github.com/prometheus/procfs v0.9.0 // indirect
+	github.com/prometheus/procfs v0.10.1 // indirect
 	github.com/richardlehane/mscfb v1.0.4 // indirect
 	github.com/richardlehane/msoleps v1.0.3 // indirect
+	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/spf13/afero v1.9.3 // indirect
 	github.com/spf13/cast v1.5.0 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/subosito/gotenv v1.4.2 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
-	github.com/ugorji/go/codec v1.2.9 // indirect
+	github.com/ugorji/go/codec v1.2.11 // indirect
 	github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
 	github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
 	go.uber.org/atomic v1.9.0 // indirect
-	go.uber.org/multierr v1.8.0 // indirect
-	golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
-	golang.org/x/crypto v0.8.0 // indirect
-	golang.org/x/net v0.9.0 // indirect
-	golang.org/x/sys v0.7.0 // indirect
+	golang.org/x/arch v0.3.0 // indirect
+	golang.org/x/crypto v0.9.0 // indirect
+	golang.org/x/net v0.10.0 // indirect
+	golang.org/x/sys v0.8.0 // indirect
 	golang.org/x/text v0.9.0 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20230731193218-e0aa005b6bdf // indirect
+	google.golang.org/grpc v1.57.0 // indirect
+	google.golang.org/protobuf v1.31.0 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )

+ 72 - 59
go.sum

@@ -36,17 +36,26 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
 cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20231116060440-d644eee73ee6 h1:+Lah4VWetGE6dzqmOusq3212dCrVLumib9xscB85mP0=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20231116060440-d644eee73ee6/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20231116063239-b531a3099bd3 h1:JN21X8a0RJN1PBMnliQldz4YpO63IogaSVGonXo8dYw=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20231116063239-b531a3099bd3/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20231129062310-bbb6722ac3a0 h1:j/zcYZroC7tAhPSNrxgwsTkhYkn4DdjDb8ShNBcVEbw=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20231129062310-bbb6722ac3a0/go.mod h1:x47UOU+lOkZnrtAENAsOGd7mZ5I8D2JRkMKMqLLRlVw=
+gitee.com/xuyiping_admin/pkg v0.0.0-20230822102440-0e489dd5d75a h1:+SSGto+q5BKy6r9FLFQXooTNqZs4tALceFpoo2jef8w=
+gitee.com/xuyiping_admin/pkg v0.0.0-20230822102440-0e489dd5d75a/go.mod h1:vK5K2LnhWZnvZlEY9gmT6GFdq/5Y0mtxuKLNJHFJkE4=
+gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b h1:w05MxH7yqveRlaRbxHhbif5YjPrJFodRPfOjYhXn7Zk=
+gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b/go.mod h1:8tF25X6pE9WkFCczlNAC0K2mrjwKvhhp02I7o0HtDxY=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
-github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
 github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
 github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
-github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
-github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
+github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
+github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
 github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -77,8 +86,10 @@ github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
-github.com/getsentry/sentry-go v0.20.0 h1:bwXW98iMRIWxn+4FgPW7vMrjmbym6HblXALmhjHmQaQ=
-github.com/getsentry/sentry-go v0.20.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
+github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
+github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
+github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE=
+github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
 github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g=
 github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs=
 github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
@@ -96,6 +107,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
 github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
 github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
@@ -105,8 +117,8 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
 github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
-github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
-github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
+github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
+github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
 github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
 github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
 github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI=
@@ -115,8 +127,8 @@ github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ
 github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
-github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -160,7 +172,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -198,34 +209,35 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
-github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
 github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
 github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
 github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
-github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
 github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
+github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
 github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
 github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
+github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
+github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
 github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
 github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
 github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
@@ -235,8 +247,8 @@ github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN
 github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
 github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
-github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
 github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@@ -248,17 +260,19 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/nyaruka/phonenumbers v1.1.7 h1:5UUI9hE79Kk0dymSquXbMYB7IlNDNhvu2aNlJpm9et8=
-github.com/nyaruka/phonenumbers v1.1.7/go.mod h1:DC7jZd321FqUe+qWSNcHi10tyIyGNXGcNbfkPvdp1Vs=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
 github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
+github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
 github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
-github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
-github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
+github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
+github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
 github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -267,15 +281,15 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
-github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
+github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
+github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
 github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
 github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
 github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
-github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
-github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
+github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
+github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
 github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
 github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
 github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
@@ -283,12 +297,12 @@ github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN
 github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
 github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
-github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
 github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
 github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
@@ -314,16 +328,18 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
 github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
 github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
-github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
-github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
 github.com/xuri/efp v0.0.0-20220603152613-6918739fd470/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
 github.com/xuri/excelize/v2 v2.7.1 h1:gm8q0UCAyaTt3MEF5wWMjVdmthm2EHAWesGSKS9tdVI=
@@ -334,7 +350,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -354,10 +369,11 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i
 go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
 go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
 go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
-go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
-go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
-golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
+go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
+go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
+golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -367,8 +383,9 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
 golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
+golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
+golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -404,7 +421,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -440,11 +456,11 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
 golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
 golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -464,10 +480,10 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
+golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -503,21 +519,21 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -586,7 +602,6 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -656,8 +671,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY=
-google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230731193218-e0aa005b6bdf h1:guOdSPaeFgN+jEJwTo1dQ71hdBm+yKSCCKuTRkJzcVo=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230731193218-e0aa005b6bdf/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -674,8 +689,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
 google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk=
-google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
+google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
+google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -689,8 +704,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -701,8 +716,6 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
-gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -715,11 +728,11 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gorm.io/driver/mysql v1.5.0 h1:6hSAT5QcyIaty0jfnff0z0CLDjyRgZ8mlMHLqSt7uXM=
-gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo=
-gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
-gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU=
-gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
+gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
+gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
+gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

+ 69 - 0
http/debug/debug.go

@@ -1,6 +1,11 @@
 package debug
 
 import (
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
+	"kpt-tmr-group/http/middleware"
 	"net/http"
 
 	"github.com/gin-gonic/gin"
@@ -11,3 +16,67 @@ func HelloOk(c *gin.Context) {
 	// kafka
 	c.JSON(http.StatusOK, gin.H{"result": "ok"})
 }
+
+func FeedFormulaSync(c *gin.Context) {
+	var req operationPb.FeedFormulaSyncRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.FeedFormulaSyncData(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+func FeedSync(c *gin.Context) {
+	var req operationPb.FeedFormulaSyncRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.PastureId, valid.Required),
+		valid.Field(&req.Page, valid.Required),
+		valid.Field(&req.PageSize, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.FeedSyncData(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+func FeedFormulaDetailListSync(c *gin.Context) {
+	var req operationPb.FeedFormulaSyncRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.FeedFormulaDetailListSyncData(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}

+ 4 - 4
http/handler/dashboard/dashboard.go

@@ -1,11 +1,11 @@
 package dashboard
 
 import (
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	"kpt-tmr-group/pkg/valid"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 
 	"github.com/gin-gonic/gin"

+ 0 - 24
http/handler/default.go

@@ -1,10 +1,6 @@
 package handler
 
 import (
-	"compress/gzip"
-	"fmt"
-	"io/ioutil"
-	"kpt-tmr-group/pkg/xerr"
 	"net/http"
 
 	"github.com/gin-gonic/gin"
@@ -17,23 +13,3 @@ func Health(c *gin.Context) {
 func Handle404(c *gin.Context) {
 	c.String(http.StatusNotFound, "404 NotFound")
 }
-
-func dumpPerfEventBody(c *gin.Context) ([]byte, error) {
-	if c.ContentType() != "application/octet-stream" {
-		return nil, fmt.Errorf("invalid Content-Type:  %s ", c.ContentType())
-	}
-	if c.GetHeader("Content-Encoding") != "gzip" {
-		return nil, fmt.Errorf("invalid Content-Encoding:  %s ", c.GetHeader("Content-Encoding"))
-	}
-	if c.Request.Body == nil || int(c.Request.ContentLength) < 1 {
-		return nil, fmt.Errorf("invalid body:  %v ", int(c.Request.ContentLength))
-	}
-
-	reader, err := gzip.NewReader(c.Request.Body)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-	defer reader.Close()
-
-	return ioutil.ReadAll(reader)
-}

+ 289 - 13
http/handler/feed/feed_formula.go

@@ -3,23 +3,24 @@ package feed
 import (
 	"fmt"
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	"kpt-tmr-group/pkg/valid"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"mime/multipart"
 	"net/http"
 	"path"
 	"strconv"
 	"time"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+
 	"github.com/gin-gonic/gin"
 )
 
 func AddFeedFormula(c *gin.Context) {
 	var req operationPb.AddFeedFormulaRequest
-	if err := c.BindJSON(&req); err != nil {
+	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
@@ -52,9 +53,10 @@ func AddFeedFormula(c *gin.Context) {
 	})
 }
 
+// EditFeedFormula 编辑配方
 func EditFeedFormula(c *gin.Context) {
 	var req operationPb.AddFeedFormulaRequest
-	if err := c.BindJSON(&req); err != nil {
+	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
@@ -88,6 +90,201 @@ func EditFeedFormula(c *gin.Context) {
 	})
 }
 
+// AddFeedByFeedFormula 配方添加饲料
+func AddFeedByFeedFormula(c *gin.Context) {
+	var req operationPb.GroupAddFeedFormulaDetail
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required, valid.Min(1)),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.AddFeedByFeedFormula(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+// EditFeedByFeedFormula 配方饲料编辑
+func EditFeedByFeedFormula(c *gin.Context) {
+	var req operationPb.AddFeedFormulaDetail
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required, valid.Min(1)),
+		valid.Field(&req.Id, valid.Required, valid.Min(1)),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.EditFeedByFeedFormula(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+// DetailBySort 配方详情排序
+func DetailBySort(c *gin.Context) {
+	var req operationPb.GroupAddFeedFormulaDetail
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required, valid.Min(1)),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.FeedFormulaDetailBySort(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+// IsModifyFeedDetail 配方详情是否可修改
+func IsModifyFeedDetail(c *gin.Context) {
+	var req operationPb.AddFeedFormulaDetail
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required, valid.Min(1)),
+		valid.Field(&req.IsModify, valid.Required, valid.Min(1)),
+		valid.Field(&req.Id, valid.Required, valid.Min(1)),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.FeedFormulaDetailIsModify(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+// SearchFeedDetail 查询配方饲料详情
+func SearchFeedDetail(c *gin.Context) {
+	var req operationPb.AddFeedFormulaDetail
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required, valid.Min(1)),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	req.Pagination = &operationPb.PaginationModel{
+		Page:       int32(c.GetInt(middleware.Page)),
+		PageSize:   int32(c.GetInt(middleware.PageSize)),
+		PageOffset: int32(c.GetInt(middleware.PageOffset)),
+	}
+
+	if list, err := middleware.BackendOperation(c).OpsService.SearchFeedFormulaDetail(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	} else {
+		ginutil.JSONResp(c, list)
+	}
+}
+
+// DeleteFeedDetail 删除配方饲料
+func DeleteFeedDetail(c *gin.Context) {
+	var req operationPb.GroupAddFeedFormulaDetail
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required, valid.Min(1)),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.DeleteFeedFormulaDetail(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+// MixedFeedFormula 合并预混料
+func MixedFeedFormula(c *gin.Context) {
+	var req operationPb.MixedFeedFormulaRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required),
+		valid.Field(&req.Name, valid.Required),
+		valid.Field(&req.Colour, valid.Required),
+		valid.Field(&req.CattleCategoryId, valid.Required),
+		valid.Field(&req.CattleCategoryName, valid.Required),
+		valid.Field(&req.FormulaTypeId, valid.Required),
+		valid.Field(&req.FormulaTypeName, valid.Required),
+		valid.Field(&req.DataSourceId, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.MixedFeedFormula(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
 func SearchFeedFormulaList(c *gin.Context) {
 	req := &operationPb.SearchFeedFormulaRequest{}
 	if err := ginutil.BindProto(c, req); err != nil {
@@ -109,6 +306,27 @@ func SearchFeedFormulaList(c *gin.Context) {
 	ginutil.JSONResp(c, res)
 }
 
+func SearchFeedFormulaByForageList(c *gin.Context) {
+	req := &operationPb.SearchFeedFormulaRequest{}
+	if err := ginutil.BindProto(c, req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	req.Pagination = &operationPb.PaginationModel{
+		Page:       int32(c.GetInt(middleware.Page)),
+		PageSize:   int32(c.GetInt(middleware.PageSize)),
+		PageOffset: int32(c.GetInt(middleware.PageOffset)),
+	}
+
+	res, err := middleware.BackendOperation(c).OpsService.SearchFeedFormulaList(c, req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, res)
+}
+
 func DeleteFeedFormula(c *gin.Context) {
 	feedFormulaIdStr := c.Param("feed_formula_id")
 	feedFormulaId, _ := strconv.Atoi(feedFormulaIdStr)
@@ -131,7 +349,7 @@ func DeleteFeedFormula(c *gin.Context) {
 
 func IsShowModifyFeedFormula(c *gin.Context) {
 	var req operationPb.IsShowModifyFeedFormula
-	if err := c.BindJSON(&req); err != nil {
+	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
@@ -195,7 +413,7 @@ func ExcelImportFeedFormula(c *gin.Context) {
 
 func ExcelExportFeedFormula(c *gin.Context) {
 	req := &operationPb.SearchFeedFormulaRequest{}
-	if err := c.BindJSON(req); err != nil {
+	if err := ginutil.BindProto(c, req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
@@ -275,15 +493,15 @@ func DistributeFeedFormula(c *gin.Context) {
 	})
 }
 
-// Usage 配方使用情况
-func Usage(c *gin.Context) {
-	req := &operationPb.FeedFormulaUsageRequest{}
+// CancelDistributeFeedFormula 取消配方下发
+func CancelDistributeFeedFormula(c *gin.Context) {
+	req := &operationPb.DistributeFeedFormulaRequest{}
 	if err := ginutil.BindProto(c, req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
 
-	if err := middleware.BackendOperation(c).OpsService.FeedFormulaUsage(c, req); err != nil {
+	if err := middleware.BackendOperation(c).OpsService.CancelDistributeFeedFormula(c, req); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}
@@ -294,3 +512,61 @@ func Usage(c *gin.Context) {
 		Data: &operationPb.Success{Success: true},
 	})
 }
+
+// EditRecordFeedFormula 配方修改记录
+func EditRecordFeedFormula(c *gin.Context) {
+	var req operationPb.EditRecodeFeedFormulaRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required, valid.Min(1)),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if list, err := middleware.BackendOperation(c).OpsService.EditRecodeFeedFormula(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	} else {
+		ginutil.JSONResp(c, list)
+	}
+}
+
+// Usage 配方使用情况
+func Usage(c *gin.Context) {
+	var req operationPb.FeedFormulaUsageRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required, valid.Min(1)),
+		valid.Field(&req.StartTime, valid.Required),
+		valid.Field(&req.EndTime, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if res, err := middleware.BackendOperation(c).OpsService.FeedFormulaUsage(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	} else {
+		ginutil.JSONResp(c, res)
+	}
+}
+
+// ForageByGroup 集团端可用的饲料列表
+func ForageByGroup(c *gin.Context) {
+	if res, err := middleware.BackendOperation(c).OpsService.ForageListByGroup(c); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	} else {
+		ginutil.JSONResp(c, res)
+	}
+}

+ 35 - 0
http/handler/feed/feed_formula_detail.go

@@ -0,0 +1,35 @@
+package feed
+
+import (
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
+	"kpt-tmr-group/http/middleware"
+	"net/http"
+
+	"github.com/gin-gonic/gin"
+)
+
+// ForageDetailList 配方详情
+func ForageDetailList(c *gin.Context) {
+	var req operationPb.FeedFormulaDetailRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.FeedFormulaId, valid.Required, valid.Min(1)),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if list, err := middleware.BackendOperation(c).OpsService.FeedFormulaDetailList(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	} else {
+		ginutil.JSONResp(c, list)
+	}
+}

+ 3 - 3
http/handler/mobile/mobile_list.go

@@ -1,10 +1,10 @@
 package mobile
 
 import (
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 
 	"github.com/gin-gonic/gin"

+ 4 - 4
http/handler/pasture/cattle_forage_category.go

@@ -1,11 +1,11 @@
 package pasture
 
 import (
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	"kpt-tmr-group/pkg/valid"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"strconv"
 

+ 6 - 9
http/handler/pasture/forage_list.go

@@ -2,12 +2,12 @@ package pasture
 
 import (
 	"fmt"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
+	"gitee.com/xuyiping_admin/pkg/xerr"
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	"kpt-tmr-group/pkg/valid"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"mime/multipart"
 	"net/http"
 	"path"
@@ -29,10 +29,8 @@ func AddForage(c *gin.Context) {
 		valid.Field(&req.UniqueEncode, valid.Required),
 		valid.Field(&req.ForageSourceId, valid.Required),
 		valid.Field(&req.ForageSourceName, valid.Required),
-		//valid.Field(&req.PlanTypeId, valid.Required, valid.Min(0), valid.Max(2)),
 		valid.Field(&req.PlanTypeName, valid.Required),
-		valid.Field(&req.MaterialType, valid.Required),
-		//valid.Field(&req.JumpWeight, valid.Required, valid.Min(0), valid.Max(50)),
+		//valid.Field(&req.MaterialTypeKey, valid.Required),
 	); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
@@ -63,7 +61,6 @@ func EditForage(c *gin.Context) {
 		valid.Field(&req.CategoryName, valid.Required),
 		valid.Field(&req.UniqueEncode, valid.Required),
 		valid.Field(&req.ForageSourceId, valid.Required),
-		valid.Field(&req.MaterialType, valid.Required),
 	); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return

+ 4 - 4
http/handler/pasture/pasture.go

@@ -1,11 +1,11 @@
 package pasture
 
 import (
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	"kpt-tmr-group/pkg/valid"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 
 	"github.com/gin-gonic/gin"

+ 4 - 4
http/handler/pasture/pasture_list.go

@@ -1,11 +1,11 @@
 package pasture
 
 import (
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	"kpt-tmr-group/pkg/valid"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"strconv"
 

+ 124 - 5
http/handler/statistic/analysis.go

@@ -3,13 +3,14 @@ package statistic
 import (
 	"fmt"
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	"kpt-tmr-group/pkg/valid"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"time"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
+
 	"github.com/gin-gonic/gin"
 )
 
@@ -429,7 +430,7 @@ func GetDataByName(c *gin.Context) {
 	c.JSON(http.StatusOK, res)
 }
 
-// SearchProcessAnalysis 过程分析
+// SearchProcessAnalysis 过程分析-表格
 func SearchProcessAnalysis(c *gin.Context) {
 	var req operationPb.ProcessAnalysisRequest
 	if err := ginutil.BindProto(c, &req); err != nil {
@@ -461,6 +462,36 @@ func SearchProcessAnalysis(c *gin.Context) {
 	c.JSON(http.StatusOK, res)
 }
 
+// AnalysisMixedSprinkleDetail 过程分析-混料详情-过程详情-撒料详情
+func AnalysisMixedSprinkleDetail(c *gin.Context) {
+	var req operationPb.ProcessMixedSprinkleDetailRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.PastureId, valid.Required),
+		valid.Field(&req.ApiName, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	req.Pagination = &operationPb.PaginationModel{
+		Page:       int32(c.GetInt(middleware.Page)),
+		PageSize:   int32(c.GetInt(middleware.PageSize)),
+		PageOffset: int32(c.GetInt(middleware.PageOffset)),
+	}
+
+	res, err := middleware.BackendOperation(c).OpsService.AnalysisMixedSprinkleDetail(c, &req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	c.JSON(http.StatusOK, res)
+}
+
 // TrainNumber 班次
 func TrainNumber(c *gin.Context) {
 	var req operationPb.TrainNumberRequest
@@ -491,3 +522,91 @@ func TrainNumber(c *gin.Context) {
 	}
 	ginutil.JSONResp(c, res)
 }
+
+func FeedMixedAndTmrName(c *gin.Context) {
+	var req operationPb.MixedCategoryTmrName
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.ApiName, valid.Required, valid.Length(1, 100)),
+		valid.Field(&req.PastureId, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	res, err := middleware.BackendOperation(c).OpsService.FeedMixedAndTmrName(c, &req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	c.JSON(http.StatusOK, res)
+}
+
+// FeedTemplateHistory 配方修改记录
+func FeedTemplateHistory(c *gin.Context) {
+	var req operationPb.FeedTemplateHistoryRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+	res, err := middleware.BackendOperation(c).OpsService.FeedTemplateHistory(c, &req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	c.JSON(http.StatusOK, res)
+}
+
+// BarnHistory 栏色修改纪录
+func BarnHistory(c *gin.Context) {
+	var req operationPb.BarnHistoryRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.BarnName, valid.Required, valid.Length(1, 100)),
+		valid.Field(&req.StartTime, valid.Required),
+		valid.Field(&req.EndTime, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	res, err := middleware.BackendOperation(c).OpsService.BarnHistory(c, &req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	c.JSON(http.StatusOK, res)
+}
+
+// SpillageAllHistory 车次重量
+func SpillageAllHistory(c *gin.Context) {
+	var req operationPb.BarnHistoryRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.BarnName, valid.Required, valid.Length(1, 100)),
+		valid.Field(&req.StartTime, valid.Required),
+		valid.Field(&req.EndTime, valid.Required),
+		valid.Field(&req.PastureId, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	res, err := middleware.BackendOperation(c).OpsService.SpillageAllHistory(c, &req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	c.JSON(http.StatusOK, res)
+}

+ 4 - 4
http/handler/system/menu.go

@@ -1,11 +1,11 @@
 package system
 
 import (
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	"kpt-tmr-group/pkg/valid"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"strconv"
 

+ 4 - 4
http/handler/system/role.go

@@ -1,11 +1,11 @@
 package system
 
 import (
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	"kpt-tmr-group/pkg/valid"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"strconv"
 

+ 8 - 6
http/handler/system/user.go

@@ -2,13 +2,14 @@ package system
 
 import (
 	"kpt-tmr-group/http/middleware"
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/ginutil"
-	"kpt-tmr-group/pkg/valid"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"strconv"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/ginutil"
+	"gitee.com/xuyiping_admin/pkg/valid"
+
 	"github.com/gin-gonic/gin"
 )
 
@@ -108,7 +109,8 @@ func GetUserInfo(c *gin.Context) {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}
-	res, err := middleware.BackendOperation(c).OpsService.GetUserInfo(c, token)
+
+	res, err := middleware.BackendOperation(c).OpsService.GetUserInfo(c)
 	if err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
@@ -233,7 +235,7 @@ func GetSystemUserPermissions(c *gin.Context) {
 		return
 	}
 
-	res, err := middleware.BackendOperation(c).OpsService.GetSystemUserPermissions(c, token)
+	res, err := middleware.BackendOperation(c).OpsService.GetSystemUserPermissions(c)
 	if err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return

+ 4 - 3
http/middleware/cors.go

@@ -1,8 +1,8 @@
 package middleware
 
 import (
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
 	"io/ioutil"
-	"kpt-tmr-group/pkg/logger/zaplog"
 	"net/http"
 
 	"go.uber.org/zap"
@@ -25,9 +25,10 @@ func CORS(configs ...cors.Config) gin.HandlerFunc {
 			//服务器支持的所有跨域请求的方法
 			c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
 			//允许跨域设置可以返回其他子段,可以自定义字段
-			c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session")
+			c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, Content-Type,X-CSRF-Token,Accept,Referer,User-Agent")
 			// 允许浏览器(客户端)可以解析的头部 (重要)
-			c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
+			c.Header("Access-Control-Expose-Headers", "Content-Length,Content-Type, Page,Access-Control-Allow-Origin, Access-Control-Allow-Headers,Accept,Referer,User-Agent")
+
 			//设置缓存时间
 			c.Header("Access-Control-Max-Age", "172800")
 			//允许客户端传递校验信息比如 cookie (重要)

+ 107 - 0
http/middleware/log.go

@@ -0,0 +1,107 @@
+package middleware
+
+import (
+	"bytes"
+	"io/ioutil"
+
+	"net"
+	"net/http"
+	"net/http/httputil"
+	"os"
+	"runtime/debug"
+	"strings"
+	"time"
+
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"github.com/gin-gonic/gin"
+	"go.uber.org/zap"
+)
+
+type responseBodyWriter struct {
+	gin.ResponseWriter
+	body *bytes.Buffer
+}
+
+func (r responseBodyWriter) Write(b []byte) (int, error) {
+	r.body.Write(b)
+	return r.ResponseWriter.Write(b)
+}
+
+// GinLogger 接管gin框架默认的日志
+func GinLogger() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		// 获取 response 内容
+		w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}
+		c.Writer = w
+
+		var requestBody []byte
+		if c.Request.Body != nil {
+			requestBody, _ = ioutil.ReadAll(c.Request.Body)
+			c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(requestBody))
+		}
+		start := time.Now()
+		c.Next()
+		cost := time.Since(start)
+
+		logFields := []zap.Field{
+			zap.Int("status", c.Writer.Status()),
+			zap.String("request", c.Request.Method+" "+c.Request.URL.String()),
+			zap.String("query", c.Request.URL.RawQuery),
+			zap.String("ip", c.ClientIP()),
+			zap.String("user-agent", c.Request.UserAgent()),
+			zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()),
+			zap.String("time", cost.String()),
+			zap.String("x-request-id", c.Request.Header.Get("X-Request-Id")),
+		}
+		logFields = append(logFields, zap.String("Request body", string(requestBody)))
+		logFields = append(logFields, zap.String("Response body", w.body.String()))
+		zaplog.Info("Http-Access-Log", logFields...)
+	}
+}
+
+// GinRecovery recover掉我的项目可能呈现的panic
+func GinRecovery(stack bool) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		defer func() {
+			if err := recover(); err != nil {
+				// Check for a broken connection, as it is not really a
+				// condition that warrants a panic stack trace.
+				var brokenPipe bool
+				if ne, ok := err.(*net.OpError); ok {
+					if se, ok := ne.Err.(*os.SyscallError); ok {
+						if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
+							brokenPipe = true
+						}
+					}
+				}
+
+				httpRequest, _ := httputil.DumpRequest(c.Request, false)
+				if brokenPipe {
+					zaplog.Error(c.Request.URL.Path,
+						zap.Any("error", err),
+						zap.String("request", string(httpRequest)),
+					)
+					// If the connection is dead, we can't write a status to it.
+					c.Error(err.(error)) // nolint: errcheck
+					c.Abort()
+					return
+				}
+
+				if stack {
+					zaplog.Error("[Recovery from panic]",
+						zap.Any("error", err),
+						zap.String("request", string(httpRequest)),
+						zap.String("stack", string(debug.Stack())),
+					)
+				} else {
+					zaplog.Error("[Recovery from panic]",
+						zap.Any("error", err),
+						zap.String("request", string(httpRequest)),
+					)
+				}
+				c.AbortWithStatus(http.StatusInternalServerError)
+			}
+		}()
+		c.Next()
+	}
+}

+ 2 - 2
http/middleware/sentry.go

@@ -1,8 +1,8 @@
 package middleware
 
 import (
-	sentry2 "kpt-tmr-group/pkg/sentry"
-	"kpt-tmr-group/pkg/xerr"
+	sentry2 "gitee.com/xuyiping_admin/pkg/sentry"
+	"gitee.com/xuyiping_admin/pkg/xerr"
 	"sync"
 
 	"github.com/getsentry/sentry-go"

+ 12 - 6
http/middleware/sso.go

@@ -1,9 +1,13 @@
 package middleware
 
 import (
-	"kpt-tmr-group/pkg/apierr"
-	"kpt-tmr-group/pkg/jwt"
-	commonPb "kpt-tmr-group/proto/go/backend/common"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"go.uber.org/zap"
+	"kpt-tmr-group/config"
+
+	commonPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/common"
+	"gitee.com/xuyiping_admin/pkg/apierr"
+	"gitee.com/xuyiping_admin/pkg/jwt"
 
 	"net/http"
 	"strings"
@@ -44,13 +48,15 @@ func RequireAdmin() gin.HandlerFunc {
 			return
 		}
 
-		claims, err := jwt.ParseToken(token)
-		if err != nil || claims == nil || claims.Username == "" {
+		tokenVerifier := jwt.JWTTokenVerifier{PublicKey: config.Options().JwtTokenKeyConfig.PublicKey}
+		userName, err := tokenVerifier.ParseToken(token)
+		if err != nil {
+			zaplog.Error("unauthorized", zap.Any("err", err))
 			unauthorized(c)
 			return
 		}
 
-		c.Set(UserName, claims.Username)
+		c.Set(UserName, userName)
 		c.Set(XRequestId, GetXRequestId(c))
 		c.Next()
 	}

+ 3 - 0
http/route/api_debug_route.go

@@ -19,6 +19,9 @@ func DebugAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		debugRoute := authRouteGroup(s, "/api/v1/kpt/debug/")
 		// kpt debug api
 		debugRoute.GET("hello", debug.HelloOk)
+		debugRoute.POST("pasture/feed_formula/sync", debug.FeedFormulaSync)                       // 同步牧场端饲料配方
+		debugRoute.POST("pasture/feed/sync", debug.FeedSync)                                      // 同步牧场端饲料
+		debugRoute.POST("pasture/feed_formula/detail_list/sync", debug.FeedFormulaDetailListSync) // 同步牧场端饲料配方详情
 	}
 
 }

+ 19 - 1
http/route/ops_api.go

@@ -54,7 +54,15 @@ func OpsAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		// 饲料配方
 		opsRoute.POST("/feed_formula/add", feed.AddFeedFormula)
 		opsRoute.POST("/feed_formula/edit", feed.EditFeedFormula)
+		opsRoute.POST("/feed_formula/feed/add", feed.AddFeedByFeedFormula)
+		opsRoute.POST("/feed_formula/feed/edit", feed.EditFeedByFeedFormula)
+		opsRoute.POST("/feed_formula/feed/sort", feed.DetailBySort)
+		opsRoute.POST("/feed_formula/feed/is_modify", feed.IsModifyFeedDetail)
+		opsRoute.POST("/feed_formula/feed/delete", feed.DeleteFeedDetail)
+		opsRoute.POST("/feed_formula/feed/search", feed.SearchFeedDetail)
+		opsRoute.POST("/feed_formula/feed/mixed", feed.MixedFeedFormula)
 		opsRoute.POST("/feed_formula/list", feed.SearchFeedFormulaList)
+		opsRoute.POST("/feed_formula/forage_list", feed.SearchFeedFormulaByForageList)
 		opsRoute.DELETE("/feed_formula/delete/:feed_formula_id", feed.DeleteFeedFormula)
 		opsRoute.POST("/feed_formula/is_modify_show", feed.IsShowModifyFeedFormula)
 		opsRoute.POST("/feed_formula/excel_export", feed.ExcelExportFeedFormula)
@@ -62,7 +70,11 @@ func OpsAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		opsRoute.POST("/feed_formula/excel_template", feed.ExcelTemplateFeedFormula)
 		opsRoute.GET("/feed_formula/encode_number", feed.EncodeNumber)
 		opsRoute.POST("/feed_formula/distribute", feed.DistributeFeedFormula)
+		opsRoute.POST("/feed_formula/cancel/distribute", feed.CancelDistributeFeedFormula)
+		opsRoute.POST("/feed_formula/feed_detail/list", feed.ForageDetailList)
+		opsRoute.POST("/feed_formula/edit_record/list", feed.EditRecordFeedFormula)
 		opsRoute.POST("/feed_formula/usage", feed.Usage)
+		opsRoute.GET("/feed_formula/forage_list", feed.ForageByGroup)
 
 		//统计分析 statistic analysis
 		opsRoute.POST("/feed_estimate/list", statistic.SearchFormulaEstimateList)
@@ -77,9 +89,15 @@ func OpsAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		opsRoute.POST("/accuracy/agg_statistics", statistic.SearchAccuracyAggStatistics)
 		opsRoute.POST("/accuracy/mixed_statistics", statistic.SearchMixFeedStatistics)
 		opsRoute.POST("/accuracy/sprinkle_statistics", statistic.SearchSprinkleStatistics)
-		opsRoute.POST("/accuracy/data_by_name", statistic.GetDataByName)
+
 		opsRoute.POST("/process/analysis", statistic.SearchProcessAnalysis)
+		opsRoute.POST("/process/analysis/mixed_sprinkle_detail", statistic.AnalysisMixedSprinkleDetail)
 		opsRoute.POST("/statistics/train_number", statistic.TrainNumber)
+		opsRoute.POST("/statistics/mixed_category_tmr_name", statistic.FeedMixedAndTmrName)
+		opsRoute.POST("/feed_template/history", statistic.FeedTemplateHistory)
+		opsRoute.POST("/barn/history", statistic.BarnHistory)
+		opsRoute.POST("/spillage_all/history", statistic.SpillageAllHistory)
+		opsRoute.POST("/accuracy/data_by_name", statistic.GetDataByName)
 
 		// 首页仪表盘
 		opsRoute.POST("/dashboard/accuracy", dashboard.AnalysisAccuracy)

+ 1 - 1
http/route/root.go

@@ -20,7 +20,7 @@ func Root(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 			middleware.Pagination(),
 			requestid.New(),
 			gzip.Gzip(gzip.DefaultCompression),
-			gin.Recovery(),
+			middleware.GinRecovery(true),
 		)
 	}
 }

+ 1 - 1
http/util/httptt/http.go

@@ -7,7 +7,7 @@ import (
 	"net/http"
 	"testing"
 
-	"kpt-tmr-group/pkg/jsonpb"
+	"gitee.com/xuyiping_admin/pkg/jsonpb"
 
 	"github.com/golang/protobuf/proto"
 	"github.com/stretchr/testify/require"

+ 1 - 1
http/util/httptt/query_encoder.go

@@ -8,7 +8,7 @@ import (
 	"reflect"
 	"strings"
 
-	"kpt-tmr-group/pkg/xerr"
+	"gitee.com/xuyiping_admin/pkg/xerr"
 
 	"github.com/golang/protobuf/proto"
 )

+ 1 - 1
main.go

@@ -5,8 +5,8 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
 package main
 
 import (
+	"gitee.com/xuyiping_admin/pkg/logger/logrus"
 	"kpt-tmr-group/cmd"
-	"kpt-tmr-group/pkg/logger/logrus"
 )
 
 func main() {

+ 36 - 1
model/analysis_accuracy.go

@@ -1,7 +1,7 @@
 package model
 
 import (
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 )
 
 type AnalysisAccuracy struct {
@@ -27,6 +27,33 @@ func (c *AnalysisAccuracy) TableName() string {
 	return "analysis_accuracy"
 }
 
+type SearchAnalysisAccuracyResponse1 struct {
+	Code int32                  `json:"code"`
+	Msg  string                 `json:"msg"`
+	Data *AnalysisAccuracyData1 `json:"data"`
+}
+
+type AnalysisAccuracyData1 struct {
+	Table *Table  `json:"table"`
+	Chart *Chart1 `json:"chart"`
+}
+
+type Chart1 struct {
+	MixedFodderAccurateRatio    *PastureTopData1 `json:"mixed_fodder_accurate_ratio"`
+	MixedFodderCorrectRatio     *PastureTopData1 `json:"mixed_fodder_correct_ratio"`
+	SprinkleFodderAccurateRatio *PastureTopData1 `json:"sprinkle_fodder_accurate_ratio"`
+	SprinkleFodderCorrectRatio  *PastureTopData1 `json:"sprinkle_fodder_correct_ratio"`
+}
+
+type PastureTopData1 struct {
+	MaxValue    string    `json:"max_value"`    // 最高值
+	MiddleValue string    `json:"middle_value"` // 中位值
+	MinValue    string    `json:"min_value"`    // 最低值
+	TopOneName  string    `json:"top_one_name"` // 最高值牧场名称
+	Title       []string  `json:"title"`
+	Ratio       []float64 `json:"ratio"`
+}
+
 type SearchAnalysisAccuracyResponse struct {
 	Code int32                 `json:"code"`
 	Msg  string                `json:"msg"`
@@ -87,6 +114,7 @@ type PastureTop struct {
 }
 
 type PastureTopData struct {
+	PastureId   int64   `json:"pasture_id"`
 	PastureName string  `json:"pasture_name"`
 	Ratio       float64 `json:"ratio"`
 }
@@ -165,3 +193,10 @@ type SprinkleStatisticsDataList struct {
 	ProcessTime string `json:"process_time"`
 	Times       int32  `json:"times"`
 }
+
+type PastureDayTimeRatio struct {
+	PastureId   int64   `json:"pasture_id"`
+	PastureName string  `json:"pasture_name"`
+	DayTime     string  `json:"day_time"`
+	Ratio       float64 `json:"ratio"`
+}

+ 12 - 9
model/cattle_category.go

@@ -1,7 +1,7 @@
 package model
 
 import (
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"time"
 )
 
@@ -28,14 +28,16 @@ func (c *CattleCategory) TableName() string {
 
 func NewCattleCategory(req *operationPb.AddCattleCategoryRequest) *CattleCategory {
 	return &CattleCategory{
-		ParentId:   req.ParentId,
-		ParentName: req.ParentName,
-		Name:       req.Name,
-		Number:     req.Number,
-		IsShow:     operationPb.IsShow_OK,
-		IsDelete:   operationPb.IsShow_OK,
-		DataSource: operationPb.DataSource_BACKGROUND_ADD,
-		Remarks:    "集团新增数据",
+		PastureId:   0,
+		PastureName: "集团",
+		ParentId:    req.ParentId,
+		ParentName:  req.ParentName,
+		Name:        req.Name,
+		Number:      req.Number,
+		IsShow:      operationPb.IsShow_OK,
+		IsDelete:    operationPb.IsShow_OK,
+		DataSource:  operationPb.DataSource_BACKGROUND_ADD,
+		Remarks:     "集团新增数据",
 	}
 }
 
@@ -53,6 +55,7 @@ func (c CattleCategorySlice) ToPB() []*operationPb.AddCattleCategoryRequest {
 			IsShow:          v.IsShow,
 			CreatedAt:       uint32(v.CreatedAt),
 			CreatedAtFormat: time.Unix(v.CreatedAt, 0).Format(LayoutTime),
+			DataSource:      v.PastureName,
 		}
 	}
 	return res

+ 12 - 0
model/feed.go

@@ -0,0 +1,12 @@
+package model
+
+type FeedPasture struct {
+	Id            int64  `json:"id"`
+	PastureId     int64  `json:"pasture_id"`
+	PastureName   string `json:"pasture_name"`
+	PastureDataId int64  `json:"pasture_data_id"`
+}
+
+func (f *FeedPasture) TableName() string {
+	return "feed_pasture"
+}

+ 48 - 7
model/feed_formula.go

@@ -1,8 +1,9 @@
 package model
 
 import (
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"time"
+
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 )
 
 type FeedFormula struct {
@@ -12,7 +13,7 @@ type FeedFormula struct {
 	EncodeNumber       string                                `json:"encode_number"`
 	CattleCategoryId   operationPb.CattleCategoryParent_Kind `json:"cattle_category_id"`
 	CattleCategoryName string                                `json:"cattle_category_name"`
-	FormulaTypeId      int32                                 `json:"formula_type_id"`
+	FormulaTypeId      operationPb.FormulaType_Kind          `json:"formula_type_id"`
 	FormulaTypeName    string                                `json:"formula_type_name"`
 	DataSourceId       operationPb.DataSource_Kind           `json:"data_source_id"`
 	DataSourceName     string                                `json:"data_source_name"`
@@ -20,6 +21,7 @@ type FeedFormula struct {
 	Version            int64                                 `json:"version"`
 	PastureId          int64                                 `json:"pasture_id"`
 	PastureName        string                                `json:"pasture_name"`
+	PastureDataId      int64                                 `json:"pasture_data_id"`
 	IsShow             operationPb.IsShow_Kind               `json:"is_show"`
 	IsModify           operationPb.IsShow_Kind               `json:"is_modify"`
 	IsDelete           operationPb.IsShow_Kind               `json:"is_delete"`
@@ -43,9 +45,9 @@ func NewFeedFormula(req *operationPb.AddFeedFormulaRequest) *FeedFormula {
 		DataSourceId:       req.DataSourceId,
 		DataSourceName:     req.DataSourceName,
 		Remarks:            req.Remarks,
-		Version:            0,
+		Version:            1,
 		PastureId:          0,
-		PastureName:        "",
+		PastureName:        "集团",
 		IsShow:             req.IsShow,
 		IsDelete:           operationPb.IsShow_OK,
 		IsModify:           operationPb.IsShow_OK,
@@ -80,7 +82,46 @@ func (f FeedFormulaSlice) ToPB() []*operationPb.AddFeedFormulaRequest {
 	return res
 }
 
-type DistributeData struct {
-	PastureList     []*GroupPasture
-	FeedFormulaList []*FeedFormula
+func (f FeedFormulaSlice) ToDistributePB() []*operationPb.DistributeFeedRequest {
+	res := make([]*operationPb.DistributeFeedRequest, len(f))
+	for i, v := range f {
+		res[i] = &operationPb.DistributeFeedRequest{
+			Id:                 int32(v.Id),
+			Name:               v.Name,
+			Colour:             v.Colour,
+			EncodeNumber:       v.EncodeNumber,
+			CattleCategoryId:   v.CattleCategoryId,
+			CattleCategoryName: v.CattleCategoryName,
+			FormulaTypeId:      v.FormulaTypeId,
+			FormulaTypeName:    v.FormulaTypeName,
+			DataSourceName:     v.DataSourceName,
+			DataSourceId:       v.DataSourceId,
+			Remarks:            v.Remarks,
+			Version:            int32(v.Version),
+			PastureName:        v.PastureName,
+			IsShow:             v.IsShow,
+			IsModify:           v.IsModify,
+			CreatedAt:          int32(v.CreatedAt),
+			CreatedAtFormat:    time.Unix(v.CreatedAt, 0).Format(LayoutTime),
+		}
+	}
+	return res
+}
+
+func NewNewFeedFormulaByMixed(req *operationPb.MixedFeedFormulaRequest) *FeedFormula {
+	return &FeedFormula{
+		Name:               req.Name,
+		Colour:             req.Colour,
+		CattleCategoryId:   operationPb.CattleCategoryParent_Kind(req.CattleCategoryId),
+		CattleCategoryName: req.CattleCategoryName,
+		FormulaTypeId:      req.FormulaTypeId,
+		FormulaTypeName:    req.FormulaTypeName,
+		DataSourceId:       operationPb.DataSource_Kind(req.DataSourceId),
+		DataSourceName:     operationPb.DataSource_Kind_name[req.DataSourceId],
+		Remarks:            req.Remarks,
+		PastureName:        "集团",
+		IsShow:             operationPb.IsShow_OK,
+		IsModify:           operationPb.IsShow_OK,
+		IsDelete:           operationPb.IsShow_OK,
+	}
 }

+ 55 - 0
model/feed_formula_detail.go

@@ -0,0 +1,55 @@
+package model
+
+import (
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"time"
+)
+
+type FeedFormulaDetail struct {
+	Id                  int64                   `json:"id"`
+	PastureId           int64                   `json:"pasture_id"`
+	PastureName         string                  `json:"pasture_name"`
+	PastureDataId       int64                   `json:"pasture_data_id"`
+	FeedFormulaId       int64                   `json:"feed_formula_id"`
+	ForageId            int64                   `json:"forage_id"`
+	ForageName          string                  `json:"forage_name"`
+	ForageGroupName     string                  `json:"forage_group_name"`
+	Weight              int32                   `json:"weight"`
+	StirDelay           int32                   `json:"stir_delay"`
+	AllowError          int32                   `json:"allow_error"`
+	Prefit              int64                   `json:"prefit"`
+	IsShow              operationPb.IsShow_Kind `json:"is_show"`
+	IsModify            operationPb.IsShow_Kind `json:"is_modify"`
+	IsLockCowCountRatio operationPb.IsShow_Kind `json:"is_lock_cow_count_ratio"`
+	Sort                int32                   `json:"sort"`
+	CreatedAt           int64                   `json:"created_at"`
+	UpdatedAt           int64                   `json:"updated_at"`
+}
+
+func (f *FeedFormulaDetail) TableName() string {
+	return "feed_formula_detail"
+}
+
+type FeedFormulaDetailSlice []*FeedFormulaDetail
+
+func (f FeedFormulaDetailSlice) ToPB() []*operationPb.AddFeedFormulaDetail {
+	res := make([]*operationPb.AddFeedFormulaDetail, len(f))
+	for i, v := range f {
+		res[i] = &operationPb.AddFeedFormulaDetail{
+			Id:              int32(v.Id),
+			FeedFormulaId:   int32(v.FeedFormulaId),
+			ForageId:        int32(v.ForageId),
+			ForageName:      v.ForageName,
+			ForageGroupName: v.ForageGroupName,
+			Weight:          float32(v.Weight / 100),
+			StirDelay:       v.StirDelay,
+			AllowError:      v.AllowError,
+			CreatedAt:       int32(v.CreatedAt),
+			PreFit:          int32(v.Prefit),
+			IsModify:        v.IsModify,
+			Sort:            v.Sort,
+			CreatedAtFormat: time.Unix(v.CreatedAt, 0).Format(LayoutTime),
+		}
+	}
+	return res
+}

+ 4 - 9
model/feed_formula_distribute_log.go

@@ -1,6 +1,6 @@
 package model
 
-import operationPb "kpt-tmr-group/proto/go/backend/operation"
+import operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 
 type FeedFormulaDistributeLog struct {
 	Id            int64                   `json:"id"`
@@ -16,7 +16,7 @@ func (f *FeedFormulaDistributeLog) TableName() string {
 	return "feed_formula_distribute_log"
 }
 
-func NewFeedFormulaDistributeLog(feedFormulaId, pastureId int64, isShow operationPb.IsShow_Kind) *FeedFormulaDistributeLog {
+func NewFeedFormulaDistributeLog(feedFormulaId, pastureId int64, pastureName string, isShow operationPb.IsShow_Kind) *FeedFormulaDistributeLog {
 	return &FeedFormulaDistributeLog{
 		FeedFormulaId: feedFormulaId,
 		PastureId:     pastureId,
@@ -24,15 +24,10 @@ func NewFeedFormulaDistributeLog(feedFormulaId, pastureId int64, isShow operatio
 	}
 }
 
-func NewFeedFormulaDistributeLogList(feedFormulaList []*FeedFormula, pastureId int64, pastureName string, isShow operationPb.IsShow_Kind) []*FeedFormulaDistributeLog {
+func NewFeedFormulaDistributeLogList(feedFormulaList []*operationPb.DistributeFeedRequest, pastureId int64, pastureName string, isShow operationPb.IsShow_Kind) []*FeedFormulaDistributeLog {
 	res := make([]*FeedFormulaDistributeLog, 0)
 	for _, v := range feedFormulaList {
-		res = append(res, &FeedFormulaDistributeLog{
-			FeedFormulaId: v.Id,
-			PastureId:     pastureId,
-			PastureName:   pastureName,
-			IsShow:        isShow,
-		})
+		res = append(res, NewFeedFormulaDistributeLog(int64(v.Id), pastureId, pastureName, isShow))
 	}
 	return res
 }

+ 39 - 0
model/feed_formula_edit_record.go

@@ -0,0 +1,39 @@
+package model
+
+import operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+
+type FeedFormulaEditRecord struct {
+	Id            int64                                      `json:"id"`
+	GroupId       int64                                      `json:"group_id"`
+	FeedFormulaId int64                                      `json:"feed_formula_id"`
+	PastureId     int64                                      `json:"pasture_id"`
+	PastureName   string                                     `json:"pasture_name"`
+	OperationName string                                     `json:"operation_name"`
+	ForageName    string                                     `json:"forage_name"`
+	FieldName     string                                     `json:"field_name"`
+	Status        operationPb.FeedFormulaEditRecordType_Kind `json:"status"`
+	BeforeValue   string                                     `json:"before_value"`
+	AfterValue    string                                     `json:"after_value"`
+	CreatedAt     int64                                      `json:"created_at"`
+	UpdatedAt     int64                                      `json:"updated_at"`
+}
+
+func (f *FeedFormulaEditRecord) TableName() string {
+	return "feed_formula_edit_record"
+}
+
+func NewFeedFormulaEditRecord(groupId, feedFormulaId, pastureId int64, pastureName, operationName, forageName, fieldName,
+	beforeValue, afterValue string, status operationPb.FeedFormulaEditRecordType_Kind) *FeedFormulaEditRecord {
+	return &FeedFormulaEditRecord{
+		GroupId:       groupId,
+		FeedFormulaId: feedFormulaId,
+		PastureId:     pastureId,
+		PastureName:   pastureName,
+		OperationName: operationName,
+		ForageName:    forageName,
+		FieldName:     fieldName,
+		Status:        status,
+		BeforeValue:   beforeValue,
+		AfterValue:    afterValue,
+	}
+}

+ 56 - 4
model/forage.go

@@ -1,7 +1,7 @@
 package model
 
 import (
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"time"
 )
 
@@ -9,10 +9,12 @@ type Forage struct {
 	Id                 int64                           `json:"id"`
 	PastureId          int64                           `json:"pasture_id"`
 	PastureName        string                          `json:"pasture_name"`
+	PastureDataId      int64                           `json:"pasture_data_id"`
 	Name               string                          `json:"name"`
 	CategoryId         int64                           `json:"category_id"`
 	CategoryName       string                          `json:"category_name"`
-	MaterialType       int32                           `json:"material_type"`
+	MaterialTypeKey    operationPb.FormulaType_Kind    `json:"material_type_key"`
+	MaterialTypeName   string                          `json:"material_type_name"`
 	UniqueEncode       string                          `json:"unique_encode"`
 	ForageSourceId     operationPb.ForageSource_Kind   `json:"forage_source_id"`
 	ForageSourceName   string                          `json:"forage_source_name"`
@@ -45,6 +47,7 @@ func (c *Forage) TableName() string {
 func NewForage(req *operationPb.AddForageRequest) *Forage {
 	return &Forage{
 		Name:               req.Name,
+		PastureName:        "集团",
 		CategoryId:         int64(req.CategoryId),
 		CategoryName:       req.CategoryName,
 		UniqueEncode:       req.UniqueEncode,
@@ -52,7 +55,8 @@ func NewForage(req *operationPb.AddForageRequest) *Forage {
 		ForageSourceName:   req.ForageSourceName,
 		PlanTypeId:         req.PlanTypeId,
 		PlanTypeName:       req.PlanTypeName,
-		MaterialType:       req.MaterialType,
+		MaterialTypeKey:    req.MaterialTypeKey,
+		MaterialTypeName:   req.MaterialTypeName,
 		SmallMaterialScale: req.SmallMaterialScale,
 		AllowError:         int64(req.AllowError),
 		PackageWeight:      int64(req.PackageWeight),
@@ -81,7 +85,8 @@ func (f ForageSlice) ToPB() []*operationPb.AddForageRequest {
 			Name:               v.Name,
 			CategoryId:         int32(v.CategoryId),
 			CategoryName:       v.CategoryName,
-			MaterialType:       int32(v.MaterialType),
+			MaterialTypeKey:    v.MaterialTypeKey,
+			MaterialTypeName:   v.MaterialTypeName,
 			UniqueEncode:       v.UniqueEncode,
 			ForageSourceId:     v.ForageSourceId,
 			ForageSourceName:   v.ForageSourceName,
@@ -100,9 +105,56 @@ func (f ForageSlice) ToPB() []*operationPb.AddForageRequest {
 			Backup1:            v.Backup1,
 			Backup2:            v.Backup2,
 			Backup3:            v.Backup3,
+			DataSource:         v.PastureName,
 			CreatedAt:          int32(v.CreatedAt),
 			CreatedAtFormat:    time.Unix(v.CreatedAt, 0).Format(LayoutTime),
 		}
 	}
 	return res
 }
+
+func NewForageByPastureFeed(groupPasture *GroupPasture, data *Feed) *Forage {
+	forageSourceName := data.Source
+	forageSourceId := operationPb.ForageSource_SYSTEM_BUILT_IN
+	if forageSourceName == "用户自定义" {
+		forageSourceId = operationPb.ForageSource_USER_DEFINED
+	}
+
+	confirmStart := operationPb.IsShow_INVALID
+	if data.ConfirmStart == 0 {
+		confirmStart = operationPb.IsShow_NO
+	}
+
+	if data.ConfirmStart == 1 {
+		confirmStart = operationPb.IsShow_OK
+	}
+
+	return &Forage{
+		Name:               data.FName,
+		CategoryId:         data.FClassId,
+		CategoryName:       data.FClass,
+		MaterialTypeKey:    0,  // 部分牧场有该字段
+		MaterialTypeName:   "", //
+		UniqueEncode:       data.FeedCode,
+		ForageSourceId:     forageSourceId,
+		ForageSourceName:   forageSourceName,
+		PlanTypeId:         operationPb.ForagePlanType_Kind(data.PrintGroupId),
+		PlanTypeName:       data.PrintGroup,
+		SmallMaterialScale: data.SmtMrName,
+		AllowError:         data.AllowRatio,
+		PackageWeight:      data.UnitWeight,
+		Price:              int64(data.UPrice * 100),
+		JumpWeight:         data.AutoZone,
+		JumpDelay:          operationPb.JumpDelaType_Kind(data.AutoSecond),
+		ConfirmStart:       confirmStart,
+		RelayLocations:     int64(data.TrgAddress),
+		Jmp:                operationPb.IsShow_Kind(data.Jmp),
+		DataSource:         operationPb.DataSource_FROM_PASTURE,
+		Sort:               int64(data.Sort),
+		PastureId:          groupPasture.PastureId,
+		PastureName:        groupPasture.Name,
+		PastureDataId:      data.Id,
+		IsShow:             operationPb.IsShow_Kind(data.Enable),
+		IsDelete:           operationPb.IsShow_OK,
+	}
+}

+ 12 - 9
model/forage_category.go

@@ -1,7 +1,7 @@
 package model
 
 import (
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"time"
 )
 
@@ -28,14 +28,16 @@ func (s *ForageCategory) TableName() string {
 
 func NewForageCategory(req *operationPb.AddForageCategoryRequest) *ForageCategory {
 	return &ForageCategory{
-		ParentId:   req.ParentId,
-		ParentName: req.ParentName,
-		Name:       req.Name,
-		Number:     req.Number,
-		IsShow:     operationPb.IsShow_OK,
-		IsDelete:   operationPb.IsShow_OK,
-		DataSource: operationPb.DataSource_BACKGROUND_ADD,
-		Remarks:    "集团新增数据",
+		PastureId:   0,
+		PastureName: "集团",
+		ParentId:    req.ParentId,
+		ParentName:  req.ParentName,
+		Name:        req.Name,
+		Number:      req.Number,
+		IsShow:      operationPb.IsShow_OK,
+		IsDelete:    operationPb.IsShow_OK,
+		DataSource:  operationPb.DataSource_BACKGROUND_ADD,
+		Remarks:     "集团新增数据",
 	}
 }
 
@@ -53,6 +55,7 @@ func (f ForageCategorySlice) ToPB() []*operationPb.AddForageCategoryRequest {
 			IsShow:          v.IsShow,
 			CreatedAt:       uint32(v.CreatedAt),
 			CreatedAtFormat: time.Unix(v.CreatedAt, 0).Format(LayoutTime),
+			DataSource:      v.PastureName,
 		}
 	}
 	return res

+ 182 - 3
model/formula_estimate.go

@@ -1,5 +1,11 @@
 package model
 
+import (
+	"fmt"
+
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+)
+
 type PastureCommonRequest struct {
 	Name       string      `json:"name"`
 	Page       int32       `json:"page,omitempty"`
@@ -27,8 +33,8 @@ type PastureCommonResponse struct {
 }
 
 type PastureCommonData struct {
-	List     interface{} `json:"list,omitempty"`
-	Data     interface{} `json:"data,omitempty"`
+	List     interface{} `json:"list"`
+	Data     interface{} `json:"data"`
 	PageSize int32       `json:"pageSize"`
 	Total    int32       `json:"total"`
 	PageNum  int32       `json:"pageNum"`
@@ -95,6 +101,23 @@ type FeedStatisticsParams struct {
 	Times     string `json:"times"`
 }
 
+func NewFeedStatisticsParams(pastureId int64, req *operationPb.SearchFeedStatisticsRequest) *FeedStatisticsParams {
+	times := ""
+	if req.ClassNumber > 0 {
+		times = fmt.Sprintf("%d", req.ClassNumber)
+	}
+	return &FeedStatisticsParams{
+		PastureId: fmt.Sprintf("%d", pastureId),
+		StartTime: req.StartTime,
+		StopTime:  req.EndTime,
+		Date:      req.StartTime,
+		FeedTName: req.FormulaTemplate,
+		BarName:   req.BarnName,
+		CowClass:  req.CattleCategoryName,
+		Times:     times,
+	}
+}
+
 // FeedChartParams 饲喂效率-图形统计
 type FeedChartParams struct {
 	ParamMaps interface{} `json:"parammaps"`
@@ -127,6 +150,31 @@ type MixFeedStatisticsParams struct {
 	Error       bool   `json:"error,omitempty"`
 }
 
+func NewMixFeedStatisticsParams(pastureId int64, req *operationPb.MixFeedStatisticsRequest) *MixFeedStatisticsParams {
+	times := ""
+	if req.ClassNumber > 0 {
+		times = fmt.Sprintf("%d", req.ClassNumber)
+	}
+	return &MixFeedStatisticsParams{
+		PastureId:   fmt.Sprintf("%d", pastureId),
+		StartTime:   req.StartTime,
+		StopTime:    req.StartTime,
+		TmrTName:    req.EquipmentName,
+		ProjName:    req.TrainNumber,
+		Times:       times,
+		ButtonType:  req.ButtonType,
+		TempletName: req.FormulationName,
+		Isuse:       req.IsUse,
+		Hlwc1:       req.Hlwc1,
+		Hlwc2:       req.Hlwc2,
+		Hlzq1:       req.Hlzq1,
+		Hlzq2:       req.Hlzq2,
+		Hlzql1:      req.Hlzql1,
+		Hlzql2:      req.Hlzql2,
+		Error:       req.IsError,
+	}
+}
+
 // SprinkleStatisticsParams 准确性分析-撒料统计
 type SprinkleStatisticsParams struct {
 	PastureId   string `json:"pastureid"`
@@ -148,6 +196,32 @@ type SprinkleStatisticsParams struct {
 	Error       bool   `json:"error,omitempty"`
 }
 
+func NewSprinkleStatisticsParams(pastureId int64, req *operationPb.SprinkleStatisticsRequest) *SprinkleStatisticsParams {
+	times := ""
+	if req.ClassNumber > 0 {
+		times = fmt.Sprintf("%d", req.ClassNumber)
+	}
+	return &SprinkleStatisticsParams{
+		PastureId:   fmt.Sprintf("%d", pastureId),
+		StartTime:   req.StartTime,
+		StopTime:    req.StartTime,
+		TmrTName:    req.EquipmentName,
+		ProjName:    req.TrainNumber,
+		Times:       times,
+		ButtonType:  req.ButtonType,
+		TempletName: req.FormulationName,
+		Isuse:       req.IsUse,
+		Fname:       req.BarnName,
+		Slwc1:       req.Slwc1,
+		Slwc2:       req.Slwc2,
+		Slzq2:       req.Slzq2,
+		Slzq1:       req.Slzq1,
+		Slzql1:      req.Slzql1,
+		Slzql2:      req.Slzql2,
+		Error:       req.IsError,
+	}
+}
+
 // ProcessAnalysisParams 过程分析
 type ProcessAnalysisParams struct {
 	PastureId   string   `json:"pastureid"`
@@ -168,6 +242,35 @@ type ProcessAnalysisParams struct {
 	Error       string   `json:"error,omitempty"`
 }
 
+func NewProcessAnalysisParams(pastureId int64, req *operationPb.ProcessAnalysisRequest) *ProcessAnalysisParams {
+	if req.TmrName == nil {
+		req.TmrName = make([]string, 0)
+	}
+
+	lpPlanType := ""
+	if req.PlanType > 0 {
+		lpPlanType = fmt.Sprintf("%d", req.PlanType)
+	}
+	return &ProcessAnalysisParams{
+		PastureId:   fmt.Sprintf("%d", pastureId),
+		StartTime:   req.StartTime,
+		StopTime:    req.EndTime,
+		TmrTName:    req.TmrName,
+		IsCompleted: "",
+		LpPlanType:  lpPlanType,
+		FClassId:    req.MixFeedType,
+		Hlzq1:       req.Hlzq1,
+		Hlzq2:       req.Hlzq2,
+		Hlwc1:       req.Hlwc1,
+		Hlwc2:       req.Hlwc2,
+		Slwc1:       req.Slwc1,
+		Slwc2:       req.Slwc2,
+		Slzq2:       req.Slzq2,
+		Slzq1:       req.Slzq1,
+		Error:       req.ErrorRange,
+	}
+}
+
 // AccuracyAggParams 准确性分析-汇总统计
 type AccuracyAggParams struct {
 	PastureId string `json:"pastureid"`
@@ -194,6 +297,33 @@ type AccuracyAggParams struct {
 	Error     bool   `json:"error,omitempty"`
 }
 
+func NewAccuracyAggParams(pastureId int64, req *operationPb.AccuracyAggStatisticsRequest) *AccuracyAggParams {
+	return &AccuracyAggParams{
+		PastureId: fmt.Sprintf("%d", pastureId),
+		StartTime: req.StartTime,
+		StopTime:  req.EndTime,
+		FName:     req.Fname,
+		Sort:      req.Sort,
+		Status:    req.Status,
+		Times:     req.Times,
+		Genre:     req.Genre,
+		IsDate:    req.Isdate,
+		Hlwc1:     req.Hlwc1,
+		Hlwc2:     req.Hlwc2,
+		Hlzq1:     req.Hlzq1,
+		Hlzq2:     req.Hlzq2,
+		Hlzql1:    req.Hlzql1,
+		Hlzql2:    req.Hlzql2,
+		Slwc1:     req.Slwc1,
+		Slwc2:     req.Slwc2,
+		Slzq1:     req.Slzq1,
+		Slzq2:     req.Slzq2,
+		Slzql1:    req.Slzql1,
+		Slzql2:    req.Slzql2,
+		Error:     req.IsError,
+	}
+}
+
 // TrainNumberParams 班次
 type TrainNumberParams struct {
 	PastureId string `json:"pastureid"`
@@ -210,6 +340,10 @@ type GetDataByNameParams struct {
 	PastureId string `json:"pastureid"`
 	StartTime string `json:"startTime"`
 	StopTime  string `json:"stopTime"`
+	Pid       string `json:"pid"`
+	Optdevice string `json:"optdevice,omitempty"`
+	FtId      int32  `json:"ftid,omitempty"`
+	Name      string `json:"name,omitempty"`
 }
 
 type FeedStatisticsResponse struct {
@@ -219,7 +353,7 @@ type FeedStatisticsResponse struct {
 }
 
 type FeedStatisticsData struct {
-	List map[string]interface{} `json:"list,omitempty"`
+	List map[string]interface{} `json:"list"`
 }
 
 var DefaultSheetName = "Sheet1"
@@ -244,4 +378,49 @@ type FeedStatisticsConversions struct {
 	CostOfFormulation         string  `json:"cost_of_formulation"`          // 配方成本
 	FoodIntakeRate            string  `json:"food_intake_rate"`             // 采食率
 	FeedConversionRatio       float64 `json:"feed_conversion_ratio"`        // 饲料转化率
+	FeedFormulaName           string  `json:"feed_formula_name"`            // 配方模板
+	ActualMixedVolume         string  `json:"actual_mixed_volume"`          // 实际混料量
+	SprinkleVolume            string  `json:"sprinkle_volume"`              // 撒料量
+}
+
+type MixedSprinkleDetailRequest struct {
+	PastureId string `json:"pastureid"`
+	Id        string `json:"id"`
+	PId       string `json:"pid"`
+	FClassId  string `json:"fclassid"`
+}
+
+func NewMixedSprinkleDetailRequest(pastureId int64, req *operationPb.ProcessMixedSprinkleDetailRequest) *MixedSprinkleDetailRequest {
+	return &MixedSprinkleDetailRequest{
+		PastureId: fmt.Sprintf("%d", pastureId),
+		FClassId:  req.FclassId,
+		PId:       req.Pid,
+		Id:        req.Id,
+	}
+}
+
+type PastureFeedTemplateHistoryRequest struct {
+	PastureId string `json:"pastureid"`
+	FTid      int64  `json:"ftid"`
+	StartDate string `json:"startdate"`
+	EndDate   string `json:"enddate"`
+}
+
+type PastureFeedTemplateHistoryResponse struct {
+	Code int32       `json:"code"`
+	Msg  string      `json:"msg"`
+	Data interface{} `json:"data"`
+}
+
+type PastureBarnHistoryRequest struct {
+	PastureId string `json:"pastureid,omitempty"`
+	BarName   string `json:"barname"`
+	StartDate string `json:"startDate"`
+	EndDate   string `json:"endDate"`
+}
+
+type PastureBarnHistoryResponse struct {
+	Code int32       `json:"code"`
+	Msg  string      `json:"msg"`
+	Data interface{} `json:"data"`
 }

+ 59 - 45
model/group_pasture.go

@@ -3,18 +3,67 @@ package model
 import (
 	"bytes"
 	"encoding/json"
+	"fmt"
 	"io/ioutil"
-	"kpt-tmr-group/pkg/logger/zaplog"
-	"kpt-tmr-group/pkg/tool"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"strings"
 	"time"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"gitee.com/xuyiping_admin/pkg/tool"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+
 	"go.uber.org/zap"
 )
 
+const (
+	InitManagerPassword    = "123456"
+	UrlDataByName          = "authdata/GetDataByName"
+	UrlReportForm          = "authdata/GetReportform"
+	UrlSummary             = "authdata/summary"
+	UrlProcess             = "authdata/processAnalysist"
+	UrlFeedTemplateHistory = "authdata/feedtemplet/history"
+	UrlBarnHistory         = "authdata/feedp/history"
+	UrlSpillageAllHistory  = "authdata/spillageall/history"
+)
+
+const (
+	FeedFormulaDistributeUrl       = "pasture/feed_formula/distribute"
+	FeedFormulaCancelDistributeUrl = "pasture/feed_formula/cancel/distribute"
+	FeedFormulaIsModifyUrl         = "pasture/feed_formula/is_modify"
+	FeedFormulaAsyncUrl            = "pasture/feed_formula/async"
+	FeedFormulaDetailListAsyncUrl  = "pasture/feed_formula/detail_list"
+	FeedAsyncUrl                   = "pasture/feed/async"
+	DashboardAccuracyUrl           = "pasture/dashboard/accuracy_data"
+	DashboardExecTimeUrl           = "pasture/dashboard/process_analysis"
+	DashboardSprinkleFeedTimeUrl   = "pasture/dashboard/sprinkle_statistics"
+	PastureAccountDistributionURl  = "pasture/account/distribute"
+	ForageCategoryDistributionURl  = "pasture/forage_category/distribute"
+	CattleCategoryDistributionURl  = "pasture/cattle_category/distribute"
+	CattleCategoryDeleteURl        = "pasture/cattle_category/delete"
+	ForageCategoryDeleteURl        = "pasture/cattle_category/delete"
+	FeedUsageURl                   = "pasture/feed/usage"
+	FeedFormulaVersionUpdateUrl    = "pasture/feed_formula/version"
+)
+
+var (
+	UrlChart = map[string]string{
+		"mr":    "authdata/chart/feedEffMR",     // 饲喂效率-效率统计 mr 泌乳牛干物质采食量
+		"sl":    "authdata/chart/feedEffSL",     // 饲喂效率-效率统计 sl 牛栏剩料率
+		"hl":    "authdata/chart/feedEffHL",     // 饲喂效率-效率统计 hl 混料时间统计
+		"zh":    "authdata/chart/feedEffZH",     // 饲喂效率-效率统计 zh 转化率
+		"cbft":  "authdata/chart/feedEffCBFT",   // 饲喂效率-效率统计 cbft 成本分析
+		"jh":    "authdata/chart/accuracyAllJH", // 准确性分析-汇总统计-计划统计
+		"ft":    "authdata/chart/accuracyAllFT", // 准确性分析-汇总统计-配方准确率
+		"nq":    "authdata/chart/accuracyAllNQ", // 准确性分析-汇总统计-牛群准确率
+		"cc":    "authdata/chart/accuracyAllCC", // 准确性分析-汇总统计-车辆准确率(重量)
+		"allhl": "authdata/chart/accuracyAllHL", // 准确性分析-汇总统计-混料统计
+		"qx":    "authdata/chart/accuracyAllQX", // 准确性分析-汇总统计-混料计划取消次数
+		"ls":    "authdata/chart/accuracyAllLS", // 准确性分析-汇总统计-栏舍撒料时间统计
+	}
+)
+
 type GroupPasture struct {
 	Id             int64                   `json:"id,omitempty"`
 	Name           string                  `json:"name,omitempty"`
@@ -46,44 +95,6 @@ func (g *GroupPasture) GetPastureId() int64 {
 	return g.Id
 }
 
-const (
-	InitManagerPassword = "123456"
-	UrlDataByName       = "authdata/GetDataByName"
-	UrlReportForm       = "authdata/GetReportform"
-	UrlSummary          = "authdata/summary"
-	UrlProcess          = "authdata/processAnalysist"
-)
-
-const (
-	FeedFormulaDistributeUrl      = "pasture/feed_formula/distribute"
-	FeedFormulaIsModifyUrl        = "pasture/feed_formula/is_modify"
-	DashboardAccuracyUrl          = "pasture/dashboard/accuracy_data"
-	DashboardExecTimeUrl          = "pasture/dashboard/process_analysis"
-	DashboardSprinkleFeedTimeUrl  = "pasture/dashboard/sprinkle_statistics"
-	PastureAccountDistributionURl = "pasture/account/distribute"
-	ForageCategoryDistributionURl = "pasture/forage_category/distribute"
-	CattleCategoryDistributionURl = "pasture/cattle_category/distribute"
-	CattleCategoryDeleteURl       = "pasture/cattle_category/delete"
-	ForageCategoryDeleteURl       = "pasture/cattle_category/delete"
-)
-
-var (
-	UrlChart = map[string]string{
-		"mr":    "authdata/chart/feedEffMR",     // 饲喂效率-效率统计 mr 泌乳牛干物质采食量
-		"sl":    "authdata/chart/feedEffSL",     // 饲喂效率-效率统计 sl 牛栏剩料率
-		"hl":    "authdata/chart/feedEffHL",     // 饲喂效率-效率统计 hl 混料时间统计
-		"zh":    "authdata/chart/feedEffZH",     // 饲喂效率-效率统计 zh 转化率
-		"cbft":  "authdata/chart/feedEffCBFT",   // 饲喂效率-效率统计 cbft 成本分析
-		"jh":    "authdata/chart/accuracyAllJH", // 准确性分析-汇总统计-计划统计
-		"ft":    "authdata/chart/accuracyAllFT", // 准确性分析-汇总统计-配方准确率
-		"nq":    "authdata/chart/accuracyAllNQ", // 准确性分析-汇总统计-牛群准确率
-		"cc":    "authdata/chart/accuracyAllCC", // 准确性分析-汇总统计-车辆准确率(重量)
-		"allhl": "authdata/chart/accuracyAllHL", // 准确性分析-汇总统计-混料统计
-		"qx":    "authdata/chart/accuracyAllQX", // 准确性分析-汇总统计-混料计划取消次数
-		"ls":    "authdata/chart/accuracyAllLS", // 准确性分析-汇总统计-栏舍撒料时间统计
-	}
-)
-
 type PastureTokenRequest struct {
 	UserName string `json:"username"`
 	Password string `json:"password"`
@@ -137,6 +148,7 @@ func (p *PastureClient) doRequest(req *http.Request) ([]byte, error) {
 		zaplog.Error("PastureClient", zap.Any("authClient.Do", err))
 		return nil, xerr.WithStack(err)
 	}
+	defer resp.Body.Close()
 	b, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		zaplog.Error("PastureClient", zap.Any("ioutil.ReadAll", err))
@@ -167,6 +179,7 @@ func (p *PastureClient) DoGet(url string) ([]byte, error) {
 	req.Header.Add("Accept", "application/json")
 	req.Header.Add("token", p.Token)
 	req.Header.Add("Content-Type", "application/json")
+	req.Header.Add("pasture_id", fmt.Sprintf("%d", p.Detail.PastureId))
 	return p.doRequest(req)
 }
 
@@ -192,11 +205,12 @@ func (p *PastureClient) DoPost(url string, body interface{}) ([]byte, error) {
 	req.Header.Add("Accept", "application/json")
 	req.Header.Add("token", p.Token)
 	req.Header.Add("Content-Type", "application/json")
+	req.Header.Add("pasture_id", fmt.Sprintf("%d", p.Detail.PastureId))
 	return p.doRequest(req)
 }
 
 func (p *PastureClient) GetToken() error {
-	/*url := fmt.Sprintf("%s/%s", p.Detail.Domain, "auth")
+	url := fmt.Sprintf("%s/%s", p.Detail.Domain, "auth")
 	body := &PastureTokenRequest{
 		UserName: p.Detail.Account,
 		Password: p.Detail.Password,
@@ -227,8 +241,7 @@ func (p *PastureClient) GetToken() error {
 		zaplog.Error("PastureClient", zap.Any("response", response))
 		return xerr.Customf("获取牧场端token失败 Err:%s", err)
 	}
-	p.Token = response.Data.Token*/
-	p.Token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJlMTBhZGMzOTQ5YmE1OWFiYmU1NmUwNTdmMjBmODgzZSIsImV4cCI6MTY4OTI2ODIxOCwiaXNzIjoiaHR0cHM6Ly9naXRodWIuY29tL2twdHl1bi9nby1hZG1pbi8ifQ.Q2ztGs66HbIz4IpTy9pH7bZVsJEzVQBwpjJSLBzKn4c"
+	p.Token = response.Data.Token
 	return nil
 }
 
@@ -248,6 +261,7 @@ func (g GroupPastureSlice) ToPB() []*operationPb.AddPastureRequest {
 			IsShow:          v.IsShow,
 			CreatedAt:       int32(v.CreatedAt),
 			CreatedAtFormat: time.Unix(v.CreatedAt, 0).Format(LayoutTime),
+			PastureId:       int32(v.PastureId),
 		}
 	}
 	return res

+ 152 - 4
model/pasture_data.go

@@ -1,8 +1,10 @@
 package model
 
-type DistributeFeedFormulaRequest struct {
-	PastureId int64          `json:"pasture_id"`
-	Body      []*FeedFormula `json:"body"`
+import operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+
+type CancelDistributeFeedFormulaRequest struct {
+	PastureId     int64   `json:"pasture_id"`
+	PastureDataId []int64 `json:"pasture_data_id"`
 }
 
 type PastureResponse struct {
@@ -11,6 +13,10 @@ type PastureResponse struct {
 	Data interface{} `json:"data"`
 }
 
+type PastureSuccess struct {
+	Success bool `json:"success"`
+}
+
 type DashboardAccuracyRequest struct {
 	CattleParentCategoryId int32  `json:"cattle_parent_category_id,omitempty"`
 	FeedFormulaId          int32  `json:"feed_formula_id"`
@@ -30,7 +36,6 @@ type PastureAnalysisAccuracyResponse struct {
 	Msg  string                       `json:"msg"`
 	Data *PastureAnalysisAccuracyData `json:"data"`
 }
-
 type PastureAnalysisAccuracyData struct {
 	MixedFodderAccurateRatio    []*PastureAnalysisAccuracyDataValue `json:"mixed_fodder_accurate_ratio"`    // 混料准确率
 	MixedFodderCorrectRatio     []*PastureAnalysisAccuracyDataValue `json:"mixed_fodder_correct_ratio"`     // 混料正确率
@@ -68,3 +73,146 @@ type CategoryDeleteRequest struct {
 	GroupId   int32 `json:"group_id"`
 	IsDelete  int32 `json:"is_delete"`
 }
+
+type FeedFormulaListRequest struct {
+	PastureId int32 `json:"pasture_id"`
+	Page      int32 `json:"page"`
+	PageSize  int32 `json:"page_size"`
+}
+
+type FeedFormulaListResponse struct {
+	Code int32            `json:"code"`
+	Msg  string           `json:"msg"`
+	Data *FeedFormulaData `json:"data"`
+}
+
+type FeedFormulaData struct {
+	Total    int32           `json:"total"`
+	Page     int32           `json:"page"`
+	PageSize int32           `json:"page_size"`
+	List     []*FeedTemplate `json:"list"`
+}
+
+type FeedTemplate struct {
+	Id           int64   `json:"id"`
+	PastureId    int64   `json:"pasture_id"`
+	TCode        string  `json:"t_code"`
+	TName        string  `json:"t_name"`
+	TColor       string  `json:"t_color"`
+	CCid         int64   `json:"c_cid"`
+	CCName       string  `json:"cc_name"`
+	FTType       string  `json:"ft_type"`
+	FTTypeId     int32   `json:"ft_type_id"`
+	Source       string  `json:"source"`
+	Remark       string  `json:"remark"`
+	Enable       int32   `json:"enable"`
+	Sort         int64   `json:"sort"`
+	Owner        string  `json:"owner"`
+	Weight       float64 `json:"weight"`
+	DryWeight    float64 `json:"dry_weight"`
+	IsDelete     int32   `json:"is_delete"`
+	Version      int64   `json:"version"`
+	SaveTime     string  `json:"save_time"`
+	IsIssue      int32   `json:"is_issue"`
+	IssueVersion int32   `json:"issue_version"`
+	IssueId      int64   `json:"issue_id"`
+	Backup1      string  `json:"backup1"`
+	Backup2      string  `json:"backup2"`
+	IsModify     int32   `json:"is_modify"`
+}
+
+// MixedCategoryTmrNameParams tmr名称和混料类别
+type MixedCategoryTmrNameParams struct {
+	PastureId string `json:"pastureid"` //牧场id
+	StartTime string `json:"startdate,omitempty"`
+	EndTime   string `json:"enddate,omitempty"`
+}
+
+type FeedListResponse struct {
+	Code int32     `json:"code"`
+	Msg  string    `json:"msg"`
+	Data *FeedData `json:"data"`
+}
+
+type FeedData struct {
+	Total    int32   `json:"total"`
+	Page     int32   `json:"page"`
+	PageSize int32   `json:"page_size"`
+	List     []*Feed `json:"list"`
+}
+
+type Feed struct {
+	Id             int64   `xorm:"id" json:"id"`
+	PastureId      int64   `xorm:"pastureid" json:"pasture_id"`
+	FeedCode       string  `xorm:"feedcode" json:"feed_code"`
+	FName          string  `xorm:"fname" json:"f_name"`
+	FClass         string  `xorm:"fclass" json:"f_class"`
+	FClassId       int64   `xorm:"fclassid" json:"f_class_id"`
+	AllowRatio     int64   `xorm:"allowratio" json:"allow_ratio"`
+	PrintGroupId   int64   `xorm:"printgroupid" json:"print_group_id"`
+	PrintGroup     string  `xorm:"printgroup" json:"print_group"`
+	UnitWeight     int64   `xorm:"unitweight" json:"unit_weight"`
+	UPrice         float64 `xorm:"uprice" json:"u_price"`
+	Dry            float64 `xorm:"dry" json:"dry"`
+	AutoZone       int64   `xorm:"autozone" json:"auto_zone"`
+	AutoSecond     int64   `xorm:"autosecond" json:"auto_second"`
+	AutoSecondName string  `xorm:"autosecondname" json:"auto_second_name"`
+	ConfirmStart   int32   `xorm:"confirmstart" json:"confirm_start"`
+	TrgAddress     int32   `xorm:"trgaddress" json:"trg_address"`
+	SmtMrId        int64   `xorm:"smt_mr_id" json:"smt_mr_id"`
+	SmtMrName      string  `xorm:"smtmrname" json:"smt_mr_name"`
+	Sort           int32   `xorm:"sort" json:"sort"`
+	Enable         int32   `xorm:"enable" json:"enable"`
+	Jmp            int32   `xorm:"jmp" json:"jmp"`
+	Source         string  `xorm:"source"`
+	Backup1        string  `xorm:"backup1" json:"backup1"`
+	Backup2        string  `xorm:"backup2" json:"backup2"`
+	Backup3        string  `xorm:"backup3" json:"backup3"`
+}
+
+type FeedFormulaDetailListResponse struct {
+	Code int32                  `json:"code"`
+	Msg  string                 `json:"msg"`
+	Data *FeedFormulaDetailData `json:"data"`
+}
+
+type FeedFormulaDetailData struct {
+	Total    int32                 `json:"total"`
+	Page     int32                 `json:"page"`
+	PageSize int32                 `json:"page_size"`
+	List     []*FeedTemplateDetail `json:"list"`
+}
+
+type FeedTemplateDetail struct {
+	Id             int64   `json:"id"`
+	PastureId      int64   `json:"pasture_id"`
+	FtId           int64   `json:"ft_id"`
+	FId            int64   `json:"f_id"`
+	FName          string  `json:"f_name"`
+	LWeight        float64 `json:"l_weight"`
+	FWeight        float64 `json:"f_weight"`
+	IsLockCount    int32   `json:"is_lock_count"`
+	IsFg           int32   `json:"is_fg"`
+	Sort           int32   `json:"sort"`
+	FeedGroup      string  `json:"feed_group"`
+	PreFtId        int64   `json:"pre_ft_id"`
+	AutoSecond     int32   `json:"auto_second"`
+	AutoSecondName string  `json:"auto_second_name"`
+	SplitFtPreId   int64   `json:"split_ft_pre_id"`
+	Deviation      int32   `json:"deviation"`
+}
+
+type FeedFormulaUpdateVersionRequest struct {
+	FeedTemplateId int64                               `json:"feed_template_id"` // 配方id
+	Version        int64                               `json:"version"`          // 版本号
+	Belong         int32                               `json:"belong"`           // 配方归属  0 无效 1 归属集团端 2 归属牧场端
+	Data           []*operationPb.AddFeedFormulaDetail `json:"data"`
+}
+
+type FeedFormulaUpdateVersionResponse struct {
+	Code int32  `json:"code"`
+	Msg  string `json:"msg"`
+	Data struct {
+		Success bool `json:"success"`
+	} `json:"data"`
+}

+ 1 - 1
model/system_group_pasture_permissions.go

@@ -1,6 +1,6 @@
 package model
 
-import operationPb "kpt-tmr-group/proto/go/backend/operation"
+import operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 
 type SystemGroupPasturePermissions struct {
 	Id        int64                   `json:"id,omitempty"`

+ 1 - 1
model/system_menu.go

@@ -1,7 +1,7 @@
 package model
 
 import (
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"time"
 )
 

+ 1 - 1
model/system_menu_permissions.go

@@ -1,6 +1,6 @@
 package model
 
-import operationPb "kpt-tmr-group/proto/go/backend/operation"
+import operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 
 type SystemMenuPermissions struct {
 	Id        int64                   `json:"id,omitempty"`

+ 1 - 1
model/system_mobile.go

@@ -1,7 +1,7 @@
 package model
 
 import (
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"time"
 )
 

+ 1 - 1
model/system_mobile_permissions.go

@@ -1,6 +1,6 @@
 package model
 
-import operationPb "kpt-tmr-group/proto/go/backend/operation"
+import operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 
 type SystemMobilePermissions struct {
 	Id        int64                   `json:"id,omitempty"`

+ 1 - 1
model/system_role.go

@@ -1,7 +1,7 @@
 package model
 
 import (
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"time"
 )
 

+ 1 - 1
model/system_user.go

@@ -2,7 +2,7 @@ package model
 
 import (
 	"fmt"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"net/http"
 	"strconv"
 	"strings"

+ 328 - 165
module/backend/dashboard_service.go

@@ -5,20 +5,23 @@ import (
 	"encoding/json"
 	"fmt"
 	"kpt-tmr-group/model"
-	"kpt-tmr-group/pkg/logger/zaplog"
-	"kpt-tmr-group/pkg/tool"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"sort"
 	"sync"
 	"time"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"gitee.com/xuyiping_admin/pkg/tool"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+
 	"go.uber.org/multierr"
 	"go.uber.org/zap"
 )
 
-const compareTime = 10 * 60
+const (
+	compareTime = 10 * 60
+)
 
 // PasturePrefAnalysisData  PasturePrefExecTimeData PastureSprinkleFeedTime TODO  后期三个函数封装一下
 func (s *StoreEntry) PasturePrefAnalysisData(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (map[int64]*model.PastureAnalysisAccuracyData, error) {
@@ -47,9 +50,8 @@ func (s *StoreEntry) PasturePrefAnalysisData(ctx context.Context, req *operation
 				StartDate:              req.StartDate,
 				EndDate:                req.EndDate,
 			}
-			_, err = s.PastureHttpClient(ctx, model.DashboardAccuracyUrl, int64(pId), body, response)
-			if err != nil {
-				zaplog.Error("DistributeFeedFormula",
+			if err = s.PastureHttpClient(ctx, model.DashboardAccuracyUrl, int64(pId), body, response); err != nil {
+				zaplog.Error("PasturePrefAnalysisData",
 					zap.String("url", model.DashboardAccuracyUrl),
 					zap.Any("pasture", groupPasture), zap.Any("body", body),
 					zap.Any("err", err), zap.Any("response", response))
@@ -60,14 +62,13 @@ func (s *StoreEntry) PasturePrefAnalysisData(ctx context.Context, req *operation
 				return
 			}
 			if response.Code != http.StatusOK {
-				zaplog.Error("DistributeFeedFormula-response",
+				zaplog.Error("PasturePrefAnalysisData-response",
 					zap.String("url", model.DashboardAccuracyUrl),
 					zap.Any("pasture", groupPasture), zap.Any("body", body),
 					zap.Any("response", response), zap.Any("response", response))
 				return
 			}
 			res[groupPasture.Id] = response.Data
-
 		}(pastureId)
 	}
 	wg.Wait()
@@ -75,7 +76,6 @@ func (s *StoreEntry) PasturePrefAnalysisData(ctx context.Context, req *operation
 }
 
 func (s *StoreEntry) PasturePrefExecTimeData(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (map[string]*model.ExecTimeData, error) {
-
 	res := make(map[string]*model.ExecTimeData, 0)
 	wg := sync.WaitGroup{}
 	wg.Add(len(req.PastureIds))
@@ -97,7 +97,7 @@ func (s *StoreEntry) PasturePrefExecTimeData(ctx context.Context, req *operation
 				StartDate:              req.StartDate,
 				EndDate:                req.EndDate,
 			}
-			if _, err = s.PastureHttpClient(ctx, model.DashboardExecTimeUrl, int64(pId), body, response); err != nil {
+			if err = s.PastureHttpClient(ctx, model.DashboardExecTimeUrl, int64(pId), body, response); err != nil {
 				zaplog.Error("PasturePrefExecTimeData",
 					zap.String("url", model.DashboardExecTimeUrl),
 					zap.Any("pasture", groupPasture), zap.Any("body", body),
@@ -123,16 +123,14 @@ func (s *StoreEntry) PasturePrefExecTimeData(ctx context.Context, req *operation
 	return res, nil
 }
 
-func (s *StoreEntry) PastureSprinkleFeedTime(ctx context.Context, req *operationPb.SprinkleFeedTimeRequest) (map[string][]*model.SprinkleStatisticsDataList, error) {
-
-	res := make(map[string][]*model.SprinkleStatisticsDataList, 0)
+func (s *StoreEntry) PastureSprinkleFeedTime(ctx context.Context, req *operationPb.SprinkleFeedTimeRequest) (map[int64][]*model.SprinkleStatisticsDataList, map[int64]*model.GroupPasture, error) {
+	res, pastureList := make(map[int64][]*model.SprinkleStatisticsDataList), make(map[int64]*model.GroupPasture, 0)
 	wg := sync.WaitGroup{}
 	wg.Add(len(req.PastureIds))
 	var muError error
 	for _, pasture := range req.PastureIds {
 		go func(pId int32) {
 			defer wg.Done()
-
 			groupPasture, err := s.GetGroupPastureListById(ctx, int64(pId))
 			if err != nil {
 				zaplog.Error("PastureSprinkleFeedTime", zap.Any("GetGroupPastureListById", err))
@@ -146,7 +144,8 @@ func (s *StoreEntry) PastureSprinkleFeedTime(ctx context.Context, req *operation
 				StartDate:     req.StartDate,
 				EndDate:       req.EndDate,
 			}
-			if _, err = s.PastureHttpClient(ctx, model.DashboardSprinkleFeedTimeUrl, int64(pId), body, response); err != nil {
+
+			if err = s.PastureHttpClient(ctx, model.DashboardSprinkleFeedTimeUrl, int64(pId), body, response); err != nil {
 				muError = multierr.Append(muError, err)
 				zaplog.Error("PastureSprinkleFeedTime",
 					zap.String("url", model.DashboardSprinkleFeedTimeUrl),
@@ -160,127 +159,144 @@ func (s *StoreEntry) PastureSprinkleFeedTime(ctx context.Context, req *operation
 			if response.Code != http.StatusOK {
 				muError = multierr.Append(muError, xerr.Custom(response.Msg))
 			}
-			res[groupPasture.Name] = response.Data
+			res[groupPasture.Id] = response.Data
+			pastureList[groupPasture.Id] = groupPasture
 		}(pasture)
 	}
 	wg.Wait()
-	return res, nil
+	return res, pastureList, nil
 }
 
-func (s *StoreEntry) SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error) {
-	res := &model.SearchAnalysisAccuracyResponse{
+// SearchAnalysisAccuracy 准确性分析
+func (s *StoreEntry) SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse1, error) {
+	res := &model.SearchAnalysisAccuracyResponse1{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: &model.AnalysisAccuracyData{
-			Chart: &model.Chart{},
+		Data: &model.AnalysisAccuracyData1{
 			Table: &model.Table{
 				TitleList: make([]*model.TableList, 0),
 				DataList:  &model.DataList{},
 			},
+			Chart: nil,
 		},
 	}
+
 	res.Data.Table.TitleList = append(res.Data.Table.TitleList, &model.TableList{
 		Name:  "title",
 		Value: "牧场",
 	})
-	pastureAnalysisAccuracy, err := s.PasturePrefAnalysisData(ctx, req)
+
+	dashboardTopData, pastureAnalysisAccuracy, err := s.DashboardTopPasture(ctx, req)
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	res.Data.Table = s.TitleList(ctx, pastureAnalysisAccuracy)
 
-	mixedFodderAccurateRatio, mixedFodderCorrectRatio, sprinkleFodderAccurateRatio, sprinkleFodderCorrectRatio :=
-		&model.CommonValueRatio{}, &model.CommonValueRatio{}, &model.CommonValueRatio{}, &model.CommonValueRatio{}
-	maTitleValueList, mcTitleValueList, saTitleValueList, scTitleValueList := make([]float64, 0), make([]float64, 0), make([]float64, 0), make([]float64, 0)
-	mTopOneName := ""
-	for pastureId, data := range pastureAnalysisAccuracy {
-		groupPasture, err := s.GetGroupPastureListById(ctx, pastureId)
-		if err != nil {
-			zaplog.Error("SearchAnalysisAccuracy GetGroupPastureListById",
-				zap.Any("pastureId", pastureId), zap.Any("error", err))
-			continue
-		}
-		if data == nil {
-			continue
-		}
-
-		mixedFodderAccurateRatioDataList := make([]string, 0)
-		for _, v := range data.MixedFodderAccurateRatio {
-			mixedFodderAccurateRatioDataList = append(mixedFodderAccurateRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
-			mixedFodderAccurateRatio.DateDay = append(mixedFodderAccurateRatio.DateDay, v.DayTime)
-			maTitleValueList = append(maTitleValueList, v.Ratio)
-		}
-
-		mixedFodderAccurateRatio.DataList = append(mixedFodderAccurateRatio.DataList, mixedFodderAccurateRatioDataList)
-		mixedFodderAccurateRatio.PastureIds = append(mixedFodderAccurateRatio.PastureIds, int32(pastureId))
-		mixedFodderAccurateRatio.PastureName = append(mixedFodderAccurateRatio.PastureName, groupPasture.Name)
-
-		mixedFodderCorrectRatioDataList := make([]string, 0)
-		for _, v := range data.MixedFodderCorrectRatio {
-			mixedFodderCorrectRatioDataList = append(mixedFodderCorrectRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
-			mixedFodderCorrectRatio.DateDay = append(mixedFodderCorrectRatio.DateDay, v.DayTime)
-			mcTitleValueList = append(mcTitleValueList, v.Ratio)
-		}
-
-		mixedFodderCorrectRatio.DataList = append(mixedFodderCorrectRatio.DataList, mixedFodderCorrectRatioDataList)
-		mixedFodderCorrectRatio.PastureIds = append(mixedFodderCorrectRatio.PastureIds, int32(pastureId))
-		mixedFodderCorrectRatio.PastureName = append(mixedFodderCorrectRatio.PastureName, groupPasture.Name)
-
-		sprinkleFodderRatioDataList := make([]string, 0)
-		for _, v := range data.SprinkleFodderAccurateRatio {
-			sprinkleFodderRatioDataList = append(sprinkleFodderRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
-			sprinkleFodderAccurateRatio.DateDay = append(sprinkleFodderAccurateRatio.DateDay, v.DayTime)
-			saTitleValueList = append(saTitleValueList, v.Ratio)
-		}
-
-		sprinkleFodderAccurateRatio.DataList = append(sprinkleFodderAccurateRatio.DataList, sprinkleFodderRatioDataList)
-		sprinkleFodderAccurateRatio.PastureIds = append(sprinkleFodderAccurateRatio.PastureIds, int32(pastureId))
-		sprinkleFodderAccurateRatio.PastureName = append(sprinkleFodderAccurateRatio.PastureName, groupPasture.Name)
-
-		sprinkleFodderCorrectRatioDataList := make([]string, 0)
-		for _, v := range data.SprinkleFodderCorrectRatio {
-			sprinkleFodderCorrectRatioDataList = append(sprinkleFodderCorrectRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
-			sprinkleFodderCorrectRatio.DateDay = append(sprinkleFodderCorrectRatio.DateDay, v.DayTime)
-			scTitleValueList = append(scTitleValueList, v.Ratio)
-		}
-
-		sprinkleFodderCorrectRatio.DataList = append(sprinkleFodderCorrectRatio.DataList, sprinkleFodderCorrectRatioDataList)
-		sprinkleFodderCorrectRatio.PastureIds = append(sprinkleFodderCorrectRatio.PastureIds, int32(pastureId))
-		sprinkleFodderCorrectRatio.PastureName = append(sprinkleFodderCorrectRatio.PastureName, groupPasture.Name)
+	dashboardTopData1 := &model.Chart1{
+		MixedFodderAccurateRatio: &model.PastureTopData1{
+			Title: make([]string, 0),
+			Ratio: make([]float64, 0),
+		},
+		MixedFodderCorrectRatio: &model.PastureTopData1{
+			Title: make([]string, 0),
+			Ratio: make([]float64, 0),
+		},
+		SprinkleFodderAccurateRatio: &model.PastureTopData1{
+			Title: make([]string, 0),
+			Ratio: make([]float64, 0),
+		},
+		SprinkleFodderCorrectRatio: &model.PastureTopData1{
+			Title: make([]string, 0),
+			Ratio: make([]float64, 0),
+		},
+	}
+	pastureDayTimeRatioList := make(map[operationPb.DashboardTopType_Kind][]*model.PastureDayTimeRatio)
+
+	for _, v := range dashboardTopData.MixedFodderCorrectRatio {
+		pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE] =
+			append(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE],
+				&model.PastureDayTimeRatio{
+					PastureId:   v.PastureId,
+					PastureName: v.PastureName,
+					Ratio:       v.Ratio,
+				})
+		dashboardTopData1.MixedFodderCorrectRatio.Title = append(dashboardTopData1.MixedFodderCorrectRatio.Title, v.PastureName)
+		dashboardTopData1.MixedFodderCorrectRatio.Ratio = append(dashboardTopData1.MixedFodderCorrectRatio.Ratio, v.Ratio)
 	}
 
-	sort.Float64s(maTitleValueList)
-	mixedFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", maTitleValueList[len(maTitleValueList)-1])
-	mixedFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", maTitleValueList[0])
-	mixedFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(maTitleValueList))
-	mixedFodderAccurateRatio.TopOneName = mTopOneName
-
-	sort.Float64s(mcTitleValueList)
-	mixedFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", mcTitleValueList[len(mcTitleValueList)-1])
-	mixedFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", mcTitleValueList[0])
-	mixedFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(mcTitleValueList))
-	mixedFodderCorrectRatio.TopOneName = mTopOneName
-
-	sort.Float64s(saTitleValueList)
-	sprinkleFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", saTitleValueList[len(saTitleValueList)-1])
-	sprinkleFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", saTitleValueList[0])
-	sprinkleFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(saTitleValueList))
-	sprinkleFodderAccurateRatio.TopOneName = mTopOneName
-
-	sort.Float64s(scTitleValueList)
-	sprinkleFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", scTitleValueList[len(scTitleValueList)-1])
-	sprinkleFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", scTitleValueList[0])
-	sprinkleFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(scTitleValueList))
-	sprinkleFodderCorrectRatio.TopOneName = mTopOneName
+	for _, v := range dashboardTopData.MixedFodderAccurateRatio {
+		pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT] =
+			append(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT],
+				&model.PastureDayTimeRatio{
+					PastureId:   v.PastureId,
+					PastureName: v.PastureName,
+					Ratio:       v.Ratio,
+				})
+		dashboardTopData1.MixedFodderAccurateRatio.Title = append(dashboardTopData1.MixedFodderAccurateRatio.Title, v.PastureName)
+		dashboardTopData1.MixedFodderAccurateRatio.Ratio = append(dashboardTopData1.MixedFodderAccurateRatio.Ratio, v.Ratio)
+	}
 
-	chart := &model.Chart{
-		MixedFodderAccurateRatio:    mixedFodderAccurateRatio,
-		MixedFodderCorrectRatio:     mixedFodderCorrectRatio,
-		SprinkleFodderAccurateRatio: sprinkleFodderAccurateRatio,
-		SprinkleFodderCorrectRatio:  sprinkleFodderCorrectRatio,
+	for _, v := range dashboardTopData.SprinkleFodderAccurateRatio {
+		pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE] =
+			append(pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE],
+				&model.PastureDayTimeRatio{
+					PastureId:   v.PastureId,
+					PastureName: v.PastureName,
+					Ratio:       v.Ratio,
+				})
+		dashboardTopData1.SprinkleFodderAccurateRatio.Title = append(dashboardTopData1.SprinkleFodderAccurateRatio.Title, v.PastureName)
+		dashboardTopData1.SprinkleFodderAccurateRatio.Ratio = append(dashboardTopData1.SprinkleFodderAccurateRatio.Ratio, v.Ratio)
 	}
 
-	res.Data.Chart = chart
-	res.Data.Table = s.TitleList(ctx, pastureAnalysisAccuracy)
+	for _, v := range dashboardTopData.SprinkleFodderCorrectRatio {
+		pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT] =
+			append(pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT],
+				&model.PastureDayTimeRatio{
+					PastureId:   v.PastureId,
+					PastureName: v.PastureName,
+					Ratio:       v.Ratio,
+				})
+		dashboardTopData1.SprinkleFodderCorrectRatio.Title = append(dashboardTopData1.SprinkleFodderCorrectRatio.Title, v.PastureName)
+		dashboardTopData1.SprinkleFodderCorrectRatio.Ratio = append(dashboardTopData1.SprinkleFodderCorrectRatio.Ratio, v.Ratio)
+	}
+	// 排序 最大值。最小值。中位数
+	sort.Slice(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE], func(i, j int) bool {
+		return pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE][i].Ratio < pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE][j].Ratio
+	})
+	sort.Slice(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT], func(i, j int) bool {
+		return pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT][i].Ratio < pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT][j].Ratio
+	})
+	sort.Slice(pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE], func(i, j int) bool {
+		return pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE][i].Ratio < pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE][j].Ratio
+	})
+	sort.Slice(pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT], func(i, j int) bool {
+		return pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT][i].Ratio < pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT][j].Ratio
+	})
+	// 混料准确率
+	dashboardTopData1.MixedFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE][len(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE])-1].Ratio)
+	dashboardTopData1.MixedFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE][0].Ratio)
+	dashboardTopData1.MixedFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", getPastureDayTimeRatioMiddleValue(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE]))
+	dashboardTopData1.MixedFodderAccurateRatio.TopOneName = pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE][len(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE])-1].PastureName
+
+	// 混料正确率
+	dashboardTopData1.MixedFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT][len(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT])-1].Ratio)
+	dashboardTopData1.MixedFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT][0].Ratio)
+	dashboardTopData1.MixedFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", getPastureDayTimeRatioMiddleValue(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT]))
+	dashboardTopData1.MixedFodderCorrectRatio.TopOneName = pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT][len(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT])-1].PastureName
+
+	// 散料准确率
+	dashboardTopData1.SprinkleFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE][len(pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE])-1].Ratio)
+	dashboardTopData1.SprinkleFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE][0].Ratio)
+	dashboardTopData1.SprinkleFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", getPastureDayTimeRatioMiddleValue(pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE]))
+	dashboardTopData1.SprinkleFodderAccurateRatio.TopOneName = pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE][len(pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE])-1].PastureName
+
+	// 散料正确率
+	dashboardTopData1.SprinkleFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT][len(pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT])-1].Ratio)
+	dashboardTopData1.SprinkleFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT][0].Ratio)
+	dashboardTopData1.SprinkleFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", getPastureDayTimeRatioMiddleValue(pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT]))
+	dashboardTopData1.SprinkleFodderCorrectRatio.TopOneName = pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT][len(pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT])-1].PastureName
+
+	res.Data.Chart = dashboardTopData1
 	return res, nil
 }
 
@@ -289,28 +305,35 @@ func (s *StoreEntry) TopPasture(ctx context.Context, req *operationPb.SearchAnal
 	res := &model.GetPastureTopResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: &model.PastureTop{
-			MixedFodderAccurateRatio:    make([]*model.PastureTopData, 0),
-			MixedFodderCorrectRatio:     make([]*model.PastureTopData, 0),
-			SprinkleFodderAccurateRatio: make([]*model.PastureTopData, 0),
-			SprinkleFodderCorrectRatio:  make([]*model.PastureTopData, 0),
-		},
+		Data: nil,
 	}
-	analysisAccuracy, err := s.PasturePrefAnalysisData(ctx, req)
+	dashboardTopData, _, err := s.DashboardTopPasture(ctx, req)
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	res.Data = dashboardTopData
+	return res, nil
+}
+
+func (s *StoreEntry) DashboardTopPasture(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.PastureTop, map[int64]*model.PastureAnalysisAccuracyData, error) {
+	dashboardTopData := &model.PastureTop{
+		MixedFodderAccurateRatio:    make([]*model.PastureTopData, 0),
+		MixedFodderCorrectRatio:     make([]*model.PastureTopData, 0),
+		SprinkleFodderAccurateRatio: make([]*model.PastureTopData, 0),
+		SprinkleFodderCorrectRatio:  make([]*model.PastureTopData, 0),
+	}
+	analysisAccuracy, err := s.PasturePrefAnalysisData(ctx, req)
+	if err != nil {
+		return nil, nil, xerr.WithStack(err)
+	}
 
-	mixedFodderAccurateRatio := make([]*model.PastureTopData, 0)
-	mixedFodderCorrectRatio := make([]*model.PastureTopData, 0)
-	sprinkleFodderAccurateRatio := make([]*model.PastureTopData, 0)
-	sprinkleFodderCorrectRatio := make([]*model.PastureTopData, 0)
 	for pastureId, data := range analysisAccuracy {
 		groupPasture, err := s.GetGroupPastureListById(ctx, pastureId)
 		if err != nil {
 			zaplog.Error("TopPasture", zap.Any("GetGroupPastureListById", pastureId), zap.Any("err", err))
 			continue
 		}
+
 		if data == nil {
 			continue
 		}
@@ -319,54 +342,67 @@ func (s *StoreEntry) TopPasture(ctx context.Context, req *operationPb.SearchAnal
 		for _, v := range data.MixedFodderAccurateRatio {
 			allMaRatio += v.Ratio
 		}
-		mixedFodderAccurateRatio = append(mixedFodderAccurateRatio, &model.PastureTopData{
+		dashboardTopData.MixedFodderAccurateRatio = append(dashboardTopData.MixedFodderAccurateRatio, &model.PastureTopData{
+			PastureId:   pastureId,
 			PastureName: groupPasture.Name,
-			Ratio:       allMaRatio / float64(len(data.MixedFodderAccurateRatio)),
+			Ratio:       tool.Decimal(allMaRatio / float64(len(data.MixedFodderAccurateRatio))),
 		})
 
 		for _, v := range data.MixedFodderCorrectRatio {
 			allMcRatio += v.Ratio
 		}
-		mixedFodderCorrectRatio = append(mixedFodderCorrectRatio, &model.PastureTopData{
+		dashboardTopData.MixedFodderCorrectRatio = append(dashboardTopData.MixedFodderCorrectRatio, &model.PastureTopData{
+			PastureId:   pastureId,
 			PastureName: groupPasture.Name,
-			Ratio:       allMaRatio / float64(len(data.MixedFodderCorrectRatio)),
+			Ratio:       tool.Decimal(allMcRatio / float64(len(data.MixedFodderCorrectRatio))),
 		})
 
 		for _, v := range data.SprinkleFodderAccurateRatio {
 			allSaRatio += v.Ratio
 		}
-		sprinkleFodderAccurateRatio = append(sprinkleFodderAccurateRatio, &model.PastureTopData{
+		dashboardTopData.SprinkleFodderAccurateRatio = append(dashboardTopData.SprinkleFodderAccurateRatio, &model.PastureTopData{
+			PastureId:   pastureId,
 			PastureName: groupPasture.Name,
-			Ratio:       allSaRatio / float64(len(data.SprinkleFodderAccurateRatio)),
+			Ratio:       tool.Decimal(allSaRatio / float64(len(data.SprinkleFodderAccurateRatio))),
 		})
 
 		for _, v := range data.SprinkleFodderCorrectRatio {
 			allScRatio += v.Ratio
 		}
-		sprinkleFodderCorrectRatio = append(sprinkleFodderCorrectRatio, &model.PastureTopData{
+		dashboardTopData.SprinkleFodderCorrectRatio = append(dashboardTopData.SprinkleFodderCorrectRatio, &model.PastureTopData{
+			PastureId:   pastureId,
 			PastureName: groupPasture.Name,
-			Ratio:       allScRatio / float64(len(data.SprinkleFodderCorrectRatio)),
+			Ratio:       tool.Decimal(allScRatio / float64(len(data.SprinkleFodderCorrectRatio))),
 		})
 	}
 
-	sort.Slice(mixedFodderAccurateRatio, func(i, j int) bool {
-		return mixedFodderAccurateRatio[i].Ratio > mixedFodderAccurateRatio[j].Ratio
+	sort.Slice(dashboardTopData.MixedFodderAccurateRatio, func(i, j int) bool {
+		return dashboardTopData.MixedFodderAccurateRatio[i].Ratio > dashboardTopData.MixedFodderAccurateRatio[j].Ratio
 	})
-	sort.Slice(mixedFodderCorrectRatio, func(i, j int) bool {
-		return mixedFodderCorrectRatio[i].Ratio > mixedFodderCorrectRatio[j].Ratio
+	sort.Slice(dashboardTopData.MixedFodderCorrectRatio, func(i, j int) bool {
+		return dashboardTopData.MixedFodderCorrectRatio[i].Ratio > dashboardTopData.MixedFodderCorrectRatio[j].Ratio
 	})
-	sort.Slice(sprinkleFodderAccurateRatio, func(i, j int) bool {
-		return sprinkleFodderAccurateRatio[i].Ratio > sprinkleFodderAccurateRatio[j].Ratio
+	sort.Slice(dashboardTopData.SprinkleFodderAccurateRatio, func(i, j int) bool {
+		return dashboardTopData.SprinkleFodderAccurateRatio[i].Ratio > dashboardTopData.SprinkleFodderAccurateRatio[j].Ratio
 	})
-	sort.Slice(sprinkleFodderCorrectRatio, func(i, j int) bool {
-		return sprinkleFodderCorrectRatio[i].Ratio > sprinkleFodderCorrectRatio[j].Ratio
+	sort.Slice(dashboardTopData.SprinkleFodderCorrectRatio, func(i, j int) bool {
+		return dashboardTopData.SprinkleFodderCorrectRatio[i].Ratio > dashboardTopData.SprinkleFodderCorrectRatio[j].Ratio
 	})
 
-	res.Data.MixedFodderAccurateRatio = mixedFodderAccurateRatio
-	res.Data.MixedFodderCorrectRatio = mixedFodderCorrectRatio
-	res.Data.SprinkleFodderAccurateRatio = sprinkleFodderAccurateRatio
-	res.Data.SprinkleFodderCorrectRatio = sprinkleFodderCorrectRatio
-	return res, nil
+	if req.DashboardTopType > 0 {
+		switch req.DashboardTopType {
+		case operationPb.DashboardTopType_MIXED_ACCURATE:
+			dashboardTopData.MixedFodderAccurateRatio = dashboardTopRand(req, dashboardTopData.MixedFodderAccurateRatio)
+		case operationPb.DashboardTopType_MIXED_CORRECT:
+			dashboardTopData.MixedFodderCorrectRatio = dashboardTopRand(req, dashboardTopData.MixedFodderCorrectRatio)
+		case operationPb.DashboardTopType_SPRINKLE_ACCURATE:
+			dashboardTopData.SprinkleFodderAccurateRatio = dashboardTopRand(req, dashboardTopData.SprinkleFodderAccurateRatio)
+		case operationPb.DashboardTopType_Sprinkle_CORRECT:
+			dashboardTopData.SprinkleFodderCorrectRatio = dashboardTopRand(req, dashboardTopData.SprinkleFodderCorrectRatio)
+		}
+	}
+
+	return dashboardTopData, analysisAccuracy, nil
 }
 
 func (s *StoreEntry) TitleList(ctx context.Context, pastureAnalysisList map[int64]*model.PastureAnalysisAccuracyData) *model.Table {
@@ -516,40 +552,141 @@ func (s *StoreEntry) SprinkleFeedTime(ctx context.Context, req *operationPb.Spri
 			TableList: make([]*model.SprinkleFeedTimeTable, 0),
 		},
 	}
-	pastureSprinkleDataList, err := s.PastureSprinkleFeedTime(ctx, req)
+	pastureSprinkleDataList, pastureList, err := s.PastureSprinkleFeedTime(ctx, req)
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
 
 	tableList := make([]*model.SprinkleFeedTimeTable, 0)
-	infoSprinkleNumber, errorSprinkleNumber := make([]int32, 0), make([]int32, 0)
-	for pastureName, data := range pastureSprinkleDataList {
-		sprinkleFeedTimeList := make(map[int32]map[int32][]int64, 0)
-		for _, v := range data {
-			tableList = append(tableList, &model.SprinkleFeedTimeTable{
-				PastureName:             pastureName,
-				BarnName:                v.FName,
-				ClassNumber:             fmt.Sprintf("%d", v.Times),
-				RealitySprinkleFeedTime: tool.TimeSub(v.InTime, v.ProcessTime),
-			})
-			realityTime := tool.TimeSub(v.InTime, v.ProcessTime)
-			realityTimeUnix, _ := time.Parse(model.LayoutTime, realityTime)
-			if sprinkleFeedTimeList[v.FBarId] == nil {
-				sprinkleFeedTimeList[v.FBarId] = make(map[int32][]int64, 0)
-			}
-			sprinkleFeedTimeList[v.FBarId][v.Times] = append(sprinkleFeedTimeList[v.FBarId][v.Times], realityTimeUnix.Unix())
+	infoSprinkleNumber, errorSprinkleNumber, pastureIds := make([]int32, 0), make([]int32, 0), make([]int, 0)
+
+	for pastureId, _ := range pastureSprinkleDataList {
+		pastureIds = append(pastureIds, int(pastureId))
+	}
+
+	sort.Ints(pastureIds)
+	pastureInfo := &model.GroupPasture{}
+	for _, pastureId := range pastureIds {
+		if pastureData, ok := pastureList[int64(pastureId)]; ok {
+			pastureInfo = pastureData
 		}
-		res.Data.Chart.Title = append(res.Data.Chart.Title, pastureName)
 
-		infoNumber, errNumber := sprinkleExecTimeAnalysis(sprinkleFeedTimeList)
-		infoSprinkleNumber = append(infoSprinkleNumber, infoNumber)
-		errorSprinkleNumber = append(errorSprinkleNumber, errNumber)
+		if data, ok := pastureSprinkleDataList[int64(pastureId)]; ok {
+			sprinkleFeedTimeList := make(map[int32]map[int32][]int64, 0)
+			for _, v := range data {
+				tableList = append(tableList, &model.SprinkleFeedTimeTable{
+					PastureName:             pastureInfo.Name,
+					BarnName:                v.FName,
+					ClassNumber:             fmt.Sprintf("%d", v.Times),
+					RealitySprinkleFeedTime: tool.TimeSub(v.InTime, v.ProcessTime),
+				})
+				realityTime := tool.TimeSub(v.InTime, v.ProcessTime)
+				realityTimeUnix, _ := time.Parse(model.LayoutTime, realityTime)
+				if sprinkleFeedTimeList[v.FBarId] == nil {
+					sprinkleFeedTimeList[v.FBarId] = make(map[int32][]int64, 0)
+				}
+				sprinkleFeedTimeList[v.FBarId][v.Times] = append(sprinkleFeedTimeList[v.FBarId][v.Times], realityTimeUnix.Unix())
+			}
+
+			res.Data.Chart.Title = append(res.Data.Chart.Title, pastureInfo.Name)
+			infoNumber, errNumber := sprinkleExecTimeAnalysis(sprinkleFeedTimeList)
+			infoSprinkleNumber = append(infoSprinkleNumber, infoNumber)
+			errorSprinkleNumber = append(errorSprinkleNumber, errNumber)
+		}
 	}
+
 	res.Data.Chart.SprinkleNumberList = append(res.Data.Chart.SprinkleNumberList, infoSprinkleNumber, errorSprinkleNumber)
 	res.Data.TableList = tableList
 	return res, nil
 }
 
+func (s *StoreEntry) FeedMixedAndTmrName(ctx context.Context, req *operationPb.MixedCategoryTmrName) (*model.PastureCommonResponse, error) {
+	groupPasture, err := s.GetGroupPastureListById(ctx, int64(req.PastureId))
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	pastureId := req.PastureId
+	if groupPasture.PastureId > 0 {
+		pastureId = int32(groupPasture.PastureId)
+	}
+	body := &model.PastureCommonRequest{
+		Name:       req.ApiName,
+		ReturnType: "Map",
+		ParamMaps: &model.MixedCategoryTmrNameParams{
+			PastureId: fmt.Sprintf("%d", pastureId),
+			StartTime: req.StartTime,
+			EndTime:   req.EndTime,
+		},
+	}
+	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
+	if err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	return response, nil
+}
+
+func (s *StoreEntry) FeedTemplateHistory(ctx context.Context, req *operationPb.FeedTemplateHistoryRequest) (*model.PastureFeedTemplateHistoryResponse, error) {
+	groupPasture, err := s.GetGroupPastureListById(ctx, int64(req.PastureId))
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	pastureId := req.PastureId
+	if groupPasture.PastureId > 0 {
+		pastureId = int32(groupPasture.PastureId)
+	}
+
+	body := &model.PastureFeedTemplateHistoryRequest{
+		PastureId: fmt.Sprintf("%d", pastureId),
+		FTid:      int64(req.Ftid),
+		StartDate: req.StartTime,
+		EndDate:   req.EndTime,
+	}
+	response := &model.PastureFeedTemplateHistoryResponse{}
+	if err = s.PastureHttpClient(ctx, model.UrlFeedTemplateHistory, int64(req.PastureId), body, response); err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	return response, nil
+}
+
+func (s *StoreEntry) BarnHistory(ctx context.Context, req *operationPb.BarnHistoryRequest) (*model.PastureBarnHistoryResponse, error) {
+	_, err := s.GetGroupPastureListById(ctx, int64(req.PastureId))
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	body := &model.PastureBarnHistoryRequest{
+		BarName:   req.BarnName,
+		StartDate: req.StartTime,
+		EndDate:   req.EndTime,
+	}
+	response := &model.PastureBarnHistoryResponse{}
+	if err = s.PastureHttpClient(ctx, model.UrlBarnHistory, int64(req.PastureId), body, response); err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	return response, nil
+}
+
+func (s *StoreEntry) SpillageAllHistory(ctx context.Context, req *operationPb.BarnHistoryRequest) (*model.PastureBarnHistoryResponse, error) {
+	groupPasture, err := s.GetGroupPastureListById(ctx, int64(req.PastureId))
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	pastureId := req.PastureId
+	if groupPasture.PastureId > 0 {
+		pastureId = int32(groupPasture.PastureId)
+	}
+	body := &model.PastureBarnHistoryRequest{
+		PastureId: fmt.Sprintf("%d", pastureId),
+		BarName:   req.BarnName,
+		StartDate: req.StartTime,
+		EndDate:   req.EndTime,
+	}
+	response := &model.PastureBarnHistoryResponse{}
+	if err = s.PastureHttpClient(ctx, model.UrlSpillageAllHistory, int64(req.PastureId), body, response); err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	return response, nil
+}
+
 func sprinkleExecTimeAnalysis(sprinkleFeedTimeList map[int32]map[int32][]int64) (int32, int32) {
 	var infoSprinkleNumber, errorSprinkleNumber int32 = 0, 0
 	if len(sprinkleFeedTimeList) <= 0 {
@@ -571,3 +708,29 @@ func sprinkleExecTimeAnalysis(sprinkleFeedTimeList map[int32]map[int32][]int64)
 
 	return infoSprinkleNumber, errorSprinkleNumber
 }
+
+func dashboardTopRand(req *operationPb.SearchAnalysisAccuracyRequest, data []*model.PastureTopData) []*model.PastureTopData {
+	if req.TopRandStart < 0 || req.TopRandEnd < 0 || req.TopRandStart > req.TopRandEnd {
+		return data
+	}
+
+	res := make([]*model.PastureTopData, 0)
+	for _, v := range data {
+		if v.Ratio >= float64(req.TopRandStart) && v.Ratio <= float64(req.TopRandEnd) {
+			res = append(res, v)
+		}
+	}
+	return res
+}
+
+func getPastureDayTimeRatioMiddleValue(pastureDayTimeRatio []*model.PastureDayTimeRatio) float64 {
+	if len(pastureDayTimeRatio) <= 0 {
+		return 0
+	}
+	ratioList := make([]float64, 0)
+	for _, v := range pastureDayTimeRatio {
+		ratioList = append(ratioList, v.Ratio)
+	}
+	sort.Float64s(ratioList)
+	return tool.Median(ratioList)
+}

+ 15 - 0
module/backend/edit_record_service.go

@@ -0,0 +1,15 @@
+package backend
+
+import (
+	"context"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+	"kpt-tmr-group/model"
+)
+
+func (s *StoreEntry) GetEditRecordLastGroupId(ctx context.Context) (*model.FeedFormulaEditRecord, error) {
+	editRecord := &model.FeedFormulaEditRecord{}
+	if err := s.DB.Model(new(model.FeedFormulaEditRecord)).Order("group_id desc").Take(editRecord).Error; err != nil {
+		return editRecord, xerr.WithStack(err)
+	}
+	return editRecord, nil
+}

+ 780 - 56
module/backend/feed_service.go

@@ -8,14 +8,15 @@ import (
 	"fmt"
 	"io"
 	"kpt-tmr-group/model"
-	"kpt-tmr-group/pkg/logger/zaplog"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"strconv"
 	"sync"
 	"time"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+
 	"go.uber.org/multierr"
 
 	"github.com/xuri/excelize/v2"
@@ -26,8 +27,16 @@ import (
 const EncodeNumberPrefix = "encode_number"
 
 var PastureDataLogType = map[string]int32{
-	"FeedFormula_Distribute": 1,
-	"FeedFormula_IsModify":   2,
+	"FeedFormula_Distribute":        1,
+	"FeedFormula_IsModify":          2,
+	"FeedFormula_Cancel_Distribute": 3,
+}
+var EditRecodeMap = map[string]string{
+	"forage_name": "饲料名称",
+	"weight":      "重量",
+	"stir_delay":  "搅拌延迟",
+	"allow_error": "允许误差",
+	"sort":        "排序",
 }
 
 // CreateFeedFormula 添加数据
@@ -41,38 +50,373 @@ func (s *StoreEntry) CreateFeedFormula(ctx context.Context, req *operationPb.Add
 
 // EditFeedFormula 编辑数据
 func (s *StoreEntry) EditFeedFormula(ctx context.Context, req *operationPb.AddFeedFormulaRequest) error {
-
-	forage := model.FeedFormula{Id: int64(req.Id)}
-	if err := s.DB.Where("is_delete = ?", operationPb.IsShow_OK).First(&forage).Error; err != nil {
+	feedFormula := &model.FeedFormula{Id: int64(req.Id)}
+	if err := s.DB.Where("is_delete = ?", operationPb.IsShow_OK).First(feedFormula).Error; err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
 			return xerr.Custom("该数据不存在")
 		}
 		return xerr.WithStack(err)
 	}
+	// 更新版本号
+	defer s.UpdateFeedFormalVersion(ctx, feedFormula)
+	if err := s.DB.Model(new(model.FeedFormula)).
+		Omit("is_show", "is_delete", "encode_number", "formula_type_id",
+			"formula_type_name", "data_source", "is_modify").
+		Where("id = ?", req.Id).
+		Updates(map[string]interface{}{
+			"name":                 req.Name,
+			"colour":               req.Colour,
+			"cattle_category_id":   req.CattleCategoryId,
+			"cattle_category_name": req.CattleCategoryName,
+			"data_source_id":       req.DataSourceId,
+			"data_source_name":     req.DataSourceName,
+			"remarks":              req.Remarks,
+		}).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
 
-	updateData := &model.FeedFormula{
-		Name:               req.Name,
-		Colour:             req.Colour,
-		CattleCategoryId:   req.CattleCategoryId,
-		CattleCategoryName: req.CattleCategoryName,
-		FormulaTypeId:      req.FormulaTypeId,
-		FormulaTypeName:    req.FormulaTypeName,
-		DataSourceId:       req.DataSourceId,
-		DataSourceName:     req.DataSourceName,
-		Remarks:            req.Remarks,
-		IsShow:             req.IsShow,
+// AddFeedByFeedFormula 配方添加饲料
+func (s *StoreEntry) AddFeedByFeedFormula(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) error {
+	feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
+	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	// 更新修改记录
+	defer s.addFeedFormulaDetailAddRecode(ctx, req)
+	// 更新版本号
+	defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
+	insertData := make([]*model.FeedFormulaDetail, 0)
+	for _, v := range req.List {
+		feedData := &model.Forage{Id: int64(v.ForageId)}
+		if err := s.DB.Model(new(model.Forage)).First(feedData).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		if v.AllowError > v.StirDelay {
+			return xerr.Customf("允许误差不能大于搅拌延迟")
+		}
+		insertData = append(insertData, &model.FeedFormulaDetail{
+			PastureName:     "集团",
+			FeedFormulaId:   int64(req.FeedFormulaId),
+			ForageId:        int64(v.ForageId),
+			ForageName:      v.ForageName,
+			ForageGroupName: v.ForageGroupName,
+			Weight:          int32(v.Weight * 100),
+			StirDelay:       v.StirDelay,
+			AllowError:      v.AllowError,
+			IsShow:          operationPb.IsShow_OK,
+			IsModify:        v.IsModify,
+			Sort:            v.Sort,
+		})
 	}
 
-	if err := s.DB.Model(new(model.FeedFormula)).
-		Omit("is_show", "is_delete", "encode_number", "formula_type_id", "formula_type_name", "data_source", "version", "is_modify").
-		Where("id = ?", req.Id).
-		Updates(updateData).Error; err != nil {
+	if err := s.DB.Model(new(model.FeedFormulaDetail)).Save(insertData).Error; err != nil {
 		return xerr.WithStack(err)
 	}
+	return nil
+}
+
+// addFeedFormulaDetailAddRecode 添加配方记录
+func (s *StoreEntry) addFeedFormulaDetailAddRecode(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) {
+	editRecord, _ := s.GetEditRecordLastGroupId(ctx)
+	editRecordList := make([]*model.FeedFormulaEditRecord, 0)
+
+	operationName := s.GetCurrentUserName(ctx)
+	for _, v := range req.List {
+		editRecordList = append(editRecordList, &model.FeedFormulaEditRecord{
+			FeedFormulaId: int64(req.FeedFormulaId),
+			PastureName:   "集团",
+			ForageName:    v.ForageName,
+			Status:        operationPb.FeedFormulaEditRecordType_INSERT,
+			GroupId:       editRecord.GroupId + 1,
+			OperationName: operationName,
+		})
+	}
+
+	if err := s.CreateFeedFormulaEditRecord(ctx, editRecordList); err != nil {
+		zaplog.Error("deleteFeedFormulaDetailAddRecode", zap.Any("CreateFeedFormulaEditRecord", err))
+	}
+}
+
+// EditFeedByFeedFormula 配方饲料编辑
+func (s *StoreEntry) EditFeedByFeedFormula(ctx context.Context, req *operationPb.AddFeedFormulaDetail) error {
+	feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
+	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	feedFormulaDetail := &model.FeedFormulaDetail{Id: int64(req.Id)}
+	if err := s.DB.Model(new(model.FeedFormulaDetail)).
+		Where("is_show = ?", operationPb.IsShow_OK).
+		First(feedFormulaDetail).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	// 添加修改记录
+	defer s.editFeedFormulaDetailAddRecode(ctx, req, feedFormulaDetail)
+	// 更新版本号
+	defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
+	// 更新数据
+	updateData := &model.FeedFormulaDetail{
+		ForageId:        int64(req.ForageId),
+		ForageName:      req.ForageName,
+		ForageGroupName: req.ForageGroupName,
+		Weight:          int32(req.Weight * 100),
+		StirDelay:       req.StirDelay,
+		AllowError:      req.AllowError,
+		Sort:            req.Sort,
+	}
+	if err := s.DB.Model(new(model.FeedFormulaDetail)).Where("id = ?", req.Id).Updates(updateData).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+
+	return nil
+}
+
+// EditFeedFormulaDetailAddRecode 更新饲料配方修改记录
+func (s *StoreEntry) editFeedFormulaDetailAddRecode(ctx context.Context, req *operationPb.AddFeedFormulaDetail, feedFormulaDetail *model.FeedFormulaDetail) {
+	editRecordList := make([]*model.FeedFormulaEditRecord, 0)
+
+	editRecordData := &model.FeedFormulaEditRecord{
+		FeedFormulaId: int64(req.FeedFormulaId),
+		PastureName:   "集团",
+		ForageName:    req.ForageName,
+		Status:        operationPb.FeedFormulaEditRecordType_UPDATE,
+	}
 
+	operationName := s.GetCurrentUserName(ctx)
+	editRecordData.OperationName = operationName
+
+	lastGroupIdData := &model.FeedFormulaEditRecord{}
+	if err := s.DB.Model(new(model.FeedFormulaEditRecord)).
+		Order("group_id desc").
+		First(&lastGroupIdData).Error; err != nil {
+		zaplog.Error("EditFeedByFeedFormula", zap.Any("lastGroupIdData", err))
+	} else {
+		editRecordData.GroupId = lastGroupIdData.GroupId + 1
+		editRecordData.BeforeValue = lastGroupIdData.BeforeValue
+	}
+
+	if feedFormulaDetail.ForageName != req.ForageName {
+		editRecordData.FieldName = EditRecodeMap["forage_name"]
+		editRecordData.BeforeValue = lastGroupIdData.ForageName
+		editRecordData.AfterValue = req.ForageName
+		editRecordList = append(editRecordList, editRecordData)
+	}
+
+	if feedFormulaDetail.Weight != int32(req.Weight*100) {
+		editRecordData.FieldName = EditRecodeMap["weight"]
+		editRecordData.AfterValue = fmt.Sprintf("%d", int32(req.Weight*100))
+		editRecordList = append(editRecordList, editRecordData)
+	}
+
+	if feedFormulaDetail.AllowError != req.AllowError {
+		editRecordData.FieldName = EditRecodeMap["allow_error"]
+		editRecordData.AfterValue = fmt.Sprintf("%d", req.AllowError)
+		editRecordList = append(editRecordList, editRecordData)
+	}
+
+	if feedFormulaDetail.StirDelay != req.StirDelay {
+		editRecordData.FieldName = EditRecodeMap["stir_delay"]
+		editRecordData.AfterValue = fmt.Sprintf("%d", req.StirDelay)
+		editRecordList = append(editRecordList, editRecordData)
+	}
+
+	if feedFormulaDetail.Sort != req.Sort {
+		editRecordData.FieldName = EditRecodeMap["sort"]
+		editRecordData.AfterValue = fmt.Sprintf("%d", req.Sort)
+		editRecordList = append(editRecordList, editRecordData)
+	}
+
+	if err := s.CreateFeedFormulaEditRecord(ctx, editRecordList); err != nil {
+		zaplog.Error("EditFeedByFeedFormula", zap.Any("CreateFeedFormulaEditRecord", err))
+	}
+}
+
+// CreateFeedFormulaEditRecord 创建配方修改记录
+func (s *StoreEntry) CreateFeedFormulaEditRecord(ctx context.Context, req []*model.FeedFormulaEditRecord) error {
+	if req == nil {
+		return nil
+	}
+	if err := s.DB.Model(new(model.FeedFormulaEditRecord)).Save(req).Error; err != nil {
+		return xerr.WithStack(err)
+	}
 	return nil
 }
 
+// FeedFormulaDetailBySort 配方饲料排序
+func (s *StoreEntry) FeedFormulaDetailBySort(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) error {
+	feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
+	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	// 更新版本号
+	defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
+	tx := s.DB.Transaction(func(tx *gorm.DB) error {
+		for _, v := range req.List {
+			if err := tx.Model(new(model.FeedFormulaDetail)).
+				Where("id = ?", v.Id).
+				Updates(map[string]interface{}{
+					"sort": v.Sort,
+				}).Error; err != nil {
+				return xerr.WithStack(err)
+			}
+		}
+		return nil
+	})
+	return tx
+}
+
+// FeedFormulaDetailIsModify 配方饲料是否可修改
+func (s *StoreEntry) FeedFormulaDetailIsModify(ctx context.Context, req *operationPb.AddFeedFormulaDetail) error {
+	feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
+	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	// 更新版本号
+	defer s.UpdateFeedFormalVersion(ctx, feedFormulaData)
+
+	return s.DB.Model(new(model.FeedFormulaDetail)).
+		Where("id = ?", req.Id).
+		Where("feed_formula_id = ?", req.FeedFormulaId).
+		Updates(map[string]interface{}{
+			"is_modify": req.IsModify,
+		}).Error
+}
+
+// DeleteFeedFormulaDetail 配方删除饲料
+func (s *StoreEntry) DeleteFeedFormulaDetail(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) error {
+	feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
+	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+
+	// 增加配方记录
+	defer s.deleteFeedFormulaDetailAddRecode(ctx, req)
+
+	tr := s.DB.Transaction(func(tx *gorm.DB) error {
+		for _, v := range req.List {
+			if err := tx.Model(new(model.FeedFormulaDetail)).
+				Where("id = ?", v.Id).
+				Updates(map[string]interface{}{
+					"is_show": operationPb.IsShow_NO,
+				}).Error; err != nil {
+				return xerr.WithStack(err)
+			}
+		}
+		return nil
+	})
+	return tr
+}
+
+// deleteFeedFormulaDetailAddRecode 删除配方增加修改记录
+func (s *StoreEntry) deleteFeedFormulaDetailAddRecode(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) {
+	editRecordList := make([]*model.FeedFormulaEditRecord, 0)
+	for _, v := range req.List {
+		editRecordList = append(editRecordList, &model.FeedFormulaEditRecord{
+			FeedFormulaId: int64(req.FeedFormulaId),
+			PastureName:   "集团",
+			ForageName:    v.ForageName,
+			Status:        operationPb.FeedFormulaEditRecordType_DELETE,
+		})
+	}
+
+	if err := s.CreateFeedFormulaEditRecord(ctx, editRecordList); err != nil {
+		zaplog.Error("deleteFeedFormulaDetailAddRecode", zap.Any("CreateFeedFormulaEditRecord", err))
+	}
+}
+
+// SearchFeedFormulaDetail 查询配方饲料详情
+func (s *StoreEntry) SearchFeedFormulaDetail(ctx context.Context, req *operationPb.AddFeedFormulaDetail) (*operationPb.FeedFormulaDetailResponse, error) {
+	feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
+	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Debug().Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	var count int64
+	feedFormulaDetailList := make([]*model.FeedFormulaDetail, 0)
+
+	pref := s.DB.Model(new(model.FeedFormulaDetail)).
+		Where("is_show = ?", operationPb.IsShow_OK).
+		Where("feed_formula_id = ?", req.FeedFormulaId)
+
+	if req.ForageName != "" {
+		pref.Where("forage_name = ?", req.ForageName)
+	}
+
+	if req.ForageGroupName != "" {
+		pref.Where("forage_group_name = ?", req.ForageGroupName)
+	}
+
+	if req.Weight > 0 {
+		pref.Where("weight = ?", int64(req.Weight*100))
+	}
+
+	if req.IsLockCowCountRatio > 0 {
+		pref.Where("is_lock_cow_count_ratio = ?", req.IsLockCowCountRatio)
+	}
+
+	if req.StirDelay > 0 {
+		pref.Where("stir_delay = ?", req.StirDelay)
+	}
+
+	if req.Sort > 0 {
+		pref.Where("sort = ?", req.Sort)
+	}
+
+	if err := pref.Order("sort").Count(&count).Limit(int(req.Pagination.PageSize)).
+		Offset(int(req.Pagination.PageOffset)).Find(&feedFormulaDetailList).Debug().Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return &operationPb.FeedFormulaDetailResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: model.FeedFormulaDetailSlice(feedFormulaDetailList).ToPB(),
+	}, nil
+
+}
+
+// MixedFeedFormula 合成预混料
+func (s *StoreEntry) MixedFeedFormula(ctx context.Context, req *operationPb.MixedFeedFormulaRequest) error {
+
+	feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
+	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	if feedFormulaData.FormulaTypeId == operationPb.FormulaType_PREMIXED_FORMULA {
+		return xerr.Customf("预混料配方不能合成预混料")
+	}
+
+	tr := s.DB.Transaction(func(tx *gorm.DB) error {
+		newFeedFormulaData := model.NewNewFeedFormulaByMixed(req)
+		newFeedFormulaData.EncodeNumber = s.EncodeNumber(ctx)
+
+		if err := s.DB.Model(new(model.FeedFormula)).Create(newFeedFormulaData).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		feedFormulaDetailList := make([]*model.FeedFormulaDetail, 0)
+		for _, v := range req.FeedList {
+			feedFormulaDetailList = append(feedFormulaDetailList, &model.FeedFormulaDetail{
+				PastureName:     "集团",
+				FeedFormulaId:   newFeedFormulaData.Id,
+				ForageId:        int64(v.ForageId),
+				ForageName:      v.ForageName,
+				ForageGroupName: v.ForageGroupName,
+				Weight:          int32(v.Weight * 100),
+				StirDelay:       v.StirDelay,
+				AllowError:      v.AllowError,
+				IsShow:          operationPb.IsShow_OK,
+				Sort:            v.Sort,
+			})
+		}
+		if err := s.DB.Model(new(model.FeedFormulaDetail)).Save(feedFormulaDetailList).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		return nil
+	})
+	return tr
+}
+
 // SearchFeedFormulaList 查询数据列表
 func (s *StoreEntry) SearchFeedFormulaList(ctx context.Context, req *operationPb.SearchFeedFormulaRequest) (*operationPb.SearchFeedFormulaListResponse, error) {
 	feedFormula := make([]*model.FeedFormula, 0)
@@ -120,6 +464,19 @@ func (s *StoreEntry) SearchFeedFormulaList(ctx context.Context, req *operationPb
 	}, nil
 }
 
+// SearchFeedFormulaById 查询指定数据
+func (s *StoreEntry) SearchFeedFormulaById(ctx context.Context, foodFormulaId int64) (*model.FeedFormula, error) {
+	feedFormula := &model.FeedFormula{}
+	if err := s.DB.Model(new(model.FeedFormula)).
+		Where("is_delete = ?", operationPb.IsShow_OK).
+		Where("id = ?", foodFormulaId).
+		First(feedFormula).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return feedFormula, nil
+}
+
 // IsShowFeedFormula 是否启用和是否可修改
 func (s *StoreEntry) IsShowFeedFormula(ctx context.Context, req *operationPb.IsShowModifyFeedFormula) error {
 	feedFormula := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
@@ -266,7 +623,7 @@ func (s *StoreEntry) ExcelExportFeedFormula(ctx context.Context, req *operationP
 	for i, item := range res.Data.List {
 		cell, err := excelize.CoordinatesToCellName(1, i+2)
 		if err != nil {
-			zaplog.Error("excelize.CoordinatesToCellName", zap.Any("Err", err))
+			zaplog.Error("exclude CoordinatesToCellName", zap.Any("Err", err))
 			continue
 		}
 		row := make([]interface{}, 0)
@@ -342,47 +699,123 @@ func (s *StoreEntry) DistributeFeedFormula(ctx context.Context, req *operationPb
 	if err != nil {
 		return xerr.WithStack(err)
 	}
-	if len(distributeData.PastureList) <= 0 {
-		return nil
-	}
 
 	wg := sync.WaitGroup{}
 	wg.Add(len(distributeData.PastureList))
 	var muError error
 
 	for _, pasture := range distributeData.PastureList {
-		go func(p *model.GroupPasture) {
-			// 过滤已下发的
-			body := make([]*model.FeedFormula, 0)
+		go func(p *operationPb.AddPastureRequest) {
+			defer wg.Done()
+
+			// 过滤掉自己本牧场上报的配方数据
+			newDistributeFeedRequest := make([]*operationPb.DistributeFeedRequest, 0)
 			for _, v := range distributeData.FeedFormulaList {
-				if ok := s.checkoutDistributeLog(ctx, p.Id, v.Id); !ok {
-					body = append(body, v)
+				if v.PastureId != p.Id {
+					newDistributeFeedRequest = append(newDistributeFeedRequest, v)
 				}
 			}
-			if len(body) <= 0 {
+
+			if len(newDistributeFeedRequest) <= 0 {
 				return
 			}
 
-			request := &model.DistributeFeedFormulaRequest{
-				PastureId: p.Id,
-				Body:      body,
+			// 过滤掉已经下发过配方
+			putDistributeFeedRequest := make([]*operationPb.DistributeFeedRequest, 0)
+			for _, v := range newDistributeFeedRequest {
+				if !s.CheckFeedFormulaDistribute(ctx, int64(p.Id), int64(v.Id)) {
+					putDistributeFeedRequest = append(putDistributeFeedRequest, v)
+				}
+			}
+
+			if len(putDistributeFeedRequest) <= 0 {
+				return
 			}
-			response := &model.PastureResponse{}
+
+			// 请求参数
+			request, response := &operationPb.DistributeDataRequest{
+				PastureId:       p.PastureId,
+				FeedFormulaList: newDistributeFeedRequest,
+			}, &model.PastureResponse{
+				Code: 0,
+				Msg:  "",
+				Data: &model.PastureSuccess{Success: false},
+			}
+
 			defer func() {
 				if response.Code == http.StatusOK {
-					s.DB.Create(model.NewFeedFormulaDistributeLogList(distributeData.FeedFormulaList, p.Id, p.Name, operationPb.IsShow_OK))
+					feedFormulaDistributeLog := model.NewFeedFormulaDistributeLogList(distributeData.FeedFormulaList, int64(p.Id), p.Name, operationPb.IsShow_OK)
+					if err = s.DB.Create(feedFormulaDistributeLog).Error; err != nil {
+						zaplog.Error("DistributeFeedFormula", zap.Any("feedFormulaDistributeLog", feedFormulaDistributeLog), zap.Any("err", err))
+					}
 				} else {
-					muError = multierr.Append(muError, xerr.Custom(response.Msg))
+					muError = multierr.Append(muError, err)
 				}
-				wg.Done()
 			}()
 
-			if _, err = s.PastureHttpClient(ctx, model.FeedFormulaDistributeUrl, p.Id, request, response); err != nil {
+			if err = s.PastureHttpClient(ctx, model.FeedFormulaDistributeUrl, int64(p.Id), request, response); err != nil {
 				muError = multierr.Append(muError, err)
-				zaplog.Error("DistributeFeedFormula", zap.Any("pasture", p), zap.Any("body", distributeData.FeedFormulaList), zap.Any("err", err), zap.Any("response", response))
+				zaplog.Error("DistributeFeedFormula",
+					zap.Any("pasture", p),
+					zap.Any("body", distributeData.FeedFormulaList),
+					zap.Any("err", err),
+					zap.Any("response", response),
+				)
+				b, _ := json.Marshal(request)
+				res, _ := json.Marshal(response)
+				pastureDataLog := model.NewPastureDataLog(int64(p.Id), PastureDataLogType["FeedFormula_Distribute"], model.FeedFormulaDistributeUrl, string(b), string(res))
+				if err = s.DB.Create(pastureDataLog).Error; err != nil {
+					zaplog.Error("DistributeFeedFormula", zap.Any("pastureDataLog", pastureDataLog), zap.Any("err", err))
+				}
+			}
+
+		}(pasture)
+	}
+	wg.Wait()
+	return xerr.WithStack(muError)
+}
+
+// CancelDistributeFeedFormula 取消配方下发牧场
+func (s *StoreEntry) CancelDistributeFeedFormula(ctx context.Context, req *operationPb.DistributeFeedFormulaRequest) error {
+	distributeData, err := s.checkoutDistributeData(ctx, req)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
+	wg := sync.WaitGroup{}
+	wg.Add(len(distributeData.PastureList))
+	var muError error
+
+	for _, pasture := range distributeData.PastureList {
+		go func(p *operationPb.AddPastureRequest) {
+			defer wg.Done()
+
+			pastureDataId := make([]int64, 0)
+			for _, v := range distributeData.FeedFormulaList {
+				if v.PastureId == p.Id {
+					pastureDataId = append(pastureDataId, int64(v.PastureDataId))
+				}
+			}
+			if len(pastureDataId) <= 0 {
+				return
+			}
+
+			request := &model.CancelDistributeFeedFormulaRequest{
+				PastureId:     int64(p.Id),
+				PastureDataId: pastureDataId,
+			}
+			response := &model.PastureResponse{}
+
+			if err = s.PastureHttpClient(ctx, model.FeedFormulaCancelDistributeUrl, int64(p.Id), request, response); err != nil {
+				zaplog.Error("DistributeFeedFormula",
+					zap.String("url", model.FeedFormulaCancelDistributeUrl),
+					zap.Any("pasture", p),
+					zap.Any("body", distributeData.FeedFormulaList),
+					zap.Any("err", err),
+					zap.Any("response", response))
 				b, _ := json.Marshal(request)
 				res, _ := json.Marshal(response)
-				pastureDataLog := model.NewPastureDataLog(p.Id, PastureDataLogType["FeedFormula_Distribute"], model.FeedFormulaDistributeUrl, string(b), string(res))
+				pastureDataLog := model.NewPastureDataLog(int64(p.Id), PastureDataLogType["FeedFormula_Cancel_Distribute"], model.FeedFormulaCancelDistributeUrl, string(b), string(res))
 				s.DB.Create(pastureDataLog)
 			}
 
@@ -392,14 +825,122 @@ func (s *StoreEntry) DistributeFeedFormula(ctx context.Context, req *operationPb
 	return muError
 }
 
+// EditRecodeFeedFormula 配方修改记录
+func (s *StoreEntry) EditRecodeFeedFormula(ctx context.Context, req *operationPb.EditRecodeFeedFormulaRequest) (*operationPb.EditRecodeFeedFormulaResponse, error) {
+	feedFormulaData := &model.FeedFormula{Id: int64(req.FeedFormulaId)}
+	if err := s.DB.Model(new(model.FeedFormula)).First(feedFormulaData).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	res := &operationPb.EditRecodeFeedFormulaResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: make([]*operationPb.EditRecodeFeedFormulaData, 0),
+	}
+
+	feedFormulaEditRecordList := make([]*model.FeedFormulaEditRecord, 0)
+	pref := s.DB.Model(new(model.FeedFormulaEditRecord)).Where("status > 0").Where("feed_formula_id = ?", req.FeedFormulaId)
+	if req.PastureId > 0 {
+		pref.Where("pasture_id = ?", req.PastureId)
+	}
+
+	if req.StartTime > 0 && req.EndTime > 0 && req.EndTime >= req.StartTime {
+		pref.Where("created_at >= ?", req.StartTime).Where("created_at <= ?", req.EndTime)
+	}
+
+	if err := pref.Order("group_id").Find(&feedFormulaEditRecordList).Error; err != nil {
+		return res, xerr.WithStack(err)
+	}
+
+	groupByFeedFormulaEditRecordList := make(map[int64][]*model.FeedFormulaEditRecord)
+	for _, v := range feedFormulaEditRecordList {
+		if groupByFeedFormulaEditRecordList[v.GroupId] == nil {
+			groupByFeedFormulaEditRecordList[v.GroupId] = make([]*model.FeedFormulaEditRecord, 0)
+		}
+		groupByFeedFormulaEditRecordList[v.GroupId] = append(groupByFeedFormulaEditRecordList[v.GroupId], v)
+	}
+
+	editRecodeFeedFormulaDataList := make([]*operationPb.EditRecodeFeedFormulaData, 0)
+	for _, data := range groupByFeedFormulaEditRecordList {
+		var modifyDetail = ""
+		var pastureId int32 = 0
+		var pastureName = ""
+		var createTime int64 = 0
+
+		for i, v := range data {
+			if i == 0 {
+				modifyDetail += fmt.Sprintf("%s\n ", v.PastureName)
+				pastureId = int32(v.PastureId)
+				pastureName = v.PastureName
+				createTime = v.CreatedAt
+			}
+			switch v.Status {
+			case operationPb.FeedFormulaEditRecordType_INSERT:
+				modifyDetail += fmt.Sprintf(`%s新增了饲料%s\n `, v.OperationName, v.ForageName)
+			case operationPb.FeedFormulaEditRecordType_UPDATE:
+				modifyDetail += fmt.Sprintf(`%s将%s的%s"%s"更新为"%s"\n `, v.OperationName, v.ForageName, v.FieldName, v.BeforeValue, v.AfterValue)
+			case operationPb.FeedFormulaEditRecordType_DELETE:
+				modifyDetail += fmt.Sprintf(`%s删除了%s\n `, v.OperationName, v.ForageName)
+			}
+		}
+		editRecodeFeedFormulaDataList = append(editRecodeFeedFormulaDataList, &operationPb.EditRecodeFeedFormulaData{
+			PastureId:    pastureId,
+			PastureName:  pastureName,
+			ModifyTime:   time.Unix(createTime, 0).Format(model.LayoutTime),
+			ModifyDetail: modifyDetail,
+		})
+	}
+	res.Data = editRecodeFeedFormulaDataList
+	return res, nil
+}
+
+func (s *StoreEntry) FeedFormulaDetailList(ctx context.Context, req *operationPb.FeedFormulaDetailRequest) (*operationPb.FeedFormulaDetailResponse, error) {
+	res := &operationPb.FeedFormulaDetailResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: make([]*operationPb.AddFeedFormulaDetail, 0),
+	}
+
+	feedFormula, err := s.SearchFeedFormulaById(ctx, int64(req.FeedFormulaId))
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	feedFormulaId := feedFormula.Id
+	if feedFormula.PastureDataId > 0 {
+		feedFormulaId = feedFormula.PastureDataId
+	}
+
+	list, err := s.SearchFeedFormalDetailById(ctx, feedFormulaId, feedFormula.PastureId)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	if len(list) <= 0 {
+		list, err = s.SearchFeedFormalDetailById(ctx, feedFormula.Id, 0)
+		if err != nil {
+			return nil, xerr.WithStack(err)
+		}
+	}
+
+	res.Data = model.FeedFormulaDetailSlice(list).ToPB()
+	return res, nil
+}
+
 // FeedFormulaUsage 配方使用概况
-func (s *StoreEntry) FeedFormulaUsage(ctx context.Context, req *operationPb.FeedFormulaUsageRequest) error {
+func (s *StoreEntry) FeedFormulaUsage(ctx context.Context, req *operationPb.FeedFormulaUsageRequest) (*operationPb.FeedFormulaUsageResponse, error) {
 	feedFormulaDistributeLogList := make([]*model.FeedFormulaDistributeLog, 0)
 	if err := s.DB.Model(new(model.FeedFormulaDistributeLog)).
 		Where("feed_formula_id = ?", req.FeedFormulaId).
-		Where("is_show = ?", operationPb.IsShow_OK).
+		Where("is_show = ?", operationPb.IsShow_OK).Group("pasture_id").
 		Find(&feedFormulaDistributeLogList).Error; err != nil {
-		return xerr.WithStack(err)
+		return nil, xerr.WithStack(err)
+	}
+
+	res := &operationPb.FeedFormulaUsageResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: make([]*operationPb.FeedFormulaUsageList, 0),
 	}
 
 	wg := sync.WaitGroup{}
@@ -408,11 +949,42 @@ func (s *StoreEntry) FeedFormulaUsage(ctx context.Context, req *operationPb.Feed
 	for _, list := range feedFormulaDistributeLogList {
 		go func(l *model.FeedFormulaDistributeLog) {
 			defer wg.Done()
+			groupDetail, err := s.PastureDetailById(ctx, l.PastureId)
+			if err != nil {
+				zaplog.Error("FeedFormulaUsage", zap.Any("PastureDetailById", err))
+				return
+			}
+
+			req.PastureId = int32(groupDetail.PastureId)
+			response := &operationPb.PastureFeedFormulaUsageResponse{}
+			if err = s.PastureHttpClient(ctx, model.FeedUsageURl, groupDetail.Id, req, response); err != nil {
+				zaplog.Error("FeedFormulaUsage", zap.Any("PastureDetailById", err))
+				return
+			}
+
+			if response.Code == http.StatusOK {
+				data := &operationPb.FeedFormulaUsageList{
+					PastureId:                   int32(groupDetail.Id),
+					PastureName:                 groupDetail.Name,
+					MixedFodderAccurateRatio:    response.Data.MixedFodderAccurateRatio,
+					MixedFodderCorrectRatio:     response.Data.MixedFodderCorrectRatio,
+					SprinkleFodderAccurateRatio: response.Data.SprinkleFodderAccurateRatio,
+					SprinkleFodderCorrectRatio:  response.Data.SprinkleFodderCorrectRatio,
+					AddFeedTime:                 response.Data.AddFeedTime,
+					SprinkleTime:                response.Data.SprinkleTime,
+					StirTime:                    response.Data.StirTime,
+					LastEditTime:                response.Data.LastEditTime,
+				}
+				res.Data = append(res.Data, data)
+			} else {
+				zaplog.Error("FeedFormulaUsage-http", zap.Any("response", response))
+				return
+			}
 		}(list)
 	}
 
 	wg.Wait()
-	return nil
+	return res, nil
 }
 
 func (s *StoreEntry) PastureFeedFormulaIsModify(ctx context.Context, feedFormulaId int32, isModify operationPb.IsShow_Kind) {
@@ -430,7 +1002,7 @@ func (s *StoreEntry) PastureFeedFormulaIsModify(ctx context.Context, feedFormula
 			FeedFormulaId: v.FeedFormulaId,
 			IsModify:      int32(isModify),
 		}
-		if _, err := s.PastureHttpClient(ctx, model.FeedFormulaIsModifyUrl, v.Id, request, response); err != nil {
+		if err := s.PastureHttpClient(ctx, model.FeedFormulaIsModifyUrl, v.Id, request, response); err != nil {
 			zaplog.Error("PastureFeedFormulaIsModify", zap.Any("request", request), zap.Any("err", err), zap.Any("response", response))
 			b, _ := json.Marshal(request)
 			res, _ := json.Marshal(response)
@@ -439,24 +1011,44 @@ func (s *StoreEntry) PastureFeedFormulaIsModify(ctx context.Context, feedFormula
 		}
 	}
 }
-func (s *StoreEntry) checkoutDistributeData(ctx context.Context, req *operationPb.DistributeFeedFormulaRequest) (*model.DistributeData, error) {
-	result := &model.DistributeData{
-		PastureList:     make([]*model.GroupPasture, 0),
-		FeedFormulaList: make([]*model.FeedFormula, 0),
-	}
 
-	if err := s.DB.Where("id IN ?", req.PastureIds).Where("is_delete = ?", operationPb.IsShow_OK).Find(&result.PastureList).Error; err != nil {
+func (s *StoreEntry) checkoutDistributeData(ctx context.Context, req *operationPb.DistributeFeedFormulaRequest) (*operationPb.CheckDistributeData, error) {
+	result := &operationPb.CheckDistributeData{
+		PastureList:     make([]*operationPb.AddPastureRequest, 0),
+		FeedFormulaList: make([]*operationPb.DistributeFeedRequest, 0),
+	}
+	newGroupPastureList := make([]*model.GroupPasture, 0)
+	if err := s.DB.Model(new(model.GroupPasture)).Where("id IN ?", req.PastureIds).Where("is_delete = ?", operationPb.IsShow_OK).Find(&newGroupPastureList).Error; err != nil {
 		return result, xerr.WithStack(err)
 	}
+	result.PastureList = model.GroupPastureSlice(newGroupPastureList).ToPB()
 
-	if err := s.DB.Where("id IN ?", req.FeedFormulaIds).Find(&result.FeedFormulaList).Error; err != nil {
+	newFeedFormulaList := make([]*model.FeedFormula, 0)
+	if err := s.DB.Model(new(model.FeedFormula)).Where("id IN ?", req.FeedFormulaIds).Where("is_show = ?", operationPb.IsShow_OK).Find(&newFeedFormulaList).Error; err != nil {
 		return result, xerr.WithStack(err)
 	}
+	result.FeedFormulaList = model.FeedFormulaSlice(newFeedFormulaList).ToDistributePB()
+
+	if len(result.FeedFormulaList) != len(req.FeedFormulaIds) {
+		return result, xerr.Customf("有禁用的配方数据或者数据错误")
+	}
+
+	for _, v := range result.FeedFormulaList {
+		feedFormulaDetail := make([]*model.FeedFormulaDetail, 0)
+		if err := s.DB.Model(new(model.FeedFormulaDetail)).Where("feed_formula_id = ?", v.Id).Find(&feedFormulaDetail).Error; err != nil {
+			zaplog.Error("checkoutDistributeData", zap.Any("feed_formula_id", v.Id), zap.Any("err", err))
+			return result, xerr.Customf("%v", err)
+		}
+
+		if len(feedFormulaDetail) <= 0 {
+			return result, xerr.Customf("请先添加配方饲料信息: %s", v.Name)
+		}
+		v.FeedFormulaDetail = model.FeedFormulaDetailSlice(feedFormulaDetail).ToPB()
+	}
 
 	if len(result.PastureList) <= 0 || len(result.FeedFormulaList) <= 0 {
 		return result, xerr.Customf("数据错误")
 	}
-
 	return result, nil
 }
 
@@ -471,3 +1063,135 @@ func (s *StoreEntry) checkoutDistributeLog(ctx context.Context, pastureId, feedF
 	}
 	return false
 }
+
+func (s *StoreEntry) SearchFeedFormalDetailById(ctx context.Context, feedFormulaId, pastureId int64) ([]*model.FeedFormulaDetail, error) {
+	res := make([]*model.FeedFormulaDetail, 0)
+	if err := s.DB.Model(new(model.FeedFormulaDetail)).Where("pasture_id = ?", pastureId).
+		Where("feed_formula_id = ?", feedFormulaId).
+		Where("is_show = ?", operationPb.IsShow_OK).
+		Order("id desc").Find(&res).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	return res, nil
+}
+
+// UpdateFeedFormalVersion 更新版本库并通知牧场端
+func (s *StoreEntry) UpdateFeedFormalVersion(ctx context.Context, req *model.FeedFormula) {
+	if err := s.DB.Model(req).UpdateColumn("version", gorm.Expr("version + ?", 1)).Error; err != nil {
+		zaplog.Error("UpdateFeedFormalVersion-UpdateColumn", zap.Any("err", err))
+	}
+
+	// 获取该配方下发记录表
+	feedFormulaDistributeLogList := make([]*model.FeedFormulaDistributeLog, 0)
+	if err := s.DB.Table(new(model.FeedFormulaDistributeLog).TableName()).
+		Where("feed_formula_id = ?", req.Id).
+		Where("is_show = ?", operationPb.IsShow_OK).
+		Group("pasture_id").
+		Find(&feedFormulaDistributeLogList).Error; err != nil {
+		if !errors.Is(err, gorm.ErrRecordNotFound) {
+			zaplog.Error("UpdateFeedFormalVersion-feedFormulaDistributeLog", zap.Any("err", err))
+		}
+		return
+	}
+	if len(feedFormulaDistributeLogList) > 0 {
+		wg := sync.WaitGroup{}
+		wg.Add(len(feedFormulaDistributeLogList))
+		for _, v := range feedFormulaDistributeLogList {
+			go func(feedFormulaDistributeLog *model.FeedFormulaDistributeLog) {
+				defer wg.Done()
+				// 更新牧场端配方版本
+				s.UpdatePastureFeedDetailVersionLog(ctx, feedFormulaDistributeLog, req)
+			}(v)
+		}
+		wg.Wait()
+	}
+}
+
+func (s *StoreEntry) UpdatePastureFeedDetailVersionLog(ctx context.Context, distributeLog *model.FeedFormulaDistributeLog, req *model.FeedFormula) {
+	pastureId := distributeLog.PastureId
+	groupPasture, err := s.GetGroupPastureById(ctx, pastureId)
+	if err != nil {
+		zaplog.Error("UpdateFeedFormalVersion", zap.Any("GetGroupPastureById", pastureId), zap.Any("err", err))
+		return
+	}
+	if groupPasture.IsDistribution != operationPb.IsShow_OK {
+		return
+	}
+	var (
+		belong         int32 = 1
+		feedTemplateId       = req.Id
+	)
+
+	if req.PastureDataId > 0 {
+		belong = 2
+		feedTemplateId = req.PastureDataId
+	}
+
+	list := make([]*operationPb.AddFeedFormulaDetail, 0)
+	if err = s.DB.Model(new(model.FeedFormulaDetail)).Where("feed_formula_id = ?", req.Id).Find(&list).Error; err != nil {
+		zaplog.Error("UpdatePastureFeedDetailVersionLog-getFeedFormulaDetail",
+			zap.Any("err", err),
+			zap.Any("feed_formula_id", req.Id))
+		return
+	}
+
+	response := &model.FeedFormulaUpdateVersionResponse{}
+	body := &model.FeedFormulaUpdateVersionRequest{
+		FeedTemplateId: feedTemplateId,
+		Version:        req.Version,
+		Belong:         belong,
+		Data:           make([]*operationPb.AddFeedFormulaDetail, 0),
+	}
+
+	body.Data = list
+	zaplog.Info("UpdateFeedFormalVersion", zap.Any("body", body))
+	if err = s.PastureHttpClient(ctx, model.FeedFormulaVersionUpdateUrl, pastureId, body, response); err != nil {
+		zaplog.Error("UpdateFeedFormalVersion-http",
+			zap.String("url", model.FeedFormulaVersionUpdateUrl),
+			zap.Any("pasture", groupPasture), zap.Any("body", body),
+			zap.Any("err", err), zap.Any("response", response))
+		return
+	}
+
+	if response.Code != http.StatusOK {
+		zaplog.Error("UpdateFeedFormalVersion-response",
+			zap.String("url", model.DashboardExecTimeUrl),
+			zap.Any("pasture", groupPasture), zap.Any("body", body),
+			zap.Any("err", err), zap.Any("response", response))
+		return
+	}
+}
+
+// CheckFeedFormulaDistribute 检查该配方是否下发牧场端
+func (s *StoreEntry) CheckFeedFormulaDistribute(ctx context.Context, pastureId, feedFormulaId int64) bool {
+	res := &model.FeedFormulaDistributeLog{}
+	if err := s.DB.Where("feed_formula_id = ?", feedFormulaId).Where("pasture_id = ?", pastureId).First(res).Error; err != nil {
+		return false
+	}
+	if res.IsShow == operationPb.IsShow_OK {
+		return true
+	}
+
+	return false
+}
+
+// ForageListByGroup 查询集团端饲料的列表数据
+func (s *StoreEntry) ForageListByGroup(ctx context.Context) (*operationPb.SearchForageListResponse, error) {
+	forage := make([]*model.Forage, 0)
+	var count int64 = 0
+
+	if err := s.DB.Model(new(model.Forage)).Where("is_delete = ?", operationPb.IsShow_OK).
+		Where("pasture_id = 0").Where("is_show = ?", operationPb.IsShow_OK).
+		Order("id DESC").Count(&count).Find(&forage).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return &operationPb.SearchForageListResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.SearchForageList{
+			Total: int32(count),
+			List:  model.ForageSlice(forage).ToPB(),
+		},
+	}, nil
+}

+ 32 - 6
module/backend/interface.go

@@ -6,11 +6,12 @@ import (
 	"io"
 	"kpt-tmr-group/config"
 	"kpt-tmr-group/model"
-	"kpt-tmr-group/pkg/di"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"kpt-tmr-group/service/wechat"
 	"kpt-tmr-group/store/kptstore"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/di"
+
 	"go.uber.org/dig"
 )
 
@@ -50,6 +51,7 @@ type KptService interface {
 	PastureSyncService // 牧场端数据同步
 }
 
+//go:generate mockgen -destination mock/PastureService.go -package kptservicemock kpt-tmr-group/module/backend PastureService
 type PastureService interface {
 	// CreateGroupPasture 牧场管理相关
 	CreateGroupPasture(ctx context.Context, req *operationPb.AddPastureRequest) error
@@ -89,6 +91,13 @@ type PastureService interface {
 	// CreateFeedFormula 饲料配方
 	CreateFeedFormula(ctx context.Context, req *operationPb.AddFeedFormulaRequest) error
 	EditFeedFormula(ctx context.Context, req *operationPb.AddFeedFormulaRequest) error
+	AddFeedByFeedFormula(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) error
+	EditFeedByFeedFormula(ctx context.Context, req *operationPb.AddFeedFormulaDetail) error
+	FeedFormulaDetailBySort(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) error
+	FeedFormulaDetailIsModify(ctx context.Context, req *operationPb.AddFeedFormulaDetail) error
+	DeleteFeedFormulaDetail(ctx context.Context, req *operationPb.GroupAddFeedFormulaDetail) error
+	SearchFeedFormulaDetail(ctx context.Context, req *operationPb.AddFeedFormulaDetail) (*operationPb.FeedFormulaDetailResponse, error)
+	MixedFeedFormula(ctx context.Context, req *operationPb.MixedFeedFormulaRequest) error
 	SearchFeedFormulaList(ctx context.Context, req *operationPb.SearchFeedFormulaRequest) (*operationPb.SearchFeedFormulaListResponse, error)
 	IsShowFeedFormula(ctx context.Context, req *operationPb.IsShowModifyFeedFormula) error
 	DeleteFeedFormula(ctx context.Context, feedFormulaId int64) error
@@ -97,13 +106,19 @@ type PastureService interface {
 	ExcelTemplateFeedFormula(ctx context.Context) (*bytes.Buffer, error)
 	EncodeNumber(ctx context.Context) string
 	DistributeFeedFormula(ctx context.Context, req *operationPb.DistributeFeedFormulaRequest) error
-	FeedFormulaUsage(ctx context.Context, req *operationPb.FeedFormulaUsageRequest) error
+	CancelDistributeFeedFormula(ctx context.Context, req *operationPb.DistributeFeedFormulaRequest) error
+	EditRecodeFeedFormula(ctx context.Context, req *operationPb.EditRecodeFeedFormulaRequest) (*operationPb.EditRecodeFeedFormulaResponse, error)
+	FeedFormulaDetailList(ctx context.Context, req *operationPb.FeedFormulaDetailRequest) (*operationPb.FeedFormulaDetailResponse, error)
+	FeedFormulaUsage(ctx context.Context, req *operationPb.FeedFormulaUsageRequest) (*operationPb.FeedFormulaUsageResponse, error)
+	ForageListByGroup(ctx context.Context) (*operationPb.SearchForageListResponse, error)
 }
 
+//go:generate mockgen -destination mock/SystemService.go -package kptservicemock kpt-tmr-group/module/backend SystemService
 type SystemService interface {
 	// Auth 系统用户相关
 	Auth(ctx context.Context, auth *operationPb.UserAuthData) (*operationPb.SystemToken, error)
-	GetUserInfo(ctx context.Context, token string) (*operationPb.UserAuth, error)
+	GetCurrentUserName(ctx context.Context) string
+	GetUserInfo(ctx context.Context) (*operationPb.UserAuth, error)
 	CreateSystemUser(ctx context.Context, req *operationPb.AddSystemUser) error
 	SearchSystemUserList(ctx context.Context, req *operationPb.SearchUserRequest) (*operationPb.SearchUserResponse, error)
 	EditSystemUser(ctx context.Context, req *operationPb.AddSystemUser) error
@@ -111,7 +126,7 @@ type SystemService interface {
 	ResetPasswordSystemUser(ctx context.Context, userId int64) error
 	DetailsSystemUser(ctx context.Context, userId int64) (*operationPb.UserDetails, error)
 	IsShowSystemUser(ctx context.Context, req *operationPb.IsShowSystemUserRequest) error
-	GetSystemUserPermissions(ctx context.Context, token string) (*operationPb.SystemUserMenuPermissions, error)
+	GetSystemUserPermissions(ctx context.Context) (*operationPb.SystemUserMenuPermissions, error)
 
 	// CreateSystemRole 系统角色相关
 	CreateSystemRole(ctx context.Context, req *operationPb.AddRoleRequest) error
@@ -131,6 +146,7 @@ type SystemService interface {
 	SearchMobileList(ctx context.Context, req *operationPb.SearchMobileRequest) (*operationPb.SearchMobileResponse, error)
 }
 
+//go:generate mockgen -destination mock/StatisticService.go -package kptservicemock kpt-tmr-group/module/backend StatisticService
 type StatisticService interface {
 	SearchFormulaEstimateList(ctx context.Context, req *operationPb.SearchFormulaEstimateRequest) (*model.PastureCommonResponse, error)
 	SearchInventoryStatistics(ctx context.Context, req *operationPb.SearchInventoryStatisticsRequest) (*model.PastureCommonResponse, error)
@@ -147,20 +163,30 @@ type StatisticService interface {
 	SearchMixFeedStatistics(ctx context.Context, req *operationPb.MixFeedStatisticsRequest) (*model.PastureCommonResponse, error)
 	SearchSprinkleStatistics(ctx context.Context, req *operationPb.SprinkleStatisticsRequest) (*model.PastureCommonResponse, error)
 	SearchProcessAnalysis(ctx context.Context, req *operationPb.ProcessAnalysisRequest) (*model.PastureCommonResponse, error)
+	AnalysisMixedSprinkleDetail(ctx context.Context, req *operationPb.ProcessMixedSprinkleDetailRequest) (*model.PastureCommonResponse, error)
 	GetDataByName(ctx context.Context, req *operationPb.GetDataByNameRequest) (*model.PastureCommonResponse, error)
 
 	GetTrainNumber(ctx context.Context, req *operationPb.TrainNumberRequest) (*operationPb.TrainNumberResponse, error)
-	SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error)
+	SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse1, error)
 	TopPasture(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.GetPastureTopResponse, error)
 	ExecutionTime(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.ExecTimeResponse, error)
 	SprinkleFeedTime(ctx context.Context, req *operationPb.SprinkleFeedTimeRequest) (*model.SprinkleFeedTimeResponse, error)
+	FeedMixedAndTmrName(ctx context.Context, req *operationPb.MixedCategoryTmrName) (*model.PastureCommonResponse, error)
+	FeedTemplateHistory(ctx context.Context, req *operationPb.FeedTemplateHistoryRequest) (*model.PastureFeedTemplateHistoryResponse, error)
+	BarnHistory(ctx context.Context, req *operationPb.BarnHistoryRequest) (*model.PastureBarnHistoryResponse, error)
+	SpillageAllHistory(ctx context.Context, req *operationPb.BarnHistoryRequest) (*model.PastureBarnHistoryResponse, error)
 }
 
+//go:generate mockgen -destination mock/WxAppletService.go -package kptservicemock kpt-tmr-group/module/backend WxAppletService
 type WxAppletService interface {
 	GetOpenId(ctx context.Context, jsCode string) (*operationPb.WxOpenId, error)
 }
 
+//go:generate mockgen -destination mock/PastureSyncService.go -package kptservicemock kpt-tmr-group/module/backend PastureSyncService
 type PastureSyncService interface {
 	CategorySyncData(ctx context.Context, req *operationPb.CategorySyncRequest) error
 	CategoryDeleteData(ctx context.Context, req *operationPb.CategoryDeleteRequest) error
+	FeedFormulaSyncData(ctx context.Context, req *operationPb.FeedFormulaSyncRequest) error
+	FeedSyncData(ctx context.Context, req *operationPb.FeedFormulaSyncRequest) error
+	FeedFormulaDetailListSyncData(ctx context.Context, req *operationPb.FeedFormulaSyncRequest) error
 }

+ 725 - 0
module/backend/mock/PastureService.go

@@ -0,0 +1,725 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: kpt-tmr-group/module/backend (interfaces: PastureService)
+
+// Package kptservicemock is a generated GoMock package.
+package kptservicemock
+
+import (
+	bytes "bytes"
+	context "context"
+	io "io"
+	model "kpt-tmr-group/model"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+)
+
+// MockPastureService is a mock of PastureService interface.
+type MockPastureService struct {
+	ctrl     *gomock.Controller
+	recorder *MockPastureServiceMockRecorder
+}
+
+// MockPastureServiceMockRecorder is the mock recorder for MockPastureService.
+type MockPastureServiceMockRecorder struct {
+	mock *MockPastureService
+}
+
+// NewMockPastureService creates a new mock instance.
+func NewMockPastureService(ctrl *gomock.Controller) *MockPastureService {
+	mock := &MockPastureService{ctrl: ctrl}
+	mock.recorder = &MockPastureServiceMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockPastureService) EXPECT() *MockPastureServiceMockRecorder {
+	return m.recorder
+}
+
+// AddCattleCategory mocks base method.
+func (m *MockPastureService) AddCattleCategory(arg0 context.Context, arg1 *operationPb.AddCattleCategoryRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "AddCattleCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// AddCattleCategory indicates an expected call of AddCattleCategory.
+func (mr *MockPastureServiceMockRecorder) AddCattleCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddCattleCategory", reflect.TypeOf((*MockPastureService)(nil).AddCattleCategory), arg0, arg1)
+}
+
+// AddFeedByFeedFormula mocks base method.
+func (m *MockPastureService) AddFeedByFeedFormula(arg0 context.Context, arg1 *operationPb.GroupAddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "AddFeedByFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// AddFeedByFeedFormula indicates an expected call of AddFeedByFeedFormula.
+func (mr *MockPastureServiceMockRecorder) AddFeedByFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddFeedByFeedFormula", reflect.TypeOf((*MockPastureService)(nil).AddFeedByFeedFormula), arg0, arg1)
+}
+
+// AddForageCategory mocks base method.
+func (m *MockPastureService) AddForageCategory(arg0 context.Context, arg1 *operationPb.AddForageCategoryRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "AddForageCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// AddForageCategory indicates an expected call of AddForageCategory.
+func (mr *MockPastureServiceMockRecorder) AddForageCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddForageCategory", reflect.TypeOf((*MockPastureService)(nil).AddForageCategory), arg0, arg1)
+}
+
+// CancelDistributeFeedFormula mocks base method.
+func (m *MockPastureService) CancelDistributeFeedFormula(arg0 context.Context, arg1 *operationPb.DistributeFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CancelDistributeFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CancelDistributeFeedFormula indicates an expected call of CancelDistributeFeedFormula.
+func (mr *MockPastureServiceMockRecorder) CancelDistributeFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CancelDistributeFeedFormula", reflect.TypeOf((*MockPastureService)(nil).CancelDistributeFeedFormula), arg0, arg1)
+}
+
+// CreateFeedFormula mocks base method.
+func (m *MockPastureService) CreateFeedFormula(arg0 context.Context, arg1 *operationPb.AddFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateFeedFormula indicates an expected call of CreateFeedFormula.
+func (mr *MockPastureServiceMockRecorder) CreateFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFeedFormula", reflect.TypeOf((*MockPastureService)(nil).CreateFeedFormula), arg0, arg1)
+}
+
+// CreateForage mocks base method.
+func (m *MockPastureService) CreateForage(arg0 context.Context, arg1 *operationPb.AddForageRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateForage", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateForage indicates an expected call of CreateForage.
+func (mr *MockPastureServiceMockRecorder) CreateForage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateForage", reflect.TypeOf((*MockPastureService)(nil).CreateForage), arg0, arg1)
+}
+
+// CreateGroupPasture mocks base method.
+func (m *MockPastureService) CreateGroupPasture(arg0 context.Context, arg1 *operationPb.AddPastureRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateGroupPasture", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateGroupPasture indicates an expected call of CreateGroupPasture.
+func (mr *MockPastureServiceMockRecorder) CreateGroupPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateGroupPasture", reflect.TypeOf((*MockPastureService)(nil).CreateGroupPasture), arg0, arg1)
+}
+
+// DeleteCattleCategory mocks base method.
+func (m *MockPastureService) DeleteCattleCategory(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteCattleCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteCattleCategory indicates an expected call of DeleteCattleCategory.
+func (mr *MockPastureServiceMockRecorder) DeleteCattleCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCattleCategory", reflect.TypeOf((*MockPastureService)(nil).DeleteCattleCategory), arg0, arg1)
+}
+
+// DeleteFeedFormula mocks base method.
+func (m *MockPastureService) DeleteFeedFormula(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteFeedFormula indicates an expected call of DeleteFeedFormula.
+func (mr *MockPastureServiceMockRecorder) DeleteFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFeedFormula", reflect.TypeOf((*MockPastureService)(nil).DeleteFeedFormula), arg0, arg1)
+}
+
+// DeleteFeedFormulaDetail mocks base method.
+func (m *MockPastureService) DeleteFeedFormulaDetail(arg0 context.Context, arg1 *operationPb.GroupAddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteFeedFormulaDetail", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteFeedFormulaDetail indicates an expected call of DeleteFeedFormulaDetail.
+func (mr *MockPastureServiceMockRecorder) DeleteFeedFormulaDetail(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFeedFormulaDetail", reflect.TypeOf((*MockPastureService)(nil).DeleteFeedFormulaDetail), arg0, arg1)
+}
+
+// DeleteForageCategory mocks base method.
+func (m *MockPastureService) DeleteForageCategory(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteForageCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteForageCategory indicates an expected call of DeleteForageCategory.
+func (mr *MockPastureServiceMockRecorder) DeleteForageCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteForageCategory", reflect.TypeOf((*MockPastureService)(nil).DeleteForageCategory), arg0, arg1)
+}
+
+// DeleteForageList mocks base method.
+func (m *MockPastureService) DeleteForageList(arg0 context.Context, arg1 []int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteForageList", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteForageList indicates an expected call of DeleteForageList.
+func (mr *MockPastureServiceMockRecorder) DeleteForageList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteForageList", reflect.TypeOf((*MockPastureService)(nil).DeleteForageList), arg0, arg1)
+}
+
+// DeleteGroupPasture mocks base method.
+func (m *MockPastureService) DeleteGroupPasture(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteGroupPasture", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteGroupPasture indicates an expected call of DeleteGroupPasture.
+func (mr *MockPastureServiceMockRecorder) DeleteGroupPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteGroupPasture", reflect.TypeOf((*MockPastureService)(nil).DeleteGroupPasture), arg0, arg1)
+}
+
+// DistributeFeedFormula mocks base method.
+func (m *MockPastureService) DistributeFeedFormula(arg0 context.Context, arg1 *operationPb.DistributeFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DistributeFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DistributeFeedFormula indicates an expected call of DistributeFeedFormula.
+func (mr *MockPastureServiceMockRecorder) DistributeFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DistributeFeedFormula", reflect.TypeOf((*MockPastureService)(nil).DistributeFeedFormula), arg0, arg1)
+}
+
+// EditCattleCategory mocks base method.
+func (m *MockPastureService) EditCattleCategory(arg0 context.Context, arg1 *operationPb.AddCattleCategoryRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditCattleCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditCattleCategory indicates an expected call of EditCattleCategory.
+func (mr *MockPastureServiceMockRecorder) EditCattleCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditCattleCategory", reflect.TypeOf((*MockPastureService)(nil).EditCattleCategory), arg0, arg1)
+}
+
+// EditFeedByFeedFormula mocks base method.
+func (m *MockPastureService) EditFeedByFeedFormula(arg0 context.Context, arg1 *operationPb.AddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditFeedByFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditFeedByFeedFormula indicates an expected call of EditFeedByFeedFormula.
+func (mr *MockPastureServiceMockRecorder) EditFeedByFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditFeedByFeedFormula", reflect.TypeOf((*MockPastureService)(nil).EditFeedByFeedFormula), arg0, arg1)
+}
+
+// EditFeedFormula mocks base method.
+func (m *MockPastureService) EditFeedFormula(arg0 context.Context, arg1 *operationPb.AddFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditFeedFormula indicates an expected call of EditFeedFormula.
+func (mr *MockPastureServiceMockRecorder) EditFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditFeedFormula", reflect.TypeOf((*MockPastureService)(nil).EditFeedFormula), arg0, arg1)
+}
+
+// EditForage mocks base method.
+func (m *MockPastureService) EditForage(arg0 context.Context, arg1 *operationPb.AddForageRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditForage", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditForage indicates an expected call of EditForage.
+func (mr *MockPastureServiceMockRecorder) EditForage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditForage", reflect.TypeOf((*MockPastureService)(nil).EditForage), arg0, arg1)
+}
+
+// EditForageCategory mocks base method.
+func (m *MockPastureService) EditForageCategory(arg0 context.Context, arg1 *operationPb.AddForageCategoryRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditForageCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditForageCategory indicates an expected call of EditForageCategory.
+func (mr *MockPastureServiceMockRecorder) EditForageCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditForageCategory", reflect.TypeOf((*MockPastureService)(nil).EditForageCategory), arg0, arg1)
+}
+
+// EditGroupPasture mocks base method.
+func (m *MockPastureService) EditGroupPasture(arg0 context.Context, arg1 *operationPb.AddPastureRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditGroupPasture", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditGroupPasture indicates an expected call of EditGroupPasture.
+func (mr *MockPastureServiceMockRecorder) EditGroupPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditGroupPasture", reflect.TypeOf((*MockPastureService)(nil).EditGroupPasture), arg0, arg1)
+}
+
+// EditRecodeFeedFormula mocks base method.
+func (m *MockPastureService) EditRecodeFeedFormula(arg0 context.Context, arg1 *operationPb.EditRecodeFeedFormulaRequest) (*operationPb.EditRecodeFeedFormulaResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditRecodeFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.EditRecodeFeedFormulaResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// EditRecodeFeedFormula indicates an expected call of EditRecodeFeedFormula.
+func (mr *MockPastureServiceMockRecorder) EditRecodeFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditRecodeFeedFormula", reflect.TypeOf((*MockPastureService)(nil).EditRecodeFeedFormula), arg0, arg1)
+}
+
+// EncodeNumber mocks base method.
+func (m *MockPastureService) EncodeNumber(arg0 context.Context) string {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EncodeNumber", arg0)
+	ret0, _ := ret[0].(string)
+	return ret0
+}
+
+// EncodeNumber indicates an expected call of EncodeNumber.
+func (mr *MockPastureServiceMockRecorder) EncodeNumber(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EncodeNumber", reflect.TypeOf((*MockPastureService)(nil).EncodeNumber), arg0)
+}
+
+// ExcelExportFeedFormula mocks base method.
+func (m *MockPastureService) ExcelExportFeedFormula(arg0 context.Context, arg1 *operationPb.SearchFeedFormulaRequest) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelExportFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExcelExportFeedFormula indicates an expected call of ExcelExportFeedFormula.
+func (mr *MockPastureServiceMockRecorder) ExcelExportFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelExportFeedFormula", reflect.TypeOf((*MockPastureService)(nil).ExcelExportFeedFormula), arg0, arg1)
+}
+
+// ExcelExportForage mocks base method.
+func (m *MockPastureService) ExcelExportForage(arg0 context.Context, arg1 *operationPb.SearchForageListRequest) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelExportForage", arg0, arg1)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExcelExportForage indicates an expected call of ExcelExportForage.
+func (mr *MockPastureServiceMockRecorder) ExcelExportForage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelExportForage", reflect.TypeOf((*MockPastureService)(nil).ExcelExportForage), arg0, arg1)
+}
+
+// ExcelImportFeedFormula mocks base method.
+func (m *MockPastureService) ExcelImportFeedFormula(arg0 context.Context, arg1 io.Reader) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelImportFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ExcelImportFeedFormula indicates an expected call of ExcelImportFeedFormula.
+func (mr *MockPastureServiceMockRecorder) ExcelImportFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelImportFeedFormula", reflect.TypeOf((*MockPastureService)(nil).ExcelImportFeedFormula), arg0, arg1)
+}
+
+// ExcelImportForage mocks base method.
+func (m *MockPastureService) ExcelImportForage(arg0 context.Context, arg1 io.Reader) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelImportForage", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ExcelImportForage indicates an expected call of ExcelImportForage.
+func (mr *MockPastureServiceMockRecorder) ExcelImportForage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelImportForage", reflect.TypeOf((*MockPastureService)(nil).ExcelImportForage), arg0, arg1)
+}
+
+// ExcelTemplateFeedFormula mocks base method.
+func (m *MockPastureService) ExcelTemplateFeedFormula(arg0 context.Context) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelTemplateFeedFormula", arg0)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExcelTemplateFeedFormula indicates an expected call of ExcelTemplateFeedFormula.
+func (mr *MockPastureServiceMockRecorder) ExcelTemplateFeedFormula(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelTemplateFeedFormula", reflect.TypeOf((*MockPastureService)(nil).ExcelTemplateFeedFormula), arg0)
+}
+
+// ExcelTemplateForage mocks base method.
+func (m *MockPastureService) ExcelTemplateForage(arg0 context.Context) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExcelTemplateForage", arg0)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExcelTemplateForage indicates an expected call of ExcelTemplateForage.
+func (mr *MockPastureServiceMockRecorder) ExcelTemplateForage(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelTemplateForage", reflect.TypeOf((*MockPastureService)(nil).ExcelTemplateForage), arg0)
+}
+
+// FeedFormulaDetailBySort mocks base method.
+func (m *MockPastureService) FeedFormulaDetailBySort(arg0 context.Context, arg1 *operationPb.GroupAddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailBySort", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaDetailBySort indicates an expected call of FeedFormulaDetailBySort.
+func (mr *MockPastureServiceMockRecorder) FeedFormulaDetailBySort(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailBySort", reflect.TypeOf((*MockPastureService)(nil).FeedFormulaDetailBySort), arg0, arg1)
+}
+
+// FeedFormulaDetailIsModify mocks base method.
+func (m *MockPastureService) FeedFormulaDetailIsModify(arg0 context.Context, arg1 *operationPb.AddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailIsModify", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaDetailIsModify indicates an expected call of FeedFormulaDetailIsModify.
+func (mr *MockPastureServiceMockRecorder) FeedFormulaDetailIsModify(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailIsModify", reflect.TypeOf((*MockPastureService)(nil).FeedFormulaDetailIsModify), arg0, arg1)
+}
+
+// FeedFormulaDetailList mocks base method.
+func (m *MockPastureService) FeedFormulaDetailList(arg0 context.Context, arg1 *operationPb.FeedFormulaDetailRequest) (*operationPb.FeedFormulaDetailResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.FeedFormulaDetailResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedFormulaDetailList indicates an expected call of FeedFormulaDetailList.
+func (mr *MockPastureServiceMockRecorder) FeedFormulaDetailList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailList", reflect.TypeOf((*MockPastureService)(nil).FeedFormulaDetailList), arg0, arg1)
+}
+
+// FeedFormulaUsage mocks base method.
+func (m *MockPastureService) FeedFormulaUsage(arg0 context.Context, arg1 *operationPb.FeedFormulaUsageRequest) (*operationPb.FeedFormulaUsageResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaUsage", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.FeedFormulaUsageResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedFormulaUsage indicates an expected call of FeedFormulaUsage.
+func (mr *MockPastureServiceMockRecorder) FeedFormulaUsage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaUsage", reflect.TypeOf((*MockPastureService)(nil).FeedFormulaUsage), arg0, arg1)
+}
+
+// ForageEnumList mocks base method.
+func (m *MockPastureService) ForageEnumList(arg0 context.Context) *operationPb.ForageEnumListResponse {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ForageEnumList", arg0)
+	ret0, _ := ret[0].(*operationPb.ForageEnumListResponse)
+	return ret0
+}
+
+// ForageEnumList indicates an expected call of ForageEnumList.
+func (mr *MockPastureServiceMockRecorder) ForageEnumList(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForageEnumList", reflect.TypeOf((*MockPastureService)(nil).ForageEnumList), arg0)
+}
+
+// ForageListSort mocks base method.
+func (m *MockPastureService) ForageListSort(arg0 context.Context, arg1 *operationPb.ForageListSortRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ForageListSort", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ForageListSort indicates an expected call of ForageListSort.
+func (mr *MockPastureServiceMockRecorder) ForageListSort(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForageListSort", reflect.TypeOf((*MockPastureService)(nil).ForageListSort), arg0, arg1)
+}
+
+// IsShowCattleCategory mocks base method.
+func (m *MockPastureService) IsShowCattleCategory(arg0 context.Context, arg1 *operationPb.IsShowCattleCategory) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowCattleCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowCattleCategory indicates an expected call of IsShowCattleCategory.
+func (mr *MockPastureServiceMockRecorder) IsShowCattleCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowCattleCategory", reflect.TypeOf((*MockPastureService)(nil).IsShowCattleCategory), arg0, arg1)
+}
+
+// IsShowFeedFormula mocks base method.
+func (m *MockPastureService) IsShowFeedFormula(arg0 context.Context, arg1 *operationPb.IsShowModifyFeedFormula) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowFeedFormula indicates an expected call of IsShowFeedFormula.
+func (mr *MockPastureServiceMockRecorder) IsShowFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowFeedFormula", reflect.TypeOf((*MockPastureService)(nil).IsShowFeedFormula), arg0, arg1)
+}
+
+// IsShowForage mocks base method.
+func (m *MockPastureService) IsShowForage(arg0 context.Context, arg1 *operationPb.IsShowForage) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowForage", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowForage indicates an expected call of IsShowForage.
+func (mr *MockPastureServiceMockRecorder) IsShowForage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowForage", reflect.TypeOf((*MockPastureService)(nil).IsShowForage), arg0, arg1)
+}
+
+// IsShowForageCategory mocks base method.
+func (m *MockPastureService) IsShowForageCategory(arg0 context.Context, arg1 *operationPb.IsShowForageCategory) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowForageCategory", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowForageCategory indicates an expected call of IsShowForageCategory.
+func (mr *MockPastureServiceMockRecorder) IsShowForageCategory(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowForageCategory", reflect.TypeOf((*MockPastureService)(nil).IsShowForageCategory), arg0, arg1)
+}
+
+// IsShowGroupPasture mocks base method.
+func (m *MockPastureService) IsShowGroupPasture(arg0 context.Context, arg1 *operationPb.IsShowGroupPasture) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowGroupPasture", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowGroupPasture indicates an expected call of IsShowGroupPasture.
+func (mr *MockPastureServiceMockRecorder) IsShowGroupPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowGroupPasture", reflect.TypeOf((*MockPastureService)(nil).IsShowGroupPasture), arg0, arg1)
+}
+
+// MixedFeedFormula mocks base method.
+func (m *MockPastureService) MixedFeedFormula(arg0 context.Context, arg1 *operationPb.MixedFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "MixedFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// MixedFeedFormula indicates an expected call of MixedFeedFormula.
+func (mr *MockPastureServiceMockRecorder) MixedFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MixedFeedFormula", reflect.TypeOf((*MockPastureService)(nil).MixedFeedFormula), arg0, arg1)
+}
+
+// ResetPasswordGroupPasture mocks base method.
+func (m *MockPastureService) ResetPasswordGroupPasture(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ResetPasswordGroupPasture", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ResetPasswordGroupPasture indicates an expected call of ResetPasswordGroupPasture.
+func (mr *MockPastureServiceMockRecorder) ResetPasswordGroupPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetPasswordGroupPasture", reflect.TypeOf((*MockPastureService)(nil).ResetPasswordGroupPasture), arg0, arg1)
+}
+
+// SearchCattleCategoryList mocks base method.
+func (m *MockPastureService) SearchCattleCategoryList(arg0 context.Context, arg1 *operationPb.SearchCattleCategoryRequest) (*operationPb.SearchCattleCategoryResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchCattleCategoryList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchCattleCategoryResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchCattleCategoryList indicates an expected call of SearchCattleCategoryList.
+func (mr *MockPastureServiceMockRecorder) SearchCattleCategoryList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchCattleCategoryList", reflect.TypeOf((*MockPastureService)(nil).SearchCattleCategoryList), arg0, arg1)
+}
+
+// SearchFeedFormulaDetail mocks base method.
+func (m *MockPastureService) SearchFeedFormulaDetail(arg0 context.Context, arg1 *operationPb.AddFeedFormulaDetail) (*operationPb.FeedFormulaDetailResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchFeedFormulaDetail", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.FeedFormulaDetailResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchFeedFormulaDetail indicates an expected call of SearchFeedFormulaDetail.
+func (mr *MockPastureServiceMockRecorder) SearchFeedFormulaDetail(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchFeedFormulaDetail", reflect.TypeOf((*MockPastureService)(nil).SearchFeedFormulaDetail), arg0, arg1)
+}
+
+// SearchFeedFormulaList mocks base method.
+func (m *MockPastureService) SearchFeedFormulaList(arg0 context.Context, arg1 *operationPb.SearchFeedFormulaRequest) (*operationPb.SearchFeedFormulaListResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchFeedFormulaList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchFeedFormulaListResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchFeedFormulaList indicates an expected call of SearchFeedFormulaList.
+func (mr *MockPastureServiceMockRecorder) SearchFeedFormulaList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchFeedFormulaList", reflect.TypeOf((*MockPastureService)(nil).SearchFeedFormulaList), arg0, arg1)
+}
+
+// SearchForageCategoryList mocks base method.
+func (m *MockPastureService) SearchForageCategoryList(arg0 context.Context, arg1 *operationPb.SearchForageCategoryRequest) (*operationPb.SearchForageCategoryResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchForageCategoryList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchForageCategoryResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchForageCategoryList indicates an expected call of SearchForageCategoryList.
+func (mr *MockPastureServiceMockRecorder) SearchForageCategoryList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchForageCategoryList", reflect.TypeOf((*MockPastureService)(nil).SearchForageCategoryList), arg0, arg1)
+}
+
+// SearchForageList mocks base method.
+func (m *MockPastureService) SearchForageList(arg0 context.Context, arg1 *operationPb.SearchForageListRequest) (*operationPb.SearchForageListResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchForageList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchForageListResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchForageList indicates an expected call of SearchForageList.
+func (mr *MockPastureServiceMockRecorder) SearchForageList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchForageList", reflect.TypeOf((*MockPastureService)(nil).SearchForageList), arg0, arg1)
+}
+
+// SearchGroupPastureList mocks base method.
+func (m *MockPastureService) SearchGroupPastureList(arg0 context.Context, arg1 *operationPb.SearchPastureRequest) (*operationPb.SearchPastureResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchGroupPastureList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchPastureResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchGroupPastureList indicates an expected call of SearchGroupPastureList.
+func (mr *MockPastureServiceMockRecorder) SearchGroupPastureList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchGroupPastureList", reflect.TypeOf((*MockPastureService)(nil).SearchGroupPastureList), arg0, arg1)
+}
+
+// SmallMaterial mocks base method.
+func (m *MockPastureService) SmallMaterial(arg0 context.Context, arg1 *operationPb.SmallMaterialRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SmallMaterial", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SmallMaterial indicates an expected call of SmallMaterial.
+func (mr *MockPastureServiceMockRecorder) SmallMaterial(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SmallMaterial", reflect.TypeOf((*MockPastureService)(nil).SmallMaterial), arg0, arg1)
+}

+ 106 - 0
module/backend/mock/PastureSyncService.go

@@ -0,0 +1,106 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: kpt-tmr-group/module/backend (interfaces: PastureSyncService)
+
+// Package kptservicemock is a generated GoMock package.
+package kptservicemock
+
+import (
+	context "context"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+)
+
+// MockPastureSyncService is a mock of PastureSyncService interface.
+type MockPastureSyncService struct {
+	ctrl     *gomock.Controller
+	recorder *MockPastureSyncServiceMockRecorder
+}
+
+// MockPastureSyncServiceMockRecorder is the mock recorder for MockPastureSyncService.
+type MockPastureSyncServiceMockRecorder struct {
+	mock *MockPastureSyncService
+}
+
+// NewMockPastureSyncService creates a new mock instance.
+func NewMockPastureSyncService(ctrl *gomock.Controller) *MockPastureSyncService {
+	mock := &MockPastureSyncService{ctrl: ctrl}
+	mock.recorder = &MockPastureSyncServiceMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockPastureSyncService) EXPECT() *MockPastureSyncServiceMockRecorder {
+	return m.recorder
+}
+
+// CategoryDeleteData mocks base method.
+func (m *MockPastureSyncService) CategoryDeleteData(arg0 context.Context, arg1 *operationPb.CategoryDeleteRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CategoryDeleteData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CategoryDeleteData indicates an expected call of CategoryDeleteData.
+func (mr *MockPastureSyncServiceMockRecorder) CategoryDeleteData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CategoryDeleteData", reflect.TypeOf((*MockPastureSyncService)(nil).CategoryDeleteData), arg0, arg1)
+}
+
+// CategorySyncData mocks base method.
+func (m *MockPastureSyncService) CategorySyncData(arg0 context.Context, arg1 *operationPb.CategorySyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CategorySyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CategorySyncData indicates an expected call of CategorySyncData.
+func (mr *MockPastureSyncServiceMockRecorder) CategorySyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CategorySyncData", reflect.TypeOf((*MockPastureSyncService)(nil).CategorySyncData), arg0, arg1)
+}
+
+// FeedFormulaDetailListSyncData mocks base method.
+func (m *MockPastureSyncService) FeedFormulaDetailListSyncData(arg0 context.Context, arg1 *operationPb.FeedFormulaSyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailListSyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaDetailListSyncData indicates an expected call of FeedFormulaDetailListSyncData.
+func (mr *MockPastureSyncServiceMockRecorder) FeedFormulaDetailListSyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailListSyncData", reflect.TypeOf((*MockPastureSyncService)(nil).FeedFormulaDetailListSyncData), arg0, arg1)
+}
+
+// FeedFormulaSyncData mocks base method.
+func (m *MockPastureSyncService) FeedFormulaSyncData(arg0 context.Context, arg1 *operationPb.FeedFormulaSyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaSyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaSyncData indicates an expected call of FeedFormulaSyncData.
+func (mr *MockPastureSyncServiceMockRecorder) FeedFormulaSyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaSyncData", reflect.TypeOf((*MockPastureSyncService)(nil).FeedFormulaSyncData), arg0, arg1)
+}
+
+// FeedSyncData mocks base method.
+func (m *MockPastureSyncService) FeedSyncData(arg0 context.Context, arg1 *operationPb.FeedFormulaSyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedSyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedSyncData indicates an expected call of FeedSyncData.
+func (mr *MockPastureSyncServiceMockRecorder) FeedSyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedSyncData", reflect.TypeOf((*MockPastureSyncService)(nil).FeedSyncData), arg0, arg1)
+}

+ 353 - 0
module/backend/mock/StatisticService.go

@@ -0,0 +1,353 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: kpt-tmr-group/module/backend (interfaces: StatisticService)
+
+// Package kptservicemock is a generated GoMock package.
+package kptservicemock
+
+import (
+	bytes "bytes"
+	context "context"
+	model "kpt-tmr-group/model"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+)
+
+// MockStatisticService is a mock of StatisticService interface.
+type MockStatisticService struct {
+	ctrl     *gomock.Controller
+	recorder *MockStatisticServiceMockRecorder
+}
+
+// MockStatisticServiceMockRecorder is the mock recorder for MockStatisticService.
+type MockStatisticServiceMockRecorder struct {
+	mock *MockStatisticService
+}
+
+// NewMockStatisticService creates a new mock instance.
+func NewMockStatisticService(ctrl *gomock.Controller) *MockStatisticService {
+	mock := &MockStatisticService{ctrl: ctrl}
+	mock.recorder = &MockStatisticServiceMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockStatisticService) EXPECT() *MockStatisticServiceMockRecorder {
+	return m.recorder
+}
+
+// AnalysisMixedSprinkleDetail mocks base method.
+func (m *MockStatisticService) AnalysisMixedSprinkleDetail(arg0 context.Context, arg1 *operationPb.ProcessMixedSprinkleDetailRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "AnalysisMixedSprinkleDetail", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// AnalysisMixedSprinkleDetail indicates an expected call of AnalysisMixedSprinkleDetail.
+func (mr *MockStatisticServiceMockRecorder) AnalysisMixedSprinkleDetail(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AnalysisMixedSprinkleDetail", reflect.TypeOf((*MockStatisticService)(nil).AnalysisMixedSprinkleDetail), arg0, arg1)
+}
+
+// CowsAnalysis mocks base method.
+func (m *MockStatisticService) CowsAnalysis(arg0 context.Context, arg1 *operationPb.CowsAnalysisRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CowsAnalysis", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// CowsAnalysis indicates an expected call of CowsAnalysis.
+func (mr *MockStatisticServiceMockRecorder) CowsAnalysis(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CowsAnalysis", reflect.TypeOf((*MockStatisticService)(nil).CowsAnalysis), arg0, arg1)
+}
+
+// ExecutionTime mocks base method.
+func (m *MockStatisticService) ExecutionTime(arg0 context.Context, arg1 *operationPb.SearchAnalysisAccuracyRequest) (*model.ExecTimeResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExecutionTime", arg0, arg1)
+	ret0, _ := ret[0].(*model.ExecTimeResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExecutionTime indicates an expected call of ExecutionTime.
+func (mr *MockStatisticServiceMockRecorder) ExecutionTime(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecutionTime", reflect.TypeOf((*MockStatisticService)(nil).ExecutionTime), arg0, arg1)
+}
+
+// FeedChartStatistics mocks base method.
+func (m *MockStatisticService) FeedChartStatistics(arg0 context.Context, arg1 *operationPb.FeedChartStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedChartStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedChartStatistics indicates an expected call of FeedChartStatistics.
+func (mr *MockStatisticServiceMockRecorder) FeedChartStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedChartStatistics", reflect.TypeOf((*MockStatisticService)(nil).FeedChartStatistics), arg0, arg1)
+}
+
+// FeedMixedAndTmrName mocks base method.
+func (m *MockStatisticService) FeedMixedAndTmrName(arg0 context.Context, arg1 *operationPb.MixedCategoryTmrName) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedMixedAndTmrName", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedMixedAndTmrName indicates an expected call of FeedMixedAndTmrName.
+func (mr *MockStatisticServiceMockRecorder) FeedMixedAndTmrName(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedMixedAndTmrName", reflect.TypeOf((*MockStatisticService)(nil).FeedMixedAndTmrName), arg0, arg1)
+}
+
+// GetDataByName mocks base method.
+func (m *MockStatisticService) GetDataByName(arg0 context.Context, arg1 *operationPb.GetDataByNameRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetDataByName", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetDataByName indicates an expected call of GetDataByName.
+func (mr *MockStatisticServiceMockRecorder) GetDataByName(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDataByName", reflect.TypeOf((*MockStatisticService)(nil).GetDataByName), arg0, arg1)
+}
+
+// GetTrainNumber mocks base method.
+func (m *MockStatisticService) GetTrainNumber(arg0 context.Context, arg1 *operationPb.TrainNumberRequest) (*operationPb.TrainNumberResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetTrainNumber", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.TrainNumberResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetTrainNumber indicates an expected call of GetTrainNumber.
+func (mr *MockStatisticServiceMockRecorder) GetTrainNumber(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTrainNumber", reflect.TypeOf((*MockStatisticService)(nil).GetTrainNumber), arg0, arg1)
+}
+
+// InventoryStatisticsExcelExport mocks base method.
+func (m *MockStatisticService) InventoryStatisticsExcelExport(arg0 context.Context, arg1 *operationPb.SearchInventoryStatisticsRequest) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "InventoryStatisticsExcelExport", arg0, arg1)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// InventoryStatisticsExcelExport indicates an expected call of InventoryStatisticsExcelExport.
+func (mr *MockStatisticServiceMockRecorder) InventoryStatisticsExcelExport(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InventoryStatisticsExcelExport", reflect.TypeOf((*MockStatisticService)(nil).InventoryStatisticsExcelExport), arg0, arg1)
+}
+
+// SearchAccuracyAggStatistics mocks base method.
+func (m *MockStatisticService) SearchAccuracyAggStatistics(arg0 context.Context, arg1 *operationPb.AccuracyAggStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchAccuracyAggStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchAccuracyAggStatistics indicates an expected call of SearchAccuracyAggStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchAccuracyAggStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchAccuracyAggStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchAccuracyAggStatistics), arg0, arg1)
+}
+
+// SearchAnalysisAccuracy mocks base method.
+func (m *MockStatisticService) SearchAnalysisAccuracy(arg0 context.Context, arg1 *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchAnalysisAccuracy", arg0, arg1)
+	ret0, _ := ret[0].(*model.SearchAnalysisAccuracyResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchAnalysisAccuracy indicates an expected call of SearchAnalysisAccuracy.
+func (mr *MockStatisticServiceMockRecorder) SearchAnalysisAccuracy(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchAnalysisAccuracy", reflect.TypeOf((*MockStatisticService)(nil).SearchAnalysisAccuracy), arg0, arg1)
+}
+
+// SearchFeedStatistics mocks base method.
+func (m *MockStatisticService) SearchFeedStatistics(arg0 context.Context, arg1 *operationPb.SearchFeedStatisticsRequest) (*model.FeedStatisticsResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchFeedStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.FeedStatisticsResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchFeedStatistics indicates an expected call of SearchFeedStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchFeedStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchFeedStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchFeedStatistics), arg0, arg1)
+}
+
+// SearchFormulaEstimateList mocks base method.
+func (m *MockStatisticService) SearchFormulaEstimateList(arg0 context.Context, arg1 *operationPb.SearchFormulaEstimateRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchFormulaEstimateList", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchFormulaEstimateList indicates an expected call of SearchFormulaEstimateList.
+func (mr *MockStatisticServiceMockRecorder) SearchFormulaEstimateList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchFormulaEstimateList", reflect.TypeOf((*MockStatisticService)(nil).SearchFormulaEstimateList), arg0, arg1)
+}
+
+// SearchInventoryStatistics mocks base method.
+func (m *MockStatisticService) SearchInventoryStatistics(arg0 context.Context, arg1 *operationPb.SearchInventoryStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchInventoryStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchInventoryStatistics indicates an expected call of SearchInventoryStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchInventoryStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchInventoryStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchInventoryStatistics), arg0, arg1)
+}
+
+// SearchMixFeedStatistics mocks base method.
+func (m *MockStatisticService) SearchMixFeedStatistics(arg0 context.Context, arg1 *operationPb.MixFeedStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchMixFeedStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchMixFeedStatistics indicates an expected call of SearchMixFeedStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchMixFeedStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchMixFeedStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchMixFeedStatistics), arg0, arg1)
+}
+
+// SearchPriceStatistics mocks base method.
+func (m *MockStatisticService) SearchPriceStatistics(arg0 context.Context, arg1 *operationPb.SearchPriceStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchPriceStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchPriceStatistics indicates an expected call of SearchPriceStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchPriceStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchPriceStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchPriceStatistics), arg0, arg1)
+}
+
+// SearchProcessAnalysis mocks base method.
+func (m *MockStatisticService) SearchProcessAnalysis(arg0 context.Context, arg1 *operationPb.ProcessAnalysisRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchProcessAnalysis", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchProcessAnalysis indicates an expected call of SearchProcessAnalysis.
+func (mr *MockStatisticServiceMockRecorder) SearchProcessAnalysis(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchProcessAnalysis", reflect.TypeOf((*MockStatisticService)(nil).SearchProcessAnalysis), arg0, arg1)
+}
+
+// SearchSprinkleStatistics mocks base method.
+func (m *MockStatisticService) SearchSprinkleStatistics(arg0 context.Context, arg1 *operationPb.SprinkleStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchSprinkleStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchSprinkleStatistics indicates an expected call of SearchSprinkleStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchSprinkleStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchSprinkleStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchSprinkleStatistics), arg0, arg1)
+}
+
+// SearchUserMaterialsStatistics mocks base method.
+func (m *MockStatisticService) SearchUserMaterialsStatistics(arg0 context.Context, arg1 *operationPb.SearchUserMaterialsStatisticsRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchUserMaterialsStatistics", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchUserMaterialsStatistics indicates an expected call of SearchUserMaterialsStatistics.
+func (mr *MockStatisticServiceMockRecorder) SearchUserMaterialsStatistics(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchUserMaterialsStatistics", reflect.TypeOf((*MockStatisticService)(nil).SearchUserMaterialsStatistics), arg0, arg1)
+}
+
+// SprinkleFeedTime mocks base method.
+func (m *MockStatisticService) SprinkleFeedTime(arg0 context.Context, arg1 *operationPb.SprinkleFeedTimeRequest) (*model.SprinkleFeedTimeResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SprinkleFeedTime", arg0, arg1)
+	ret0, _ := ret[0].(*model.SprinkleFeedTimeResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SprinkleFeedTime indicates an expected call of SprinkleFeedTime.
+func (mr *MockStatisticServiceMockRecorder) SprinkleFeedTime(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SprinkleFeedTime", reflect.TypeOf((*MockStatisticService)(nil).SprinkleFeedTime), arg0, arg1)
+}
+
+// TopPasture mocks base method.
+func (m *MockStatisticService) TopPasture(arg0 context.Context, arg1 *operationPb.SearchAnalysisAccuracyRequest) (*model.GetPastureTopResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "TopPasture", arg0, arg1)
+	ret0, _ := ret[0].(*model.GetPastureTopResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// TopPasture indicates an expected call of TopPasture.
+func (mr *MockStatisticServiceMockRecorder) TopPasture(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TopPasture", reflect.TypeOf((*MockStatisticService)(nil).TopPasture), arg0, arg1)
+}
+
+// UserMaterialsStatisticsExcelExport mocks base method.
+func (m *MockStatisticService) UserMaterialsStatisticsExcelExport(arg0 context.Context, arg1 *operationPb.SearchUserMaterialsStatisticsRequest) (*bytes.Buffer, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "UserMaterialsStatisticsExcelExport", arg0, arg1)
+	ret0, _ := ret[0].(*bytes.Buffer)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// UserMaterialsStatisticsExcelExport indicates an expected call of UserMaterialsStatisticsExcelExport.
+func (mr *MockStatisticServiceMockRecorder) UserMaterialsStatisticsExcelExport(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserMaterialsStatisticsExcelExport", reflect.TypeOf((*MockStatisticService)(nil).UserMaterialsStatisticsExcelExport), arg0, arg1)
+}

+ 354 - 0
module/backend/mock/SystemService.go

@@ -0,0 +1,354 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: kpt-tmr-group/module/backend (interfaces: SystemService)
+
+// Package kptservicemock is a generated GoMock package.
+package kptservicemock
+
+import (
+	context "context"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+)
+
+// MockSystemService is a mock of SystemService interface.
+type MockSystemService struct {
+	ctrl     *gomock.Controller
+	recorder *MockSystemServiceMockRecorder
+}
+
+// MockSystemServiceMockRecorder is the mock recorder for MockSystemService.
+type MockSystemServiceMockRecorder struct {
+	mock *MockSystemService
+}
+
+// NewMockSystemService creates a new mock instance.
+func NewMockSystemService(ctrl *gomock.Controller) *MockSystemService {
+	mock := &MockSystemService{ctrl: ctrl}
+	mock.recorder = &MockSystemServiceMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockSystemService) EXPECT() *MockSystemServiceMockRecorder {
+	return m.recorder
+}
+
+// Auth mocks base method.
+func (m *MockSystemService) Auth(arg0 context.Context, arg1 *operationPb.UserAuthData) (*operationPb.SystemToken, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "Auth", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SystemToken)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// Auth indicates an expected call of Auth.
+func (mr *MockSystemServiceMockRecorder) Auth(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Auth", reflect.TypeOf((*MockSystemService)(nil).Auth), arg0, arg1)
+}
+
+// CreateSystemMenu mocks base method.
+func (m *MockSystemService) CreateSystemMenu(arg0 context.Context, arg1 *operationPb.AddMenuRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateSystemMenu", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateSystemMenu indicates an expected call of CreateSystemMenu.
+func (mr *MockSystemServiceMockRecorder) CreateSystemMenu(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSystemMenu", reflect.TypeOf((*MockSystemService)(nil).CreateSystemMenu), arg0, arg1)
+}
+
+// CreateSystemRole mocks base method.
+func (m *MockSystemService) CreateSystemRole(arg0 context.Context, arg1 *operationPb.AddRoleRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateSystemRole", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateSystemRole indicates an expected call of CreateSystemRole.
+func (mr *MockSystemServiceMockRecorder) CreateSystemRole(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSystemRole", reflect.TypeOf((*MockSystemService)(nil).CreateSystemRole), arg0, arg1)
+}
+
+// CreateSystemUser mocks base method.
+func (m *MockSystemService) CreateSystemUser(arg0 context.Context, arg1 *operationPb.AddSystemUser) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CreateSystemUser indicates an expected call of CreateSystemUser.
+func (mr *MockSystemServiceMockRecorder) CreateSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSystemUser", reflect.TypeOf((*MockSystemService)(nil).CreateSystemUser), arg0, arg1)
+}
+
+// DeleteSystemMenu mocks base method.
+func (m *MockSystemService) DeleteSystemMenu(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteSystemMenu", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteSystemMenu indicates an expected call of DeleteSystemMenu.
+func (mr *MockSystemServiceMockRecorder) DeleteSystemMenu(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSystemMenu", reflect.TypeOf((*MockSystemService)(nil).DeleteSystemMenu), arg0, arg1)
+}
+
+// DeleteSystemRole mocks base method.
+func (m *MockSystemService) DeleteSystemRole(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteSystemRole", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteSystemRole indicates an expected call of DeleteSystemRole.
+func (mr *MockSystemServiceMockRecorder) DeleteSystemRole(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSystemRole", reflect.TypeOf((*MockSystemService)(nil).DeleteSystemRole), arg0, arg1)
+}
+
+// DeleteSystemUser mocks base method.
+func (m *MockSystemService) DeleteSystemUser(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteSystemUser indicates an expected call of DeleteSystemUser.
+func (mr *MockSystemServiceMockRecorder) DeleteSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSystemUser", reflect.TypeOf((*MockSystemService)(nil).DeleteSystemUser), arg0, arg1)
+}
+
+// DetailsSystemUser mocks base method.
+func (m *MockSystemService) DetailsSystemUser(arg0 context.Context, arg1 int64) (*operationPb.UserDetails, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DetailsSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.UserDetails)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// DetailsSystemUser indicates an expected call of DetailsSystemUser.
+func (mr *MockSystemServiceMockRecorder) DetailsSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DetailsSystemUser", reflect.TypeOf((*MockSystemService)(nil).DetailsSystemUser), arg0, arg1)
+}
+
+// EditSystemMenu mocks base method.
+func (m *MockSystemService) EditSystemMenu(arg0 context.Context, arg1 *operationPb.AddMenuRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditSystemMenu", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditSystemMenu indicates an expected call of EditSystemMenu.
+func (mr *MockSystemServiceMockRecorder) EditSystemMenu(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditSystemMenu", reflect.TypeOf((*MockSystemService)(nil).EditSystemMenu), arg0, arg1)
+}
+
+// EditSystemRole mocks base method.
+func (m *MockSystemService) EditSystemRole(arg0 context.Context, arg1 *operationPb.AddRoleRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditSystemRole", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditSystemRole indicates an expected call of EditSystemRole.
+func (mr *MockSystemServiceMockRecorder) EditSystemRole(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditSystemRole", reflect.TypeOf((*MockSystemService)(nil).EditSystemRole), arg0, arg1)
+}
+
+// EditSystemUser mocks base method.
+func (m *MockSystemService) EditSystemUser(arg0 context.Context, arg1 *operationPb.AddSystemUser) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditSystemUser indicates an expected call of EditSystemUser.
+func (mr *MockSystemServiceMockRecorder) EditSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditSystemUser", reflect.TypeOf((*MockSystemService)(nil).EditSystemUser), arg0, arg1)
+}
+
+// GetCurrentUserName mocks base method.
+func (m *MockSystemService) GetCurrentUserName(arg0 context.Context) (string, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetCurrentUserName", arg0)
+	ret0, _ := ret[0].(string)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetCurrentUserName indicates an expected call of GetCurrentUserName.
+func (mr *MockSystemServiceMockRecorder) GetCurrentUserName(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentUserName", reflect.TypeOf((*MockSystemService)(nil).GetCurrentUserName), arg0)
+}
+
+// GetRolePermissions mocks base method.
+func (m *MockSystemService) GetRolePermissions(arg0 context.Context, arg1 int64) (*operationPb.RolePermissionsList, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetRolePermissions", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.RolePermissionsList)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetRolePermissions indicates an expected call of GetRolePermissions.
+func (mr *MockSystemServiceMockRecorder) GetRolePermissions(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRolePermissions", reflect.TypeOf((*MockSystemService)(nil).GetRolePermissions), arg0, arg1)
+}
+
+// GetSystemUserPermissions mocks base method.
+func (m *MockSystemService) GetSystemUserPermissions(arg0 context.Context, arg1 string) (*operationPb.SystemUserMenuPermissions, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetSystemUserPermissions", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SystemUserMenuPermissions)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetSystemUserPermissions indicates an expected call of GetSystemUserPermissions.
+func (mr *MockSystemServiceMockRecorder) GetSystemUserPermissions(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSystemUserPermissions", reflect.TypeOf((*MockSystemService)(nil).GetSystemUserPermissions), arg0, arg1)
+}
+
+// GetUserInfo mocks base method.
+func (m *MockSystemService) GetUserInfo(arg0 context.Context, arg1 string) (*operationPb.UserAuth, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetUserInfo", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.UserAuth)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetUserInfo indicates an expected call of GetUserInfo.
+func (mr *MockSystemServiceMockRecorder) GetUserInfo(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserInfo", reflect.TypeOf((*MockSystemService)(nil).GetUserInfo), arg0, arg1)
+}
+
+// IsShowSystemMenu mocks base method.
+func (m *MockSystemService) IsShowSystemMenu(arg0 context.Context, arg1 *operationPb.IsShowSystemMenuRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowSystemMenu", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowSystemMenu indicates an expected call of IsShowSystemMenu.
+func (mr *MockSystemServiceMockRecorder) IsShowSystemMenu(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowSystemMenu", reflect.TypeOf((*MockSystemService)(nil).IsShowSystemMenu), arg0, arg1)
+}
+
+// IsShowSystemUser mocks base method.
+func (m *MockSystemService) IsShowSystemUser(arg0 context.Context, arg1 *operationPb.IsShowSystemUserRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "IsShowSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// IsShowSystemUser indicates an expected call of IsShowSystemUser.
+func (mr *MockSystemServiceMockRecorder) IsShowSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowSystemUser", reflect.TypeOf((*MockSystemService)(nil).IsShowSystemUser), arg0, arg1)
+}
+
+// ResetPasswordSystemUser mocks base method.
+func (m *MockSystemService) ResetPasswordSystemUser(arg0 context.Context, arg1 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ResetPasswordSystemUser", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ResetPasswordSystemUser indicates an expected call of ResetPasswordSystemUser.
+func (mr *MockSystemServiceMockRecorder) ResetPasswordSystemUser(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetPasswordSystemUser", reflect.TypeOf((*MockSystemService)(nil).ResetPasswordSystemUser), arg0, arg1)
+}
+
+// SearchMobileList mocks base method.
+func (m *MockSystemService) SearchMobileList(arg0 context.Context, arg1 *operationPb.SearchMobileRequest) (*operationPb.SearchMobileResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchMobileList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchMobileResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchMobileList indicates an expected call of SearchMobileList.
+func (mr *MockSystemServiceMockRecorder) SearchMobileList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchMobileList", reflect.TypeOf((*MockSystemService)(nil).SearchMobileList), arg0, arg1)
+}
+
+// SearchSystemMenuList mocks base method.
+func (m *MockSystemService) SearchSystemMenuList(arg0 context.Context, arg1 *operationPb.SearchMenuRequest) (*operationPb.SearchMenuResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchSystemMenuList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchMenuResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchSystemMenuList indicates an expected call of SearchSystemMenuList.
+func (mr *MockSystemServiceMockRecorder) SearchSystemMenuList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchSystemMenuList", reflect.TypeOf((*MockSystemService)(nil).SearchSystemMenuList), arg0, arg1)
+}
+
+// SearchSystemRoleList mocks base method.
+func (m *MockSystemService) SearchSystemRoleList(arg0 context.Context, arg1 *operationPb.SearchRoleRequest) (*operationPb.SearchRoleResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchSystemRoleList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchRoleResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchSystemRoleList indicates an expected call of SearchSystemRoleList.
+func (mr *MockSystemServiceMockRecorder) SearchSystemRoleList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchSystemRoleList", reflect.TypeOf((*MockSystemService)(nil).SearchSystemRoleList), arg0, arg1)
+}
+
+// SearchSystemUserList mocks base method.
+func (m *MockSystemService) SearchSystemUserList(arg0 context.Context, arg1 *operationPb.SearchUserRequest) (*operationPb.SearchUserResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchSystemUserList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.SearchUserResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchSystemUserList indicates an expected call of SearchSystemUserList.
+func (mr *MockSystemServiceMockRecorder) SearchSystemUserList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchSystemUserList", reflect.TypeOf((*MockSystemService)(nil).SearchSystemUserList), arg0, arg1)
+}

+ 51 - 0
module/backend/mock/WxAppletService.go

@@ -0,0 +1,51 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: kpt-tmr-group/module/backend (interfaces: WxAppletService)
+
+// Package kptservicemock is a generated GoMock package.
+package kptservicemock
+
+import (
+	context "context"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	reflect "reflect"
+
+	gomock "github.com/golang/mock/gomock"
+)
+
+// MockWxAppletService is a mock of WxAppletService interface.
+type MockWxAppletService struct {
+	ctrl     *gomock.Controller
+	recorder *MockWxAppletServiceMockRecorder
+}
+
+// MockWxAppletServiceMockRecorder is the mock recorder for MockWxAppletService.
+type MockWxAppletServiceMockRecorder struct {
+	mock *MockWxAppletService
+}
+
+// NewMockWxAppletService creates a new mock instance.
+func NewMockWxAppletService(ctrl *gomock.Controller) *MockWxAppletService {
+	mock := &MockWxAppletService{ctrl: ctrl}
+	mock.recorder = &MockWxAppletServiceMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockWxAppletService) EXPECT() *MockWxAppletServiceMockRecorder {
+	return m.recorder
+}
+
+// GetOpenId mocks base method.
+func (m *MockWxAppletService) GetOpenId(arg0 context.Context, arg1 string) (*operationPb.WxOpenId, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetOpenId", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.WxOpenId)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetOpenId indicates an expected call of GetOpenId.
+func (mr *MockWxAppletServiceMockRecorder) GetOpenId(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOpenId", reflect.TypeOf((*MockWxAppletService)(nil).GetOpenId), arg0, arg1)
+}

+ 328 - 24
module/backend/mock/kptservice.go

@@ -9,7 +9,7 @@ import (
 	context "context"
 	io "io"
 	model "kpt-tmr-group/model"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	reflect "reflect"
 
 	gomock "github.com/golang/mock/gomock"
@@ -52,6 +52,20 @@ func (mr *MockKptServiceMockRecorder) AddCattleCategory(arg0, arg1 interface{})
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddCattleCategory", reflect.TypeOf((*MockKptService)(nil).AddCattleCategory), arg0, arg1)
 }
 
+// AddFeedByFeedFormula mocks base method.
+func (m *MockKptService) AddFeedByFeedFormula(arg0 context.Context, arg1 *operationPb.GroupAddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "AddFeedByFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// AddFeedByFeedFormula indicates an expected call of AddFeedByFeedFormula.
+func (mr *MockKptServiceMockRecorder) AddFeedByFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddFeedByFeedFormula", reflect.TypeOf((*MockKptService)(nil).AddFeedByFeedFormula), arg0, arg1)
+}
+
 // AddForageCategory mocks base method.
 func (m *MockKptService) AddForageCategory(arg0 context.Context, arg1 *operationPb.AddForageCategoryRequest) error {
 	m.ctrl.T.Helper()
@@ -66,6 +80,21 @@ func (mr *MockKptServiceMockRecorder) AddForageCategory(arg0, arg1 interface{})
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddForageCategory", reflect.TypeOf((*MockKptService)(nil).AddForageCategory), arg0, arg1)
 }
 
+// AnalysisMixedSprinkleDetail mocks base method.
+func (m *MockKptService) AnalysisMixedSprinkleDetail(arg0 context.Context, arg1 *operationPb.ProcessMixedSprinkleDetailRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "AnalysisMixedSprinkleDetail", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// AnalysisMixedSprinkleDetail indicates an expected call of AnalysisMixedSprinkleDetail.
+func (mr *MockKptServiceMockRecorder) AnalysisMixedSprinkleDetail(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AnalysisMixedSprinkleDetail", reflect.TypeOf((*MockKptService)(nil).AnalysisMixedSprinkleDetail), arg0, arg1)
+}
+
 // Auth mocks base method.
 func (m *MockKptService) Auth(arg0 context.Context, arg1 *operationPb.UserAuthData) (*operationPb.SystemToken, error) {
 	m.ctrl.T.Helper()
@@ -81,6 +110,48 @@ func (mr *MockKptServiceMockRecorder) Auth(arg0, arg1 interface{}) *gomock.Call
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Auth", reflect.TypeOf((*MockKptService)(nil).Auth), arg0, arg1)
 }
 
+// CancelDistributeFeedFormula mocks base method.
+func (m *MockKptService) CancelDistributeFeedFormula(arg0 context.Context, arg1 *operationPb.DistributeFeedFormulaRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CancelDistributeFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CancelDistributeFeedFormula indicates an expected call of CancelDistributeFeedFormula.
+func (mr *MockKptServiceMockRecorder) CancelDistributeFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CancelDistributeFeedFormula", reflect.TypeOf((*MockKptService)(nil).CancelDistributeFeedFormula), arg0, arg1)
+}
+
+// CategoryDeleteData mocks base method.
+func (m *MockKptService) CategoryDeleteData(arg0 context.Context, arg1 *operationPb.CategoryDeleteRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CategoryDeleteData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CategoryDeleteData indicates an expected call of CategoryDeleteData.
+func (mr *MockKptServiceMockRecorder) CategoryDeleteData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CategoryDeleteData", reflect.TypeOf((*MockKptService)(nil).CategoryDeleteData), arg0, arg1)
+}
+
+// CategorySyncData mocks base method.
+func (m *MockKptService) CategorySyncData(arg0 context.Context, arg1 *operationPb.CategorySyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CategorySyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// CategorySyncData indicates an expected call of CategorySyncData.
+func (mr *MockKptServiceMockRecorder) CategorySyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CategorySyncData", reflect.TypeOf((*MockKptService)(nil).CategorySyncData), arg0, arg1)
+}
+
 // CowsAnalysis mocks base method.
 func (m *MockKptService) CowsAnalysis(arg0 context.Context, arg1 *operationPb.CowsAnalysisRequest) (*model.PastureCommonResponse, error) {
 	m.ctrl.T.Helper()
@@ -208,6 +279,20 @@ func (mr *MockKptServiceMockRecorder) DeleteFeedFormula(arg0, arg1 interface{})
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFeedFormula", reflect.TypeOf((*MockKptService)(nil).DeleteFeedFormula), arg0, arg1)
 }
 
+// DeleteFeedFormulaDetail mocks base method.
+func (m *MockKptService) DeleteFeedFormulaDetail(arg0 context.Context, arg1 *operationPb.GroupAddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteFeedFormulaDetail", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteFeedFormulaDetail indicates an expected call of DeleteFeedFormulaDetail.
+func (mr *MockKptServiceMockRecorder) DeleteFeedFormulaDetail(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFeedFormulaDetail", reflect.TypeOf((*MockKptService)(nil).DeleteFeedFormulaDetail), arg0, arg1)
+}
+
 // DeleteForageCategory mocks base method.
 func (m *MockKptService) DeleteForageCategory(arg0 context.Context, arg1 int64) error {
 	m.ctrl.T.Helper()
@@ -335,6 +420,20 @@ func (mr *MockKptServiceMockRecorder) EditCattleCategory(arg0, arg1 interface{})
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditCattleCategory", reflect.TypeOf((*MockKptService)(nil).EditCattleCategory), arg0, arg1)
 }
 
+// EditFeedByFeedFormula mocks base method.
+func (m *MockKptService) EditFeedByFeedFormula(arg0 context.Context, arg1 *operationPb.AddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditFeedByFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// EditFeedByFeedFormula indicates an expected call of EditFeedByFeedFormula.
+func (mr *MockKptServiceMockRecorder) EditFeedByFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditFeedByFeedFormula", reflect.TypeOf((*MockKptService)(nil).EditFeedByFeedFormula), arg0, arg1)
+}
+
 // EditFeedFormula mocks base method.
 func (m *MockKptService) EditFeedFormula(arg0 context.Context, arg1 *operationPb.AddFeedFormulaRequest) error {
 	m.ctrl.T.Helper()
@@ -391,6 +490,21 @@ func (mr *MockKptServiceMockRecorder) EditGroupPasture(arg0, arg1 interface{}) *
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditGroupPasture", reflect.TypeOf((*MockKptService)(nil).EditGroupPasture), arg0, arg1)
 }
 
+// EditRecodeFeedFormula mocks base method.
+func (m *MockKptService) EditRecodeFeedFormula(arg0 context.Context, arg1 *operationPb.EditRecodeFeedFormulaRequest) (*operationPb.EditRecodeFeedFormulaResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "EditRecodeFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.EditRecodeFeedFormulaResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// EditRecodeFeedFormula indicates an expected call of EditRecodeFeedFormula.
+func (mr *MockKptServiceMockRecorder) EditRecodeFeedFormula(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EditRecodeFeedFormula", reflect.TypeOf((*MockKptService)(nil).EditRecodeFeedFormula), arg0, arg1)
+}
+
 // EditSystemMenu mocks base method.
 func (m *MockKptService) EditSystemMenu(arg0 context.Context, arg1 *operationPb.AddMenuRequest) error {
 	m.ctrl.T.Helper()
@@ -535,6 +649,21 @@ func (mr *MockKptServiceMockRecorder) ExcelTemplateForage(arg0 interface{}) *gom
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExcelTemplateForage", reflect.TypeOf((*MockKptService)(nil).ExcelTemplateForage), arg0)
 }
 
+// ExecutionTime mocks base method.
+func (m *MockKptService) ExecutionTime(arg0 context.Context, arg1 *operationPb.SearchAnalysisAccuracyRequest) (*model.ExecTimeResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ExecutionTime", arg0, arg1)
+	ret0, _ := ret[0].(*model.ExecTimeResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// ExecutionTime indicates an expected call of ExecutionTime.
+func (mr *MockKptServiceMockRecorder) ExecutionTime(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecutionTime", reflect.TypeOf((*MockKptService)(nil).ExecutionTime), arg0, arg1)
+}
+
 // FeedChartStatistics mocks base method.
 func (m *MockKptService) FeedChartStatistics(arg0 context.Context, arg1 *operationPb.FeedChartStatisticsRequest) (*model.PastureCommonResponse, error) {
 	m.ctrl.T.Helper()
@@ -550,6 +679,121 @@ func (mr *MockKptServiceMockRecorder) FeedChartStatistics(arg0, arg1 interface{}
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedChartStatistics", reflect.TypeOf((*MockKptService)(nil).FeedChartStatistics), arg0, arg1)
 }
 
+// FeedFormulaDetailBySort mocks base method.
+func (m *MockKptService) FeedFormulaDetailBySort(arg0 context.Context, arg1 *operationPb.GroupAddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailBySort", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaDetailBySort indicates an expected call of FeedFormulaDetailBySort.
+func (mr *MockKptServiceMockRecorder) FeedFormulaDetailBySort(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailBySort", reflect.TypeOf((*MockKptService)(nil).FeedFormulaDetailBySort), arg0, arg1)
+}
+
+// FeedFormulaDetailIsModify mocks base method.
+func (m *MockKptService) FeedFormulaDetailIsModify(arg0 context.Context, arg1 *operationPb.AddFeedFormulaDetail) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailIsModify", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaDetailIsModify indicates an expected call of FeedFormulaDetailIsModify.
+func (mr *MockKptServiceMockRecorder) FeedFormulaDetailIsModify(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailIsModify", reflect.TypeOf((*MockKptService)(nil).FeedFormulaDetailIsModify), arg0, arg1)
+}
+
+// FeedFormulaDetailList mocks base method.
+func (m *MockKptService) FeedFormulaDetailList(arg0 context.Context, arg1 *operationPb.FeedFormulaDetailRequest) (*operationPb.FeedFormulaDetailResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailList", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.FeedFormulaDetailResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedFormulaDetailList indicates an expected call of FeedFormulaDetailList.
+func (mr *MockKptServiceMockRecorder) FeedFormulaDetailList(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailList", reflect.TypeOf((*MockKptService)(nil).FeedFormulaDetailList), arg0, arg1)
+}
+
+// FeedFormulaDetailListSyncData mocks base method.
+func (m *MockKptService) FeedFormulaDetailListSyncData(arg0 context.Context, arg1 *operationPb.FeedFormulaSyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaDetailListSyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaDetailListSyncData indicates an expected call of FeedFormulaDetailListSyncData.
+func (mr *MockKptServiceMockRecorder) FeedFormulaDetailListSyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaDetailListSyncData", reflect.TypeOf((*MockKptService)(nil).FeedFormulaDetailListSyncData), arg0, arg1)
+}
+
+// FeedFormulaSyncData mocks base method.
+func (m *MockKptService) FeedFormulaSyncData(arg0 context.Context, arg1 *operationPb.FeedFormulaSyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaSyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedFormulaSyncData indicates an expected call of FeedFormulaSyncData.
+func (mr *MockKptServiceMockRecorder) FeedFormulaSyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaSyncData", reflect.TypeOf((*MockKptService)(nil).FeedFormulaSyncData), arg0, arg1)
+}
+
+// FeedFormulaUsage mocks base method.
+func (m *MockKptService) FeedFormulaUsage(arg0 context.Context, arg1 *operationPb.FeedFormulaUsageRequest) (*operationPb.FeedFormulaUsageResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedFormulaUsage", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.FeedFormulaUsageResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedFormulaUsage indicates an expected call of FeedFormulaUsage.
+func (mr *MockKptServiceMockRecorder) FeedFormulaUsage(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedFormulaUsage", reflect.TypeOf((*MockKptService)(nil).FeedFormulaUsage), arg0, arg1)
+}
+
+// FeedMixedAndTmrName mocks base method.
+func (m *MockKptService) FeedMixedAndTmrName(arg0 context.Context, arg1 *operationPb.MixedCategoryTmrName) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedMixedAndTmrName", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// FeedMixedAndTmrName indicates an expected call of FeedMixedAndTmrName.
+func (mr *MockKptServiceMockRecorder) FeedMixedAndTmrName(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedMixedAndTmrName", reflect.TypeOf((*MockKptService)(nil).FeedMixedAndTmrName), arg0, arg1)
+}
+
+// FeedSyncData mocks base method.
+func (m *MockKptService) FeedSyncData(arg0 context.Context, arg1 *operationPb.FeedFormulaSyncRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "FeedSyncData", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// FeedSyncData indicates an expected call of FeedSyncData.
+func (mr *MockKptServiceMockRecorder) FeedSyncData(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeedSyncData", reflect.TypeOf((*MockKptService)(nil).FeedSyncData), arg0, arg1)
+}
+
 // ForageEnumList mocks base method.
 func (m *MockKptService) ForageEnumList(arg0 context.Context) *operationPb.ForageEnumListResponse {
 	m.ctrl.T.Helper()
@@ -564,6 +808,35 @@ func (mr *MockKptServiceMockRecorder) ForageEnumList(arg0 interface{}) *gomock.C
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForageEnumList", reflect.TypeOf((*MockKptService)(nil).ForageEnumList), arg0)
 }
 
+// ForageListSort mocks base method.
+func (m *MockKptService) ForageListSort(arg0 context.Context, arg1 *operationPb.ForageListSortRequest) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ForageListSort", arg0, arg1)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// ForageListSort indicates an expected call of ForageListSort.
+func (mr *MockKptServiceMockRecorder) ForageListSort(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForageListSort", reflect.TypeOf((*MockKptService)(nil).ForageListSort), arg0, arg1)
+}
+
+// GetCurrentUserName mocks base method.
+func (m *MockKptService) GetCurrentUserName(arg0 context.Context) (string, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetCurrentUserName", arg0)
+	ret0, _ := ret[0].(string)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetCurrentUserName indicates an expected call of GetCurrentUserName.
+func (mr *MockKptServiceMockRecorder) GetCurrentUserName(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentUserName", reflect.TypeOf((*MockKptService)(nil).GetCurrentUserName), arg0)
+}
+
 // GetDataByName mocks base method.
 func (m *MockKptService) GetDataByName(arg0 context.Context, arg1 *operationPb.GetDataByNameRequest) (*model.PastureCommonResponse, error) {
 	m.ctrl.T.Helper()
@@ -767,32 +1040,18 @@ func (mr *MockKptServiceMockRecorder) IsShowSystemUser(arg0, arg1 interface{}) *
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsShowSystemUser", reflect.TypeOf((*MockKptService)(nil).IsShowSystemUser), arg0, arg1)
 }
 
-// ParentCattleCategoryList mocks base method.
-func (m *MockKptService) ParentCattleCategoryList(arg0 context.Context) map[operationPb.CattleCategoryParent_Kind]string {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "ParentCattleCategoryList", arg0)
-	ret0, _ := ret[0].(map[operationPb.CattleCategoryParent_Kind]string)
-	return ret0
-}
-
-// ParentCattleCategoryList indicates an expected call of ParentCattleCategoryList.
-func (mr *MockKptServiceMockRecorder) ParentCattleCategoryList(arg0 interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParentCattleCategoryList", reflect.TypeOf((*MockKptService)(nil).ParentCattleCategoryList), arg0)
-}
-
-// ParentForageCategoryList mocks base method.
-func (m *MockKptService) ParentForageCategoryList(arg0 context.Context) map[operationPb.ForageCategoryParent_Kind]string {
+// MixedFeedFormula mocks base method.
+func (m *MockKptService) MixedFeedFormula(arg0 context.Context, arg1 *operationPb.MixedFeedFormulaRequest) error {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "ParentForageCategoryList", arg0)
-	ret0, _ := ret[0].(map[operationPb.ForageCategoryParent_Kind]string)
+	ret := m.ctrl.Call(m, "MixedFeedFormula", arg0, arg1)
+	ret0, _ := ret[0].(error)
 	return ret0
 }
 
-// ParentForageCategoryList indicates an expected call of ParentForageCategoryList.
-func (mr *MockKptServiceMockRecorder) ParentForageCategoryList(arg0 interface{}) *gomock.Call {
+// MixedFeedFormula indicates an expected call of MixedFeedFormula.
+func (mr *MockKptServiceMockRecorder) MixedFeedFormula(arg0, arg1 interface{}) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParentForageCategoryList", reflect.TypeOf((*MockKptService)(nil).ParentForageCategoryList), arg0)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MixedFeedFormula", reflect.TypeOf((*MockKptService)(nil).MixedFeedFormula), arg0, arg1)
 }
 
 // ResetPasswordGroupPasture mocks base method.
@@ -868,6 +1127,21 @@ func (mr *MockKptServiceMockRecorder) SearchCattleCategoryList(arg0, arg1 interf
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchCattleCategoryList", reflect.TypeOf((*MockKptService)(nil).SearchCattleCategoryList), arg0, arg1)
 }
 
+// SearchFeedFormulaDetail mocks base method.
+func (m *MockKptService) SearchFeedFormulaDetail(arg0 context.Context, arg1 *operationPb.AddFeedFormulaDetail) (*operationPb.FeedFormulaDetailResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SearchFeedFormulaDetail", arg0, arg1)
+	ret0, _ := ret[0].(*operationPb.FeedFormulaDetailResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SearchFeedFormulaDetail indicates an expected call of SearchFeedFormulaDetail.
+func (mr *MockKptServiceMockRecorder) SearchFeedFormulaDetail(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchFeedFormulaDetail", reflect.TypeOf((*MockKptService)(nil).SearchFeedFormulaDetail), arg0, arg1)
+}
+
 // SearchFeedFormulaList mocks base method.
 func (m *MockKptService) SearchFeedFormulaList(arg0 context.Context, arg1 *operationPb.SearchFeedFormulaRequest) (*operationPb.SearchFeedFormulaListResponse, error) {
 	m.ctrl.T.Helper()
@@ -884,10 +1158,10 @@ func (mr *MockKptServiceMockRecorder) SearchFeedFormulaList(arg0, arg1 interface
 }
 
 // SearchFeedStatistics mocks base method.
-func (m *MockKptService) SearchFeedStatistics(arg0 context.Context, arg1 *operationPb.SearchFeedStatisticsRequest) (*model.PastureCommonResponse, error) {
+func (m *MockKptService) SearchFeedStatistics(arg0 context.Context, arg1 *operationPb.SearchFeedStatisticsRequest) (*model.FeedStatisticsResponse, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "SearchFeedStatistics", arg0, arg1)
-	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret0, _ := ret[0].(*model.FeedStatisticsResponse)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1108,6 +1382,36 @@ func (mr *MockKptServiceMockRecorder) SearchUserMaterialsStatistics(arg0, arg1 i
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchUserMaterialsStatistics", reflect.TypeOf((*MockKptService)(nil).SearchUserMaterialsStatistics), arg0, arg1)
 }
 
+// SmallMaterial mocks base method.
+func (m *MockKptService) SmallMaterial(arg0 context.Context, arg1 *operationPb.SmallMaterialRequest) (*model.PastureCommonResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SmallMaterial", arg0, arg1)
+	ret0, _ := ret[0].(*model.PastureCommonResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SmallMaterial indicates an expected call of SmallMaterial.
+func (mr *MockKptServiceMockRecorder) SmallMaterial(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SmallMaterial", reflect.TypeOf((*MockKptService)(nil).SmallMaterial), arg0, arg1)
+}
+
+// SprinkleFeedTime mocks base method.
+func (m *MockKptService) SprinkleFeedTime(arg0 context.Context, arg1 *operationPb.SprinkleFeedTimeRequest) (*model.SprinkleFeedTimeResponse, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "SprinkleFeedTime", arg0, arg1)
+	ret0, _ := ret[0].(*model.SprinkleFeedTimeResponse)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// SprinkleFeedTime indicates an expected call of SprinkleFeedTime.
+func (mr *MockKptServiceMockRecorder) SprinkleFeedTime(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SprinkleFeedTime", reflect.TypeOf((*MockKptService)(nil).SprinkleFeedTime), arg0, arg1)
+}
+
 // TopPasture mocks base method.
 func (m *MockKptService) TopPasture(arg0 context.Context, arg1 *operationPb.SearchAnalysisAccuracyRequest) (*model.GetPastureTopResponse, error) {
 	m.ctrl.T.Helper()

+ 36 - 19
module/backend/pasture_service.go

@@ -7,14 +7,15 @@ import (
 	"fmt"
 	"io"
 	"kpt-tmr-group/model"
-	"kpt-tmr-group/pkg/logger/zaplog"
-	"kpt-tmr-group/pkg/tool"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"strconv"
 	"sync"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"gitee.com/xuyiping_admin/pkg/tool"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+
 	"go.uber.org/zap"
 
 	"github.com/xuri/excelize/v2"
@@ -32,8 +33,6 @@ func (s *StoreEntry) CreateGroupPasture(ctx context.Context, req *operationPb.Ad
 	if err := s.PastureAccountDistribution(ctx, groupPasture); err != nil {
 		s.DB.Model(new(model.GroupPasture)).Where("id = ?", groupPasture.Id).Update("is_delete", operationPb.IsShow_NO)
 		return xerr.WithStack(err)
-	} else {
-		s.DB.Model(new(model.GroupPasture)).Where("id = ?", groupPasture.Id).Update("is_distribution", operationPb.IsShow_OK)
 	}
 	return nil
 }
@@ -43,22 +42,27 @@ func (s *StoreEntry) PastureAccountDistribution(ctx context.Context, groupPastur
 	if groupPasture.Domain == "" {
 		return nil
 	}
+
+	pastureId := groupPasture.Id
+	if groupPasture.PastureId > 0 {
+		pastureId = groupPasture.PastureId
+	}
 	body := &model.AccountDistribution{
 		Account:     groupPasture.Account,
 		UserName:    groupPasture.ManagerUser,
 		Password:    groupPasture.Password,
 		Phone:       groupPasture.ManagerPhone,
-		PastureId:   int32(groupPasture.Id),
+		PastureId:   int32(pastureId),
 		PastureName: groupPasture.Name,
 		Address:     groupPasture.Address,
 	}
 	res := &model.PastureCommonResponse{}
-	if _, err := s.PastureHttpClient(ctx, model.PastureAccountDistributionURl, groupPasture.GetPastureId(), body, res); err != nil {
+	if err := s.PastureHttpClient(ctx, model.PastureAccountDistributionURl, groupPasture.Id, body, res); err != nil {
 		zaplog.Error("AccountDistribution", zap.Any("url", model.PastureAccountDistributionURl), zap.Any("err", err), zap.Any("body", body), zap.Any("res", res))
 		return xerr.WithStack(err)
 	}
 
-	if res.Code != http.StatusOK {
+	if res.Code == http.StatusOK {
 		if err := s.DB.Model(new(model.GroupPasture)).Where("id = ?", groupPasture.Id).Update("is_distribution", operationPb.IsShow_OK).Error; err != nil {
 			zaplog.Error("AccountDistribution-Update", zap.Any("url", model.PastureAccountDistributionURl), zap.Any("err", err), zap.Any("body", body), zap.Any("res", res))
 			return xerr.Customf("%s", res.Msg)
@@ -154,6 +158,18 @@ func (s *StoreEntry) SearchGroupPastureList(ctx context.Context, req *operationP
 	}, nil
 }
 
+// GetGroupPastureById 根据id获取牧场端数据
+func (s *StoreEntry) GetGroupPastureById(ctx context.Context, id int64) (*model.GroupPasture, error) {
+	groupPasture := &model.GroupPasture{Id: id}
+	if err := s.DB.Model(new(model.GroupPasture)).
+		Where("is_delete = ?", operationPb.IsShow_OK).
+		Where("is_show = ?", operationPb.IsShow_OK).
+		First(groupPasture).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	return groupPasture, nil
+}
+
 // DataSyncGroupPastureList 用户数据下发的牧场
 func (s *StoreEntry) DataSyncGroupPastureList(ctx context.Context) ([]*model.GroupPasture, error) {
 	groupPastureList := make([]*model.GroupPasture, 0)
@@ -522,8 +538,8 @@ func (s *StoreEntry) CategoryDistribution(ctx context.Context, url string, req *
 		go func(data *model.GroupPasture) {
 			defer wg.Done()
 			res := &model.PastureCommonResponse{}
-			req.PastureId = int32(data.Id)
-			if _, err = s.PastureHttpClient(ctx, url, int64(data.Id), req, res); err != nil {
+			req.PastureId = int32(data.PastureId)
+			if err = s.PastureHttpClient(ctx, url, data.Id, req, res); err != nil {
 				zaplog.Error("CategoryDistribution",
 					zap.Any("url", url),
 					zap.Any("err", err),
@@ -539,7 +555,6 @@ func (s *StoreEntry) CategoryDistribution(ctx context.Context, url string, req *
 					zap.Any("res", res),
 				)
 			}
-
 		}(v)
 	}
 	wg.Wait()
@@ -559,7 +574,7 @@ func (s *StoreEntry) CategoryDelete(ctx context.Context, url string, req *model.
 			defer wg.Done()
 			res := &model.PastureCommonResponse{}
 			req.PastureId = int32(data.Id)
-			if _, err = s.PastureHttpClient(ctx, url, int64(data.Id), req, res); err != nil {
+			if err = s.PastureHttpClient(ctx, url, int64(data.Id), req, res); err != nil {
 				zaplog.Error("CategoryDelete",
 					zap.Any("url", url),
 					zap.Any("err", err),
@@ -605,7 +620,8 @@ func (s *StoreEntry) EditForage(ctx context.Context, req *operationPb.AddForageR
 		Name:               req.Name,
 		CategoryId:         int64(req.CategoryId),
 		CategoryName:       req.CategoryName,
-		MaterialType:       req.MaterialType,
+		MaterialTypeKey:    req.MaterialTypeKey,
+		MaterialTypeName:   req.MaterialTypeName,
 		UniqueEncode:       req.UniqueEncode,
 		ForageSourceId:     req.ForageSourceId,
 		PlanTypeId:         req.PlanTypeId,
@@ -664,7 +680,7 @@ func (s *StoreEntry) SearchForageList(ctx context.Context, req *operationPb.Sear
 		pref.Where("jump_delay = ?", req.JumpDelay)
 	}
 
-	if err := pref.Order("sort").Count(&count).Limit(int(req.Pagination.PageSize)).Offset(int(req.Pagination.PageOffset)).
+	if err := pref.Order("id DESC").Count(&count).Limit(int(req.Pagination.PageSize)).Offset(int(req.Pagination.PageOffset)).
 		Find(&forage).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
@@ -754,7 +770,7 @@ func (s *StoreEntry) ForageEnumList(ctx context.Context) *operationPb.ForageEnum
 	res.Data.CattleParentCategory = append(res.Data.CattleParentCategory,
 		&operationPb.CattleParentCategoryEnum{
 			Value: operationPb.CattleCategoryParent_INVALID,
-			Label: "所有",
+			Label: "所有类别",
 		},
 		&operationPb.CattleParentCategoryEnum{
 			Value: operationPb.CattleCategoryParent_LACTATION_CAW,
@@ -892,7 +908,7 @@ func (s *StoreEntry) ForageEnumList(ctx context.Context) *operationPb.ForageEnum
 
 	res.Data.FormulaList = append(res.Data.FormulaList, &operationPb.FormulaOptionEnum{
 		Value: 0,
-		Label: "所有",
+		Label: "所有配方",
 	})
 	formulaList := make([]*model.FeedFormula, 0)
 	if err := s.DB.Where("is_delete = ?", operationPb.IsShow_OK).Find(&formulaList).Error; err != nil {
@@ -1009,7 +1025,8 @@ func (s *StoreEntry) ExcelImportForage(ctx context.Context, req io.Reader) error
 		forageItem := &model.Forage{
 			Name:               name,
 			CategoryId:         int64(categoryId),
-			MaterialType:       0,
+			MaterialTypeKey:    0,
+			MaterialTypeName:   "",
 			UniqueEncode:       uniqueEncode,
 			ForageSourceId:     operationPb.ForageSource_Kind(forageSourceId),
 			PlanTypeId:         0,
@@ -1118,7 +1135,7 @@ func (s *StoreEntry) SmallMaterial(ctx context.Context, req *operationPb.SmallMa
 		},
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
+	if err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil

+ 244 - 2
module/backend/pasture_sync_service.go

@@ -4,8 +4,11 @@ import (
 	"context"
 	"errors"
 	"kpt-tmr-group/model"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	"math"
+	"net/http"
+
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/xerr"
 
 	"gorm.io/gorm"
 )
@@ -102,3 +105,242 @@ func (s *StoreEntry) CategoryDeleteData(ctx context.Context, req *operationPb.Ca
 	}
 	return nil
 }
+
+func (s *StoreEntry) FeedFormulaSyncData(ctx context.Context, req *operationPb.FeedFormulaSyncRequest) error {
+	groupPastureList, err := s.DataSyncGroupPastureList(ctx)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
+	var (
+		ok           bool
+		groupPasture *model.GroupPasture
+	)
+	for _, pastureDetail := range groupPastureList {
+		if pastureDetail.Id != int64(req.PastureId) {
+			continue
+		}
+		groupPasture = pastureDetail
+		ok = true
+	}
+
+	if ok {
+		total := 0
+		page := 1
+		pageSize := 100
+		for i := 0; i <= total; i++ {
+			body := &model.FeedFormulaListRequest{
+				PastureId: int32(groupPasture.PastureId),
+				Page:      int32(page),
+				PageSize:  int32(pageSize),
+			}
+			response := &model.FeedFormulaListResponse{}
+			if err = s.PastureHttpClient(ctx, model.FeedFormulaAsyncUrl, int64(req.PastureId), body, response); err != nil {
+				return xerr.WithStack(err)
+			}
+
+			if response.Code != http.StatusOK {
+				return xerr.Customf("%s", response.Msg)
+			}
+			if response.Data.Total > 0 && response.Data.List != nil {
+				total = int(math.Ceil(float64(response.Data.Total) / float64(pageSize)))
+			}
+			if err = s.FeedFormulaInsert(ctx, groupPasture, response.Data.List); err != nil {
+				return xerr.WithStack(err)
+			}
+			if total <= (pageSize * page) {
+				break
+			}
+			page++
+		}
+
+	}
+	return nil
+}
+
+func (s *StoreEntry) FeedFormulaInsert(ctx context.Context, groupPasture *model.GroupPasture, list []*model.FeedTemplate) error {
+	res := make([]*model.FeedFormula, 0)
+	for _, data := range list {
+		res = append(res, &model.FeedFormula{
+			Name:               data.TName,
+			Colour:             data.TColor,
+			EncodeNumber:       data.TCode,
+			CattleCategoryId:   operationPb.CattleCategoryParent_Kind(data.CCid),
+			CattleCategoryName: data.CCName,
+			FormulaTypeId:      operationPb.FormulaType_Kind(data.FTTypeId),
+			FormulaTypeName:    data.FTType,
+			DataSourceId:       operationPb.DataSource_FROM_PASTURE,
+			DataSourceName:     "牧场同步",
+			Remarks:            data.Remark,
+			Version:            data.Version,
+			PastureId:          groupPasture.PastureId,
+			PastureName:        groupPasture.Name,
+			PastureDataId:      data.Id,
+			IsShow:             operationPb.IsShow_Kind(data.Enable),
+			IsModify:           operationPb.IsShow_Kind(data.IsModify),
+			IsDelete:           operationPb.IsShow_OK,
+		})
+	}
+	if err := s.DB.Model(new(model.FeedFormula)).Create(res).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
+
+func (s *StoreEntry) FeedSyncData(ctx context.Context, req *operationPb.FeedFormulaSyncRequest) error {
+	groupPastureList, err := s.DataSyncGroupPastureList(ctx)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
+	var (
+		ok           bool
+		groupPasture *model.GroupPasture
+	)
+
+	for _, pastureDetail := range groupPastureList {
+		if pastureDetail.Id != int64(req.PastureId) {
+			continue
+		}
+		groupPasture = pastureDetail
+		ok = true
+	}
+
+	if ok {
+
+		if req.Page <= 0 {
+			req.Page = 1
+		}
+		if req.PageSize <= 0 {
+			req.PageSize = 1000
+		}
+
+		body := &model.FeedFormulaListRequest{
+			PastureId: int32(groupPasture.PastureId),
+			Page:      req.Page,
+			PageSize:  req.PageSize,
+		}
+		response := &model.FeedListResponse{}
+		if err = s.PastureHttpClient(ctx, model.FeedAsyncUrl, int64(req.PastureId), body, response); err != nil {
+			return xerr.WithStack(err)
+		}
+
+		if response.Code != http.StatusOK {
+			return xerr.Customf("%s", response.Msg)
+		}
+		if err = s.FeedInsert(ctx, groupPasture, response.Data.List); err != nil {
+			return xerr.WithStack(err)
+		}
+
+	}
+	return nil
+}
+
+// FeedInsert 饲料数据同步
+func (s *StoreEntry) FeedInsert(ctx context.Context, groupPasture *model.GroupPasture, list []*model.Feed) error {
+	res := make([]*model.Forage, 0)
+	for _, data := range list {
+		if data.Id <= 0 {
+			continue
+		}
+
+		res = append(res, model.NewForageByPastureFeed(groupPasture, data))
+	}
+
+	if err := s.DB.Model(new(model.Forage)).Create(res).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
+
+// FeedFormulaDetailListSyncData 饲料配方详情同步
+func (s *StoreEntry) FeedFormulaDetailListSyncData(ctx context.Context, req *operationPb.FeedFormulaSyncRequest) error {
+	groupPastureList, err := s.DataSyncGroupPastureList(ctx)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
+	var (
+		ok           bool
+		groupPasture *model.GroupPasture
+	)
+	for _, pastureDetail := range groupPastureList {
+		if pastureDetail.Id != int64(req.PastureId) {
+			continue
+		}
+		groupPasture = pastureDetail
+		ok = true
+	}
+
+	if ok {
+		total := 0
+		page := 1
+		pageSize := 100
+		for i := 0; i <= total; i++ {
+			body := &model.FeedFormulaListRequest{
+				PastureId: int32(groupPasture.PastureId),
+				Page:      int32(page),
+				PageSize:  int32(pageSize),
+			}
+			response := &model.FeedFormulaDetailListResponse{}
+			if err = s.PastureHttpClient(ctx, model.FeedFormulaDetailListAsyncUrl, int64(req.PastureId), body, response); err != nil {
+				return xerr.WithStack(err)
+			}
+
+			if response.Code != http.StatusOK {
+				return xerr.Customf("%s", response.Msg)
+			}
+			if response.Data.Total > 0 && response.Data.List != nil {
+				total = int(math.Ceil(float64(response.Data.Total) / float64(pageSize)))
+			}
+			if total <= (page * pageSize) {
+				break
+			}
+			page++
+			if err = s.FeedFormulaDetailInsert(ctx, groupPasture, response.Data.List); err != nil {
+				return xerr.WithStack(err)
+			}
+		}
+
+	}
+	return nil
+}
+
+func (s *StoreEntry) FeedFormulaDetailInsert(ctx context.Context, groupPasture *model.GroupPasture, list []*model.FeedTemplateDetail) error {
+	res := make([]*model.FeedFormulaDetail, 0)
+	for _, data := range list {
+		if data.Id <= 0 {
+			continue
+		}
+
+		isLockCowCountRatio := 0
+		if data.IsLockCount == 0 {
+			isLockCowCountRatio = 2
+		}
+		if data.IsLockCount == 1 {
+			isLockCowCountRatio = 1
+		}
+
+		res = append(res, &model.FeedFormulaDetail{
+			PastureId:           groupPasture.PastureId,
+			PastureName:         groupPasture.Name,
+			PastureDataId:       data.Id,
+			ForageId:            data.FId,
+			FeedFormulaId:       data.FtId,
+			Weight:              int32(data.FWeight * 100),
+			ForageGroupName:     data.FeedGroup,
+			ForageName:          data.FName,
+			StirDelay:           data.AutoSecond,
+			AllowError:          data.Deviation,
+			Prefit:              data.PreFtId,
+			IsShow:              operationPb.IsShow_OK,
+			IsLockCowCountRatio: operationPb.IsShow_Kind(isLockCowCountRatio),
+			Sort:                data.Sort,
+		})
+	}
+
+	if err := s.DB.Model(new(model.FeedFormulaDetail)).Create(res).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}

+ 188 - 223
module/backend/statistic_service.go

@@ -7,13 +7,14 @@ import (
 	"errors"
 	"fmt"
 	"kpt-tmr-group/model"
-	"kpt-tmr-group/pkg/logger/zaplog"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"sort"
 	"sync"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+
 	"gorm.io/gorm"
 
 	"github.com/xuri/excelize/v2"
@@ -32,27 +33,27 @@ func (s *StoreEntry) PastureDetailById(ctx context.Context, pastureId int64) (*m
 	return result, nil
 }
 
-func (s *StoreEntry) PastureHttpClient(ctx context.Context, apiUrl string, pastureId int64, body, response interface{}) (*model.GroupPasture, error) {
+func (s *StoreEntry) PastureHttpClient(ctx context.Context, apiUrl string, pastureId int64, body, response interface{}) error {
 	pastureDetail, err := s.PastureDetailById(ctx, pastureId)
 	if err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
-			return nil, xerr.Customf("该牧场不存在")
+			return xerr.Customf("该牧场不存在")
 		}
 		zaplog.Error("PastureHttpClient", zap.Any("Err", err), zap.Int64("pastureId", pastureId))
-		return nil, xerr.Customf("该牧场数据错误,Err:%s", err)
+		return xerr.Customf("该牧场数据错误,Err:%s", err)
 	}
 	pastureClient := model.NewPastureClient(pastureDetail)
 	url := fmt.Sprintf("%s/%s", pastureDetail.Domain, apiUrl)
 	result, err := pastureClient.DoPost(url, body)
 	if err != nil {
-		return pastureDetail, xerr.WithStack(err)
+		return xerr.WithStack(err)
 	}
 
 	zaplog.Info("PastureHttpClient", zap.String("url", url), zap.Any("request", body), zap.String("response", string(result)))
 	if err = json.Unmarshal(result, response); err != nil {
-		return pastureDetail, xerr.WithStack(err)
+		return xerr.WithStack(err)
 	}
-	return pastureDetail, nil
+	return nil
 }
 
 // SearchFormulaEstimateList 配方评估
@@ -61,18 +62,18 @@ func (s *StoreEntry) SearchFormulaEstimateList(ctx context.Context, req *operati
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
-		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
 		ParamMaps: &model.FormulaEstimateParams{
-			PastureId: fmt.Sprintf("%d", req.PastureId),
+			PastureId: fmt.Sprintf("%d", pastureId),
 			StartTime: req.StartTime,
 			StopTime:  req.EndTime,
 			Search:    fmt.Sprintf("%d", req.SearchType),
@@ -81,7 +82,7 @@ func (s *StoreEntry) SearchFormulaEstimateList(ctx context.Context, req *operati
 		},
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -93,18 +94,18 @@ func (s *StoreEntry) SearchInventoryStatistics(ctx context.Context, req *operati
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
-		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
 		ParamMaps: &model.InventoryStatisticsParams{
-			PastureId: fmt.Sprintf("%d", req.PastureId),
+			PastureId: fmt.Sprintf("%d", pastureId),
 			StartTime: req.StartTime,
 			StopTime:  req.EndTime,
 			FeedName:  req.FeedName,
@@ -115,7 +116,7 @@ func (s *StoreEntry) SearchInventoryStatistics(ctx context.Context, req *operati
 			List: make([]*model.InventoryStatisticsList, 0),
 		},
 	}
-	if _, err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -214,19 +215,19 @@ func (s *StoreEntry) SearchUserMaterialsStatistics(ctx context.Context, req *ope
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
-		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
 		Checked:    req.ErrorCheck,
 		ParamMaps: &model.UserMaterialsStatisticsParams{
-			PastureId: fmt.Sprintf("%d", req.PastureId),
+			PastureId: fmt.Sprintf("%d", pastureId),
 			StartTime: req.StartTime,
 			StopTime:  req.EndTime,
 			FeedName:  req.FeedName,
@@ -236,7 +237,7 @@ func (s *StoreEntry) SearchUserMaterialsStatistics(ctx context.Context, req *ope
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{
 		List: &model.UserMaterialsList{},
 	}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlReportForm, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, model.UrlReportForm, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -304,7 +305,7 @@ func (s *StoreEntry) UserMaterialsStatisticsExcelExport(ctx context.Context, req
 	}
 
 	excelValuesKeys := make([]int, 0)
-	for k, _ := range excelValuesList {
+	for k := range excelValuesList {
 		excelValuesKeys = append(excelValuesKeys, k)
 	}
 	sort.Ints(excelValuesKeys)
@@ -327,25 +328,25 @@ func (s *StoreEntry) SearchPriceStatistics(ctx context.Context, req *operationPb
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
-		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
 		ParamMaps: &model.PriceStatisticsParams{
-			PastureId: fmt.Sprintf("%d", req.PastureId),
+			PastureId: fmt.Sprintf("%d", pastureId),
 			StartTime: req.StartTime,
 			StopTime:  req.EndTime,
 			FeedName:  req.FeedName,
 		},
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlReportForm, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, model.UrlReportForm, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -374,38 +375,34 @@ func (s *StoreEntry) SearchFeedStatistics(ctx context.Context, req *operationPb.
 		}
 	}
 
-	times := ""
-	if req.ClassNumber > 0 {
-		times = fmt.Sprintf("%d", req.ClassNumber)
-	}
-
 	wg := sync.WaitGroup{}
 	wg.Add(len(req.PastureId))
 	for _, v := range req.PastureId {
 		go func(pastureId int32) {
 			defer wg.Done()
+
+			groupPasture, err := s.GetGroupPastureListById(ctx, int64(pastureId))
+			if err != nil {
+				zaplog.Error("SearchFeedStatistics", zap.Any("GetGroupPastureListById", err))
+				return
+			}
+			pastureID := pastureId
+			if groupPasture.PastureId > 0 {
+				pastureID = int32(groupPasture.PastureId)
+			}
+
 			body := &model.PastureCommonRequest{
 				Name:       req.ApiName,
 				Page:       req.Pagination.Page,
 				Offset:     req.Pagination.PageOffset,
-				PageCount:  req.Pagination.PageSize,
 				ReturnType: "Map",
-				ParamMaps: &model.FeedStatisticsParams{
-					PastureId: fmt.Sprintf("%d", pastureId),
-					StartTime: req.StartTime,
-					StopTime:  req.StartTime,
-					Date:      req.StartTime,
-					FeedTName: req.FormulaTemplate,
-					BarName:   req.BarnName,
-					CowClass:  req.CattleCategoryName,
-					Times:     times,
-				},
+				ParamMaps:  model.NewFeedStatisticsParams(int64(pastureID), req),
 			}
 			response := &model.PastureCommonResponse{
 				Data: &model.PastureCommonData{},
 			}
-			groupPasture, err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(pastureId), body, response)
-			if err != nil {
+
+			if err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(pastureId), body, response); err != nil {
 				zaplog.Error("SearchFeedStatistics",
 					zap.Any("pastureId", pastureId),
 					zap.Any("url", model.UrlDataByName),
@@ -413,14 +410,10 @@ func (s *StoreEntry) SearchFeedStatistics(ctx context.Context, req *operationPb.
 					zap.Any("response", response))
 				return
 			}
+
 			if response.Code == http.StatusOK && response.Data.List != nil {
-				if req.ApiName == "getFeedEfficiencySC" {
-					feedStatisticsConversions := FeedStatisticsConversions(response.Data.List)
-					feedStatisticsConversions.PastureName = groupPasture.Name
-					res.Data.List[groupPasture.Name] = FeedStatisticsConversions(response.Data.List)
-				} else {
-					res.Data.List[groupPasture.Name] = response.Data.List
-				}
+				feedStatisticsConversions := FeedStatisticsConversions(response.Data.List, groupPasture.Name)
+				res.Data.List[groupPasture.Name] = feedStatisticsConversions
 			}
 		}(v)
 	}
@@ -430,65 +423,79 @@ func (s *StoreEntry) SearchFeedStatistics(ctx context.Context, req *operationPb.
 }
 
 // FeedStatisticsConversions 数据转换
-func FeedStatisticsConversions(req interface{}) *model.FeedStatisticsConversions {
-	feedStatisticsList := &model.FeedStatisticsConversions{}
+func FeedStatisticsConversions(req interface{}, pastureName string) []*model.FeedStatisticsConversions {
+	feedStatisticsList := make([]*model.FeedStatisticsConversions, 0)
 	if data, ok := req.([]interface{}); ok && len(data) > 0 {
-		value := data[0]
-		if v, yes := value.(map[string]interface{}); yes {
-			if d, t := v["TMR干物质"]; t {
-				feedStatisticsList.TmrDryMatter = d.(string)
-			}
-			if d, t := v["barname"]; t {
-				feedStatisticsList.BarName = d.(string)
-			}
-			if d, t := v["产奶量"]; t {
-				feedStatisticsList.MilkYield = d.(string)
-			}
-			if d, t := v["今日剩料量"]; t {
-				feedStatisticsList.TodayLeftovers = d.(string)
-			}
-			if d, t := v["公斤奶饲料成本"]; t {
-				feedStatisticsList.FeedCosts = d.(float64)
-			}
-			if d, t := v["剩料率"]; t {
-				feedStatisticsList.LeftoverRate = d.(string)
-			}
-			if d, t := v["实际干物质采食量"]; t {
-				feedStatisticsList.ActualDryMatterIntake = d.(string)
-			}
-			if d, t := v["实际成本"]; t {
-				feedStatisticsList.ActualCost = d.(string)
-			}
-			if d, t := v["实际牛头数"]; t {
-				feedStatisticsList.ActualNumberOfCattle = d.(string)
-			}
-			if d, t := v["应混料量"]; t {
-				feedStatisticsList.AmountToBeMixed = d.(string)
-			}
-			if d, t := v["混料时间"]; t {
-				feedStatisticsList.MixingTime = d.(string)
+		for _, value := range data {
+			feedStatistics := &model.FeedStatisticsConversions{
+				PastureName: pastureName,
 			}
-			if d, t := v["牲畜类别"]; t {
-				feedStatisticsList.CategoryCattleName = d.(string)
-			}
-			if d, t := v["理论干物质"]; t {
-				feedStatisticsList.TheoreticalDryMatter = d.(string)
-			}
-			if d, t := v["转投剩料量"]; t {
-				feedStatisticsList.LeftoverMaterial = d.(float64)
-			}
-			if d, t := v["配方干物质采食量"]; t {
-				feedStatisticsList.FormulatedDryMatterIntake = d.(string)
-			}
-			if d, t := v["配方成本"]; t {
-				feedStatisticsList.CostOfFormulation = d.(string)
-			}
-			if d, t := v["采食率"]; t {
-				feedStatisticsList.FoodIntakeRate = d.(string)
-			}
-			if d, t := v["饲料转化率"]; t {
-				feedStatisticsList.FeedConversionRatio = d.(float64)
+			if v, yes := value.(map[string]interface{}); yes {
+				if d, t := v["TMR干物质"]; t {
+					feedStatistics.TmrDryMatter = d.(string)
+				}
+				if d, t := v["barname"]; t {
+					feedStatistics.BarName = d.(string)
+				}
+				if d, t := v["产奶量"]; t {
+					feedStatistics.MilkYield = d.(string)
+				}
+				if d, t := v["今日剩料量"]; t {
+					feedStatistics.TodayLeftovers = d.(string)
+				}
+				if d, t := v["公斤奶饲料成本"]; t {
+					feedStatistics.FeedCosts = d.(float64)
+				}
+				if d, t := v["剩料率"]; t {
+					feedStatistics.LeftoverRate = d.(string)
+				}
+				if d, t := v["实际干物质采食量"]; t {
+					feedStatistics.ActualDryMatterIntake = d.(string)
+				}
+				if d, t := v["实际成本"]; t {
+					feedStatistics.ActualCost = d.(string)
+				}
+				if d, t := v["实际牛头数"]; t {
+					feedStatistics.ActualNumberOfCattle = d.(string)
+				}
+				if d, t := v["应混料量"]; t {
+					feedStatistics.AmountToBeMixed = d.(string)
+				}
+				if d, t := v["混料时间"]; t {
+					feedStatistics.MixingTime = d.(string)
+				}
+				if d, t := v["牲畜类别"]; t {
+					feedStatistics.CategoryCattleName = d.(string)
+				}
+				if d, t := v["理论干物质"]; t {
+					feedStatistics.TheoreticalDryMatter = d.(string)
+				}
+				if d, t := v["转投剩料量"]; t {
+					feedStatistics.LeftoverMaterial = d.(float64)
+				}
+				if d, t := v["配方干物质采食量"]; t {
+					feedStatistics.FormulatedDryMatterIntake = d.(string)
+				}
+				if d, t := v["配方成本"]; t {
+					feedStatistics.CostOfFormulation = d.(string)
+				}
+				if d, t := v["采食率"]; t {
+					feedStatistics.FoodIntakeRate = d.(string)
+				}
+				if d, t := v["饲料转化率"]; t {
+					feedStatistics.FeedConversionRatio = d.(float64)
+				}
+				if d, t := v["配方模板"]; t {
+					feedStatistics.FeedFormulaName = d.(string)
+				}
+				if d, t := v["实际混料量"]; t {
+					feedStatistics.ActualMixedVolume = d.(string)
+				}
+				if d, t := v["撒料量"]; t {
+					feedStatistics.SprinkleVolume = d.(string)
+				}
 			}
+			feedStatisticsList = append(feedStatisticsList, feedStatistics)
 		}
 	}
 	return feedStatisticsList
@@ -500,15 +507,16 @@ func (s *StoreEntry) FeedChartStatistics(ctx context.Context, req *operationPb.F
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.FeedChartParams{
 		ParamMaps: &model.ParamMaps{
-			PastureId: fmt.Sprintf("%d", req.PastureId),
+			PastureId: fmt.Sprintf("%d", pastureId),
 			StartTime: req.StartTime,
-			StopTime:  req.StartTime,
+			StopTime:  req.EndTime,
 			Status:    req.Status,
 		},
 	}
@@ -517,7 +525,7 @@ func (s *StoreEntry) FeedChartStatistics(ctx context.Context, req *operationPb.F
 		return nil, xerr.Customf("错误的接口类型:%s", req.ApiType)
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, url, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, url, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -529,24 +537,24 @@ func (s *StoreEntry) CowsAnalysis(ctx context.Context, req *operationPb.CowsAnal
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
-		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
 		ParamMaps: &model.MixFeedStatisticsParams{
-			PastureId: fmt.Sprintf("%d", req.PastureId),
+			PastureId: fmt.Sprintf("%d", pastureId),
 			StartTime: req.StartTime,
 			StopTime:  req.StartTime,
 		},
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -558,38 +566,17 @@ func (s *StoreEntry) SearchAccuracyAggStatistics(ctx context.Context, req *opera
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.FeedChartParams{
-		ParamMaps: &model.AccuracyAggParams{
-			PastureId: fmt.Sprintf("%d", req.PastureId),
-			StartTime: req.StartTime,
-			StopTime:  req.EndTime,
-			FName:     req.Fname,
-			Sort:      req.Sort,
-			Status:    req.Status,
-			Times:     req.Times,
-			Genre:     req.Genre,
-			IsDate:    req.Isdate,
-			Hlwc1:     req.Hlwc1,
-			Hlwc2:     req.Hlwc2,
-			Hlzq1:     req.Hlzq1,
-			Hlzq2:     req.Hlzq2,
-			Hlzql1:    req.Hlzql1,
-			Hlzql2:    req.Hlzql2,
-			Slwc1:     req.Slwc1,
-			Slwc2:     req.Slwc2,
-			Slzq1:     req.Slzq1,
-			Slzq2:     req.Slzq2,
-			Slzql1:    req.Slzql1,
-			Slzql2:    req.Slzql2,
-			Error:     req.IsError,
-		},
+		ParamMaps: model.NewAccuracyAggParams(int64(pastureId), req),
 	}
+
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlSummary, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, model.UrlSummary, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -601,42 +588,20 @@ func (s *StoreEntry) SearchMixFeedStatistics(ctx context.Context, req *operation
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
-	}
-
-	times := ""
-	if req.ClassNumber > 0 {
-		times = fmt.Sprintf("%d", req.ClassNumber)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
-		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
-		ParamMaps: &model.MixFeedStatisticsParams{
-			PastureId:   fmt.Sprintf("%d", req.PastureId),
-			StartTime:   req.StartTime,
-			StopTime:    req.StartTime,
-			TmrTName:    req.EquipmentName,
-			ProjName:    req.TrainNumber,
-			Times:       times,
-			ButtonType:  req.ButtonType,
-			TempletName: req.FormulationName,
-			Isuse:       req.IsUse,
-			Hlwc1:       req.Hlwc1,
-			Hlwc2:       req.Hlwc2,
-			Hlzq1:       req.Hlzq1,
-			Hlzq2:       req.Hlzq2,
-			Hlzql1:      req.Hlzql1,
-			Hlzql2:      req.Hlzql2,
-			Error:       req.IsError,
-		},
+		ParamMaps:  model.NewMixFeedStatisticsParams(int64(pastureId), req),
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -648,42 +613,20 @@ func (s *StoreEntry) SearchSprinkleStatistics(ctx context.Context, req *operatio
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
-	times := ""
-	if req.ClassNumber > 0 {
-		times = fmt.Sprintf("%d", req.ClassNumber)
-	}
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
-		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
-		ParamMaps: &model.SprinkleStatisticsParams{
-			PastureId:   fmt.Sprintf("%d", req.PastureId),
-			StartTime:   req.StartTime,
-			StopTime:    req.StartTime,
-			TmrTName:    req.EquipmentName,
-			ProjName:    req.TrainNumber,
-			Times:       times,
-			ButtonType:  req.ButtonType,
-			TempletName: req.FormulationName,
-			Isuse:       req.IsUse,
-			Fname:       req.BarnName,
-			Slwc1:       req.Slwc1,
-			Slwc2:       req.Slwc2,
-			Slzq2:       req.Slzq2,
-			Slzq1:       req.Slzq1,
-			Slzql1:      req.Slzql1,
-			Slzql2:      req.Slzql2,
-			Error:       req.IsError,
-		},
+		ParamMaps:  model.NewSprinkleStatisticsParams(int64(pastureId), req),
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -695,37 +638,52 @@ func (s *StoreEntry) SearchProcessAnalysis(ctx context.Context, req *operationPb
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
-		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
-		ParamMaps: &model.ProcessAnalysisParams{
-			PastureId:   fmt.Sprintf("%d", req.PastureId),
-			StartTime:   req.StartTime,
-			StopTime:    req.StartTime,
-			TmrTName:    req.TmrName,
-			IsCompleted: "",
-			LpPlanType:  fmt.Sprintf("%d", req.PlanType),
-			FClassId:    req.MixFeedType,
-			Hlzq1:       req.Hlzq1,
-			Hlzq2:       req.Hlzq2,
-			Hlwc1:       req.Hlwc1,
-			Hlwc2:       req.Hlwc2,
-			Slwc1:       req.Slwc1,
-			Slwc2:       req.Slwc2,
-			Slzq2:       req.Slzq2,
-			Slzq1:       req.Slzq1,
-			Error:       req.ErrorRange,
-		},
+		ParamMaps:  model.NewProcessAnalysisParams(int64(pastureId), req),
+	}
+	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
+	if err = s.PastureHttpClient(ctx, model.UrlProcess, int64(req.PastureId), body, response); err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	if response.Data.List == nil {
+		response.Data.List = []int64{}
+	}
+	return response, nil
+}
+
+func (s *StoreEntry) AnalysisMixedSprinkleDetail(ctx context.Context, req *operationPb.ProcessMixedSprinkleDetailRequest) (*model.PastureCommonResponse, error) {
+	groupPasture, err := s.GetGroupPastureListById(ctx, int64(req.PastureId))
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	pastureId := req.PastureId
+	if groupPasture.PastureId > 0 {
+		pastureId = int32(groupPasture.PastureId)
+	}
+	body := &model.PastureCommonRequest{
+		Name:       req.ApiName,
+		Page:       req.Pagination.Page,
+		Offset:     req.Pagination.PageOffset,
+		ReturnType: "Map",
+		ParamMaps:  model.NewMixedSprinkleDetailRequest(int64(pastureId), req),
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlProcess, int64(req.PastureId), body, response); err != nil {
+
+	apiURl := model.UrlDataByName
+	if req.ApiName == "getprocessAnalysisTB" {
+		apiURl = model.UrlReportForm
+	}
+	if err = s.PastureHttpClient(ctx, apiURl, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -737,20 +695,27 @@ func (s *StoreEntry) GetDataByName(ctx context.Context, req *operationPb.GetData
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.PastureCommonRequest{
-		Name: req.ApiName,
+		Name:   req.ApiName,
+		Page:   req.Page,
+		Offset: req.Offset,
 		ParamMaps: &model.GetDataByNameParams{
-			PastureId: fmt.Sprintf("%d", req.PastureId),
+			PastureId: fmt.Sprintf("%d", pastureId),
 			StartTime: req.StartTime,
-			StopTime:  req.StartTime,
+			StopTime:  req.EndTime,
+			Pid:       req.Pid,
+			Optdevice: req.Optdevice,
+			FtId:      req.Ftid,
+			Name:      req.Name,
 		},
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return response, nil
@@ -762,23 +727,23 @@ func (s *StoreEntry) GetTrainNumber(ctx context.Context, req *operationPb.TrainN
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	pastureId := req.PastureId
 	if groupPasture.PastureId > 0 {
-		req.PastureId = int32(groupPasture.PastureId)
+		pastureId = int32(groupPasture.PastureId)
 	}
 
 	body := &model.PastureCommonRequest{
 		Name:       req.ApiName,
 		Page:       req.Pagination.Page,
 		Offset:     req.Pagination.PageOffset,
-		PageCount:  req.Pagination.PageSize,
 		ReturnType: "Map",
 		ParamMaps: &model.TrainNumberParams{
-			PastureId: fmt.Sprintf("%d", req.PastureId),
+			PastureId: fmt.Sprintf("%d", pastureId),
 			InfoRName: req.InfoName,
 		},
 	}
 	response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}}
-	if _, err := s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
+	if err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil {
 		return nil, xerr.WithStack(err)
 	}
 

+ 3 - 3
module/backend/system_permissions.go

@@ -2,10 +2,10 @@ package backend
 
 import (
 	"context"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"gitee.com/xuyiping_admin/pkg/xerr"
 	"kpt-tmr-group/model"
-	"kpt-tmr-group/pkg/logger/zaplog"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"sort"
 	"strings"

+ 37 - 32
module/backend/system_service.go

@@ -5,20 +5,23 @@ import (
 	"errors"
 	"fmt"
 	"kpt-tmr-group/model"
-	"kpt-tmr-group/pkg/jwt"
-	"kpt-tmr-group/pkg/logger/zaplog"
-	"kpt-tmr-group/pkg/tool"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
 	"strconv"
 	"strings"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/jwt"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"gitee.com/xuyiping_admin/pkg/tool"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+
 	"go.uber.org/zap"
 
 	"gorm.io/gorm"
 )
 
+const CurrentUserName = "userName"
+
 // Auth 用户登录
 func (s *StoreEntry) Auth(ctx context.Context, auth *operationPb.UserAuthData) (*operationPb.SystemToken, error) {
 	systemUser := &model.SystemUser{}
@@ -33,7 +36,8 @@ func (s *StoreEntry) Auth(ctx context.Context, auth *operationPb.UserAuthData) (
 		return nil, xerr.Customf("该账号已被禁用,请联系管理员")
 	}
 
-	token, err := jwt.GenerateToken(systemUser.Name, systemUser.Password)
+	jwtToken := jwt.NewJWTTokenGen(s.Cfg.AppName, s.Cfg.JwtTokenKeyConfig.PrivateKey)
+	token, err := jwtToken.GenerateToken(systemUser.Name, s.Cfg.JwtExpireTime)
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
@@ -48,18 +52,27 @@ func (s *StoreEntry) Auth(ctx context.Context, auth *operationPb.UserAuthData) (
 	}, nil
 }
 
-// GetUserInfo 获取用户信息
-func (s *StoreEntry) GetUserInfo(ctx context.Context, token string) (*operationPb.UserAuth, error) {
-	systemUser := &model.SystemUser{}
-	claims, err := jwt.ParseToken(token)
-	if err != nil {
-		return nil, xerr.WithStack(err)
+func (s *StoreEntry) GetCurrentUserName(ctx context.Context) string {
+	userNameInter := ctx.Value(CurrentUserName)
+	if userNameInter == nil {
+		zaplog.Error("GetCurrentUserName", zap.String("userNameInter", "cannot userName"))
+		return ""
 	}
-	if claims.Username == "" {
-		return nil, xerr.Custom("token解析失败")
+
+	if userName, ok := userNameInter.(string); ok {
+		return userName
+	} else {
+		zaplog.Error("GetCurrentUserName", zap.String("userNameInter", "waring userName"))
+		return ""
 	}
+}
 
-	if err = s.DB.Where("name = ?", claims.Username).First(systemUser).Error; err != nil {
+// GetUserInfo 获取用户信息
+func (s *StoreEntry) GetUserInfo(ctx context.Context) (*operationPb.UserAuth, error) {
+	systemUser := &model.SystemUser{}
+	userName := s.GetCurrentUserName(ctx)
+
+	if err := s.DB.Where("name = ?", userName).First(systemUser).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
 
@@ -73,12 +86,12 @@ func (s *StoreEntry) GetUserInfo(ctx context.Context, token string) (*operationP
 			roleIds = append(roleIds, roleId)
 		}
 
-		if err = s.DB.Model(new(model.SystemGroupPasturePermissions)).Select("DISTINCT(group_pasture.id) AS did, group_pasture.id as id,group_pasture.name as name").
+		if err := s.DB.Model(new(model.SystemGroupPasturePermissions)).Select("DISTINCT(group_pasture.id) AS did, group_pasture.id as id,group_pasture.name as name").
 			Where("system_group_pasture_permissions.role_id IN ?", roleIds).Where("system_group_pasture_permissions.is_show = ?", operationPb.IsShow_OK).
 			Joins("right join group_pasture  on system_group_pasture_permissions.pasture_id = group_pasture.id").Find(&pastureList).Debug().Error; err != nil {
 		}
 
-		if err = s.DB.Find(&systemRole, roleIds).Error; err != nil {
+		if err := s.DB.Find(&systemRole, roleIds).Error; err != nil {
 			return nil, xerr.WithStack(err)
 		}
 	}
@@ -88,13 +101,12 @@ func (s *StoreEntry) GetUserInfo(ctx context.Context, token string) (*operationP
 
 // CreateSystemUser 创建系统用户
 func (s *StoreEntry) CreateSystemUser(ctx context.Context, req *operationPb.AddSystemUser) error {
-
 	systemUsers := &model.SystemUser{
 		Name:         req.Name,
 		EmployeeName: req.EmployeeName,
 		Phone:        req.Phone,
 		Password:     tool.Md5String(model.InitManagerPassword),
-		CreateUser:   req.CreateUser,
+		CreateUser:   s.GetCurrentUserName(ctx),
 		IsShow:       operationPb.IsShow_OK,
 		IsDelete:     operationPb.IsShow_OK,
 	}
@@ -249,20 +261,12 @@ func (s *StoreEntry) IsShowSystemUser(ctx context.Context, req *operationPb.IsSh
 }
 
 // GetSystemUserPermissions 返回系统用户相关菜单权限
-func (s *StoreEntry) GetSystemUserPermissions(ctx context.Context, token string) (*operationPb.SystemUserMenuPermissions, error) {
+func (s *StoreEntry) GetSystemUserPermissions(ctx context.Context) (*operationPb.SystemUserMenuPermissions, error) {
 	// 解析token
-	claims, err := jwt.ParseToken(token)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	if err = claims.Valid(); err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
+	userName := s.GetCurrentUserName(ctx)
 	// 根据用户token获取用户数据
-	systemUser := &model.SystemUser{Name: claims.Username}
-	if err = s.DB.Where("name = ?", claims.Username).First(systemUser).Error; err != nil {
+	systemUser := &model.SystemUser{Name: userName}
+	if err := s.DB.Where("name = ?", userName).First(systemUser).Error; err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
 			return nil, xerr.Custom("该用户数据不存在")
 		}
@@ -272,7 +276,7 @@ func (s *StoreEntry) GetSystemUserPermissions(ctx context.Context, token string)
 
 	// 获取用户角色数据
 	systemRoles := make([]*model.SystemRole, 0)
-	if err = s.DB.Where("is_show = ?", operationPb.IsShow_OK).Find(&systemRoles, roleIds).Error; err != nil {
+	if err := s.DB.Where("is_show = ?", operationPb.IsShow_OK).Find(&systemRoles, roleIds).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
 
@@ -313,6 +317,7 @@ func (s *StoreEntry) GetSystemUserPermissions(ctx context.Context, token string)
 func (s *StoreEntry) CreateSystemRole(ctx context.Context, req *operationPb.AddRoleRequest) error {
 	if err := s.DB.Transaction(func(tx *gorm.DB) error {
 		// 创建角色数据
+		req.CreateUser = s.GetCurrentUserName(ctx)
 		role := model.NewSystemRole(req)
 		if err := tx.Create(role).Error; err != nil {
 			return xerr.WithStack(err)

+ 3 - 3
module/backend/wx_applet_service.go

@@ -4,10 +4,10 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"gitee.com/xuyiping_admin/pkg/xerr"
 	"kpt-tmr-group/model"
-	"kpt-tmr-group/pkg/logger/zaplog"
-	"kpt-tmr-group/pkg/xerr"
-	operationPb "kpt-tmr-group/proto/go/backend/operation"
 
 	"go.uber.org/zap"
 )

+ 0 - 207
pkg/apierr/apierr.go

@@ -1,207 +0,0 @@
-package apierr
-
-import (
-	"encoding/json"
-	"kpt-tmr-group/pkg/xerr"
-	common "kpt-tmr-group/proto/go/backend/common"
-	"net/http"
-
-	"github.com/gin-gonic/gin"
-)
-
-func New(code common.Error_Code) *Error {
-	return &Error{err: &common.Error{
-		Code: code,
-		Msg:  errorMessage(code),
-	}}
-}
-
-func errorMessage(code common.Error_Code) string {
-	var errMessage string
-	if msg, ok := common.Error_Code_name[int32(code)]; ok {
-		errMessage = msg
-	} else {
-		errMessage = "INTERNAL_ERROR"
-	}
-
-	return errMessage
-}
-
-type Error struct {
-	err *common.Error
-}
-
-func (e *Error) GetCode() common.Error_Code {
-	return e.err.Code
-}
-
-func (e *Error) GetMsg() string {
-	return e.err.Msg
-}
-
-func (e *Error) GetErrors() []string {
-	return e.err.Errors
-}
-
-func (e *Error) Error() string {
-	bs, _ := json.Marshal(e.err)
-	return string(bs)
-}
-
-// Is 判断 err 和 e 是否相同
-func (e *Error) Is(err error) bool {
-	if gotErr, ok := err.(*Error); !ok {
-		return false
-	} else {
-		return e.err.Code == gotErr.err.Code
-	}
-}
-
-func (e *Error) MarshalJSON() ([]byte, error) {
-	return json.Marshal(e.err)
-}
-
-func (e *Error) UnmarshalJSON(data []byte) error {
-	var commonErr common.Error
-	if err := json.Unmarshal(data, &commonErr); err != nil {
-		return err
-	}
-
-	e.err = &commonErr
-	return nil
-}
-
-func (e *Error) WithLocaleMessage(c *gin.Context) *Error {
-	if msg := e.GetMsg(); msg != "" {
-		return e.SetMessage(msg)
-	}
-
-	return e
-}
-
-func (e *Error) SetMessage(m string) *Error {
-	e.err.Msg = m
-	return e
-}
-
-func (e *Error) SetErrors(errMessages []string) *Error {
-	e.err.Errors = errMessages
-	return e
-}
-
-// With more information
-func (e *Error) With(errs ...error) *Error {
-	for _, err := range errs {
-		e.err.Errors = append(e.err.Errors, err.Error())
-	}
-
-	return e
-}
-
-// WithContext return error with i18n message ?
-func WithContext(c *gin.Context, code common.Error_Code) *Error {
-	return New(code).WithLocaleMessage(c)
-}
-
-// AbortError 用来处理多种内部错误.
-// 在复杂业务场景中,存在一个接口返回多种业务错误码情况,通过这个函数来统一处理
-func AbortError(c *gin.Context, err error) {
-	if err == nil {
-		return
-	}
-
-	if e, ok := xerr.Cause(err).(*Error); ok {
-		// 取默认状态码
-		statusCode := DefaultErrorStatusCode(e.err.Code)
-		if !shouldIgnoreCode(statusCode) {
-			c.Error(e)
-		}
-		c.AbortWithStatusJSON(statusCode, e.WithLocaleMessage(c))
-		return
-	}
-
-	c.Error(err)
-	c.AbortWithStatusJSON(http.StatusInternalServerError, WithContext(c, common.Error_INTERNAL_ERROR).With(err))
-}
-
-// AbortStatusError 用来处理多种内部错误和定制返回的 http status code.
-// 在复杂业务场景中,存在一个接口返回多种业务错误码情况,通过这个函数来统一处理
-func AbortStatusError(c *gin.Context, httpCode int, err error) {
-	if err == nil {
-		return
-	}
-
-	if e, ok := xerr.Cause(err).(*Error); ok {
-		c.Error(e)
-		c.AbortWithStatusJSON(httpCode, WithContext(c, e.err.Code))
-		return
-	}
-
-	c.Error(err)
-	c.AbortWithStatusJSON(httpCode, WithContext(c, common.Error_INTERNAL_ERROR).With(err))
-}
-
-// DefaultErrorStatusCode 返回错误码对应的默认 http status code
-func DefaultErrorStatusCode(code common.Error_Code) int {
-	if statusCode, ok := errorStatusCode[int(code)]; ok {
-		return statusCode
-	}
-
-	return http.StatusInternalServerError
-}
-
-// 错误对应默认返回的 http status code
-var errorStatusCode = map[int]int{
-	0:     http.StatusOK,
-	10000: http.StatusUnauthorized,
-	11000: http.StatusBadRequest,
-	11001: http.StatusBadRequest,
-	11002: http.StatusBadRequest,
-	11003: http.StatusTooManyRequests,
-	11100: http.StatusBadRequest,
-	11200: http.StatusBadRequest,
-	20000: http.StatusBadRequest,
-	21000: http.StatusBadRequest,
-	22000: http.StatusBadRequest,
-	23000: http.StatusBadRequest,
-	23001: http.StatusBadRequest,
-	24000: http.StatusBadRequest,
-	24100: http.StatusBadRequest,
-	24101: http.StatusBadRequest,
-	24102: http.StatusBadRequest,
-	24103: http.StatusBadRequest,
-	24104: http.StatusBadRequest,
-	24400: http.StatusBadRequest,
-	24500: http.StatusBadRequest,
-	24501: http.StatusBadRequest,
-	24502: http.StatusBadRequest,
-	24520: http.StatusBadRequest,
-	24521: http.StatusBadRequest,
-	24522: http.StatusBadRequest,
-	24523: http.StatusBadRequest,
-	24524: http.StatusBadRequest,
-	24525: http.StatusBadRequest,
-	24526: http.StatusBadRequest,
-	24527: http.StatusBadRequest,
-	24528: http.StatusBadRequest,
-	24600: http.StatusBadRequest,
-	24601: http.StatusBadRequest,
-	24602: http.StatusBadRequest,
-	24603: http.StatusBadRequest,
-	24700: http.StatusBadRequest,
-	24701: http.StatusBadRequest,
-	24702: http.StatusBadRequest,
-	24704: http.StatusBadRequest,
-	24705: http.StatusBadRequest,
-	24706: http.StatusBadRequest,
-	24707: http.StatusBadRequest,
-	24800: http.StatusBadRequest,
-	24801: http.StatusBadRequest,
-	24802: http.StatusBadRequest,
-	24803: http.StatusBadRequest,
-	90000: http.StatusInternalServerError,
-	90100: http.StatusBadRequest,
-	90101: http.StatusBadRequest,
-	90102: http.StatusBadRequest,
-	91000: http.StatusInternalServerError,
-}

+ 0 - 761
pkg/apierr/apierr_gen.go

@@ -1,761 +0,0 @@
-package apierr
-
-import (
-	common "kpt-tmr-group/proto/go/backend/common"
-
-	"github.com/gin-gonic/gin"
-)
-
-// NewErrUnauthorized create err with default message
-func NewErrUnauthorized(err ...error) *Error {
-	return New(common.Error_UNAUTHORIZED).With(err...)
-}
-
-// ErrUnauthorized create err with locales
-func ErrUnauthorized(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_UNAUTHORIZED).With(err...)
-}
-
-// AbortUnauthorized abort with status code and log common.Error_UNAUTHORIZED to newrelic
-func AbortUnauthorized(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrUnauthorized(c, err...))
-}
-
-// AbortStatusUnauthorized abort with status code and log common.Error_UNAUTHORIZED to newrelic
-func AbortStatusUnauthorized(c *gin.Context, err ...error) {
-	AbortUnauthorized(c, 401, err...)
-}
-
-// NewErrBadRequest create err with default message
-func NewErrBadRequest(err ...error) *Error {
-	return New(common.Error_BAD_REQUEST).With(err...)
-}
-
-// ErrBadRequest create err with locales
-func ErrBadRequest(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_BAD_REQUEST).With(err...)
-}
-
-// AbortBadRequest abort with status code and log common.Error_BAD_REQUEST to newrelic
-func AbortBadRequest(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrBadRequest(c, err...))
-}
-
-// AbortStatusBadRequest abort with status code and log common.Error_BAD_REQUEST to newrelic
-func AbortStatusBadRequest(c *gin.Context, err ...error) {
-	AbortBadRequest(c, 400, err...)
-}
-
-// NewErrInvalidContentType create err with default message
-func NewErrInvalidContentType(err ...error) *Error {
-	return New(common.Error_INVALID_CONTENT_TYPE).With(err...)
-}
-
-// ErrInvalidContentType create err with locales
-func ErrInvalidContentType(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_INVALID_CONTENT_TYPE).With(err...)
-}
-
-// AbortInvalidContentType abort with status code and log common.Error_INVALID_CONTENT_TYPE to newrelic
-func AbortInvalidContentType(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrInvalidContentType(c, err...))
-}
-
-// AbortStatusInvalidContentType abort with status code and log common.Error_INVALID_CONTENT_TYPE to newrelic
-func AbortStatusInvalidContentType(c *gin.Context, err ...error) {
-	AbortInvalidContentType(c, 400, err...)
-}
-
-// NewErrInvalidContentEncoding create err with default message
-func NewErrInvalidContentEncoding(err ...error) *Error {
-	return New(common.Error_INVALID_CONTENT_ENCODING).With(err...)
-}
-
-// ErrInvalidContentEncoding create err with locales
-func ErrInvalidContentEncoding(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_INVALID_CONTENT_ENCODING).With(err...)
-}
-
-// AbortInvalidContentEncoding abort with status code and log common.Error_INVALID_CONTENT_ENCODING to newrelic
-func AbortInvalidContentEncoding(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrInvalidContentEncoding(c, err...))
-}
-
-// AbortStatusInvalidContentEncoding abort with status code and log common.Error_INVALID_CONTENT_ENCODING to newrelic
-func AbortStatusInvalidContentEncoding(c *gin.Context, err ...error) {
-	AbortInvalidContentEncoding(c, 400, err...)
-}
-
-// NewErrTooManyRequests create err with default message
-func NewErrTooManyRequests(err ...error) *Error {
-	return New(common.Error_TOO_MANY_REQUESTS).With(err...)
-}
-
-// ErrTooManyRequests create err with locales
-func ErrTooManyRequests(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_TOO_MANY_REQUESTS).With(err...)
-}
-
-// AbortTooManyRequests abort with status code and log common.Error_TOO_MANY_REQUESTS to newrelic
-func AbortTooManyRequests(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrTooManyRequests(c, err...))
-}
-
-// AbortStatusTooManyRequests abort with status code and log common.Error_TOO_MANY_REQUESTS to newrelic
-func AbortStatusTooManyRequests(c *gin.Context, err ...error) {
-	AbortTooManyRequests(c, 429, err...)
-}
-
-// NewErrInvalidStorageType create err with default message
-func NewErrInvalidStorageType(err ...error) *Error {
-	return New(common.Error_INVALID_STORAGE_TYPE).With(err...)
-}
-
-// ErrInvalidStorageType create err with locales
-func ErrInvalidStorageType(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_INVALID_STORAGE_TYPE).With(err...)
-}
-
-// AbortInvalidStorageType abort with status code and log common.Error_INVALID_STORAGE_TYPE to newrelic
-func AbortInvalidStorageType(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrInvalidStorageType(c, err...))
-}
-
-// AbortStatusInvalidStorageType abort with status code and log common.Error_INVALID_STORAGE_TYPE to newrelic
-func AbortStatusInvalidStorageType(c *gin.Context, err ...error) {
-	AbortInvalidStorageType(c, 400, err...)
-}
-
-// NewErrInvalidDeData create err with default message
-func NewErrInvalidDeData(err ...error) *Error {
-	return New(common.Error_INVALID_DE_DATA).With(err...)
-}
-
-// ErrInvalidDeData create err with locales
-func ErrInvalidDeData(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_INVALID_DE_DATA).With(err...)
-}
-
-// AbortInvalidDeData abort with status code and log common.Error_INVALID_DE_DATA to newrelic
-func AbortInvalidDeData(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrInvalidDeData(c, err...))
-}
-
-// AbortStatusInvalidDeData abort with status code and log common.Error_INVALID_DE_DATA to newrelic
-func AbortStatusInvalidDeData(c *gin.Context, err ...error) {
-	AbortInvalidDeData(c, 400, err...)
-}
-
-// NewErrCheckinRepeated create err with default message
-func NewErrCheckinRepeated(err ...error) *Error {
-	return New(common.Error_CHECKIN_REPEATED).With(err...)
-}
-
-// ErrCheckinRepeated create err with locales
-func ErrCheckinRepeated(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_CHECKIN_REPEATED).With(err...)
-}
-
-// AbortCheckinRepeated abort with status code and log common.Error_CHECKIN_REPEATED to newrelic
-func AbortCheckinRepeated(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrCheckinRepeated(c, err...))
-}
-
-// AbortStatusCheckinRepeated abort with status code and log common.Error_CHECKIN_REPEATED to newrelic
-func AbortStatusCheckinRepeated(c *gin.Context, err ...error) {
-	AbortCheckinRepeated(c, 400, err...)
-}
-
-// NewErrCourseNotFound create err with default message
-func NewErrCourseNotFound(err ...error) *Error {
-	return New(common.Error_COURSE_NOT_FOUND).With(err...)
-}
-
-// ErrCourseNotFound create err with locales
-func ErrCourseNotFound(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_COURSE_NOT_FOUND).With(err...)
-}
-
-// AbortCourseNotFound abort with status code and log common.Error_COURSE_NOT_FOUND to newrelic
-func AbortCourseNotFound(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrCourseNotFound(c, err...))
-}
-
-// AbortStatusCourseNotFound abort with status code and log common.Error_COURSE_NOT_FOUND to newrelic
-func AbortStatusCourseNotFound(c *gin.Context, err ...error) {
-	AbortCourseNotFound(c, 400, err...)
-}
-
-// NewErrCourseNotInterest create err with default message
-func NewErrCourseNotInterest(err ...error) *Error {
-	return New(common.Error_COURSE_NOT_INTEREST).With(err...)
-}
-
-// ErrCourseNotInterest create err with locales
-func ErrCourseNotInterest(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_COURSE_NOT_INTEREST).With(err...)
-}
-
-// AbortCourseNotInterest abort with status code and log common.Error_COURSE_NOT_INTEREST to newrelic
-func AbortCourseNotInterest(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrCourseNotInterest(c, err...))
-}
-
-// AbortStatusCourseNotInterest abort with status code and log common.Error_COURSE_NOT_INTEREST to newrelic
-func AbortStatusCourseNotInterest(c *gin.Context, err ...error) {
-	AbortCourseNotInterest(c, 500, err...)
-}
-
-// NewErrModuleNotFound create err with default message
-func NewErrModuleNotFound(err ...error) *Error {
-	return New(common.Error_MODULE_NOT_FOUND).With(err...)
-}
-
-// ErrModuleNotFound create err with locales
-func ErrModuleNotFound(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_MODULE_NOT_FOUND).With(err...)
-}
-
-// AbortModuleNotFound abort with status code and log common.Error_MODULE_NOT_FOUND to newrelic
-func AbortModuleNotFound(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrModuleNotFound(c, err...))
-}
-
-// AbortStatusModuleNotFound abort with status code and log common.Error_MODULE_NOT_FOUND to newrelic
-func AbortStatusModuleNotFound(c *gin.Context, err ...error) {
-	AbortModuleNotFound(c, 400, err...)
-}
-
-// NewErrUserCourseAlreadyAdded create err with default message
-func NewErrUserCourseAlreadyAdded(err ...error) *Error {
-	return New(common.Error_USER_COURSE_ALREADY_ADDED).With(err...)
-}
-
-// ErrUserCourseAlreadyAdded create err with locales
-func ErrUserCourseAlreadyAdded(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_USER_COURSE_ALREADY_ADDED).With(err...)
-}
-
-// AbortUserCourseAlreadyAdded abort with status code and log common.Error_USER_COURSE_ALREADY_ADDED to newrelic
-func AbortUserCourseAlreadyAdded(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrUserCourseAlreadyAdded(c, err...))
-}
-
-// AbortStatusUserCourseAlreadyAdded abort with status code and log common.Error_USER_COURSE_ALREADY_ADDED to newrelic
-func AbortStatusUserCourseAlreadyAdded(c *gin.Context, err ...error) {
-	AbortUserCourseAlreadyAdded(c, 400, err...)
-}
-
-// NewErrUserCourseNotFound create err with default message
-func NewErrUserCourseNotFound(err ...error) *Error {
-	return New(common.Error_USER_COURSE_NOT_FOUND).With(err...)
-}
-
-// ErrUserCourseNotFound create err with locales
-func ErrUserCourseNotFound(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_USER_COURSE_NOT_FOUND).With(err...)
-}
-
-// AbortUserCourseNotFound abort with status code and log common.Error_USER_COURSE_NOT_FOUND to newrelic
-func AbortUserCourseNotFound(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrUserCourseNotFound(c, err...))
-}
-
-// AbortStatusUserCourseNotFound abort with status code and log common.Error_USER_COURSE_NOT_FOUND to newrelic
-func AbortStatusUserCourseNotFound(c *gin.Context, err ...error) {
-	AbortUserCourseNotFound(c, 400, err...)
-}
-
-// NewErrPtLimited create err with default message
-func NewErrPtLimited(err ...error) *Error {
-	return New(common.Error_PT_LIMITED).With(err...)
-}
-
-// ErrPtLimited create err with locales
-func ErrPtLimited(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_PT_LIMITED).With(err...)
-}
-
-// AbortPtLimited abort with status code and log common.Error_PT_LIMITED to newrelic
-func AbortPtLimited(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrPtLimited(c, err...))
-}
-
-// AbortStatusPtLimited abort with status code and log common.Error_PT_LIMITED to newrelic
-func AbortStatusPtLimited(c *gin.Context, err ...error) {
-	AbortPtLimited(c, 400, err...)
-}
-
-// NewErrInvalidPrice create err with default message
-func NewErrInvalidPrice(err ...error) *Error {
-	return New(common.Error_INVALID_PRICE).With(err...)
-}
-
-// ErrInvalidPrice create err with locales
-func ErrInvalidPrice(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_INVALID_PRICE).With(err...)
-}
-
-// AbortInvalidPrice abort with status code and log common.Error_INVALID_PRICE to newrelic
-func AbortInvalidPrice(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrInvalidPrice(c, err...))
-}
-
-// AbortStatusInvalidPrice abort with status code and log common.Error_INVALID_PRICE to newrelic
-func AbortStatusInvalidPrice(c *gin.Context, err ...error) {
-	AbortInvalidPrice(c, 400, err...)
-}
-
-// NewErrInvalidProductId create err with default message
-func NewErrInvalidProductId(err ...error) *Error {
-	return New(common.Error_INVALID_PRODUCT_ID).With(err...)
-}
-
-// ErrInvalidProductId create err with locales
-func ErrInvalidProductId(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_INVALID_PRODUCT_ID).With(err...)
-}
-
-// AbortInvalidProductId abort with status code and log common.Error_INVALID_PRODUCT_ID to newrelic
-func AbortInvalidProductId(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrInvalidProductId(c, err...))
-}
-
-// AbortStatusInvalidProductId abort with status code and log common.Error_INVALID_PRODUCT_ID to newrelic
-func AbortStatusInvalidProductId(c *gin.Context, err ...error) {
-	AbortInvalidProductId(c, 400, err...)
-}
-
-// NewErrInvalidOrderNumber create err with default message
-func NewErrInvalidOrderNumber(err ...error) *Error {
-	return New(common.Error_INVALID_ORDER_NUMBER).With(err...)
-}
-
-// ErrInvalidOrderNumber create err with locales
-func ErrInvalidOrderNumber(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_INVALID_ORDER_NUMBER).With(err...)
-}
-
-// AbortInvalidOrderNumber abort with status code and log common.Error_INVALID_ORDER_NUMBER to newrelic
-func AbortInvalidOrderNumber(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrInvalidOrderNumber(c, err...))
-}
-
-// AbortStatusInvalidOrderNumber abort with status code and log common.Error_INVALID_ORDER_NUMBER to newrelic
-func AbortStatusInvalidOrderNumber(c *gin.Context, err ...error) {
-	AbortInvalidOrderNumber(c, 400, err...)
-}
-
-// NewErrInvalidUserId create err with default message
-func NewErrInvalidUserId(err ...error) *Error {
-	return New(common.Error_INVALID_USER_ID).With(err...)
-}
-
-// ErrInvalidUserId create err with locales
-func ErrInvalidUserId(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_INVALID_USER_ID).With(err...)
-}
-
-// AbortInvalidUserId abort with status code and log common.Error_INVALID_USER_ID to newrelic
-func AbortInvalidUserId(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrInvalidUserId(c, err...))
-}
-
-// AbortStatusInvalidUserId abort with status code and log common.Error_INVALID_USER_ID to newrelic
-func AbortStatusInvalidUserId(c *gin.Context, err ...error) {
-	AbortInvalidUserId(c, 400, err...)
-}
-
-// NewErrInvalidReceipt create err with default message
-func NewErrInvalidReceipt(err ...error) *Error {
-	return New(common.Error_INVALID_RECEIPT).With(err...)
-}
-
-// ErrInvalidReceipt create err with locales
-func ErrInvalidReceipt(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_INVALID_RECEIPT).With(err...)
-}
-
-// AbortInvalidReceipt abort with status code and log common.Error_INVALID_RECEIPT to newrelic
-func AbortInvalidReceipt(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrInvalidReceipt(c, err...))
-}
-
-// AbortStatusInvalidReceipt abort with status code and log common.Error_INVALID_RECEIPT to newrelic
-func AbortStatusInvalidReceipt(c *gin.Context, err ...error) {
-	AbortInvalidReceipt(c, 400, err...)
-}
-
-// NewErrEmptyIosReceipt create err with default message
-func NewErrEmptyIosReceipt(err ...error) *Error {
-	return New(common.Error_EMPTY_IOS_RECEIPT).With(err...)
-}
-
-// ErrEmptyIosReceipt create err with locales
-func ErrEmptyIosReceipt(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_EMPTY_IOS_RECEIPT).With(err...)
-}
-
-// AbortEmptyIosReceipt abort with status code and log common.Error_EMPTY_IOS_RECEIPT to newrelic
-func AbortEmptyIosReceipt(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrEmptyIosReceipt(c, err...))
-}
-
-// AbortStatusEmptyIosReceipt abort with status code and log common.Error_EMPTY_IOS_RECEIPT to newrelic
-func AbortStatusEmptyIosReceipt(c *gin.Context, err ...error) {
-	AbortEmptyIosReceipt(c, 500, err...)
-}
-
-// NewErrUserPlanLimitedCourseCount create err with default message
-func NewErrUserPlanLimitedCourseCount(err ...error) *Error {
-	return New(common.Error_USER_PLAN_LIMITED_COURSE_COUNT).With(err...)
-}
-
-// ErrUserPlanLimitedCourseCount create err with locales
-func ErrUserPlanLimitedCourseCount(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_USER_PLAN_LIMITED_COURSE_COUNT).With(err...)
-}
-
-// AbortUserPlanLimitedCourseCount abort with status code and log common.Error_USER_PLAN_LIMITED_COURSE_COUNT to newrelic
-func AbortUserPlanLimitedCourseCount(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrUserPlanLimitedCourseCount(c, err...))
-}
-
-// AbortStatusUserPlanLimitedCourseCount abort with status code and log common.Error_USER_PLAN_LIMITED_COURSE_COUNT to newrelic
-func AbortStatusUserPlanLimitedCourseCount(c *gin.Context, err ...error) {
-	AbortUserPlanLimitedCourseCount(c, 500, err...)
-}
-
-// NewErrInternalError create err with default message
-func NewErrInternalError(err ...error) *Error {
-	return New(common.Error_INTERNAL_ERROR).With(err...)
-}
-
-// ErrInternalError create err with locales
-func ErrInternalError(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_INTERNAL_ERROR).With(err...)
-}
-
-// AbortInternalError abort with status code and log common.Error_INTERNAL_ERROR to newrelic
-func AbortInternalError(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrInternalError(c, err...))
-}
-
-// AbortStatusInternalError abort with status code and log common.Error_INTERNAL_ERROR to newrelic
-func AbortStatusInternalError(c *gin.Context, err ...error) {
-	AbortInternalError(c, 500, err...)
-}
-
-// NewErrJsonpbError create err with default message
-func NewErrJsonpbError(err ...error) *Error {
-	return New(common.Error_JSONPB_ERROR).With(err...)
-}
-
-// ErrJsonpbError create err with locales
-func ErrJsonpbError(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_JSONPB_ERROR).With(err...)
-}
-
-// AbortJsonpbError abort with status code and log common.Error_JSONPB_ERROR to newrelic
-func AbortJsonpbError(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrJsonpbError(c, err...))
-}
-
-// AbortStatusJsonpbError abort with status code and log common.Error_JSONPB_ERROR to newrelic
-func AbortStatusJsonpbError(c *gin.Context, err ...error) {
-	AbortJsonpbError(c, 400, err...)
-}
-
-// NewErrJsonError create err with default message
-func NewErrJsonError(err ...error) *Error {
-	return New(common.Error_JSON_ERROR).With(err...)
-}
-
-// ErrJsonError create err with locales
-func ErrJsonError(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_JSON_ERROR).With(err...)
-}
-
-// AbortJsonError abort with status code and log common.Error_JSON_ERROR to newrelic
-func AbortJsonError(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrJsonError(c, err...))
-}
-
-// AbortStatusJsonError abort with status code and log common.Error_JSON_ERROR to newrelic
-func AbortStatusJsonError(c *gin.Context, err ...error) {
-	AbortJsonError(c, 400, err...)
-}
-
-// NewErrPbError create err with default message
-func NewErrPbError(err ...error) *Error {
-	return New(common.Error_PB_ERROR).With(err...)
-}
-
-// ErrPbError create err with locales
-func ErrPbError(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_PB_ERROR).With(err...)
-}
-
-// AbortPbError abort with status code and log common.Error_PB_ERROR to newrelic
-func AbortPbError(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrPbError(c, err...))
-}
-
-// AbortStatusPbError abort with status code and log common.Error_PB_ERROR to newrelic
-func AbortStatusPbError(c *gin.Context, err ...error) {
-	AbortPbError(c, 400, err...)
-}
-
-// NewErrExternalError create err with default message
-func NewErrExternalError(err ...error) *Error {
-	return New(common.Error_EXTERNAL_ERROR).With(err...)
-}
-
-// ErrExternalError create err with locales
-func ErrExternalError(c *gin.Context, err ...error) *Error {
-	return WithContext(c, common.Error_EXTERNAL_ERROR).With(err...)
-}
-
-// AbortExternalError abort with status code and log common.Error_EXTERNAL_ERROR to newrelic
-func AbortExternalError(c *gin.Context, code int, err ...error) {
-	for _, e := range err {
-		// if err is nil, gin will panic
-		if e != nil {
-			// so many 4xx error in new relic, only ignore 400/401/404 error, have fun!
-			if !shouldIgnoreCode(code) {
-				c.Error(e)
-			}
-		}
-	}
-	c.AbortWithStatusJSON(code, ErrExternalError(c, err...))
-}
-
-// AbortStatusExternalError abort with status code and log common.Error_EXTERNAL_ERROR to newrelic
-func AbortStatusExternalError(c *gin.Context, err ...error) {
-	AbortExternalError(c, 500, err...)
-}

+ 0 - 47
pkg/apierr/config.go

@@ -1,47 +0,0 @@
-package apierr
-
-import (
-	"net/http"
-	"sort"
-
-	"github.com/gin-gonic/gin"
-
-	"kpt-tmr-group/pkg/grpcutil"
-	"kpt-tmr-group/pkg/xerr"
-)
-
-var (
-	ignoreCodes = []int{400, 401, 404, 429}
-	codesSize   = int(3)
-)
-
-// IgnoreStatusCodes ignore error with status codes
-func IgnoreStatusCodes(codes ...int) {
-	sort.Ints(codes)
-
-	ignoreCodes = codes
-	codesSize = len(codes)
-}
-
-func shouldIgnoreCode(code int) bool {
-	// SearchInts using binary search, more fast
-	idx := sort.SearchInts(ignoreCodes, code)
-	return idx < codesSize && ignoreCodes[idx] == code
-}
-
-// ClassifiedAbort classify base on error type
-func ClassifiedAbort(c *gin.Context, err error) {
-	if err == nil {
-		return
-	}
-
-	if e, isc := xerr.IsCustomError(err); isc {
-		// 服务内部自定义错误
-		AbortBadRequest(c, http.StatusBadRequest, e)
-	} else if !grpcutil.FilterServerError(err) {
-		// gRPC 部分错误
-		AbortBadRequest(c, http.StatusBadRequest, err)
-	} else {
-		AbortError(c, err)
-	}
-}

+ 0 - 23
pkg/apiok/common.go

@@ -1,23 +0,0 @@
-package apiok
-
-/*type OkResponse struct {
-	Code int         `json:"code"`
-	Msg  string      `json:"msg"`
-	Data interface{} `json:"data"`
-}
-
-func CommonResponse(data interface{}) *OkResponse {
-	return &OkResponse{
-		Code: 200,
-		Msg:  "ok",
-		Data: data,
-	}
-}
-*/
-type ApiOk struct {
-	Success bool `json:"success"`
-}
-
-func NewApiOk(success bool) *ApiOk {
-	return &ApiOk{Success: success}
-}

+ 0 - 133
pkg/cleanup/entry.go

@@ -1,133 +0,0 @@
-// Package cleanup provides a single point for registering clean up functions.
-// This is similar to Finalizer, except that the clean up functions are
-// guaranteed to be called if the process terminates normally.
-//
-// Usage:
-//
-// In my_package.go
-//
-//   cleanup.Register(func(){
-//     // Arbitrary clean up function, most likely close goroutine, etc.
-//   })
-//
-// In main.go
-//
-//   func main() {
-//     flag.Parse()
-//     defer cleanup.Run()
-//   }
-package cleanup
-
-import (
-	"context"
-	"reflect"
-	"sync"
-
-	"kpt-tmr-group/pkg/logger/logrus"
-	"kpt-tmr-group/pkg/xerr"
-)
-
-// entry global cleanup entry
-var entry Entry
-
-// Register adds a function to the global cleanup queue.
-func Register(container interface{}) {
-	entry.Register(container)
-}
-
-// Run runs all the global cleanup functions registered.
-func Run() {
-	entry.Run()
-}
-
-type Entry struct {
-	mu   sync.Mutex
-	fns  []func()
-	once sync.Once
-}
-
-// Run runs all the cleanup functions registered.
-func (entry *Entry) Run() {
-	logrus.Infof("cleanup: performing %d cleanups", len(entry.fns))
-
-	entry.once.Do(func() {
-		for _, f := range entry.fns {
-			f()
-		}
-	})
-
-	logrus.Infof("cleanup: all done")
-}
-
-// Register adds a function to the cleanup queue.
-func (entry *Entry) Register(container interface{}) {
-	v := reflect.Indirect(reflect.ValueOf(container))
-	var err error
-	switch v.Kind() {
-	case reflect.Func:
-		err = entry.RegisterFunc(v.Interface())
-	case reflect.Struct:
-		err = entry.RegisterStruct(v.Interface())
-	default:
-		panic("cleanup: unsupported type")
-	}
-	if err != nil {
-		panic(err)
-	}
-}
-
-func (entry *Entry) RegisterStruct(ctor interface{}) error {
-	cValue := reflect.Indirect(reflect.ValueOf(ctor))
-	if cValue.Kind() != reflect.Struct {
-		return xerr.New("RegisterStruct receive a struct or ptr to struct")
-	}
-	for i := 0; i < cValue.NumField(); i++ {
-		field := cValue.Field(i)
-		if field.IsZero() {
-			continue
-		}
-		method := field.MethodByName("Close")
-		if !method.IsValid() {
-			method = field.MethodByName("Flush")
-		}
-		if method.IsValid() {
-			if err := entry.RegisterFunc(method.Interface()); err != nil {
-				logrus.WithError(err).WithField("fieldName", field.Type().Name()).Error("register func failed")
-			}
-		}
-	}
-	return nil
-}
-
-// RegisterFunc receive func() or func() error
-func (entry *Entry) RegisterFunc(fn interface{}) error {
-	fType := reflect.TypeOf(fn)
-	if fType.Kind() != reflect.Func {
-		return xerr.New("cleanup: unsupported type")
-	}
-	if fType.NumIn() > 0 {
-		return xerr.New("RegisterFunc receive func() or func() error")
-	}
-
-	if f, ok := fn.(func()); ok {
-		entry.register(f)
-		return nil
-	}
-	if f, ok := fn.(func() error); ok {
-		entry.register(func() {
-			if err := f(); err != nil {
-				_ = xerr.ReportError(context.Background(), err)
-			}
-		})
-		return nil
-	}
-	return xerr.New("RegisterFunc receive func() or func() error")
-}
-
-func (entry *Entry) register(fns ...func()) {
-	entry.mu.Lock()
-	defer entry.mu.Unlock()
-	for _, fn := range fns {
-		entry.fns = append(entry.fns, fn)
-	}
-}

+ 0 - 53
pkg/cleanup/entry_test.go

@@ -1,53 +0,0 @@
-package cleanup
-
-import (
-	"testing"
-)
-
-type f1 struct{}
-
-func (*f1) Close() {}
-
-type f2 struct{}
-
-func (*f2) Close() error { return nil }
-
-type f3 struct{}
-
-func (*f3) Flush() {}
-
-type f4 struct{}
-
-func (*f4) NoCloseOrFlush() {}
-
-type TestStruct struct {
-	F1 *f1
-	F2 *f2
-	F3 *f3
-	F4 *f4
-}
-
-func TestRegisterStruct(t *testing.T) {
-	var e Entry
-	s := TestStruct{
-		F1: &f1{},
-		F2: &f2{},
-		F3: &f3{},
-		F4: &f4{},
-	}
-	e.Register(s)
-}
-
-func TestCleanup(t *testing.T) {
-	var e Entry
-	i, j := 0, 0
-	func() {
-		e.Register(func() { i += 1 })
-		e.Register(func() { j += 2 })
-		e.Run()
-		e.Run() // multiple runs will be OK.
-	}()
-	if i != 1 || j != 2 {
-		t.Errorf("Run() incorrect, want i = 1, j = 2, got i = %d, j = %d", i, j)
-	}
-}

+ 0 - 19
pkg/cputil/cp.go

@@ -1,19 +0,0 @@
-package cputil
-
-import (
-	"github.com/jinzhu/copier"
-)
-
-func ShallowCopy(toValue interface{}, fromValue interface{}) error {
-	return copier.CopyWithOption(toValue, fromValue, copier.Option{
-		IgnoreEmpty: true,
-		DeepCopy:    false,
-	})
-}
-
-func DeepCopy(toValue interface{}, fromValue interface{}) error {
-	return copier.CopyWithOption(toValue, fromValue, copier.Option{
-		IgnoreEmpty: true,
-		DeepCopy:    true,
-	})
-}

+ 0 - 59
pkg/cputil/cp_test.go

@@ -1,59 +0,0 @@
-package cputil
-
-import (
-	"testing"
-
-	"github.com/google/go-cmp/cmp"
-	"github.com/stretchr/testify/require"
-)
-
-type Dummy struct {
-	A1 int
-	A2 int
-	B1 bool
-	B2 bool
-	C1 map[string]interface{}
-	D1 []int
-}
-
-func TestShallowCopy(t *testing.T) {
-	d1 := &Dummy{
-		A1: 0,
-		A2: 1,
-		B1: false,
-		B2: true,
-		C1: map[string]interface{}{
-			"a": 1,
-		},
-		D1: []int{0, 1},
-	}
-
-	d2 := &Dummy{}
-	_ = ShallowCopy(&d2, d1)
-	require.Empty(t, cmp.Diff(d1, d2))
-
-	// case: 浅拷贝会互相影响
-	d1.C1["a"] = 2
-	require.Equal(t, d2.C1["a"], d1.C1["a"])
-}
-
-func TestDeepCopy(t *testing.T) {
-	d1 := &Dummy{
-		A1: 0,
-		A2: 1,
-		B1: false,
-		B2: true,
-		C1: map[string]interface{}{
-			"a": 1,
-		},
-		D1: []int{0, 1},
-	}
-
-	d2 := &Dummy{}
-	_ = DeepCopy(&d2, d1)
-	require.Empty(t, cmp.Diff(d1, d2))
-
-	// case: 深拷贝不会互相影响
-	d1.C1["a"] = 2
-	require.NotEqual(t, d2.C1["a"], d1.C1["a"])
-}

+ 0 - 26
pkg/di/annotation.go

@@ -1,26 +0,0 @@
-package di
-
-type Annotated struct {
-	// If specified, this will be used as the name for all non-error values returned
-	// by the constructor. For more information on named values, see the documentation
-	// for the fx.Out type.
-	//
-	// A name option may not be provided if a group option is provided.
-	Name string
-
-	// If specified, this will be used as the group name for all non-error values returned
-	// by the constructor. For more information on value groups, see the package documentation.
-	//
-	// A group option may not be provided if a name option is provided.
-	//
-	// Similar to group tags, the group name may be followed by a `,flatten`
-	// option to indicate that each element in the slice returned by the
-	// constructor should be injected into the value group individually.
-	Group string
-
-	// Target is the constructor or value being annotated with fx.Annotated.
-	Target interface{}
-
-	// Close is the function being closed when container is destroy
-	Close interface{}
-}

+ 0 - 153
pkg/di/hub.go

@@ -1,153 +0,0 @@
-package di
-
-import (
-	"reflect"
-
-	"kpt-tmr-group/pkg/cleanup"
-	"kpt-tmr-group/pkg/di/xreflect"
-	"kpt-tmr-group/pkg/xerr"
-
-	"go.uber.org/dig"
-)
-
-func New(opts ...HubOption) (*Hub, error) {
-	hub := &Hub{
-		cleanup:  cleanup.Entry{},
-		provides: make([]Provided, 0),
-	}
-	for _, opt := range opts {
-		opt.Apply(hub)
-	}
-
-	hub.container = dig.New(
-		dig.DryRun(hub.validate),
-	)
-	for i, p := range hub.provides {
-		if err := hub.usingProvide(p); err != nil {
-			return nil, xerr.Errorf("error after options[%d] were applied: %v", i, err)
-		}
-	}
-
-	return hub, nil
-}
-
-// Hub is a directed acyclic graph of types and their dependencies.
-// extend dig.Container
-type Hub struct {
-	container *dig.Container
-	cleanup   cleanup.Entry
-	provides  []Provided
-	validate  bool
-}
-
-// Cleanup runs all the cleanup functions registered in the hub.
-func (hub *Hub) Cleanup() {
-	hub.cleanup.Run()
-}
-
-// Provided is a single constructor provided to di.
-type Provided struct {
-	// Constructor provided to di. This may be an di.Annotated.
-	Target interface{}
-
-	// Stack trace of where this Provided was made.
-	Stack xreflect.Stack
-
-	// IsSupply is true when the Target constructor was emitted by di.Supply.
-	IsSupply bool
-}
-
-func (hub *Hub) usingProvide(p Provided) error {
-	constructor := p.Target
-
-	if _, ok := constructor.(HubOption); ok {
-		return xerr.Errorf("di.Option should be passed to di.New directly, "+
-			"not to di.Provide: di.Provide received %v from:\n%+v",
-			constructor, p.Stack)
-	}
-
-	if ann, ok := constructor.(Annotated); ok {
-		var opts []dig.ProvideOption
-		switch {
-		case len(ann.Group) > 0 && len(ann.Name) > 0:
-			return xerr.Errorf(
-				"di.Annotated may specify only one of Name or Group: received %v from:\n%+v",
-				ann, p.Stack)
-		case len(ann.Name) > 0:
-			opts = append(opts, dig.Name(ann.Name))
-		case len(ann.Group) > 0:
-			opts = append(opts, dig.Group(ann.Group))
-
-		}
-
-		// 注册初始化函数
-		if err := hub.Provide(ann.Target, opts...); err != nil {
-			return xerr.Errorf("di.Provide(%v) from:\n%+vFailed: %v", ann, p.Stack, err)
-		}
-
-		// 注册清理函数
-		if ann.Close != nil {
-			hub.cleanup.Register(ann.Close)
-		}
-
-		return nil
-	}
-
-	if reflect.TypeOf(constructor).Kind() == reflect.Func {
-		ft := reflect.ValueOf(constructor).Type()
-
-		for i := 0; i < ft.NumOut(); i++ {
-			t := ft.Out(i)
-
-			if t == reflect.TypeOf(Annotated{}) {
-				return xerr.Errorf(
-					"di.Annotated should be passed to di.Provide directly, "+
-						"it should not be returned by the constructor: "+
-						"di.Provide received %v from:\n%+v",
-					xreflect.FuncName(constructor), p.Stack)
-			}
-		}
-	}
-
-	if err := hub.Provide(constructor); err != nil {
-		return xerr.Errorf("di.Provide(%v) from:\n%+vFailed: %v", xreflect.FuncName(constructor), p.Stack, err)
-	}
-
-	return nil
-}
-
-// Invoke runs the given function after instantiating its dependencies.
-//
-// Any arguments that the function has are treated as its dependencies. The
-// dependencies are instantiated in an unspecified order along with any
-// dependencies that they might have.
-//
-// The function may return an error to indicate failure. The error will be
-// returned to the caller as-is.
-func (hub *Hub) Invoke(function interface{}, opts ...InvokeOption) error {
-	return hub.container.Invoke(function, opts...)
-}
-
-// Provide teaches the container how to build values of one or more types and
-// expresses their dependencies.
-//
-// The first argument of Provide is a function that accepts zero or more
-// parameters and returns one or more results. The function may optionally
-// return an error to indicate that it failed to build the value. This
-// function will be treated as the constructor for all the types it returns.
-// This function will be called AT MOST ONCE when a type produced by it, or a
-// type that consumes this function's output, is requested via Invoke. If the
-// same types are requested multiple times, the previously produced value will
-// be reused.
-//
-// In addition to accepting constructors that accept dependencies as separate
-// arguments and produce results as separate return values, Provide also
-// accepts constructors that specify dependencies as dig.In structs and/or
-// specify results as dig.Out structs.
-func (hub *Hub) Provide(constructor interface{}, opts ...ProvideOption) error {
-	return hub.container.Provide(constructor, opts...)
-}
-
-func (hub *Hub) GetProvidedSlice() []Provided {
-	return hub.provides
-}

+ 0 - 187
pkg/di/hub_test.go

@@ -1,187 +0,0 @@
-package di
-
-import (
-	"strings"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-	"go.uber.org/dig"
-)
-
-func TestHub_New(t *testing.T) {
-	t.Run("basic di", func(t *testing.T) {
-		hub, err := New(module1, ValidateHub(true))
-		require.NoError(t, err)
-		require.NotNil(t, hub)
-
-		err = hub.Invoke(func(c C) {
-			assert.Equal(t, c.Number, int64(100))
-		})
-		require.NoError(t, err)
-
-		err = hub.Invoke(func(d D) {
-			assert.Equal(t, d.C.Number, int64(100))
-		})
-		require.NoError(t, err)
-
-		err = hub.Invoke(func(f1 F1) {
-			assert.Equal(t, f1.Name, "f1")
-		})
-		require.NoError(t, err)
-	})
-
-	t.Run("annotation", func(t *testing.T) {
-		k0 := &K0{}
-		hub, err := New(module2, Annotation(func(ann *Annotated) {
-			ann.Target = func() *K0 { return k0 }
-			ann.Close = k0.Close
-		}))
-		require.NoError(t, err)
-		require.NotNil(t, hub)
-
-		// invoke now
-		err = hub.Invoke(func(k1 K1) { assert.Equal(t, k1.J.Name, "j1") })
-		require.NoError(t, err)
-		err = hub.Invoke(func(k2 K2) { assert.Equal(t, k2.J.Name, "j2") })
-		require.NoError(t, err)
-
-		// cleanup and check it
-		hub.Cleanup()
-		require.True(t, k0.Closed)
-	})
-
-	t.Run("missing deps", func(t *testing.T) {
-		hub, err := New(moduleFailed, ValidateHub(false))
-		require.NoError(t, err) // won't check missing H in G, only check it after invoke
-		require.NotNil(t, hub)
-
-		err = hub.Invoke(func(g G) {})
-		assert.Error(t, err)
-		assert.True(t, strings.Contains(err.Error(), "missing dependencies"))
-	})
-}
-
-var module1 = Options(
-	Provide(func() A {
-		return A{Name: "a"}
-	}),
-	Provide(func(a A) B {
-		return B{
-			A:   a,
-			Age: 20,
-		}
-	}),
-	Provide(func(a A, b B) C {
-		return C{
-			A:      a,
-			B:      b,
-			Number: 100,
-		}
-	}),
-	Provide(NewE),
-)
-
-var module2 = Options(
-	Provide(Annotated{
-		Name: "j1",
-		Target: func() J {
-			return J{Name: "j1"}
-		},
-	}),
-	Provide(Annotated{
-		Name: "j2",
-		Target: func() J {
-			return J{Name: "j2"}
-		},
-	}),
-)
-
-var moduleFailed = Options(
-	Provide(func(g G) H {
-		return H{
-			G:    g,
-			Name: "h",
-		}
-	}),
-)
-
-type A struct {
-	Name string
-}
-
-type B struct {
-	A   A
-	Age int
-}
-
-type C struct {
-	A      A
-	B      B
-	Number int64
-}
-
-type D struct {
-	dig.In
-
-	A A
-	B B
-	C C
-}
-
-func NewE() E {
-	return E{
-		F1: F1{
-			Name: "f1",
-		},
-		F2: F2{
-			Name: "f2",
-		},
-	}
-}
-
-type E struct {
-	dig.Out
-
-	F1 F1
-	F2 F2
-}
-
-type F1 struct {
-	Name string
-}
-
-type F2 struct {
-	Name string
-}
-
-type G struct {
-	Name string
-}
-
-type H struct {
-	G    G
-	Name string
-}
-
-type J struct {
-	Name string
-}
-
-type K0 struct {
-	Closed bool
-}
-
-func (k *K0) Close() {
-	k.Closed = true
-}
-
-type K1 struct {
-	dig.In
-	J J `name:"j1"`
-}
-
-type K2 struct {
-	dig.In
-	J J `name:"j2"`
-}

+ 0 - 180
pkg/di/option.go

@@ -1,180 +0,0 @@
-package di
-
-import (
-	"fmt"
-	"strings"
-
-	"kpt-tmr-group/pkg/di/xreflect"
-
-	"go.uber.org/dig"
-)
-
-// Option configures a Hub. It's included for future functionality;
-// currently, there are no concrete implementations.
-type Option = dig.Option
-
-// A ProvideOption modifies the default behavior of Provide.
-type ProvideOption = dig.ProvideOption
-
-// An InvokeOption modifies the default behavior of Invoke. It's included for
-// future functionality; currently, there are no concrete implementations.
-type InvokeOption = dig.InvokeOption
-
-// HubOption is an option configures an Hub using the functional options paradigm
-// popularized by Rob Pike. If you're unfamiliar with this style, see
-// https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html.
-type HubOption interface {
-	fmt.Stringer
-	Apply(hub *Hub)
-}
-
-// Options converts a collection of Options into a single Option. This allows
-// packages to bundle sophisticated functionality into easy-to-use Fx modules.
-// For example, a logging package might export a simple option like this:
-//
-//  package logging
-//
-//  var Module = fx.Provide(func() *log.Logger {
-//    return log.New(os.Stdout, "", 0)
-//  })
-//
-// A shared all-in-one microservice package could then use Options to bundle
-// logging with similar metrics, tracing, and gRPC modules:
-//
-//  package server
-//
-//  var Module = fx.Options(
-//    logging.Module,
-//    metrics.Module,
-//    tracing.Module,
-//    grpc.Module,
-//  )
-//
-// Since this all-in-one module1 has a minimal API surface, it's easy to add
-// new functionality to it without breaking existing users. Individual
-// applications can take advantage of all this functionality with only one
-// line of code:
-//
-//  app := di.New(server.Module)
-//
-// Use this pattern sparingly, since it limits the user's ability to customize
-// their application.
-func Options(opts ...HubOption) HubOption {
-	return optionGroup(opts)
-}
-
-type optionGroup []HubOption
-
-func (og optionGroup) Apply(hub *Hub) {
-	for _, opt := range og {
-		opt.Apply(hub)
-	}
-}
-
-func (og optionGroup) String() string {
-	items := make([]string, len(og))
-	for i, opt := range og {
-		items[i] = fmt.Sprint(opt)
-	}
-	return fmt.Sprintf("di.Options(%s)", strings.Join(items, ", "))
-}
-
-// Annotation define annotated and apply to Provided
-// Annotation provides instantiated values for dependency injection as if
-// they had been provided using a constructor that simply returns them.
-// The most specific type of each value (as determined by reflection) is used.
-//
-//	type K0 struct {
-//		Closed bool
-//	}
-//
-//	func (k *K0) Close() {
-//		k.Closed = true
-//	}
-//
-//	k0 := &K0{}
-//	var module = Annotation(func(ann *Annotated) {
-//		ann.Target = func() *K0 { return k0 }
-//		ann.Close = k0.Close
-//	})
-//
-//	hub, err := di.New(module)
-func Annotation(f func(ann *Annotated)) HubOption {
-	annotation := &Annotated{}
-	f(annotation)
-
-	return provideOption{
-		Targets: []interface{}{*annotation},
-		Stack:   xreflect.CallerStack(1, 0),
-	}
-}
-
-// Provide registers any number of constructor functions, teaching the
-// application how to instantiate various types. The supplied constructor
-// function(s) may depend on other types available in the application, must
-// return one or more objects, and may return an error. For example:
-//
-//  // Constructs type *C, depends on *A and *B.
-//  func(*A, *B) *C
-//
-//  // Constructs type *C, depends on *A and *B, and indicates failure by
-//  // returning an error.
-//  func(*A, *B) (*C, error)
-//
-//  // Constructs types *B and *C, depends on *A, and can fail.
-//  func(*A) (*B, *C, error)
-func Provide(constructors ...interface{}) HubOption {
-	// check no nil or error
-	for _, value := range constructors {
-		switch value.(type) {
-		case nil:
-			panic("untyped nil passed to di.Provide")
-		case error:
-			panic("error value passed to di.Provide")
-		}
-	}
-
-	return provideOption{
-		Targets: constructors,
-		Stack:   xreflect.CallerStack(1, 0),
-	}
-}
-
-type provideOption struct {
-	Targets []interface{}
-	Stack   xreflect.Stack
-}
-
-func (o provideOption) Apply(hub *Hub) {
-	for _, target := range o.Targets {
-		hub.provides = append(hub.provides, Provided{
-			Target: target,
-			Stack:  o.Stack,
-		})
-	}
-}
-
-func (o provideOption) String() string {
-	items := make([]string, len(o.Targets))
-	for i, c := range o.Targets {
-		items[i] = xreflect.FuncName(c)
-	}
-	return fmt.Sprintf("fx.Provide(%s)", strings.Join(items, ", "))
-}
-
-// ValidateHub validates that supplied graph would run and is not missing any dependencies.
-func ValidateHub(v bool) HubOption {
-	return validateOption{validate: v}
-}
-
-type validateOption struct {
-	validate bool
-}
-
-func (o validateOption) Apply(hub *Hub) {
-	hub.validate = o.validate
-}
-
-func (o validateOption) String() string {
-	return fmt.Sprintf("fx.validate(%v)", o.validate)
-}

+ 0 - 157
pkg/di/xreflect/reflect.go

@@ -1,157 +0,0 @@
-// Copyright (c) 2019 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package xreflect
-
-import (
-	"fmt"
-	"net/url"
-	"reflect"
-	"regexp"
-	"runtime"
-	"strings"
-
-	"go.uber.org/dig"
-)
-
-// Match from beginning of the line until the first `vendor/` (non-greedy)
-var vendorRe = regexp.MustCompile("^.*?/vendor/")
-
-// ReturnTypes takes a func and returns a slice of string'd types.
-func ReturnTypes(t interface{}) []string {
-	if reflect.TypeOf(t).Kind() != reflect.Func {
-		// Invalid provide, will be logged as an error.
-		return []string{}
-	}
-
-	rtypes := []string{}
-	ft := reflect.ValueOf(t).Type()
-
-	for i := 0; i < ft.NumOut(); i++ {
-		t := ft.Out(i)
-
-		traverseOuts(key{t: t}, func(s string) {
-			rtypes = append(rtypes, s)
-		})
-	}
-
-	return rtypes
-}
-
-type key struct {
-	t    reflect.Type
-	name string
-}
-
-func (k *key) String() string {
-	if k.name != "" {
-		return fmt.Sprintf("%v:%s", k.t, k.name)
-	}
-	return k.t.String()
-}
-
-func traverseOuts(k key, f func(s string)) {
-	// skip errors
-	if isErr(k.t) {
-		return
-	}
-
-	// call function on non-Out types
-	if dig.IsOut(k.t) {
-		// keep recursing down on field members in case they are ins
-		for i := 0; i < k.t.NumField(); i++ {
-			field := k.t.Field(i)
-			ft := field.Type
-
-			if field.PkgPath != "" {
-				continue // skip private fields
-			}
-
-			// keep recursing to traverse all the embedded objects
-			k := key{
-				t:    ft,
-				name: field.Tag.Get("name"),
-			}
-			traverseOuts(k, f)
-		}
-
-		return
-	}
-
-	f(k.String())
-}
-
-// sanitize makes the function name suitable for logging display. It removes
-// url-encoded elements from the `dot.git` package names and shortens the
-// vendored paths.
-func sanitize(function string) string {
-	// Use the stdlib to un-escape any package import paths which can happen
-	// in the case of the "dot-git" postfix. Seems like a bug in stdlib =/
-	if unescaped, err := url.QueryUnescape(function); err == nil {
-		function = unescaped
-	}
-
-	// strip everything prior to the vendor
-	return vendorRe.ReplaceAllString(function, "vendor/")
-}
-
-// Caller returns the formatted calling func name
-func Caller() string {
-	return CallerStack(1, 0).CallerName()
-}
-
-// FuncName returns a funcs formatted name
-func FuncName(fn interface{}) string {
-	fnV := reflect.ValueOf(fn)
-	if fnV.Kind() != reflect.Func {
-		return fmt.Sprint(fn)
-	}
-
-	function := runtime.FuncForPC(fnV.Pointer()).Name()
-	return fmt.Sprintf("%s()", sanitize(function))
-}
-
-func isErr(t reflect.Type) bool {
-	errInterface := reflect.TypeOf((*error)(nil)).Elem()
-	return t.Implements(errInterface)
-}
-
-// Ascend the call stack until we leave the di production code. This allows us
-// to avoid hard-coding a frame skip, which makes this code work well even
-// when it's wrapped.
-func shouldIgnoreFrame(f Frame) bool {
-	// Treat test files as leafs.
-	if strings.Contains(f.File, "_test.go") {
-		return false
-	}
-
-	// The unique, fully-qualified name for all functions begins with
-	// "{{importPath}}.". We'll ignore di and its subpackages.
-	s := strings.TrimPrefix(f.Function, "kpt-tmr-group/pkg/di")
-	if len(s) > 0 && s[0] == '.' || s[0] == '/' {
-		// We want to match,
-		//   kpt-tmr-group/pkg/di.Foo
-		//   kpt-tmr-group/pkg/di/something.Foo
-		// But not, kpt-tmr-group/pkg/difoo
-		return true
-	}
-
-	return false
-}

+ 0 - 143
pkg/di/xreflect/reflect_test.go

@@ -1,143 +0,0 @@
-// Copyright (c) 2019 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package xreflect
-
-import (
-	"errors"
-	"log"
-	"sync"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"go.uber.org/dig"
-)
-
-type hollerer interface {
-	Holler()
-}
-
-type impl struct{}
-
-func (impl) Holler() {}
-
-type result struct {
-	dig.Out // referencing di introduces import cycles
-
-	mu     sync.Mutex // unexported
-	Logger *log.Logger
-}
-
-func TestReturnTypes(t *testing.T) {
-	t.Run("non-function", func(t *testing.T) {
-		assert.Empty(t, ReturnTypes(42))
-	})
-	t.Run("primitive", func(t *testing.T) {
-		fn := func() (int, string) {
-			return 0, ""
-		}
-		assert.Equal(t, []string{"int", "string"}, ReturnTypes(fn))
-	})
-	t.Run("pointer", func(t *testing.T) {
-		type s struct{}
-		fn := func() *s {
-			return &s{}
-		}
-		assert.Equal(t, []string{"*xreflect.s"}, ReturnTypes(fn))
-	})
-	t.Run("interface", func(t *testing.T) {
-		fn := func() hollerer {
-			return impl{}
-		}
-		assert.Equal(t, []string{"xreflect.hollerer"}, ReturnTypes(fn))
-	})
-	t.Run("result struct", func(t *testing.T) {
-		fn := func() result {
-			return result{}
-		}
-		assert.Equal(t, []string{"*log.Logger"}, ReturnTypes(fn))
-	})
-	t.Run("skips errors", func(t *testing.T) {
-		fn := func() (string, error) {
-			return "", errors.New("err")
-		}
-		assert.Equal(t, []string{"string"}, ReturnTypes(fn))
-	})
-}
-
-func TestCaller(t *testing.T) {
-	assert.Equal(t, "kpt-tmr-group/pkg/di/xreflect.TestCaller", Caller())
-}
-
-func someFunc() {}
-
-func TestFuncName(t *testing.T) {
-	tests := []struct {
-		desc string
-		give interface{}
-		want string
-	}{
-		{
-			desc: "function",
-			give: someFunc,
-			want: "kpt-tmr-group/pkg/di/xreflect.someFunc()",
-		},
-		{
-			desc: "not a function",
-			give: 42,
-			want: "42",
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.desc, func(t *testing.T) {
-			assert.Equal(t, tt.want, FuncName(tt.give))
-		})
-	}
-}
-
-func TestSanitizeFuncNames(t *testing.T) {
-	cases := []struct {
-		name     string
-		input    string
-		expected string
-	}{
-		{
-			"url encoding",
-			"go.uber.org/di/sample%2egit/someFunc",
-			"go.uber.org/di/sample.git/someFunc",
-		},
-		{
-			"vendor removal",
-			"go.uber.org/di/vendor/github.com/some/lib.SomeFunc",
-			"vendor/github.com/some/lib.SomeFunc",
-		},
-		{
-			"package happens to be named vendor is untouched",
-			"go.uber.org/di/foovendor/someFunc",
-			"go.uber.org/di/foovendor/someFunc",
-		},
-	}
-	for _, c := range cases {
-		t.Run(c.name, func(t *testing.T) {
-			assert.Equal(t, c.expected, sanitize(c.input))
-		})
-	}
-}

+ 0 - 149
pkg/di/xreflect/stack.go

@@ -1,149 +0,0 @@
-// Copyright (c) 2019 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package xreflect
-
-import (
-	"fmt"
-	"io"
-	"runtime"
-	"strings"
-)
-
-// Frame holds information about a single frame in the call stack.
-type Frame struct {
-	// Unique, package path-qualified name for the function of this call
-	// frame.
-	Function string
-
-	// File and line number of our location in the frame.
-	//
-	// Note that the line number does not refer to where the function was
-	// defined but where in the function the next call was made.
-	File string
-	Line int
-}
-
-func (f Frame) String() string {
-	// This takes the following forms.
-	//  (path/to/file.go)
-	//  (path/to/file.go:42)
-	//  path/to/package.MyFunction
-	//  path/to/package.MyFunction (path/to/file.go)
-	//  path/to/package.MyFunction (path/to/file.go:42)
-
-	var sb strings.Builder
-	sb.WriteString(f.Function)
-	if len(f.File) > 0 {
-		if sb.Len() > 0 {
-			sb.WriteRune(' ')
-		}
-		fmt.Fprintf(&sb, "(%v", f.File)
-		if f.Line > 0 {
-			fmt.Fprintf(&sb, ":%d", f.Line)
-		}
-		sb.WriteRune(')')
-	}
-
-	if sb.Len() == 0 {
-		return "unknown"
-	}
-
-	return sb.String()
-}
-
-const _defaultCallersDepth = 8
-
-// Stack is a stack of call frames.
-//
-// Formatted with %v, the output is in a single-line, in the form,
-//
-//   foo/bar.Baz() (path/to/foo.go:42); bar/baz.Qux() (bar/baz/qux.go:12); ...
-//
-// Formatted with %+v, the output is in the form,
-//
-//   foo/bar.Baz()
-//   	path/to/foo.go:42
-//   bar/baz.Qux()
-//   	bar/baz/qux.go:12
-type Stack []Frame
-
-// Returns a single-line, semi-colon representation of a Stack. For a
-// multi-line representation, use %+v.
-func (fs Stack) String() string {
-	items := make([]string, len(fs))
-	for i, f := range fs {
-		items[i] = f.String()
-	}
-	return strings.Join(items, "; ")
-}
-
-// Format implements fmt.Formatter to handle "%+v".
-func (fs Stack) Format(w fmt.State, c rune) {
-	if !w.Flag('+') {
-		// Without %+v, fall back to String().
-		io.WriteString(w, fs.String())
-		return
-	}
-
-	for _, f := range fs {
-		fmt.Fprintln(w, f.Function)
-		fmt.Fprintf(w, "\t%v:%v\n", f.File, f.Line)
-	}
-}
-
-// CallerName returns the name of the first caller in this stack that isn't
-// owned by the di library.
-func (fs Stack) CallerName() string {
-	for _, f := range fs {
-		if shouldIgnoreFrame(f) {
-			continue
-		}
-		return f.Function
-	}
-	return "n/a"
-}
-
-// CallerStack returns the call stack for the calling function, up to depth frames
-// deep, skipping the provided number of frames, not including Callers itself.
-//
-// If zero, depth defaults to 8.
-func CallerStack(skip, depth int) Stack {
-	if depth <= 0 {
-		depth = _defaultCallersDepth
-	}
-
-	pcs := make([]uintptr, depth)
-
-	// +2 to skip this frame and runtime.Callers.
-	n := runtime.Callers(skip+2, pcs)
-	pcs = pcs[:n] // truncate to number of frames actually read
-
-	result := make([]Frame, 0, n)
-	frames := runtime.CallersFrames(pcs)
-	for f, more := frames.Next(); more; f, more = frames.Next() {
-		result = append(result, Frame{
-			Function: sanitize(f.Function),
-			File:     f.File,
-			Line:     f.Line,
-		})
-	}
-	return result
-}

+ 0 - 236
pkg/di/xreflect/stack_test.go

@@ -1,236 +0,0 @@
-// Copyright (c) 2019 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package xreflect
-
-import (
-	"fmt"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-)
-
-func TestStack(t *testing.T) {
-	// NOTE:
-	// We don't assert the length of the stack because we cannot make
-	// guarantees about how many frames the test runner is allowed to
-	// introduce.
-
-	t.Run("default", func(t *testing.T) {
-		frames := CallerStack(0, 0)
-		require.NotEmpty(t, frames)
-		f := frames[0]
-		assert.Equal(t, "kpt-tmr-group/pkg/di/xreflect.TestStack.func1", f.Function)
-		assert.Contains(t, f.File, "xreflect/stack_test.go")
-		assert.NotZero(t, f.Line)
-	})
-
-	t.Run("default/deeper", func(t *testing.T) {
-		// Introduce a few frames.
-		frames := func() []Frame {
-			return func() []Frame {
-				return CallerStack(0, 0)
-			}()
-		}()
-
-		require.True(t, len(frames) > 3, "expected at least three frames")
-		for i, name := range []string{"func2.1.1", "func2.1", "func2"} {
-			f := frames[i]
-			assert.Equal(t, "kpt-tmr-group/pkg/di/xreflect.TestStack."+name, f.Function)
-			assert.Contains(t, f.File, "xreflect/stack_test.go")
-			assert.NotZero(t, f.Line)
-		}
-	})
-
-	t.Run("skip", func(t *testing.T) {
-		// Introduce a few frames and skip 2.
-		frames := func() []Frame {
-			return func() []Frame {
-				return CallerStack(2, 0)
-			}()
-		}()
-
-		require.NotEmpty(t, frames)
-		f := frames[0]
-		assert.Equal(t, "kpt-tmr-group/pkg/di/xreflect.TestStack.func3", f.Function)
-		assert.Contains(t, f.File, "xreflect/stack_test.go")
-		assert.NotZero(t, f.Line)
-	})
-}
-
-func TestStackCallerName(t *testing.T) {
-	tests := []struct {
-		desc string
-		give Stack
-		want string
-	}{
-		{desc: "empty", want: "n/a"},
-		{
-			desc: "skip di components",
-			give: Stack{
-				{
-					Function: "kpt-tmr-group/pkg/di.Foo()",
-					File:     "kpt-tmr-group/pkg/di/foo.go",
-				},
-				{
-					Function: "foo/bar.Baz()",
-					File:     "foo/bar/baz.go",
-				},
-			},
-			want: "foo/bar.Baz()",
-		},
-		{
-			desc: "skip di in wrong directory",
-			give: Stack{
-				{
-					Function: "kpt-tmr-group/pkg/di/di.Foo()",
-					File:     "di/foo.go",
-				},
-				{
-					Function: "foo/bar.Baz()",
-					File:     "foo/bar/baz.go",
-				},
-			},
-			want: "foo/bar.Baz()",
-		},
-		{
-			desc: "skip di subpackage",
-			give: Stack{
-				{
-					Function: "kpt-tmr-group/pkg/di/xreflect.Foo()",
-					File:     "di/internal/xreflect/foo.go",
-				},
-				{
-					Function: "foo/bar.Baz()",
-					File:     "foo/bar/baz.go",
-				},
-			},
-			want: "foo/bar.Baz()",
-		},
-		{
-			desc: "don't skip di tests",
-			give: Stack{
-				{
-					Function: "some/thing.Foo()",
-					File:     "kpt-tmr-group/pkg/di/foo_test.go",
-				},
-			},
-			want: "some/thing.Foo()",
-		},
-		{
-			desc: "don't skip di prefix",
-			give: Stack{
-				{
-					Function: "kpt-tmr-group/pkg/difoo.Bar()",
-					File:     "kpt-tmr-group/pkg/difoo/bar.go",
-				},
-			},
-			want: "kpt-tmr-group/pkg/difoo.Bar()",
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.desc, func(t *testing.T) {
-			assert.Equal(t, tt.want, tt.give.CallerName())
-		})
-	}
-}
-
-func TestFrameString(t *testing.T) {
-	tests := []struct {
-		desc string
-		give Frame
-		want string
-	}{
-		{
-			desc: "zero",
-			give: Frame{},
-			want: "unknown",
-		},
-		{
-			desc: "file and line",
-			give: Frame{File: "foo.go", Line: 42},
-			want: "(foo.go:42)",
-		},
-		{
-			desc: "file only",
-			give: Frame{File: "foo.go"},
-			want: "(foo.go)",
-		},
-		{
-			desc: "function only",
-			give: Frame{Function: "foo"},
-			want: "foo",
-		},
-		{
-			desc: "function and file",
-			give: Frame{Function: "foo", File: "bar.go"},
-			want: "foo (bar.go)",
-		},
-		{
-			desc: "function and line",
-			give: Frame{Function: "foo", Line: 42},
-			want: "foo", // line without file is meaningless
-		},
-		{
-			desc: "function, file, and line",
-			give: Frame{Function: "foo", File: "bar.go", Line: 42},
-			want: "foo (bar.go:42)",
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.desc, func(t *testing.T) {
-			assert.Equal(t, tt.want, tt.give.String())
-		})
-	}
-}
-
-func TestStackFormat(t *testing.T) {
-	stack := Stack{
-		{
-			Function: "path/to/module.SomeFunction()",
-			File:     "path/to/file.go",
-			Line:     42,
-		},
-		{
-			Function: "path/to/another/module.AnotherFunction()",
-			File:     "path/to/another/file.go",
-			Line:     12,
-		},
-	}
-
-	t.Run("single line", func(t *testing.T) {
-		assert.Equal(t,
-			"path/to/module.SomeFunction() (path/to/file.go:42); "+
-				"path/to/another/module.AnotherFunction() (path/to/another/file.go:12)",
-			fmt.Sprintf("%v", stack))
-	})
-
-	t.Run("multi line", func(t *testing.T) {
-		assert.Equal(t, `path/to/module.SomeFunction()
-	path/to/file.go:42
-path/to/another/module.AnotherFunction()
-	path/to/another/file.go:12
-`, fmt.Sprintf("%+v", stack))
-	})
-
-}

+ 0 - 68
pkg/ginutil/bind.go

@@ -1,68 +0,0 @@
-package ginutil
-
-import (
-	"net/http"
-	"reflect"
-
-	"kpt-tmr-group/pkg/jsonpb"
-	"kpt-tmr-group/pkg/xerr"
-
-	"github.com/gin-gonic/gin"
-	"github.com/gin-gonic/gin/binding"
-	"github.com/golang/protobuf/proto"
-	"github.com/huandu/xstrings"
-)
-
-var camelQuery = &CamelQueryBinding{}
-
-// BindQuery with query params
-func BindQuery(c *gin.Context, obj interface{}) error {
-	return c.ShouldBindWith(obj, camelQuery)
-}
-
-type CamelQueryBinding struct{}
-
-func (*CamelQueryBinding) Name() string {
-	return "camel_query"
-}
-
-func (*CamelQueryBinding) Bind(req *http.Request, obj interface{}) error {
-	values := req.URL.Query()
-	if err := mapFormByTag(obj, values, "json"); err != nil {
-		return err
-	}
-	return binding.Validator.ValidateStruct(obj)
-}
-
-type camelFormSource map[string][]string
-
-// TrySet tries to set a value by request's form source (like map[string][]string)
-func (form camelFormSource) TrySet(value reflect.Value, field reflect.StructField, tagValue string, opt setOptions) (isSetted bool, err error) {
-	return setByForm(value, field, form, xstrings.FirstRuneToLower(xstrings.ToCamelCase(tagValue)), opt)
-}
-
-// BindProtoMessage with proto message from json body
-func BindProtoMessage(c *gin.Context, obj proto.Message) error {
-	return c.ShouldBindWith(obj, protoMessageBindingFromBody)
-}
-
-var protoMessageBindingFromBody = &ProtoMessageBinding{}
-
-type ProtoMessageBinding struct{}
-
-func (*ProtoMessageBinding) Name() string {
-	return "proto_message_binding"
-}
-
-func (*ProtoMessageBinding) Bind(req *http.Request, obj interface{}) error {
-	pbMessage, ok := obj.(proto.Message)
-	if !ok {
-		return xerr.New("bind obj should be proto.Message")
-	}
-
-	if err := jsonpb.Unmarshal(req.Body, pbMessage); err != nil {
-		return xerr.WithStack(err)
-	}
-
-	return binding.Validator.ValidateStruct(obj)
-}

+ 0 - 34
pkg/ginutil/bind_proto.go

@@ -1,34 +0,0 @@
-package ginutil
-
-import (
-	"net/http"
-
-	"kpt-tmr-group/pkg/jsonpb"
-	"kpt-tmr-group/pkg/xerr"
-
-	"github.com/gin-gonic/gin"
-	"github.com/golang/protobuf/proto"
-)
-
-type ProtoMessageQueryBinding struct{}
-
-func BindQueryProto(c *gin.Context, pb proto.Message) error {
-	values := c.Request.URL.Query()
-	if err := jsonpb.UnmarshalQuery(values, pb); err != nil {
-		return xerr.WithStack(err)
-	}
-	return nil
-}
-
-func BindProto(c *gin.Context, pb proto.Message) (err error) {
-	switch c.Request.Method {
-	case http.MethodGet, http.MethodDelete:
-		err = BindQueryProto(c, pb)
-	default:
-		err = BindProtoMessage(c, pb)
-	}
-	if err != nil {
-		return xerr.WithStack(err)
-	}
-	return
-}

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно