|
@@ -8,7 +8,7 @@
|
|
|
{{ item.name }}
|
|
{{ item.name }}
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="variety-tabs" v-if="varietyTabs.length > 0">
|
|
|
|
|
|
|
+ <div class="variety-tabs" v-if="varietyTabs.length > 0 && activeRegionType !== 'DORMANCY'">
|
|
|
<div v-for="(v, index) in varietyTabs" :key="index" class="variety-tab"
|
|
<div v-for="(v, index) in varietyTabs" :key="index" class="variety-tab"
|
|
|
:class="{ 'variety-tab--active': activeVariety === index }" @click="handleVarietyClick(v, index)">
|
|
:class="{ 'variety-tab--active': activeVariety === index }" @click="handleVarietyClick(v, index)">
|
|
|
{{ v.regionName || v.problemZoneTypeName }}
|
|
{{ v.regionName || v.problemZoneTypeName }}
|
|
@@ -40,7 +40,6 @@
|
|
|
<script setup>
|
|
<script setup>
|
|
|
import customHeader from "@/components/customHeader.vue";
|
|
import customHeader from "@/components/customHeader.vue";
|
|
|
import { ref, computed, onActivated, onDeactivated, nextTick } from "vue";
|
|
import { ref, computed, onActivated, onDeactivated, nextTick } from "vue";
|
|
|
-import { useStore } from "vuex";
|
|
|
|
|
import DrawRegionMap from "../../interactionList/map/drawRegionMap.js";
|
|
import DrawRegionMap from "../../interactionList/map/drawRegionMap.js";
|
|
|
import { Map as KMapMap } from "@/utils/ol-map/KMap";
|
|
import { Map as KMapMap } from "@/utils/ol-map/KMap";
|
|
|
import { useRouter, useRoute } from "vue-router";
|
|
import { useRouter, useRoute } from "vue-router";
|
|
@@ -54,12 +53,20 @@ import { Point } from "ol/geom";
|
|
|
import * as proj from "ol/proj";
|
|
import * as proj from "ol/proj";
|
|
|
import { getArea } from "ol/sphere.js";
|
|
import { getArea } from "ol/sphere.js";
|
|
|
|
|
|
|
|
-const store = useStore();
|
|
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
const route = useRoute();
|
|
|
const mapContainer = ref(null);
|
|
const mapContainer = ref(null);
|
|
|
const drawRegionMap = new DrawRegionMap();
|
|
const drawRegionMap = new DrawRegionMap();
|
|
|
|
|
|
|
|
|
|
+// handleVarietyClick 内部有延迟渲染(setTimeout),切换查看/编辑或重建地图时必须取消,避免旧回调在新实例上再次 addFeature 造成叠加
|
|
|
|
|
+const pendingGeomRenderTimer = ref(null);
|
|
|
|
|
+const clearPendingGeomRenderTimer = () => {
|
|
|
|
|
+ if (pendingGeomRenderTimer.value) {
|
|
|
|
|
+ clearTimeout(pendingGeomRenderTimer.value);
|
|
|
|
|
+ pendingGeomRenderTimer.value = null;
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const confirmDrawTypePopupRef = ref(null);
|
|
const confirmDrawTypePopupRef = ref(null);
|
|
|
const selectedDrawTypeMeta = ref({
|
|
const selectedDrawTypeMeta = ref({
|
|
|
type: "",
|
|
type: "",
|
|
@@ -79,14 +86,22 @@ const varietyTabs = ref([]);
|
|
|
const activeVariety = ref(0);
|
|
const activeVariety = ref(0);
|
|
|
const regionGeom = ref(null);
|
|
const regionGeom = ref(null);
|
|
|
|
|
|
|
|
-const categoryMap = {
|
|
|
|
|
- variety: [],
|
|
|
|
|
- abnormal: [{ regionName: "病害" }, { regionName: "虫害" }, { regionName: "长势过快" }, { regionName: "长势过慢" }],
|
|
|
|
|
- environment: [{ regionName: "渍水不畅" }, { regionName: "密不透风" }, { regionName: "高温灼伤" }, { regionName: "低温冻害" }],
|
|
|
|
|
- sleep: [],
|
|
|
|
|
|
|
+
|
|
|
|
|
+/** 切换「大类」Tab 时子类列表完全替换,regionsDraftByIndex 按下标缓存会与新区块列表错位;保存成功后也应以接口为准 */
|
|
|
|
|
+const clearDraftIndexOnly = () => {
|
|
|
|
|
+ regionsDraftByIndex.value = {};
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const clearAllRegionDrafts = () => {
|
|
|
|
|
+ regionsDraftByKey.value = {};
|
|
|
|
|
+ regionsDraftByIndex.value = {};
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handleRegionTypeClick = (item) => {
|
|
const handleRegionTypeClick = (item) => {
|
|
|
|
|
+ const prevMajor = activeRegionType.value;
|
|
|
|
|
+ if (item.code !== prevMajor) {
|
|
|
|
|
+ clearDraftIndexOnly();
|
|
|
|
|
+ }
|
|
|
activeRegionType.value = item.code;
|
|
activeRegionType.value = item.code;
|
|
|
activeVariety.value = 0;
|
|
activeVariety.value = 0;
|
|
|
if (item.code === "variety") {
|
|
if (item.code === "variety") {
|
|
@@ -148,11 +163,35 @@ const createPolygonStyleFunc = (fillColor, strokeColor) => {
|
|
|
geom.transform(proj.get("EPSG:4326"), proj.get("EPSG:38572"));
|
|
geom.transform(proj.get("EPSG:4326"), proj.get("EPSG:38572"));
|
|
|
let area = getArea(geom);
|
|
let area = getArea(geom);
|
|
|
area = (area + area / 2) / 1000;
|
|
area = (area + area / 2) / 1000;
|
|
|
|
|
+ const growth = getAbnormalGrowthOverlayMeta();
|
|
|
|
|
+ if (growth) {
|
|
|
|
|
+ styles.push(
|
|
|
|
|
+ new Style({
|
|
|
|
|
+ text: new Text({
|
|
|
|
|
+ text: growth.badgeText,
|
|
|
|
|
+ font: "bold 13px sans-serif",
|
|
|
|
|
+ fill: new Fill({ color: "#ffffff" }),
|
|
|
|
|
+ backgroundFill: new Fill({ color: growth.badgeBackground || ABNORMAL_BADGE_BG_GROWTH }),
|
|
|
|
|
+ padding: [4, 10, 4, 10],
|
|
|
|
|
+ offsetY: -40,
|
|
|
|
|
+ }),
|
|
|
|
|
+ }),
|
|
|
|
|
+ new Style({
|
|
|
|
|
+ text: new Text({
|
|
|
|
|
+ text: `发现时间:${growth.discoveryDate}`,
|
|
|
|
|
+ font: "12px sans-serif",
|
|
|
|
|
+ fill: new Fill({ color: "#ffffff" }),
|
|
|
|
|
+ offsetY: -16,
|
|
|
|
|
+ }),
|
|
|
|
|
+ })
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
const areaValStyle = new Style({
|
|
const areaValStyle = new Style({
|
|
|
text: new Text({
|
|
text: new Text({
|
|
|
font: "16px sans-serif",
|
|
font: "16px sans-serif",
|
|
|
text: area.toFixed(2) + "亩",
|
|
text: area.toFixed(2) + "亩",
|
|
|
fill: new Fill({ color: "#fff" }),
|
|
fill: new Fill({ color: "#fff" }),
|
|
|
|
|
+ offsetY: growth ? 14 : 0,
|
|
|
}),
|
|
}),
|
|
|
});
|
|
});
|
|
|
styles.push(fillStyle, areaValStyle);
|
|
styles.push(fillStyle, areaValStyle);
|
|
@@ -169,17 +208,25 @@ const applyRegionStyles = () => {
|
|
|
let fillColor = [0, 0, 0, 0.5];
|
|
let fillColor = [0, 0, 0, 0.5];
|
|
|
let strokeColor = "#2199F8";
|
|
let strokeColor = "#2199F8";
|
|
|
|
|
|
|
|
- if (activeRegionType.value === "variety") {
|
|
|
|
|
|
|
+ const styleKind = getCanonicalRegionTypeForStyles();
|
|
|
|
|
+ if (styleKind === "variety") {
|
|
|
lineColor = "#18AA8B";
|
|
lineColor = "#18AA8B";
|
|
|
vertexColor = "#18AA8B";
|
|
vertexColor = "#18AA8B";
|
|
|
fillColor = [0, 57, 44, 0.5];
|
|
fillColor = [0, 57, 44, 0.5];
|
|
|
strokeColor = "#18AA8B";
|
|
strokeColor = "#18AA8B";
|
|
|
- } else if (activeRegionType.value === "abnormal") {
|
|
|
|
|
- lineColor = "#E03131";
|
|
|
|
|
- vertexColor = "#E03131";
|
|
|
|
|
- fillColor = [100, 0, 0, 0.5];
|
|
|
|
|
- strokeColor = "#E03131";
|
|
|
|
|
- } else if (activeRegionType.value === "environment") {
|
|
|
|
|
|
|
+ } else if (styleKind === "ABNORMAL") {
|
|
|
|
|
+ if(activeVariety.value < 2){
|
|
|
|
|
+ lineColor = "#E03131";
|
|
|
|
|
+ vertexColor = "#E03131";
|
|
|
|
|
+ fillColor = [100, 0, 0, 0.5];
|
|
|
|
|
+ strokeColor = "#E03131";
|
|
|
|
|
+ }else{
|
|
|
|
|
+ lineColor = "#FF7300";
|
|
|
|
|
+ vertexColor = "#FF7300";
|
|
|
|
|
+ fillColor = [124, 46, 0, 0.5];
|
|
|
|
|
+ strokeColor = "#FF7300";
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (styleKind === "ENVIRONMENT") {
|
|
|
lineColor = "#FDCF7F";
|
|
lineColor = "#FDCF7F";
|
|
|
vertexColor = "#FDCF7F";
|
|
vertexColor = "#FDCF7F";
|
|
|
fillColor = [151, 96, 0, 0.5];
|
|
fillColor = [151, 96, 0, 0.5];
|
|
@@ -309,7 +356,43 @@ const renderAllVarietyRegionsReadonlyOnly = () => {
|
|
|
drawRegionMap.setStatusRegions(regions);
|
|
drawRegionMap.setStatusRegions(regions);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 用户“闭环(drawend)”后,把当前绘制结果自动写入草稿,避免切换 tab 时被清掉。
|
|
|
|
|
+ * 注意:getAreaGeometry 可能包含多块,这里以“最新一块”为准(最后一个 feature)
|
|
|
|
|
+ */
|
|
|
|
|
+const syncClosedDrawToDraft = () => {
|
|
|
|
|
+ const tab = varietyTabs.value?.[activeVariety.value];
|
|
|
|
|
+ if (!tab) return;
|
|
|
|
|
+ const polygonData = drawRegionMap.getAreaGeometry?.();
|
|
|
|
|
+ const geometryArr = polygonData?.geometryArr;
|
|
|
|
|
+ if (!Array.isArray(geometryArr) || geometryArr.length === 0) return;
|
|
|
|
|
+ const geom = String(geometryArr[geometryArr.length - 1] || "").trim();
|
|
|
|
|
+ if (!isValidGeom(geom)) return;
|
|
|
|
|
+
|
|
|
|
|
+ const key = draftKeyFromParts(activeRegionType.value, tab);
|
|
|
|
|
+ if (key) {
|
|
|
|
|
+ const prev = regionsDraftByKey.value[key] || {};
|
|
|
|
|
+ regionsDraftByKey.value[key] = {
|
|
|
|
|
+ ...prev,
|
|
|
|
|
+ geomArr: [geom],
|
|
|
|
|
+ geom,
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ regionsDraftByIndex.value[activeVariety.value] = { geomArr: [geom], geom };
|
|
|
|
|
+ regionGeom.value = geom;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const handleVarietyClick = (tab, index) => {
|
|
const handleVarietyClick = (tab, index) => {
|
|
|
|
|
+ // 取消上一次延迟渲染,避免快速切换 tab / 切换编辑态时重复追加要素
|
|
|
|
|
+ clearPendingGeomRenderTimer();
|
|
|
|
|
+
|
|
|
|
|
+ // 若存在“未闭环”的绘制草图(Draw 的 sketch 在 overlay 上),切换时需要清掉;已闭环的要素会走 drawend 写入草稿
|
|
|
|
|
+ const draw = drawRegionMap.kmap?.draw;
|
|
|
|
|
+ const hasUnclosedSketch = !!(draw && (draw.sketchFeature_ || draw.sketchCoords_ || draw.sketchLine_));
|
|
|
|
|
+ if (hasUnclosedSketch) {
|
|
|
|
|
+ drawRegionMap.abortOngoingDrawSketch?.();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
activeVariety.value = index;
|
|
activeVariety.value = index;
|
|
|
// 取值优先级:
|
|
// 取值优先级:
|
|
|
// 1) 草稿(regionsDraftByKey / regionsDraftByIndex)
|
|
// 1) 草稿(regionsDraftByKey / regionsDraftByIndex)
|
|
@@ -343,9 +426,11 @@ const handleVarietyClick = (tab, index) => {
|
|
|
// 切换时先清空当前可编辑图层,避免叠加
|
|
// 切换时先清空当前可编辑图层,避免叠加
|
|
|
drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
|
|
drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
|
|
|
if (geomArr.length > 0) {
|
|
if (geomArr.length > 0) {
|
|
|
- setTimeout(() => {
|
|
|
|
|
|
|
+ pendingGeomRenderTimer.value = setTimeout(() => {
|
|
|
|
|
+ // 再兜底清一次,避免异步回调在 destroy/init 后仍执行导致重复追加
|
|
|
|
|
+ drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
|
|
|
// 切换小类仅负责“显示”,不主动缩放;缩放留到点击“编辑”时触发
|
|
// 切换小类仅负责“显示”,不主动缩放;缩放留到点击“编辑”时触发
|
|
|
- drawRegionMap.setAreaGeometry(geomArr, false);
|
|
|
|
|
|
|
+ drawRegionMap.setAreaGeometry(geomArr, false, undefined, undefined, getAbnormalGrowthOverlayMeta());
|
|
|
// 需要 fit 时,确保视野包含当前渲染的所有地块(只读层 + 当前层)
|
|
// 需要 fit 时,确保视野包含当前渲染的所有地块(只读层 + 当前层)
|
|
|
drawRegionMap.fitAllRegions?.();
|
|
drawRegionMap.fitAllRegions?.();
|
|
|
}, 50);
|
|
}, 50);
|
|
@@ -355,26 +440,6 @@ const handleVarietyClick = (tab, index) => {
|
|
|
const viewOnly = computed(() => route.query.type === "viewOnly");
|
|
const viewOnly = computed(() => route.query.type === "viewOnly");
|
|
|
|
|
|
|
|
const point = ref(null);
|
|
const point = ref(null);
|
|
|
-const farmVarietyList = ref([]);
|
|
|
|
|
-async function fetchFarmSubjectDetail() {
|
|
|
|
|
- const subjectId = route.query?.subjectId;
|
|
|
|
|
- if (!subjectId) return;
|
|
|
|
|
-
|
|
|
|
|
- const { data } = await VE_API.basic_farm.fetchFarmSubjectDetail({ subjectId });
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- if (data?.regionList?.length) {
|
|
|
|
|
- if (!hasAppliedInitialVariety.value && route.query?.varietyId) {
|
|
|
|
|
- activeVariety.value = resolveInitialVarietyIndex(data?.regionList);
|
|
|
|
|
- hasAppliedInitialVariety.value = true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- point.value = data.farmLocation;
|
|
|
|
|
- // farmVarietyList.value = data.regionList;
|
|
|
|
|
- // varietyTabs.value = data.regionList;
|
|
|
|
|
- // handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
const regionTypeTabs = ref([]);
|
|
const regionTypeTabs = ref([]);
|
|
|
const activeRegionType = ref("variety");
|
|
const activeRegionType = ref("variety");
|
|
@@ -398,30 +463,55 @@ async function fetchRegionInfo() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const resolveProblemZoneGroupKind = (g) => {
|
|
|
|
|
- if (!g) return "";
|
|
|
|
|
- const code = (g.code ?? "").toString().trim().toLowerCase();
|
|
|
|
|
- const name = (g.name ?? "").toString();
|
|
|
|
|
- if (name.includes("异常") || code === "abnormal" || code.includes("abnormal")) return "abnormal";
|
|
|
|
|
- if (name.includes("环境") || code === "environment" || code.includes("environment")) return "environment";
|
|
|
|
|
- if (
|
|
|
|
|
- name.includes("休眠") ||
|
|
|
|
|
- code === "sleep" ||
|
|
|
|
|
- code.includes("sleep") ||
|
|
|
|
|
- code.includes("dormant") ||
|
|
|
|
|
- code.includes("dormancy") ||
|
|
|
|
|
- code.includes("hibern")
|
|
|
|
|
- ) {
|
|
|
|
|
- return "sleep";
|
|
|
|
|
- }
|
|
|
|
|
- return "";
|
|
|
|
|
|
|
+/** 样式用的大类:与接口 tab.code 解耦(避免 ABNORMAL / 数字 code 等导致勾画色落到默认灰) */
|
|
|
|
|
+const getCanonicalRegionTypeForStyles = () => {
|
|
|
|
|
+ const raw = activeRegionType.value;
|
|
|
|
|
+ if (raw === "variety") return "variety";
|
|
|
|
|
+ const tabs = regionTypeTabs.value || [];
|
|
|
|
|
+ const item = tabs.find((t) => String(t?.code) === String(raw));
|
|
|
|
|
+ if (item) {
|
|
|
|
|
+ const kind = item.code;
|
|
|
|
|
+ if (kind) return kind;
|
|
|
|
|
+ }
|
|
|
|
|
+ return "SLEEP";
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const ABNORMAL_BADGE_BG_DISEASE_PEST = "#E32A28";
|
|
|
|
|
+const ABNORMAL_BADGE_BG_GROWTH = "#F76F00";
|
|
|
|
|
+
|
|
|
|
|
+/** 异常区小类(长势/病害/虫害等)闭合地块后在多边形内展示标签与发现日期(查看态 setAreaGeometry 同步使用) */
|
|
|
|
|
+const getAbnormalGrowthOverlayMeta = () => {
|
|
|
|
|
+ if (getCanonicalRegionTypeForStyles() !== "ABNORMAL") return null;
|
|
|
|
|
+ const tab = varietyTabs.value?.[activeVariety.value];
|
|
|
|
|
+ if (!tab) return null;
|
|
|
|
|
+ const name = (tab.problemZoneTypeName || tab.regionName || "").toString();
|
|
|
|
|
+ let badgeText = "";
|
|
|
|
|
+ let badgeBackground = ABNORMAL_BADGE_BG_GROWTH;
|
|
|
|
|
+ if (name.includes("病害")) {
|
|
|
|
|
+ badgeText = "新增病害";
|
|
|
|
|
+ badgeBackground = ABNORMAL_BADGE_BG_DISEASE_PEST;
|
|
|
|
|
+ } else if (name.includes("虫害")) {
|
|
|
|
|
+ badgeText = "新增虫害";
|
|
|
|
|
+ badgeBackground = ABNORMAL_BADGE_BG_DISEASE_PEST;
|
|
|
|
|
+ } else if (name.includes("过慢")) {
|
|
|
|
|
+ badgeText = "新增长势过慢";
|
|
|
|
|
+ } else if (name.includes("过快")) {
|
|
|
|
|
+ badgeText = "新增长势过快";
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ const now = new Date();
|
|
|
|
|
+ const y = now.getFullYear();
|
|
|
|
|
+ const m = String(now.getMonth() + 1).padStart(2, "0");
|
|
|
|
|
+ const d = String(now.getDate()).padStart(2, "0");
|
|
|
|
|
+ return { badgeText, discoveryDate: `${y}.${m}.${d}`, badgeBackground };
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const findProblemZoneGroupByDrawType = (majorType) => {
|
|
const findProblemZoneGroupByDrawType = (majorType) => {
|
|
|
if (!majorType || majorType === "variety") return null;
|
|
if (!majorType || majorType === "variety") return null;
|
|
|
const list = regionInfo.value?.problemZoneList || [];
|
|
const list = regionInfo.value?.problemZoneList || [];
|
|
|
return (
|
|
return (
|
|
|
- list.find((x) => resolveProblemZoneGroupKind(x) === majorType) ||
|
|
|
|
|
|
|
+ list.find((x) => x.code === majorType) ||
|
|
|
list.find((x) => String(x?.code) === String(majorType))
|
|
list.find((x) => String(x?.code) === String(majorType))
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|
|
@@ -481,7 +571,7 @@ const buildProblemZoneListForSubmit = () => {
|
|
|
const subjectId = route.query.subjectId;
|
|
const subjectId = route.query.subjectId;
|
|
|
const groups = [];
|
|
const groups = [];
|
|
|
raw.forEach((group) => {
|
|
raw.forEach((group) => {
|
|
|
- const canonical = resolveProblemZoneGroupKind(group);
|
|
|
|
|
|
|
+ const canonical = group.code;
|
|
|
const children = (group.children || [])
|
|
const children = (group.children || [])
|
|
|
.map((child) => {
|
|
.map((child) => {
|
|
|
if (!canonical) return null;
|
|
if (!canonical) return null;
|
|
@@ -514,6 +604,7 @@ const buildProblemZoneListForSubmit = () => {
|
|
|
onActivated(async () => {
|
|
onActivated(async () => {
|
|
|
activeVariety.value = 0;
|
|
activeVariety.value = 0;
|
|
|
hasAppliedInitialVariety.value = false;
|
|
hasAppliedInitialVariety.value = false;
|
|
|
|
|
+ clearPendingGeomRenderTimer();
|
|
|
// keep-alive 场景下再次进入前先销毁旧地图实例,避免重复 init 导致图层状态错位
|
|
// keep-alive 场景下再次进入前先销毁旧地图实例,避免重复 init 导致图层状态错位
|
|
|
if (drawRegionMap.kmap) {
|
|
if (drawRegionMap.kmap) {
|
|
|
drawRegionMap.abortOngoingDrawSketch?.();
|
|
drawRegionMap.abortOngoingDrawSketch?.();
|
|
@@ -522,9 +613,8 @@ onActivated(async () => {
|
|
|
|
|
|
|
|
type.value = route.query.type;
|
|
type.value = route.query.type;
|
|
|
const editable = !viewOnly.value;
|
|
const editable = !viewOnly.value;
|
|
|
- // await fetchFarmSubjectDetail();
|
|
|
|
|
await fetchRegionInfo();
|
|
await fetchRegionInfo();
|
|
|
- drawRegionMap.initMap(point.value, mapContainer.value, editable, true, true);
|
|
|
|
|
|
|
+ drawRegionMap.initMap(point.value, mapContainer.value, editable, true, true, syncClosedDrawToDraft);
|
|
|
applyRegionStyles();
|
|
applyRegionStyles();
|
|
|
|
|
|
|
|
// 首次进入时,fetch 阶段可能先于地图初始化触发了 tab 渲染;
|
|
// 首次进入时,fetch 阶段可能先于地图初始化触发了 tab 渲染;
|
|
@@ -537,7 +627,7 @@ onActivated(async () => {
|
|
|
// 从编辑态进入仅查看时,需重新初始化为不可编辑
|
|
// 从编辑态进入仅查看时,需重新初始化为不可编辑
|
|
|
if (viewOnly.value && drawRegionMap.kmap && drawRegionMap.editable) {
|
|
if (viewOnly.value && drawRegionMap.kmap && drawRegionMap.editable) {
|
|
|
drawRegionMap.destroyMap();
|
|
drawRegionMap.destroyMap();
|
|
|
- drawRegionMap.initMap(point.value, mapContainer.value, false, true, false);
|
|
|
|
|
|
|
+ drawRegionMap.initMap(point.value, mapContainer.value, false, true, false, syncClosedDrawToDraft);
|
|
|
applyRegionStyles();
|
|
applyRegionStyles();
|
|
|
if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
|
|
if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
|
|
|
handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
|
|
handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
|
|
@@ -547,7 +637,7 @@ onActivated(async () => {
|
|
|
// 从仅查看进入勾画(编辑)时,需重新初始化为可编辑
|
|
// 从仅查看进入勾画(编辑)时,需重新初始化为可编辑
|
|
|
if (!viewOnly.value && drawRegionMap.kmap && !drawRegionMap.editable) {
|
|
if (!viewOnly.value && drawRegionMap.kmap && !drawRegionMap.editable) {
|
|
|
drawRegionMap.destroyMap();
|
|
drawRegionMap.destroyMap();
|
|
|
- drawRegionMap.initMap(point.value, mapContainer.value, true, true, true);
|
|
|
|
|
|
|
+ drawRegionMap.initMap(point.value, mapContainer.value, true, true, true, syncClosedDrawToDraft);
|
|
|
applyRegionStyles();
|
|
applyRegionStyles();
|
|
|
if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
|
|
if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
|
|
|
handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
|
|
handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
|
|
@@ -562,6 +652,7 @@ onActivated(async () => {
|
|
|
|
|
|
|
|
onDeactivated(() => {
|
|
onDeactivated(() => {
|
|
|
activeVariety.value = 0;
|
|
activeVariety.value = 0;
|
|
|
|
|
+ clearPendingGeomRenderTimer();
|
|
|
// 离开页面时中止未完成绘制并销毁地图,确保下次进入是干净实例
|
|
// 离开页面时中止未完成绘制并销毁地图,确保下次进入是干净实例
|
|
|
drawRegionMap.abortOngoingDrawSketch?.();
|
|
drawRegionMap.abortOngoingDrawSketch?.();
|
|
|
drawRegionMap.destroyMap?.();
|
|
drawRegionMap.destroyMap?.();
|
|
@@ -598,7 +689,13 @@ const resetPolygon = () => {
|
|
|
try {
|
|
try {
|
|
|
const parsed = JSON.parse(polygonDataStr);
|
|
const parsed = JSON.parse(polygonDataStr);
|
|
|
if (parsed && Array.isArray(parsed.geometryArr) && parsed.geometryArr.length) {
|
|
if (parsed && Array.isArray(parsed.geometryArr) && parsed.geometryArr.length) {
|
|
|
- drawRegionMap.setAreaGeometry(parsed.geometryArr);
|
|
|
|
|
|
|
+ drawRegionMap.setAreaGeometry(
|
|
|
|
|
+ parsed.geometryArr,
|
|
|
|
|
+ false,
|
|
|
|
|
+ undefined,
|
|
|
|
|
+ undefined,
|
|
|
|
|
+ getAbnormalGrowthOverlayMeta()
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
} catch (_) {
|
|
} catch (_) {
|
|
|
// 解析失败则不做处理,仅相当于清空重画
|
|
// 解析失败则不做处理,仅相当于清空重画
|
|
@@ -628,6 +725,24 @@ const submitRegions = async () => {
|
|
|
};
|
|
};
|
|
|
const res = await VE_API.basic_farm.ediRegionZone(params);
|
|
const res = await VE_API.basic_farm.ediRegionZone(params);
|
|
|
if (res?.code === 0) {
|
|
if (res?.code === 0) {
|
|
|
|
|
+ if(selectedDrawTypeMeta.value.type === 'ABNORMAL'){
|
|
|
|
|
+ let problemZoneId = null;
|
|
|
|
|
+ if(params.problemZoneList.length){
|
|
|
|
|
+ res.data[0].problemZoneList.forEach(element => {
|
|
|
|
|
+ if(element.code === selectedDrawTypeMeta.value.type){
|
|
|
|
|
+ element.children.forEach(item => {
|
|
|
|
|
+ if(item.problemZoneTypeName === selectedDrawTypeMeta.value.category.problemZoneTypeName){
|
|
|
|
|
+ problemZoneId = item.id;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ VE_API.basic_farm.saveProblemZoneImage({
|
|
|
|
|
+ problemZoneId,
|
|
|
|
|
+ imagePathList: selectedDrawTypeMeta.value.images,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
ElMessage.error(res?.msg || "保存失败");
|
|
ElMessage.error(res?.msg || "保存失败");
|
|
@@ -651,6 +766,7 @@ const confirmArea = async (drawMeta) => {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
const polygonData = drawRegionMap.getAreaGeometry?.();
|
|
const polygonData = drawRegionMap.getAreaGeometry?.();
|
|
|
|
|
+ console.log(polygonData, 'polygonData');
|
|
|
const geometryArr = polygonData?.geometryArr;
|
|
const geometryArr = polygonData?.geometryArr;
|
|
|
if (!Array.isArray(geometryArr) || geometryArr.length === 0) {
|
|
if (!Array.isArray(geometryArr) || geometryArr.length === 0) {
|
|
|
ElMessage.warning("请先勾画地块后再确认");
|
|
ElMessage.warning("请先勾画地块后再确认");
|
|
@@ -687,6 +803,8 @@ const confirmArea = async (drawMeta) => {
|
|
|
// 保存成功后:不跳走,刷新当前页并回显最新数据,并切换为查看态
|
|
// 保存成功后:不跳走,刷新当前页并回显最新数据,并切换为查看态
|
|
|
try {
|
|
try {
|
|
|
await fetchRegionInfo();
|
|
await fetchRegionInfo();
|
|
|
|
|
+ // 接口已是最新几何与 id,清空草稿避免旧 key/下标回退遮挡 geomItems
|
|
|
|
|
+ clearAllRegionDrafts();
|
|
|
|
|
|
|
|
// 恢复当前大类下的子类 tab(fetchRegionInfo 默认会填充品种区)
|
|
// 恢复当前大类下的子类 tab(fetchRegionInfo 默认会填充品种区)
|
|
|
if (activeRegionType.value === "variety") {
|
|
if (activeRegionType.value === "variety") {
|
|
@@ -732,18 +850,13 @@ const openConfirmDrawTypePopup = () => {
|
|
|
ElMessage.warning("请先勾画地块后再确认");
|
|
ElMessage.warning("请先勾画地块后再确认");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ const remark = varietyTabs?.value?.[activeVariety.value]?.geomItems?.[0]?.remark;
|
|
|
confirmDrawTypePopupRef.value.openPopup({
|
|
confirmDrawTypePopupRef.value.openPopup({
|
|
|
- varietyTabs: varietyTabs.value,
|
|
|
|
|
- regionList: regionInfo.value?.regionList ?? [],
|
|
|
|
|
- problemZoneList: regionInfo.value?.problemZoneList ?? [],
|
|
|
|
|
- /** 接口未返回子类时与地图页本地 categoryMap 一致,避免弹窗内切换大类无选项 */
|
|
|
|
|
- fallbackProblemCategories: {
|
|
|
|
|
- abnormal: categoryMap.abnormal,
|
|
|
|
|
- environment: categoryMap.environment,
|
|
|
|
|
- sleep: categoryMap.sleep,
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ regionInfo: regionInfo.value,
|
|
|
activeRegionType: activeRegionType.value,
|
|
activeRegionType: activeRegionType.value,
|
|
|
activeVarietyIndex: activeVariety.value,
|
|
activeVarietyIndex: activeVariety.value,
|
|
|
|
|
+ remark: activeRegionType.value === 'variety' ? '' : remark,
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -752,15 +865,17 @@ const handleConfirmDrawType = async (payload) => {
|
|
|
await confirmArea(payload);
|
|
await confirmArea(payload);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const handleEditRegion = () => {
|
|
|
|
|
|
|
+const handleEditRegion = async () => {
|
|
|
// 从查看态切换到可勾画编辑态:移除查看标记(所有大类共用)
|
|
// 从查看态切换到可勾画编辑态:移除查看标记(所有大类共用)
|
|
|
const nextQuery = { ...route.query };
|
|
const nextQuery = { ...route.query };
|
|
|
delete nextQuery.type;
|
|
delete nextQuery.type;
|
|
|
delete nextQuery.viewOnly;
|
|
delete nextQuery.viewOnly;
|
|
|
- router.replace({ query: nextQuery });
|
|
|
|
|
|
|
+ clearPendingGeomRenderTimer();
|
|
|
|
|
+ await router.replace({ query: nextQuery });
|
|
|
|
|
|
|
|
nextTick(() => {
|
|
nextTick(() => {
|
|
|
if (drawRegionMap.kmap) {
|
|
if (drawRegionMap.kmap) {
|
|
|
|
|
+ drawRegionMap.abortOngoingDrawSketch?.();
|
|
|
drawRegionMap.destroyMap();
|
|
drawRegionMap.destroyMap();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -769,7 +884,7 @@ const handleEditRegion = () => {
|
|
|
// - 只显示「品种区」地块作为底图参考(只读)
|
|
// - 只显示「品种区」地块作为底图参考(只读)
|
|
|
// - 不显示其它问题区地块
|
|
// - 不显示其它问题区地块
|
|
|
if (activeRegionType.value !== "variety") {
|
|
if (activeRegionType.value !== "variety") {
|
|
|
- drawRegionMap.initMap(point.value, mapContainer.value, true, true, true);
|
|
|
|
|
|
|
+ drawRegionMap.initMap(point.value, mapContainer.value, true, true, true, syncClosedDrawToDraft);
|
|
|
applyRegionStyles();
|
|
applyRegionStyles();
|
|
|
// 清空当前可编辑图层,避免残留
|
|
// 清空当前可编辑图层,避免残留
|
|
|
drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
|
|
drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
|
|
@@ -786,7 +901,14 @@ const handleEditRegion = () => {
|
|
|
regionGeom.value =
|
|
regionGeom.value =
|
|
|
currentGeomArr.length > 1 ? JSON.stringify(currentGeomArr) : currentGeomArr[0] || "";
|
|
currentGeomArr.length > 1 ? JSON.stringify(currentGeomArr) : currentGeomArr[0] || "";
|
|
|
if (currentGeomArr.length > 0) {
|
|
if (currentGeomArr.length > 0) {
|
|
|
- drawRegionMap.setAreaGeometry(currentGeomArr, true);
|
|
|
|
|
|
|
+ drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
|
|
|
|
|
+ drawRegionMap.setAreaGeometry(
|
|
|
|
|
+ currentGeomArr,
|
|
|
|
|
+ true,
|
|
|
|
|
+ undefined,
|
|
|
|
|
+ undefined,
|
|
|
|
|
+ getAbnormalGrowthOverlayMeta()
|
|
|
|
|
+ );
|
|
|
} else {
|
|
} else {
|
|
|
// 仍自适应到品种区底图
|
|
// 仍自适应到品种区底图
|
|
|
drawRegionMap.fitAllRegions?.();
|
|
drawRegionMap.fitAllRegions?.();
|
|
@@ -794,7 +916,7 @@ const handleEditRegion = () => {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- drawRegionMap.initMap(point.value, mapContainer.value, true, true, true);
|
|
|
|
|
|
|
+ drawRegionMap.initMap(point.value, mapContainer.value, true, true, true, syncClosedDrawToDraft);
|
|
|
applyRegionStyles();
|
|
applyRegionStyles();
|
|
|
|
|
|
|
|
// 切到编辑态后:统一走一遍当前 tab 的点击逻辑,确保所有有地块的品种都能显示
|
|
// 切到编辑态后:统一走一遍当前 tab 的点击逻辑,确保所有有地块的品种都能显示
|
|
@@ -813,13 +935,26 @@ const handleEditRegion = () => {
|
|
|
})();
|
|
})();
|
|
|
drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
|
|
drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
|
|
|
if (geomArr.length > 0) {
|
|
if (geomArr.length > 0) {
|
|
|
- drawRegionMap.setAreaGeometry(geomArr, true);
|
|
|
|
|
|
|
+ drawRegionMap.setAreaGeometry(
|
|
|
|
|
+ geomArr,
|
|
|
|
|
+ true,
|
|
|
|
|
+ undefined,
|
|
|
|
|
+ undefined,
|
|
|
|
|
+ getAbnormalGrowthOverlayMeta()
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
renderReadonlyVarietyRegions(activeVariety.value);
|
|
renderReadonlyVarietyRegions(activeVariety.value);
|
|
|
const fallbackGeom = regionGeom.value;
|
|
const fallbackGeom = regionGeom.value;
|
|
|
if (isValidGeom(fallbackGeom)) {
|
|
if (isValidGeom(fallbackGeom)) {
|
|
|
- drawRegionMap.setAreaGeometry([fallbackGeom], true);
|
|
|
|
|
|
|
+ drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
|
|
|
|
|
+ drawRegionMap.setAreaGeometry(
|
|
|
|
|
+ [fallbackGeom],
|
|
|
|
|
+ true,
|
|
|
|
|
+ undefined,
|
|
|
|
|
+ undefined,
|
|
|
|
|
+ getAbnormalGrowthOverlayMeta()
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
// 编辑态下:保持缩放在当前要编辑地块,不再强制 fitAllRegions 覆盖
|
|
// 编辑态下:保持缩放在当前要编辑地块,不再强制 fitAllRegions 覆盖
|