소스 검색

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

wangsisi 20 시간 전
부모
커밋
d491c6fead

+ 3 - 0
src/components/popup/restorePlantingPopup.vue

@@ -95,6 +95,9 @@
                     :class="{ disabled: submitting }"
                     @click="handleConfirm"
                 >
+                    <span v-if="submitting">
+                        <el-icon><Loading /></el-icon>
+                    </span>
                     {{ questionType === "time" ? t("agriFile.confirmNow") : t("agriFile.submitInfo") }}
                 </div>
             </div>

+ 6 - 0
src/views/old_mini/agri_file/components/addZoneInfoPopup.vue

@@ -133,6 +133,11 @@ const props = defineProps({
         type: String,
         default: "",
     },
+    /** 勾画页确认的分区范围 WKT(MULTIPOLYGON) */
+    polygon: {
+        type: String,
+        default: "",
+    },
 });
 
 const emit = defineEmits(["update:show", "confirm"]);
@@ -594,6 +599,7 @@ const handleConfirm = async () => {
         start_time: form.plantDate,
         zone_name: zoneName,
         phenophase_code: phenophaseCode,
+        polygon: props.polygon || "",
     };
 
     submitting.value = true;

+ 65 - 19
src/views/old_mini/agri_file/components/albumPanel.vue

@@ -102,18 +102,22 @@ const zoneList = ref([]);
 const albumList = ref([]);
 
 // ---------- 工具函数 ----------
+function getSelectedFarm() {
+    try {
+        return JSON.parse(localStorage.getItem("selectedFarmData") || "{}");
+    } catch {
+        return {};
+    }
+}
+
 function getSelectedFarmId() {
     const stored = localStorage.getItem("selectedFarmId");
     if (stored != null && stored !== "") {
         return Number(stored);
     }
-    try {
-        const farm = JSON.parse(localStorage.getItem("selectedFarmData") || "{}");
-        const id = farm.farm_id ?? farm.id;
-        return id != null && id !== "" ? Number(id) : null;
-    } catch {
-        return null;
-    }
+    const farm = getSelectedFarm();
+    const id = farm.farm_id ?? farm.id;
+    return id != null && id !== "" ? Number(id) : null;
 }
 
 function parsePointCoordinates(pointWkt) {
@@ -149,6 +153,8 @@ function mapZoneItem(zone) {
         longitude: coords?.longitude,
         latitude: coords?.latitude,
         point: zone.point,
+        polygon: zone.polygon || zone.geom || "",
+        geom: zone.geom || zone.polygon || "",
     };
 }
 
