ソースを参照

Merge branch 'agriculture' of http://www.sysuimars.cn:3000/feiniao/feiniao-farm-h5 into agriculture

刘秀芳 1 週間 前
親
コミット
54b5861bba

+ 5 - 0
src/api/modules/questionnaire.js

@@ -6,6 +6,11 @@ module.exports = {
         url: config.base_new_url + "pheno/initial_interact_options",
         type: "get",
     },
+    // 无分区时获取初始互动选项(录入品种页)
+    getInitialInteractionWithoutZone: {
+        url: config.base_new_url + "pheno/initial_interact_options_without_zone",
+        type: "get",
+    },
     // 保存感知结果接口
     saveInteractResult: {
         url: config.base_new_url + "pheno/interact_record",

+ 208 - 45
src/views/old_mini/entry_information/components/selectVariety.vue

@@ -296,7 +296,7 @@ const goSelectItemLocation = (item) => {
     });
 };
 
-onMounted(async () => {
+async function bootstrapVarietyPage() {
     initCategoryTabsFromSession();
     restoreSelectedListDraft();
     ensureDefaultForm();
@@ -304,19 +304,19 @@ onMounted(async () => {
     await Promise.all(
         categoryTabs.value.map((tab) => fetchVarietiesByCrop(tab.id))
     );
+    await fetchInitialInteractOptionsWithoutZone();
+}
+
+onMounted(() => {
+    bootstrapVarietyPage();
 });
 
-onActivated(async () => {
-    initCategoryTabsFromSession();
-    restoreSelectedListDraft();
-    ensureDefaultForm();
+/** keep-alive 返回时只同步点位/地图,避免重复拉接口 */
+onActivated(() => {
     syncItemLocationFromSession();
     nextTick(() => {
         itemPreviewMaps.forEach((map) => map.kmap?.map?.updateSize?.());
     });
-    await Promise.all(
-        categoryTabs.value.map((tab) => fetchVarietiesByCrop(tab.id))
-    );
 });
 
 onBeforeUnmount(() => {
@@ -404,6 +404,129 @@ const searchKeyword = ref("");
 const appliedKeyword = ref("");
 const gridExpanded = ref(false);
 const selectedList = ref([]);
+/** 无分区初始互动选项,业务侧自行对接 */
+const initialInteractOptions = ref(null);
+/** 进行中的品种请求,防止并发重复 */
+const varietyFetchPromises = new Map();
+/** 进行中的初始互动请求 key */
+let interactFetchKey = "";
+let interactFetchPromise = null;
+
+function readJson(key) {
+    try {
+        const raw = sessionStorage.getItem(key);
+        return raw ? JSON.parse(raw) : null;
+    } catch {
+        return null;
+    }
+}
+
+function writeJson(key, value) {
+    sessionStorage.setItem(key, JSON.stringify(value));
+}
+
+function saveCropDetailFromApi(data) {
+    if (data?.crop_id == null || data?.crop_id === "") return;
+    const cache = readJson("ENTRY_CROP_DETAIL") || {};
+    cache[String(data.crop_id)] = {
+        crop_id: data.crop_id,
+        crop_code: data.crop_code || "",
+        crop_group: data.crop_group || "",
+        crop_name: data.crop_name || "",
+        crop_type: data.crop_type || "",
+    };
+    writeJson("ENTRY_CROP_DETAIL", cache);
+}
+
+/** options_interact.interact → 物候期下拉(展示 period_name,提交 period_code) */
+function mapOptionsInteractToPhenology(interact) {
+    if (!interact) return [];
+    const list = Array.isArray(interact)
+        ? interact
+        : Object.keys(interact)
+              .sort((a, b) => Number(a) - Number(b))
+              .map((key) => interact[key]);
+
+    return list
+        .map((item) => {
+            if (!item || typeof item !== "object") return null;
+            const code = item.period_code ?? item.code ?? item.id;
+            const name = item.period_name ?? item.name ?? "";
+            if (!name) return null;
+            return {
+                id: code != null && code !== "" ? code : name,
+                name,
+                code: code != null && code !== "" ? String(code) : "",
+                url: item.url || "",
+            };
+        })
+        .filter(Boolean);
+}
+
+/** 将无分区初始互动结果写入当前品类:起种问题文案 + 物候期选项 */
+function applyInitialInteractToCurrentCategory(data) {
+    const tab = currentCategory.value;
+    if (!tab || !data) return;
+
+    const theme = data.date_interact?.interact_theme;
+    if (theme) {
+        tab.startingPointQuestion = theme;
+    }
+
+    const phenology = mapOptionsInteractToPhenology(data.options_interact?.interact);
+    if (!phenology.length) return;
+
+    tab.phenology = phenology;
+    const form = getCurrentForm();
+    if (!form?.phenologyId) return;
+    const stillExists = phenology.some((opt) => String(opt.id) === String(form.phenologyId));
+    if (!stillExists) form.phenologyId = "";
+}
+
+/** 组装并请求无分区初始互动选项 */
+async function fetchInitialInteractOptionsWithoutZone() {
+    const category = currentCategory.value;
+    if (!category) return;
+
+    const form = getCurrentForm();
+    const resident = readJson(LOCATION_KEY);
+    const cropDetail = readJson("ENTRY_CROP_DETAIL") || {};
+    const detail = cropDetail[String(category.id)] || {};
+
+    const params = {
+        crop_big_type: category.firstCrop || detail.crop_group || "",
+        crop_code: category.code || detail.crop_code || form?.cropCode || "",
+        crop_maturing: "P0",
+        location: form?.location || resident?.point || getDefaultPoint(),
+        date: form?.startTime || new Date().toISOString().split("T")[0],
+    };
+
+    const key = `${params.crop_code}|${params.location}|${params.date}`;
+    if (interactFetchPromise && interactFetchKey === key) {
+        return interactFetchPromise;
+    }
+
+    interactFetchKey = key;
+    interactFetchPromise = (async () => {
+        try {
+            const raw = await VE_API.questionnaire.getInitialInteractionWithoutZone(params);
+            const res = Array.isArray(raw) ? raw[0] : raw;
+            if (res?.code === 200) {
+                initialInteractOptions.value = res.data ?? null;
+                applyInitialInteractToCurrentCategory(res.data);
+            }
+        } catch (error) {
+            console.error("fetchInitialInteractOptionsWithoutZone failed", error);
+        } finally {
+            if (interactFetchKey === key) {
+                interactFetchPromise = null;
+                interactFetchKey = "";
+            }
+        }
+    })();
+
+    return interactFetchPromise;
+}
 
 const fetchVarietiesByCrop = async (cropId, force = false) => {
     if (cropId == null || cropId === "") return;
@@ -411,48 +534,85 @@ const fetchVarietiesByCrop = async (cropId, force = false) => {
     if (!tab) return;
     if (tab.loaded && !force) return;
 
+    const cacheKey = String(cropId);
+    if (!force && varietyFetchPromises.has(cacheKey)) {
+        return varietyFetchPromises.get(cacheKey);
+    }
+
     const showLoading = String(cropId) === String(activeCategoryId.value);
     if (showLoading) varietyLoading.value = true;
-    try {
-        const res = await VE_API.entry.getVarietiesByCrop({
-            crop_id: cropId,
-        });
-        if (res.code === 200 && res.data) {
-            const data = res.data;
-            tab.varieties = (data.varieties || [])
-                .map((item) => {
-                    if (typeof item === "string") {
-                        return { id: item, name: item };
+
+    const request = (async () => {
+        try {
+            const res = await VE_API.entry.getVarietiesByCrop({
+                crop_id: cropId,
+            });
+            if (res.code === 200 && res.data) {
+                const data = res.data;
+                if (data.crop_code) tab.code = data.crop_code;
+                if (data.crop_group) tab.firstCrop = tab.firstCrop || data.crop_group;
+                tab.varieties = (data.varieties || [])
+                    .map((item) => {
+                        if (typeof item === "string") {
+                            return { id: item, name: item };
+                        }
+                        const name = item?.name || "";
+                        return {
+                            id: item?.id ?? name,
+                            name,
+                        };
+                    })
+                    .filter((item) => item.name);
+                tab.phenology = mapPhenologyList(data.phenology);
+                tab.startingPointQuestion =
+                    data.starting_point_question || "起种点问题";
+                tab.loaded = true;
+
+                // 优先用已缓存的 crop_code,避免重复打 farmer_crop_detail
+                if (!tab.code) {
+                    const cached = readJson("ENTRY_CROP_DETAIL") || {};
+                    const detail = cached[cacheKey];
+                    if (detail?.crop_code) {
+                        tab.code = detail.crop_code;
+                        tab.firstCrop = tab.firstCrop || detail.crop_group || "";
                     }
-                    const name = item?.name || "";
-                    return {
-                        id: item?.id ?? name,
-                        name,
-                    };
-                })
-                .filter((item) => item.name);
-            tab.phenology = mapPhenologyList(data.phenology);
-            tab.startingPointQuestion =
-                data.starting_point_question || "起种点问题";
-            tab.loaded = true;
-        } else {
+                }
+                if (!tab.code) {
+                    try {
+                        const detailRes = await VE_API.entry.getMachines({ crop_id: cropId });
+                        const detail = detailRes?.data || {};
+                        if (detailRes?.code === 200 && detail.crop_code) {
+                            tab.code = detail.crop_code;
+                            tab.firstCrop = tab.firstCrop || detail.crop_group || "";
+                            saveCropDetailFromApi(detail);
+                        }
+                    } catch {
+                        // ignore
+                    }
+                }
+            } else {
+                tab.varieties = [];
+                tab.phenology = [];
+                tab.startingPointQuestion = "起种点问题";
+                if (showLoading) {
+                    ElMessage.error(res.msg || "获取品种列表失败");
+                }
+            }
+        } catch {
             tab.varieties = [];
             tab.phenology = [];
             tab.startingPointQuestion = "起种点问题";
             if (showLoading) {
-                ElMessage.error(res.msg || "获取品种列表失败");
+                ElMessage.error("获取品种列表失败,请稍后再试");
             }
+        } finally {
+            if (showLoading) varietyLoading.value = false;
+            varietyFetchPromises.delete(cacheKey);
         }
-    } catch {
-        tab.varieties = [];
-        tab.phenology = [];
-        tab.startingPointQuestion = "起种点问题";
-        if (showLoading) {
-            ElMessage.error("获取品种列表失败,请稍后再试");
-        }
-    } finally {
-        if (showLoading) varietyLoading.value = false;
-    }
+    })();
+
+    varietyFetchPromises.set(cacheKey, request);
+    return request;
 };
 
 watch(
@@ -567,14 +727,16 @@ const currentStartingPointQuestion = computed(() =>
     getStartingPointQuestion(currentSelected.value?.categoryId || activeCategoryId.value)
 );
 
-watch(activeCategoryId, (id) => {
+watch(activeCategoryId, async (id, prevId) => {
     searchKeyword.value = "";
     appliedKeyword.value = "";
     gridExpanded.value = false;
     ensureDefaultForm();
-    if (id != null) {
-        fetchVarietiesByCrop(id);
-    }
+    // 初始化赋值由 bootstrap 拉取,避免与 onMounted 重复请求
+    if (id == null || prevId == null) return;
+    if (String(id) === String(prevId)) return;
+    await fetchVarietiesByCrop(id);
+    fetchInitialInteractOptionsWithoutZone();
 });
 
 const isSelected = (id) =>
@@ -724,6 +886,7 @@ const handleConfirm = () => {
         const options = getPhenologyOptions(row.categoryId);
         const found = options.find((opt) => String(opt.id) === String(row.phenologyId));
         row.phenophase = found?.name || String(row.phenologyId || "");
+        row.phenophaseCode = found?.code || String(row.phenologyId || "");
     });
     saveSelectedListDraft();
     emit("next");