xsh_1997 před 1 měsícem
rodič
revize
d75ea25e8b

+ 2 - 2
ruoyi-ui/src/api/livestockFinance/yakAsset.js

@@ -9,7 +9,7 @@ export function listYakAsset(query) {
9 9
   })
10 10
 }
11 11
 
12
-/** 档案详情(主表 + 子表) */
12
+/** 档案详情(主表 + 子表) */
13 13
 export function getYakAsset(id) {
14 14
   return request({
15 15
     url: "/dataModel/yakAsset/" + id,
@@ -43,7 +43,7 @@ export function getYakGrowthChart(id, query) {
43 43
   })
44 44
 }
45 45
 
46
-/** 第三方同步 */
46
+/** 第三方五段全量同步(不含 IoT) */
47 47
 export function syncYakAsset() {
48 48
   return request({
49 49
     url: "/dataModel/yakAsset/sync",

+ 27 - 11
ruoyi-ui/src/lang/bo/livestockFinance.js

@@ -26,7 +26,13 @@ export default {
26 26
     queryYakNoPh: "འབྲོང་ཨང་འཚོལ་རོགས།",
27 27
     queryAssetStatus: "རྒྱུ་ནོར་གནས་བབ།",
28 28
     btnSync: "མཉམ་སྒྲིག",
29
-    syncSummary: "གསར་{insert} རྩོམ་{update} ཕམ་{fail}",
29
+    syncSummary: "ནང་འཇུག:གསར་{insert} རྩོམ་{update} ཕམ་{fail}",
30
+    syncMasterSummary: "མཉམ་སྒྲིག་ཚར(རྩྭ་ཁང་ {pInsert}/{pUpdate}/{pFail},ལྡེ་མིག {eInsert}/{eUpdate}/{eFail},འཆར་གཞི {plInsert}/{plUpdate}/{plFail},ཚོགས {bInsert}/{bUpdate}/{bFail},ནང་འཇུག {yInsert}/{yUpdate}/{yFail})",
31
+    syncStepPasture: "རྩྭ་ཁང་",
32
+    syncStepEnclosure: "ལྡེ་མིག",
33
+    syncStepPlan: "འཆར་གཞི",
34
+    syncStepBatch: "ཚོགས",
35
+    syncStepYakAsset: "ནང་འཇུག",
30 36
     syncTimeHint: "གཞི་གྲངས་དུས་ཚོད:{time}",
31 37
     colYakNo: "འབྲོང་ཨང་།",
32 38
     colPastureName: "རྩྭ་ཁང་།",
@@ -44,6 +50,11 @@ export default {
44 50
     sectionGrowth: "འཛོམས་རྒྱས།",
45 51
     sectionReproduction: "འཕྲོད་ནུས།",
46 52
     sectionFeeding: "ཟས་གསོས།",
53
+    sectionPen: "འབྲོང་ལྡེ་མིག",
54
+    sectionBatch: "འབྲོང་ཚོགས",
55
+    colEnclosureName: "ལྡེ་མིག་མིང་།",
56
+    colPenLocation: "ལྡེ་མིག་གནས།",
57
+    colEntryCycle: "ནང་འཇུག་དུས་ཚོད།",
47 58
     growthModeList: "ཐོ་བྱང་།",
48 59
     growthModeChart: "འཁྱར་རིས།",
49 60
     growthMetric: "ཚད་གཞི།",
@@ -74,6 +85,18 @@ export default {
74 85
     fieldEnvTemp: "ཁོར་ཡུག་དྲོད།",
75 86
     fieldLocation: "གནས་ཡུལ།",
76 87
     fieldPhysioCollectTime: "བསྡུ་ཚེས།",
88
+    fieldEarTagNumber: "རྣ་རྟགས་ཨང་།",
89
+    fieldEnclosureName: "ལྡེ་མིག་མིང་།",
90
+    fieldEntryCycle: "ནང་འཇུག་དུས་ཚོད།",
91
+    fieldCattleVariety: "འབྲོང་རིགས།",
92
+    fieldCattlePicture: "འབྲོང་པར།",
93
+    fieldRegistrant: "ཐོ་འགོད་མཁན།",
94
+    fieldRemark: "ཟུར་མཆན།",
95
+    fieldStatusChangeDate: "བསྒྱུར་ཚེས།",
96
+    fieldStatusChangeReason: "བསྒྱུར་རྒྱུ་མཚན།",
97
+    fieldPenLocation: "ལྡེ་མིག་གནས།",
98
+    fieldExpectedOutDate: "ཕྱིར་འདོན་དུས་ཚོད།",
99
+    fieldSupplementPlan: "ཟས་གསོས་འཆར་གཞི།",
77 100
     fieldLastSyncTime: "མཉམ་སྒྲིག་དུས་ཚོད།",
78 101
     colDayAge: "ཉིན་གྲངས།",
79 102
     colWeight: "ལུས་ཚད།",
@@ -96,15 +119,8 @@ export default {
96 119
     dataKindForecast: "སྔོན་དཔྱད།",
97 120
     pedigreeNotFound: "ཨང་{no} མ་རྙེད།",
98 121
     status1: "སྤྱིར་བཟང་།",
99
-    status2: "འཕྲུལ་བཞིན།",
100
-    status3: "འཕྲོད་དུས།",
101
-    status4: "ཐག་གཏོར།",
102
-    status5: "སྲུང་འཁོར།",
103
-    status6: "ཕྱིར་འདོན་སྒུག",
104
-    status7: "སྐྱུར་མེད།",
105
-    status8: "ཤི་བ།",
106
-    status9: "ཕུད།",
107
-    status10: "བཙོངས་ཟིན།",
108
-    status11: "ཆད་པ།"
122
+    status2: "ཤི་ཕུད།",
123
+    status3: "ཆད་པ།",
124
+    status4: "ཕྱིར་འདོན།"
109 125
   }
110 126
 }

+ 27 - 11
ruoyi-ui/src/lang/zh/livestockFinance.js

@@ -26,7 +26,13 @@ export default {
26 26
     queryYakNoPh: "请输入牦牛编号关键字",
27 27
     queryAssetStatus: "资产状态",
28 28
     btnSync: "同步",
29
-    syncSummary: "新增 {insert} 条,更新 {update} 条,失败 {fail} 条",
29
+    syncSummary: "入栏建档:新增 {insert} 条,更新 {update} 条,失败 {fail} 条",
30
+    syncMasterSummary: "同步完成(养殖场 {pInsert}/{pUpdate}/{pFail},圈舍 {eInsert}/{eUpdate}/{eFail},计划 {plInsert}/{plUpdate}/{plFail},批次 {bInsert}/{bUpdate}/{bFail},入栏 {yInsert}/{yUpdate}/{yFail})",
31
+    syncStepPasture: "养殖场",
32
+    syncStepEnclosure: "圈舍",
33
+    syncStepPlan: "生产计划",
34
+    syncStepBatch: "批次",
35
+    syncStepYakAsset: "入栏建档",
30 36
     syncTimeHint: "数据截至:{time}",
31 37
     colYakNo: "牦牛编号",
32 38
     colPastureName: "所属牧场",
@@ -44,6 +50,11 @@ export default {
44 50
     sectionGrowth: "生长性状",
45 51
     sectionReproduction: "繁殖性能",
46 52
     sectionFeeding: "饲喂数据",
53
+    sectionPen: "牦牛圈舍",
54
+    sectionBatch: "牦牛批次",
55
+    colEnclosureName: "圈舍名称",
56
+    colPenLocation: "圈舍位置",
57
+    colEntryCycle: "入栏周期",
47 58
     growthModeList: "列表",
48 59
     growthModeChart: "曲线图",
49 60
     growthMetric: "指标",
@@ -74,6 +85,18 @@ export default {
74 85
     fieldEnvTemp: "环境温度",
75 86
     fieldLocation: "位置",
76 87
     fieldPhysioCollectTime: "采集时间",
88
+    fieldEarTagNumber: "耳标编号",
89
+    fieldEnclosureName: "圈舍名称",
90
+    fieldEntryCycle: "入栏周期",
91
+    fieldCattleVariety: "牛只品种",
92
+    fieldCattlePicture: "牛只图片",
93
+    fieldRegistrant: "登记人",
94
+    fieldRemark: "备注",
95
+    fieldStatusChangeDate: "变更日期",
96
+    fieldStatusChangeReason: "状态变更原因",
97
+    fieldPenLocation: "圈舍位置",
98
+    fieldExpectedOutDate: "预计出栏日期",
99
+    fieldSupplementPlan: "补饲方案",
77 100
     fieldLastSyncTime: "最近同步时间",
78 101
     colDayAge: "日龄",
79 102
     colWeight: "体重",
@@ -96,15 +119,8 @@ export default {
96 119
     dataKindForecast: "预测",
97 120
     pedigreeNotFound: "未找到编号为 {no} 的档案",
98 121
     status1: "正常",
99
-    status2: "在养",
100
-    status3: "生产期",
101
-    status4: "抵押中",
102
-    status5: "投保中",
103
-    status6: "待出栏",
104
-    status7: "闲置",
105
-    status8: "死亡",
106
-    status9: "淘汰",
107
-    status10: "已出售",
108
-    status11: "丢失"
122
+    status2: "死淘",
123
+    status3: "丢失",
124
+    status4: "出栏"
109 125
   }
110 126
 }

+ 80 - 8
ruoyi-ui/src/views/livestockFinance/yakAsset/detailDrawer.vue

@@ -16,6 +16,9 @@
16 16
           <el-col :span="3"><span class="yak-detail__label">{{ lfT("fieldGender") }}:</span>{{ asset.gender || dash }}</el-col>
17 17
           <el-col :span="3"><span class="yak-detail__label">{{ lfT("fieldAgeMonths") }}:</span>{{ formatAgeMonths(asset.ageMonths) }}</el-col>
18 18
         </el-row>
19
+        <el-row v-if="asset.earTagNumber" :gutter="16" class="yak-detail__summary-extra">
20
+          <el-col :span="6"><span class="yak-detail__label">{{ lfT("fieldEarTagNumber") }}:</span>{{ asset.earTagNumber }}</el-col>
21
+        </el-row>
19 22
         <div v-if="asset.lastSyncTime" class="yak-detail__sync-hint">{{ lfT("syncTimeHint", { time: parseTime(asset.lastSyncTime) }) }}</div>
20 23
       </el-card>
21 24
 
@@ -23,9 +26,13 @@
23 26
         <div slot="header">{{ lfT("sectionBasic") }}</div>
24 27
         <el-descriptions v-if="asset" :column="3" border size="small">
25 28
           <el-descriptions-item :label="lfT('fieldYakNo')">{{ asset.yakNo || dash }}</el-descriptions-item>
29
+          <el-descriptions-item :label="lfT('fieldEarTagNumber')">{{ asset.earTagNumber || dash }}</el-descriptions-item>
26 30
           <el-descriptions-item :label="lfT('fieldPastureName')">{{ asset.pastureName || dash }}</el-descriptions-item>
27 31
           <el-descriptions-item :label="lfT('fieldBatchNo')">{{ asset.batchNo || dash }}</el-descriptions-item>
32
+          <el-descriptions-item :label="lfT('fieldEnclosureName')">{{ asset.enclosureName || dash }}</el-descriptions-item>
33
+          <el-descriptions-item :label="lfT('fieldEntryCycle')">{{ asset.entryCycle || dash }}</el-descriptions-item>
28 34
           <el-descriptions-item :label="lfT('fieldGender')">{{ asset.gender || dash }}</el-descriptions-item>
35
+          <el-descriptions-item :label="lfT('fieldCattleVariety')">{{ asset.cattleVariety || dash }}</el-descriptions-item>
29 36
           <el-descriptions-item :label="lfT('fieldBirthDate')">{{ asset.birthDate || dash }}</el-descriptions-item>
30 37
           <el-descriptions-item :label="lfT('fieldAgeMonths')">{{ formatAgeMonths(asset.ageMonths) }}</el-descriptions-item>
31 38
           <el-descriptions-item :label="lfT('fieldEntryDate')">{{ asset.entryDate || dash }}</el-descriptions-item>
@@ -33,7 +40,22 @@
33 40
           <el-descriptions-item :label="lfT('fieldSource')">{{ asset.source || dash }}</el-descriptions-item>
34 41
           <el-descriptions-item :label="lfT('fieldBreedingMethod')">{{ asset.breedingMethod || dash }}</el-descriptions-item>
35 42
           <el-descriptions-item :label="lfT('fieldAssetStatus')">{{ assetStatusLabel(asset.assetStatus) }}</el-descriptions-item>
43
+          <el-descriptions-item :label="lfT('fieldStatusChangeDate')">{{ asset.statusChangeDate || dash }}</el-descriptions-item>
44
+          <el-descriptions-item :label="lfT('fieldStatusChangeReason')">{{ asset.statusChangeReason || dash }}</el-descriptions-item>
45
+          <el-descriptions-item :label="lfT('fieldPenLocation')">{{ asset.penLocation || dash }}</el-descriptions-item>
46
+          <el-descriptions-item :label="lfT('fieldExpectedOutDate')">{{ asset.expectedOutDate || dash }}</el-descriptions-item>
47
+          <el-descriptions-item :label="lfT('fieldSupplementPlan')">{{ asset.supplementPlan || dash }}</el-descriptions-item>
48
+          <el-descriptions-item :label="lfT('fieldRegistrant')">{{ asset.registrant || dash }}</el-descriptions-item>
36 49
           <el-descriptions-item :label="lfT('fieldLastSyncTime')">{{ asset.lastSyncTime ? parseTime(asset.lastSyncTime) : dash }}</el-descriptions-item>
50
+          <el-descriptions-item :label="lfT('fieldRemark')" :span="3">{{ asset.remark || dash }}</el-descriptions-item>
51
+          <el-descriptions-item v-if="asset.cattlePicture" :label="lfT('fieldCattlePicture')" :span="3">
52
+            <el-image
53
+              :src="asset.cattlePicture"
54
+              fit="contain"
55
+              class="yak-detail__picture"
56
+              :preview-src-list="[asset.cattlePicture]"
57
+            />
58
+          </el-descriptions-item>
37 59
         </el-descriptions>
38 60
       </el-card>
39 61
 
@@ -84,7 +106,7 @@
84 106
             </el-select>
85 107
           </span>
86 108
         </div>
87
-        <el-table v-show="growthMode === 'list'" :data="growthRecords" border size="small" max-height="280">
109
+        <el-table v-show="growthMode === 'list'" :data="displayGrowthRecords" border size="small" max-height="280">
88 110
           <el-table-column :label="lfT('colDayAge')" prop="dayAge" align="center" width="80" />
89 111
           <el-table-column :label="lfT('colWeight')" align="center" width="90">
90 112
             <template slot-scope="scope">{{ formatWithUnit(scope.row.weightKg, lfCommon('unitKg')) }}</template>
@@ -142,6 +164,24 @@
142 164
           <el-table-column :label="lfT('colFeedType')" prop="feedType" align="center" min-width="120" :show-overflow-tooltip="true" />
143 165
         </el-table>
144 166
       </el-card>
167
+
168
+      <el-card shadow="never" class="yak-detail__block">
169
+        <div slot="header">{{ lfT("sectionPen") }}</div>
170
+        <el-table :data="penTableRows" border size="small">
171
+          <el-table-column :label="lfT('colEnclosureName')" prop="enclosureName" align="center" min-width="140" :show-overflow-tooltip="true" />
172
+          <el-table-column :label="lfT('colPenLocation')" prop="penLocation" align="center" min-width="140" :show-overflow-tooltip="true" />
173
+          <el-table-column :label="lfT('fieldYakNo')" prop="yakNo" align="center" min-width="120" />
174
+        </el-table>
175
+      </el-card>
176
+
177
+      <el-card shadow="never" class="yak-detail__block">
178
+        <div slot="header">{{ lfT("sectionBatch") }}</div>
179
+        <el-table :data="batchTableRows" border size="small">
180
+          <el-table-column :label="lfT('fieldBatchNo')" prop="batchNo" align="center" min-width="140" :show-overflow-tooltip="true" />
181
+          <el-table-column :label="lfT('colEntryCycle')" prop="entryCycle" align="center" min-width="120" :show-overflow-tooltip="true" />
182
+          <el-table-column :label="lfT('fieldYakNo')" prop="yakNo" align="center" min-width="120" />
183
+        </el-table>
184
+      </el-card>
145 185
     </div>
146 186
   </el-drawer>
147 187
 </template>
@@ -192,6 +232,29 @@ export default {
192 232
         { value: "chest", label: this.lfT("metricChest") },
193 233
         { value: "length", label: this.lfT("metricLength") }
194 234
       ]
235
+    },
236
+    penTableRows() {
237
+      if (!this.asset) {
238
+        return []
239
+      }
240
+      return [{
241
+        enclosureName: this.asset.enclosureName,
242
+        penLocation: this.asset.penLocation,
243
+        yakNo: this.asset.yakNo
244
+      }]
245
+    },
246
+    batchTableRows() {
247
+      if (!this.asset) {
248
+        return []
249
+      }
250
+      return [{
251
+        batchNo: this.asset.batchNo,
252
+        entryCycle: this.asset.entryCycle,
253
+        yakNo: this.asset.yakNo
254
+      }]
255
+    },
256
+    displayGrowthRecords() {
257
+      return (this.growthRecords || []).filter((row) => this.hasDayAge(row))
195 258
     }
196 259
   },
197 260
   watch: {
@@ -212,7 +275,7 @@ export default {
212 275
   },
213 276
   methods: {
214 277
     assetStatusLabel(status) {
215
-      if (status == null || status < 1 || status > 11) {
278
+      if (status == null || status < 1 || status > 4) {
216 279
         return this.dash
217 280
       }
218 281
       return this.lfT("status" + status)
@@ -313,14 +376,16 @@ export default {
313 376
         this.$nextTick(() => this.loadGrowthChart())
314 377
       }
315 378
     },
379
+    hasDayAge(item) {
380
+      return item && item.dayAge != null && item.dayAge !== ""
381
+    },
316 382
     chartPointsToSeries(points) {
317
-      const sorted = (points || []).slice().sort((a, b) => {
318
-        const da = a.dayAge != null ? a.dayAge : 0
319
-        const db = b.dayAge != null ? b.dayAge : 0
320
-        return da - db
321
-      })
383
+      const sorted = (points || [])
384
+        .filter((p) => this.hasDayAge(p))
385
+        .slice()
386
+        .sort((a, b) => a.dayAge - b.dayAge)
322 387
       return {
323
-        x: sorted.map((p) => (p.dayAge != null ? String(p.dayAge) : "")),
388
+        x: sorted.map((p) => String(p.dayAge)),
324 389
         y: sorted.map((p) => (p.value != null ? Number(p.value) : null))
325 390
       }
326 391
     },
@@ -445,6 +510,13 @@ export default {
445 510
 .yak-detail__label {
446 511
   color: #909399;
447 512
 }
513
+.yak-detail__summary-extra {
514
+  margin-top: 8px;
515
+}
516
+.yak-detail__picture {
517
+  width: 120px;
518
+  height: 120px;
519
+}
448 520
 .yak-detail__sync-hint {
449 521
   margin-top: 8px;
450 522
   font-size: 12px;

+ 63 - 13
ruoyi-ui/src/views/livestockFinance/yakAsset/index.vue

@@ -105,9 +105,9 @@ export default {
105 105
   },
106 106
   computed: {
107 107
     assetStatusOptions() {
108
-      return Array.from({ length: 11 }, (_, i) => ({
109
-        value: i + 1,
110
-        label: this.lfT("status" + (i + 1))
108
+      return [1, 2, 3, 4].map((value) => ({
109
+        value,
110
+        label: this.lfT("status" + value)
111 111
       }))
112 112
     }
113 113
   },
@@ -116,23 +116,51 @@ export default {
116 116
   },
117 117
   methods: {
118 118
     assetStatusLabel(status) {
119
-      if (status == null || status < 1 || status > 11) {
119
+      if (status == null || status < 1 || status > 4) {
120 120
         return this.lfCommon("dash")
121 121
       }
122 122
       return this.lfT("status" + status)
123 123
     },
124 124
     assetStatusTagType(status) {
125
-      if (status === 8 || status === 9 || status === 11) {
125
+      if (status === 2 || status === 3) {
126 126
         return "danger"
127 127
       }
128
-      if (status === 4 || status === 6) {
128
+      if (status === 4) {
129 129
         return "warning"
130 130
       }
131
-      if (status === 1 || status === 2) {
131
+      if (status === 1) {
132 132
         return "success"
133 133
       }
134 134
       return "info"
135 135
     },
136
+    syncStepCounts(step) {
137
+      const s = step || {}
138
+      return {
139
+        insert: s.insertCount != null ? s.insertCount : 0,
140
+        update: s.updateCount != null ? s.updateCount : 0,
141
+        fail: s.failCount != null ? s.failCount : 0
142
+      }
143
+    },
144
+    collectSyncFailMessages(data) {
145
+      const steps = ["pasture", "enclosure", "plan", "batch", "yakAsset"]
146
+      const labels = {
147
+        pasture: this.lfT("syncStepPasture"),
148
+        enclosure: this.lfT("syncStepEnclosure"),
149
+        plan: this.lfT("syncStepPlan"),
150
+        batch: this.lfT("syncStepBatch"),
151
+        yakAsset: this.lfT("syncStepYakAsset")
152
+      }
153
+      const messages = []
154
+      steps.forEach((key) => {
155
+        const step = data[key]
156
+        if (step && step.failMessages && step.failMessages.length) {
157
+          step.failMessages.forEach((msg) => {
158
+            messages.push(`${labels[key]}: ${msg}`)
159
+          })
160
+        }
161
+      })
162
+      return messages
163
+    },
136 164
     formatAgeMonths(val) {
137 165
       if (val == null || val === "") {
138 166
         return this.lfCommon("dash")
@@ -174,12 +202,34 @@ export default {
174 202
       this.runSyncWithLoading(() => syncYakAsset())
175 203
         .then((res) => {
176 204
           const data = res.data || {}
177
-          const msg = this.lfT("syncSummary", {
178
-            insert: data.insertCount != null ? data.insertCount : 0,
179
-            update: data.updateCount != null ? data.updateCount : 0,
180
-            fail: data.failCount != null ? data.failCount : 0
181
-          })
182
-          this.$modal.msgSuccess(msg)
205
+          const pasture = this.syncStepCounts(data.pasture)
206
+          const enclosure = this.syncStepCounts(data.enclosure)
207
+          const plan = this.syncStepCounts(data.plan)
208
+          const batch = this.syncStepCounts(data.batch)
209
+          const yakAsset = this.syncStepCounts(data.yakAsset)
210
+          this.$modal.msgSuccess(
211
+            this.lfT("syncMasterSummary", {
212
+              pInsert: pasture.insert,
213
+              pUpdate: pasture.update,
214
+              pFail: pasture.fail,
215
+              eInsert: enclosure.insert,
216
+              eUpdate: enclosure.update,
217
+              eFail: enclosure.fail,
218
+              plInsert: plan.insert,
219
+              plUpdate: plan.update,
220
+              plFail: plan.fail,
221
+              bInsert: batch.insert,
222
+              bUpdate: batch.update,
223
+              bFail: batch.fail,
224
+              yInsert: yakAsset.insert,
225
+              yUpdate: yakAsset.update,
226
+              yFail: yakAsset.fail
227
+            })
228
+          )
229
+          const failMessages = this.collectSyncFailMessages(data)
230
+          if (failMessages.length) {
231
+            this.$modal.msgWarning(failMessages.join(";"))
232
+          }
183 233
           if (data.syncTime) {
184 234
             this.lastSyncHint = this.lfT("syncTimeHint", { time: this.parseTime(data.syncTime) })
185 235
           }