@@ -158,14 +164,14 @@ const setMarkerEl = (id, el) => {
 };
 
 const getFarmCenter = () => {
-    try {
-        const farm = JSON.parse(localStorage.getItem("selectedFarmData") || "{}");
-        const wkt = farm.wkt || farm.geom_wkt || farm.farm_location;
-        if (typeof wkt === "string" && /^POINT\s*\(/i.test(wkt.trim())) {
+    const farm = getSelectedFarm();
+    const wkt = farm.wkt || farm.geom_wkt || farm.farm_location;
+    if (typeof wkt === "string" && /^POINT\s*\(/i.test(wkt.trim())) {
+        try {
             return util.wktCastGeom(wkt).getFirstCoordinate();
+        } catch {
+            // ignore
         }
-    } catch {
-        // ignore
     }
     const firstZone = zoneList.value.find((z) => z.longitude != null && z.latitude != null);
     if (firstZone) {
@@ -174,6 +180,28 @@ const getFarmCenter = () => {
     return DEFAULT_CENTER;
 };
 
+/** status=1 有范围;否则无范围,展示勾画遮罩 */
+async function fetchFarmRangeStatus() {
+    const farm = getSelectedFarm();
+    const farmId = getSelectedFarmId() ?? farm.farm_id ?? farm.id;
+    const zoneId = farm.zone_id ?? farm.zoneId;
+    if (farmId == null || farmId === "" || zoneId == null || zoneId === "") {
+        noFarmRange.value = true;
+        return;
+    }
+    try {
+        const res = await VE_API.questionnaire.checkZoneRange({
+            farm_id: farmId,
+            zone_id: zoneId,
+        });
+        // status=1 有范围 → noFarmRange=false
+        noFarmRange.value = Number(res?.data?.status) !== 1;
+    } catch (e) {
+        console.warn("[albumPanel] checkZoneRange failed", e);
+        noFarmRange.value = true;
+    }
+}
+
 // ---------- 业务逻辑:地图 / 区域 ----------
 const clearMapOverlays = () => {
     if (!fileMap.kmap?.map) {
@@ -201,14 +229,23 @@ const bindZoneOverlays = () => {
     });
 };
 
-/** 用区域点位写入矢量层并 fit,才会走到实例上的 fitPadding */
+/** 用分区 polygon 画范围并 fit;无 polygon 时退回 point */
 const fitZonesOnMap = () => {
     const records = zoneList.value
-        .filter((z) => z.longitude != null && z.latitude != null)
-        .map((z) => ({
-            zone_name: "",
-            polygon: `POINT(${z.longitude} ${z.latitude})`,
-        }));
+        .map((z) => {
+            const polygon =
+                (typeof z.polygon === "string" && z.polygon.trim()) ||
+                (typeof z.geom === "string" && z.geom.trim()) ||
+                (z.longitude != null && z.latitude != null
+                    ? `POINT(${z.longitude} ${z.latitude})`
+                    : "");
+            if (!polygon) return null;
+            return {
+                zone_name: z.name || "",
+                polygon,
+            };
+        })
+        .filter(Boolean);
     if (!records.length) return;
     fileMap.setRecordPolygons(records, "album");
 };
@@ -236,11 +273,20 @@ async function fetchZoneList() {
 const initAlbumMap = async () => {
     await nextTick();
     if (!mapContainer.value) return;
+    await fetchFarmRangeStatus();
+
+    // 无范围也要初始化底图,遮罩叠在地图上方
     if (noFarmRange.value) {
         zoneList.value = [];
         albumList.value = [];
+        const center = getFarmCenter();
+        fileMap.initMap(`POINT(${center[0]} ${center[1]})`, mapContainer.value);
+        clearMapOverlays();
+        fileMap.setRecordPolygons([], "album");
+        fileMap.kmap?.map?.updateSize?.();
         return;
     }
+
     await fetchZoneList();
     const center = getFarmCenter();
     fileMap.initMap(`POINT(${center[0]} ${center[1]})`, mapContainer.value);

+ 53 - 45
src/views/old_mini/agri_file/pages/addZone.vue

@@ -19,7 +19,11 @@
             <div class="bottom-btn primary-btn" @click="handleConfirmDraw">{{ t("agriFile.confirmArea") }}</div>
         </div>
         <RegionNamePopup v-model:show="showRegionNamePopup" @confirm="handleFarmNameConfirm" />
-        <add-zone-info-popup v-model:show="showZoneInfoPopup" @confirm="handleZoneInfoConfirm" />
+        <add-zone-info-popup
+            v-model:show="showZoneInfoPopup"
+            :polygon="drawnPolygon"
+            @confirm="handleZoneInfoConfirm"
+        />
 
         <tip-popup v-model:show="showExecuteSuccessPopup" type="executeSuccess" text="分区/相册已创建成功" buttonText="完成" @confirm="handleComplete">
             <!-- <template #footer>
@@ -72,55 +76,55 @@ const mapContainer = ref(null);
 const mapManage = new MapManage();
 const showRegionNamePopup = ref(false);
 const showZoneInfoPopup = ref(false);
+/** 确认勾画后传给信息弹窗提交的范围 WKT */
+const drawnPolygon = ref("");
 
 const DEFAULT_MAP_LOCATION = "POINT(113.6142086995688 23.585836479509055)";
-const FARM_DRAW_LOCATION = "POINT(113.31812938867188 23.002427029296875)";
 const ZONE_STYLE = {
     fill: "rgba(33, 153, 248, 0.35)",
     fillSelected: "rgba(33, 153, 248, 0.45)",
     stroke: "#2199F8",
 };
 
-/** 新增相册时展示的已有品种种植范围(mock,中心点附近) */
-const REGION_CENTER = [113.31812938867188, 23.002427029296875];
-const MOCK_VARIETY_ZONE_DEFS = [
-    {
-        id: 1,
-        name: "桂味",
-        dlng: -0.0032,
-        dlat: 0.0021,
-        delta: 0.00115,
-    },
-    {
-        id: 2,
-        name: "糯米糍",
-        dlng: 0.0028,
-        dlat: 0.0016,
-        delta: 0.00105,
-    },
-];
-
-function squarePolygonWkt(lng, lat, delta = 0.001) {
-    const ring = [
-        [lng - delta, lat + delta * 0.7],
-        [lng + delta * 0.35, lat + delta],
-        [lng + delta, lat - delta * 0.2],
-        [lng + delta * 0.15, lat - delta],
-        [lng - delta * 0.85, lat - delta * 0.45],
-        [lng - delta, lat + delta * 0.7],
-    ];
-    return `POLYGON((${ring.map((point) => point.join(" ")).join(", ")}))`;
+/** 已有分区种植范围样式 */
+const EXISTING_ZONE_STYLE = {
+    fill: "rgba(0, 0, 0, 0.38)",
+    stroke: "rgba(200, 200, 200, 0.55)",
+};
+
+const existingVarietyZones = ref([]);
+
+function mapExistingZoneItem(zone) {
+    const polygon = typeof zone?.polygon === "string" ? zone.polygon.trim() : "";
+    if (!polygon) return null;
+    return {
+        id: zone.zone_id,
+        name: zone.zone_name || "",
+        fill: EXISTING_ZONE_STYLE.fill,
+        stroke: EXISTING_ZONE_STYLE.stroke,
+        polygon,
+    };
 }
 
-function getMockVarietyZones() {
-    const [lng, lat] = REGION_CENTER;
-    return MOCK_VARIETY_ZONE_DEFS.map((item) => ({
-        id: item.id,
-        name: item.name,
-        fill: 'rgba(0, 0, 0, 0.38)',
-        stroke: 'rgba(200, 200, 200, 0.55)',
-        polygon: squarePolygonWkt(lng + item.dlng, lat + item.dlat, item.delta),
-    }));
+async function fetchExistingVarietyZones() {
+    const farm = getFarmData();
+    const farmId = farm.farm_id ?? farm.id;
+    if (farmId == null || farmId === "") {
+        existingVarietyZones.value = [];
+        return;
+    }
+    try {
+        const res = await VE_API.questionnaire.getZones({ farm_id: farmId });
+        const zones = Array.isArray(res?.data?.zones)
+            ? res.data.zones
+            : Array.isArray(res?.data)
+              ? res.data
+              : [];
+        existingVarietyZones.value = zones.map(mapExistingZoneItem).filter(Boolean);
+    } catch (e) {
+        console.warn("[addZone] getZones failed", e);
+        existingVarietyZones.value = [];
+    }
 }
 
 const userLocation = ref(
@@ -179,6 +183,8 @@ function getFarmMapLocation() {
     return DEFAULT_MAP_LOCATION;
 }
 
+const getFarmType = computed(() => getFarmData().variety_name);
+
 function getDefaultMapLocation() {
     return (
         toPointWkt(localStorage.getItem("MINI_USER_LOCATION_POINT")) ||
@@ -192,15 +198,15 @@ function getDefaultMapCoordinate() {
 }
 
 function getFarmDrawCoordinate() {
-    return util.wktCastGeom(FARM_DRAW_LOCATION).getFirstCoordinate();
+    return util.wktCastGeom(getFarmMapLocation()).getFirstCoordinate();
 }
 
 function getMapLocation() {
-    if (isFarmDrawMode.value || isRegionDrawMode.value) return FARM_DRAW_LOCATION;
+    if (isFarmDrawMode.value || isRegionDrawMode.value) return getFarmMapLocation();
     return getDefaultMapLocation();
 }
 
-function initMapView() {
+async function initMapView() {
     if (!mapContainer.value) return;
     mapManage.destroyMap();
     mapManage.initMap(getMapLocation(), mapContainer.value, {
@@ -220,7 +226,8 @@ function initMapView() {
         mapManage.showCenterMarker(getFarmDrawCoordinate(), POINT_ICON.plant);
     }
     if (isRegionDrawMode.value) {
-        mapManage.setExistingVarietyZones(getMockVarietyZones());
+        await fetchExistingVarietyZones();
+        mapManage.setExistingVarietyZones(existingVarietyZones.value);
         mapManage.setMapPosition(getFarmDrawCoordinate());
     }
 }
@@ -248,7 +255,7 @@ const handleClearDraw = () => {
     // 只清当前勾画,保留已有品种种植范围
     mapManage.clearLayer();
     if (isRegionDrawMode.value) {
-        mapManage.setExistingVarietyZones(getMockVarietyZones());
+        mapManage.setExistingVarietyZones(existingVarietyZones.value);
     }
 };
 
@@ -262,6 +269,7 @@ const handleConfirmDraw = () => {
         ElMessage.warning("新绘制范围不能与已有品种种植范围重叠");
         return;
     }
+    drawnPolygon.value = toMultiPolygonWkt(mapManage.mergeGeometryWkts(payload.geometryArr));
     if (isFarmDrawMode.value) {
         showRegionNamePopup.value = true;
         return;