|
@@ -8,7 +8,7 @@
|
|
|
</div>
|
|
</div>
|
|
|
<div class="record-header" v-else-if="recordType === 'pest'">
|
|
<div class="record-header" v-else-if="recordType === 'pest'">
|
|
|
<span>{{ t('agriRecord.pestWorkName') }}</span>
|
|
<span>{{ t('agriRecord.pestWorkName') }}</span>
|
|
|
- <div class="question">{{ t('recordDetails.pestQuestion') }}</div>
|
|
|
|
|
|
|
+ <div class="question">{{ currentPestDetail?.interaction_reason }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="record-header" v-else>
|
|
<div class="record-header" v-else>
|
|
|
<span>{{ t('agriRecord.phenologyWorkName') }}</span>
|
|
<span>{{ t('agriRecord.phenologyWorkName') }}</span>
|
|
@@ -46,7 +46,7 @@
|
|
|
<span class="item-label">{{ t('recordDetails.scienceLabel') }}</span>
|
|
<span class="item-label">{{ t('recordDetails.scienceLabel') }}</span>
|
|
|
<text-ellipsis class="item-value" :expand-text="expandCollapse.expand"
|
|
<text-ellipsis class="item-value" :expand-text="expandCollapse.expand"
|
|
|
:collapse-text="expandCollapse.collapse" rows="3"
|
|
:collapse-text="expandCollapse.collapse" rows="3"
|
|
|
- :content="t('recordDetails.pestScience')" />
|
|
|
|
|
|
|
+ :content="currentPestDetail?.kepu" />
|
|
|
</div>
|
|
</div>
|
|
|
<div class="pest-classify-picker">
|
|
<div class="pest-classify-picker">
|
|
|
<div class="pest-classify-picker__row pest-classify-picker__row--top">
|
|
<div class="pest-classify-picker__row pest-classify-picker__row--top">
|
|
@@ -132,9 +132,13 @@
|
|
|
<div class="current-status">{{ currentStatusText }}</div>
|
|
<div class="current-status">{{ currentStatusText }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="time-line">
|
|
<div class="time-line">
|
|
|
- <GrowthStageTimeline v-model="growthStageIndex" :stages="growthStages"
|
|
|
|
|
- @scroll-settled="onStageScrollSettled" @locale-change="getFindPhenologyInfo" />
|
|
|
|
|
- <!-- <GrowthStageTimeline v-model="growthStageIndex" :stages="growthStages" /> -->
|
|
|
|
|
|
|
+ <GrowthStageTimeline
|
|
|
|
|
+ :key="phenologyTimelineKey"
|
|
|
|
|
+ v-model="growthStageIndex"
|
|
|
|
|
+ :stages="growthStages"
|
|
|
|
|
+ @scroll-settled="onStageScrollSettled"
|
|
|
|
|
+ @locale-change="getFindPhenologyInfo"
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
<div class="confirm-btn-wrap">
|
|
<div class="confirm-btn-wrap">
|
|
|
<uploader @click="handleUploadClick" :before-read="beforeReadUpload" class="upload-wrap"
|
|
<uploader @click="handleUploadClick" :before-read="beforeReadUpload" class="upload-wrap"
|
|
@@ -492,6 +496,7 @@ const beforeReadUpload = (file) => {
|
|
|
const curStage = ref({});
|
|
const curStage = ref({});
|
|
|
const curCode = ref('')
|
|
const curCode = ref('')
|
|
|
function onStageScrollSettled(index, stage, code) {
|
|
function onStageScrollSettled(index, stage, code) {
|
|
|
|
|
+ shouldApplyPhenologyDefault.value = false;
|
|
|
if (stage) curStage.value = stage;
|
|
if (stage) curStage.value = stage;
|
|
|
curCode.value = code ?? stage?.phenophase_code ?? "";
|
|
curCode.value = code ?? stage?.phenophase_code ?? "";
|
|
|
}
|
|
}
|
|
@@ -613,22 +618,129 @@ const handleTabClick = (index) => {
|
|
|
activeTab.value = index;
|
|
activeTab.value = index;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-/** 生育期进程时间轴:接入接口后可替换为接口数据 */
|
|
|
|
|
-/** 不设初值时由 GrowthStageTimeline 默认选中间一档 */
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 物候时间轴默认定位编码(荔枝 crop_type=1:32=果皮速长/5%长果皮)
|
|
|
|
|
+ * 注意:farm_risk 的 current_phe_code / 路由 curCode 可能是 33、35 等,与轴上节点不一一对应,勿直接当数组下标用
|
|
|
|
|
+ */
|
|
|
|
|
+const DEFAULT_PHENOLOGY_CODE = '32';
|
|
|
|
|
+
|
|
|
const growthStageIndex = ref();
|
|
const growthStageIndex = ref();
|
|
|
const growthStages = ref([]);
|
|
const growthStages = ref([]);
|
|
|
|
|
+const phenologyRawList = ref([]);
|
|
|
|
|
+const phenologyTimelineKey = ref(0);
|
|
|
|
|
+/** 数据加载后按物候编码定位,用户拖动后不再自动覆盖 */
|
|
|
|
|
+const shouldApplyPhenologyDefault = ref(true);
|
|
|
|
|
+
|
|
|
|
|
+function normalizePhenologyCode(code) {
|
|
|
|
|
+ if (code == null || code === '') return '';
|
|
|
|
|
+ return String(code).trim();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function findStageIndexByPhenophaseCode(stages, code) {
|
|
|
|
|
+ const target = normalizePhenologyCode(code);
|
|
|
|
|
+ if (!Array.isArray(stages) || !stages.length || !target) return -1;
|
|
|
|
|
+ return stages.findIndex(
|
|
|
|
|
+ (s) => normalizePhenologyCode(s.phenophase_code) === target
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function resolveStageIndexByPhenophaseCode(stages, rawItems, code) {
|
|
|
|
|
+ const target = normalizePhenologyCode(code);
|
|
|
|
|
+ if (!target || !Array.isArray(stages) || !stages.length) return -1;
|
|
|
|
|
+
|
|
|
|
|
+ const byFlat = findStageIndexByPhenophaseCode(stages, target);
|
|
|
|
|
+ if (byFlat >= 0) return byFlat;
|
|
|
|
|
+
|
|
|
|
|
+ const period = (rawItems || []).find(
|
|
|
|
|
+ (item) =>
|
|
|
|
|
+ normalizePhenologyCode(item.phenophase_code ?? item.phenophaseCode) ===
|
|
|
|
|
+ target
|
|
|
|
|
+ );
|
|
|
|
|
+ if (!period) return -1;
|
|
|
|
|
+
|
|
|
|
|
+ const milestones = normalizeTimeDescribe(period.time_discribe);
|
|
|
|
|
+ const firstLabel = milestones[0]?.label;
|
|
|
|
|
+ if (!firstLabel) return -1;
|
|
|
|
|
+
|
|
|
|
|
+ return stages.findIndex(
|
|
|
|
|
+ (s) =>
|
|
|
|
|
+ s.label === firstLabel &&
|
|
|
|
|
+ normalizePhenologyCode(s.phenophase_code) === target
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function buildGrowthStagesFlat(rawItems) {
|
|
|
|
|
+ const flat = [];
|
|
|
|
|
+ for (const item of rawItems) {
|
|
|
|
|
+ const periodCode =
|
|
|
|
|
+ item.phenophase_code ?? item.phenophaseCode ?? '';
|
|
|
|
|
+ const milestones = normalizeTimeDescribe(item.time_discribe);
|
|
|
|
|
+ for (const t of milestones) {
|
|
|
|
|
+ flat.push({
|
|
|
|
|
+ label: t.label ?? '',
|
|
|
|
|
+ tags: Array.isArray(t.tags) ? t.tags : [],
|
|
|
|
|
+ periodTitle: item.phenophase_name ?? '',
|
|
|
|
|
+ periodSubtitle: item.phenophase_discribe ?? '',
|
|
|
|
|
+ phenophase_code:
|
|
|
|
|
+ t.phenophase_code ??
|
|
|
|
|
+ t.phenophaseCode ??
|
|
|
|
|
+ t.code ??
|
|
|
|
|
+ periodCode,
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return flat;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 时间轴初始定位用的物候编码(与病虫害等接口用的 route.query.curCode 分离) */
|
|
|
|
|
+function resolveTimelineDefaultCode() {
|
|
|
|
|
+ return DEFAULT_PHENOLOGY_CODE;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function applyTimelineDefaultIndex(flat, rawItems) {
|
|
|
|
|
+ const targetCode = resolveTimelineDefaultCode();
|
|
|
|
|
+ const defaultIndex = resolveStageIndexByPhenophaseCode(
|
|
|
|
|
+ flat,
|
|
|
|
|
+ rawItems,
|
|
|
|
|
+ targetCode
|
|
|
|
|
+ );
|
|
|
|
|
+ if (defaultIndex < 0) return -1;
|
|
|
|
|
+
|
|
|
|
|
+ shouldApplyPhenologyDefault.value = true;
|
|
|
|
|
+ growthStageIndex.value = defaultIndex;
|
|
|
|
|
+ growthStages.value = flat;
|
|
|
|
|
+ phenologyTimelineKey.value += 1;
|
|
|
|
|
+
|
|
|
|
|
+ return defaultIndex;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-/** 与 GrowthStageTimeline 默认档一致:未绑 v-model 时用中间索引 */
|
|
|
|
|
function syncCurStageFromModel() {
|
|
function syncCurStageFromModel() {
|
|
|
const stages = growthStages.value;
|
|
const stages = growthStages.value;
|
|
|
if (!Array.isArray(stages) || !stages.length) return;
|
|
if (!Array.isArray(stages) || !stages.length) return;
|
|
|
const n = stages.length;
|
|
const n = stages.length;
|
|
|
- let i = growthStageIndex.value;
|
|
|
|
|
- if (i === undefined || i === null) {
|
|
|
|
|
- i = Math.max(0, Math.floor((n - 1) / 2));
|
|
|
|
|
|
|
+ let i;
|
|
|
|
|
+
|
|
|
|
|
+ if (shouldApplyPhenologyDefault.value) {
|
|
|
|
|
+ const targetCode = resolveTimelineDefaultCode();
|
|
|
|
|
+ const byCode = resolveStageIndexByPhenophaseCode(
|
|
|
|
|
+ stages,
|
|
|
|
|
+ phenologyRawList.value,
|
|
|
|
|
+ targetCode
|
|
|
|
|
+ );
|
|
|
|
|
+ i = byCode >= 0 ? byCode : Math.max(0, Math.floor((n - 1) / 2));
|
|
|
|
|
+ if (byCode >= 0) {
|
|
|
|
|
+ growthStageIndex.value = i;
|
|
|
|
|
+ shouldApplyPhenologyDefault.value = false;
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
- i = Math.min(Math.max(0, i), n - 1);
|
|
|
|
|
|
|
+ i = growthStageIndex.value;
|
|
|
|
|
+ if (i === undefined || i === null) {
|
|
|
|
|
+ i = Math.max(0, Math.floor((n - 1) / 2));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ i = Math.min(Math.max(0, i), n - 1);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
const stage = stages[i];
|
|
const stage = stages[i];
|
|
|
if (stage) curStage.value = stage;
|
|
if (stage) curStage.value = stage;
|
|
|
curCode.value = stage?.phenophase_code ?? "";
|
|
curCode.value = stage?.phenophase_code ?? "";
|
|
@@ -636,7 +748,7 @@ function syncCurStageFromModel() {
|
|
|
|
|
|
|
|
watch([growthStages, growthStageIndex], syncCurStageFromModel, { immediate: true });
|
|
watch([growthStages, growthStageIndex], syncCurStageFromModel, { immediate: true });
|
|
|
|
|
|
|
|
-onActivated(() => {
|
|
|
|
|
|
|
+onActivated(async () => {
|
|
|
sessionStorage.removeItem('mapManageConfirmPayload');
|
|
sessionStorage.removeItem('mapManageConfirmPayload');
|
|
|
syncFormFromMapConfirmPayload();
|
|
syncFormFromMapConfirmPayload();
|
|
|
if (route.query.workId) {
|
|
if (route.query.workId) {
|
|
@@ -648,7 +760,7 @@ onActivated(() => {
|
|
|
if (route.query.type === 'growth') {
|
|
if (route.query.type === 'growth') {
|
|
|
getGrowthAnomalyInfo();
|
|
getGrowthAnomalyInfo();
|
|
|
}
|
|
}
|
|
|
- getFindPhenologyInfo()
|
|
|
|
|
|
|
+ getFindPhenologyInfo();
|
|
|
if (showMap.value) {
|
|
if (showMap.value) {
|
|
|
location.value = "POINT(113.6142086995688 23.585836479509055)";
|
|
location.value = "POINT(113.6142086995688 23.585836479509055)";
|
|
|
indexMap.initMap(location.value, mapContainer.value);
|
|
indexMap.initMap(location.value, mapContainer.value);
|
|
@@ -698,21 +810,16 @@ const getFindPhenologyInfo = async () => {
|
|
|
const cropType = JSON.parse(localStorage.getItem('selectedFarmData')).farm_variety;
|
|
const cropType = JSON.parse(localStorage.getItem('selectedFarmData')).farm_variety;
|
|
|
const res = await VE_API.monitor.getFindPhenologyInfo({ crop_type: cropType });
|
|
const res = await VE_API.monitor.getFindPhenologyInfo({ crop_type: cropType });
|
|
|
if (res.code === 200 && Array.isArray(res.data) && res.data.length) {
|
|
if (res.code === 200 && Array.isArray(res.data) && res.data.length) {
|
|
|
- const flat = [];
|
|
|
|
|
- for (const item of res.data) {
|
|
|
|
|
- const milestones = normalizeTimeDescribe(item.time_discribe);
|
|
|
|
|
- for (const t of milestones) {
|
|
|
|
|
- flat.push({
|
|
|
|
|
- label: t.label ?? '',
|
|
|
|
|
- tags: Array.isArray(t.tags) ? t.tags : [],
|
|
|
|
|
- periodTitle: item.phenophase_name ?? '',
|
|
|
|
|
- periodSubtitle: item.phenophase_discribe ?? '',
|
|
|
|
|
- phenophase_code: item.phenophase_code ?? item.phenophaseCode ?? '',
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- if (flat.length) {
|
|
|
|
|
- growthStages.value = flat;
|
|
|
|
|
|
|
+ phenologyRawList.value = res.data;
|
|
|
|
|
+ const flat = buildGrowthStagesFlat(res.data);
|
|
|
|
|
+ if (!flat.length) return;
|
|
|
|
|
+
|
|
|
|
|
+ const defaultIndex = applyTimelineDefaultIndex(flat, res.data);
|
|
|
|
|
+ await nextTick();
|
|
|
|
|
+ if (defaultIndex >= 0) {
|
|
|
|
|
+ growthStageIndex.value = defaultIndex;
|
|
|
|
|
+ shouldApplyPhenologyDefault.value = false;
|
|
|
|
|
+ syncCurStageFromModel();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|