|
|
@@ -155,14 +155,13 @@ const currentCropName = ref(props.cropName || "");
|
|
|
const cropMenuVisible = ref(false);
|
|
|
const guideVisible = ref(false);
|
|
|
|
|
|
+/** 防止切换农场时旧请求回写覆盖新数据 */
|
|
|
+let reloadToken = 0;
|
|
|
+
|
|
|
watch(
|
|
|
() => props.cropName,
|
|
|
(name) => {
|
|
|
- if (name) {
|
|
|
- currentCropName.value = name;
|
|
|
- fetchAlertCards();
|
|
|
- fetchZones();
|
|
|
- }
|
|
|
+ if (name) currentCropName.value = name;
|
|
|
}
|
|
|
);
|
|
|
|
|
|
@@ -300,6 +299,17 @@ const getSelectedFarm = () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+/** 以缓存为准,避免 onActivated 时 props.farmId 尚未跟上父组件同步 */
|
|
|
+const resolveFarmId = () => {
|
|
|
+ const farm = getSelectedFarm();
|
|
|
+ const id =
|
|
|
+ localStorage.getItem("selectedFarmId") ||
|
|
|
+ farm.farm_id ||
|
|
|
+ farm.id ||
|
|
|
+ props.farmId;
|
|
|
+ return id != null && id !== "" ? id : "";
|
|
|
+};
|
|
|
+
|
|
|
const formatLocalDate = (date) => {
|
|
|
const y = date.getFullYear();
|
|
|
const m = String(date.getMonth() + 1).padStart(2, "0");
|
|
|
@@ -307,20 +317,18 @@ const formatLocalDate = (date) => {
|
|
|
return `${y}-${m}-${d}`;
|
|
|
};
|
|
|
|
|
|
-/** 用当前选中农场 + 分区 + 当天日期 */
|
|
|
+/** 用当前选中农场 + 分区 + 当天日期(zone 只信面板选中态,避免缓存滞后) */
|
|
|
const getQueryParams = () => {
|
|
|
- const farm = getSelectedFarm();
|
|
|
return {
|
|
|
- farm_id: farm.farm_id ?? farm.id,
|
|
|
- zone_id: selectedZoneId.value ?? farm.zone_id ?? farm.zoneId,
|
|
|
+ farm_id: resolveFarmId(),
|
|
|
+ zone_id: selectedZoneId.value,
|
|
|
date: formatLocalDate(new Date()),
|
|
|
};
|
|
|
};
|
|
|
|
|
|
/** 拉取分区列表,填充切换作物下拉 */
|
|
|
-const fetchZones = async () => {
|
|
|
- const farm = getSelectedFarm();
|
|
|
- const farmId = props.farmId || farm.farm_id || farm.id;
|
|
|
+const fetchZones = async (token = reloadToken) => {
|
|
|
+ const farmId = resolveFarmId();
|
|
|
if (farmId == null || farmId === "") {
|
|
|
zoneList.value = [];
|
|
|
cropOptions.value = [];
|
|
|
@@ -329,11 +337,14 @@ const fetchZones = async () => {
|
|
|
}
|
|
|
try {
|
|
|
const res = await VE_API.questionnaire.getZones({ farm_id: farmId });
|
|
|
+ // 旧请求回包时不覆盖当前选中分区
|
|
|
+ if (token !== reloadToken) return;
|
|
|
const zones = Array.isArray(res?.data?.zones) ? res.data.zones : [];
|
|
|
zoneList.value = zones;
|
|
|
cropOptions.value = zones.map((item) => item.zone_name || "");
|
|
|
applySelectedZone(zones.length ? 0 : -1);
|
|
|
} catch (e) {
|
|
|
+ if (token !== reloadToken) return;
|
|
|
console.warn("[CropAlertPanel] getZones failed", e);
|
|
|
zoneList.value = [];
|
|
|
cropOptions.value = [];
|
|
|
@@ -341,6 +352,18 @@ const fetchZones = async () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+/** 切换农场 / 回页:先清旧 zone,再拉分区,最后拉预警 */
|
|
|
+const reloadFarmAlerts = async () => {
|
|
|
+ const token = ++reloadToken;
|
|
|
+ selectedZoneId.value = null;
|
|
|
+ activeIndex.value = 0;
|
|
|
+ zoneList.value = [];
|
|
|
+ cropOptions.value = [];
|
|
|
+ await fetchZones(token);
|
|
|
+ if (token !== reloadToken) return;
|
|
|
+ await fetchAlertCards(token);
|
|
|
+};
|
|
|
+
|
|
|
/** 接口可能返回对象或数组,统一取第一条 */
|
|
|
const pickFirstRecord = (res) => {
|
|
|
const data = res?.data ?? res;
|
|
|
@@ -369,9 +392,10 @@ const applyWeatherStress = (record) => {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
-const fetchAlertCards = async () => {
|
|
|
+const fetchAlertCards = async (token = reloadToken) => {
|
|
|
const queryParams = getQueryParams();
|
|
|
if (queryParams.farm_id == null || queryParams.farm_id === "") {
|
|
|
+ if (token !== reloadToken) return;
|
|
|
applyWeatherRisk(null);
|
|
|
applyWeatherStress(null);
|
|
|
nextTick(() => syncMidAnchor());
|
|
|
@@ -381,6 +405,8 @@ const fetchAlertCards = async () => {
|
|
|
VE_API.questionnaire.getWeatherRisk(queryParams),
|
|
|
VE_API.questionnaire.getWeatherStress(queryParams),
|
|
|
]);
|
|
|
+ // 切换农场期间若有更新请求,丢弃旧回包
|
|
|
+ if (token !== reloadToken) return;
|
|
|
|
|
|
// 成功但无数据时清空旧卡片,避免切换农场后残留
|
|
|
applyWeatherRisk(riskRes.status === "fulfilled" ? pickFirstRecord(riskRes.value) : null);
|
|
|
@@ -441,10 +467,11 @@ onMounted(() => {
|
|
|
document.addEventListener("click", handleOutsideClick, true);
|
|
|
});
|
|
|
|
|
|
-/** 进入 / 从切换农场返回时:先拉分区,再拉预警 */
|
|
|
-onActivated(async () => {
|
|
|
- await fetchZones();
|
|
|
- await fetchAlertCards();
|
|
|
+/** 进入 / 从切换农场返回:nextTick 等父组件 syncSelectedFarmId 落盘后再拉 */
|
|
|
+onActivated(() => {
|
|
|
+ nextTick(() => {
|
|
|
+ reloadFarmAlerts();
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
@@ -453,7 +480,7 @@ onBeforeUnmount(() => {
|
|
|
resizeObserver = null;
|
|
|
});
|
|
|
|
|
|
-defineExpose({ refreshAlerts: fetchAlertCards, refreshZones: fetchZones });
|
|
|
+defineExpose({ refreshAlerts: fetchAlertCards, refreshZones: fetchZones, reloadFarmAlerts });
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|