|
|
@@ -2,13 +2,8 @@
|
|
|
<div class="edit-map">
|
|
|
<custom-header :name="viewOnly ? '查看区域' : '勾选地块'"></custom-header>
|
|
|
<div class="variety-tabs" v-if="varietyTabs.length > 0">
|
|
|
- <div
|
|
|
- v-for="(v, index) in varietyTabs"
|
|
|
- :key="index"
|
|
|
- class="variety-tab"
|
|
|
- :class="{ 'variety-tab--active': activeVariety === index }"
|
|
|
- @click="handleVarietyClick(v, index)"
|
|
|
- >
|
|
|
+ <div v-for="(v, index) in varietyTabs" :key="index" class="variety-tab"
|
|
|
+ :class="{ 'variety-tab--active': activeVariety === index }" @click="handleVarietyClick(v, index)">
|
|
|
{{ v.regionName }}
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -19,29 +14,26 @@
|
|
|
<div class="footer-back" @click="goBack">
|
|
|
<img class="back-icon" src="@/assets/img/home/go-back.png" alt="" />
|
|
|
</div>
|
|
|
- <div class="edit-map-footer-btn" v-if="!viewOnly">
|
|
|
- <!-- <div class="edit-map-footer-btn confirm-btn-box" v-if="!viewOnly"> -->
|
|
|
- <div class="btn-reset" @click="resetPolygon">重置区域</div>
|
|
|
- <div class="btn-confirm" @click="confirm">确认</div>
|
|
|
- <!-- <div class="btn-confirm" @click="confirm">编辑区域</div> -->
|
|
|
+ <div class="edit-map-footer-btn" :class="{ 'confirm-btn-box': viewOnly }">
|
|
|
+ <template v-if="!viewOnly">
|
|
|
+ <div class="btn-reset" @click="resetPolygon">重置区域</div>
|
|
|
+ <div class="btn-confirm" @click="confirmArea">确认</div>
|
|
|
+ </template>
|
|
|
+ <div v-else class="btn-confirm" @click="handleEditRegion">编辑区域</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <save-region-success-popup
|
|
|
- v-if="!viewOnly"
|
|
|
- v-model:show="showSuccessPopup"
|
|
|
+ <save-region-success-popup v-if="!viewOnly" v-model:show="showSuccessPopup"
|
|
|
:title="`${activeVarietyName} 区域已保存成功`"
|
|
|
- :has-next="varietyTabs.length > 0 && activeVariety < varietyTabs.length - 1"
|
|
|
- @know="handleKnow"
|
|
|
- @next="handleSelectNextVariety"
|
|
|
- />
|
|
|
+ :has-next="varietyTabs.length > 0 && activeVariety < varietyTabs.length - 1" @know="handleKnow"
|
|
|
+ @next="handleSelectNextVariety" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import customHeader from "@/components/customHeader.vue";
|
|
|
import SaveRegionSuccessPopup from "@/components/popup/saveRegionSuccessPopup.vue";
|
|
|
-import { ref, computed, onMounted, onActivated, onDeactivated } from "vue";
|
|
|
+import { ref, computed, onMounted, onActivated, onDeactivated, nextTick } from "vue";
|
|
|
import { useStore } from "vuex";
|
|
|
import DrawRegionMap from "../../interactionList/map/drawRegionMap.js";
|
|
|
import { useRouter, useRoute } from "vue-router";
|
|
|
@@ -57,64 +49,41 @@ const drawRegionMap = new DrawRegionMap();
|
|
|
const showSuccessPopup = ref(false);
|
|
|
// 是否从第一个品种开始的引导流程(需要全部品种都确认后再退出)
|
|
|
const isGuidedFlow = ref(false);
|
|
|
+// 每个品种(tab)对应的地块数据草稿:key 为 tab index,value 为 { geomArr, geom }
|
|
|
+const regionsDraftByIndex = ref({});
|
|
|
+const submitting = ref(false);
|
|
|
|
|
|
const type = ref(null);
|
|
|
const varietyTabs = ref([]);
|
|
|
const activeVariety = ref(0);
|
|
|
-const farmIdData = ref(null);
|
|
|
-const gardenId = ref(store.state.home.gardenId);
|
|
|
-
|
|
|
-const getVarietyTabs = async () => {
|
|
|
- if (!gardenId.value) return;
|
|
|
- try {
|
|
|
- const res = await VE_API.monitor.listRegionsBySubjectId({
|
|
|
- subjectId: gardenId.value,
|
|
|
- });
|
|
|
- varietyTabs.value = res.data || [];
|
|
|
- if (varietyTabs.value.length > 0) {
|
|
|
- handleVarietyClick(varietyTabs.value[0], 0);
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error("获取主体分区列表失败:", error);
|
|
|
- }
|
|
|
-};
|
|
|
+const regionGeom = ref(null);
|
|
|
|
|
|
const handleVarietyClick = (tab, index) => {
|
|
|
activeVariety.value = index;
|
|
|
- farmIdData.value = tab.farmId;
|
|
|
+ regionGeom.value = tab.geom;
|
|
|
+
|
|
|
+ if (tab.geom?.length) {
|
|
|
+ drawRegionMap.kmap.polygonLayer.source.clear();
|
|
|
+ drawRegionMap.setAreaGeometry([tab.geom],true);
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
const activeVarietyName = computed(() => {
|
|
|
const current = varietyTabs.value[activeVariety.value];
|
|
|
return current?.regionName || "";
|
|
|
});
|
|
|
-const viewOnly = computed(() => route.query.viewOnly === "1" || route.query.viewOnly === "true");
|
|
|
+const viewOnly = computed(() => route.query.type === "viewOnly");
|
|
|
|
|
|
onMounted(() => {
|
|
|
type.value = route.query.type;
|
|
|
const point = route.query.mapCenter || "POINT (113.6142086995688 23.585836479509055)";
|
|
|
const editable = !viewOnly.value;
|
|
|
- const showPoint = !viewOnly.value;
|
|
|
- drawRegionMap.initMap(point, mapContainer.value, editable, true, showPoint);
|
|
|
-
|
|
|
- // 初始化品种 tabs
|
|
|
- getVarietyTabs();
|
|
|
-
|
|
|
- // 地图初始化之后(比如 initPreviewMap 里)
|
|
|
- // const regions = [
|
|
|
- // {
|
|
|
- // geometry:
|
|
|
- // "MULTIPOLYGON(((113.61674040430906 23.586573370597367,113.61586610436014 23.585922976493354,113.61710291900188 23.58486741952544,113.61770000158238 23.585651090473736,113.61674040430906 23.586573370597367)))",
|
|
|
- // status: "unresolved", // 未解决(蓝色)
|
|
|
- // },
|
|
|
- // {
|
|
|
- // geometry:
|
|
|
- // "MULTIPOLYGON(((113.61516640298626 23.588441931082958,113.61445736699218 23.58799411906573,113.61572616841707 23.586954554834552,113.61642987338976 23.588180707433526,113.61516640298626 23.588441931082958)))",
|
|
|
- // status: "resolved", // 已解决(灰色)
|
|
|
- // },
|
|
|
- // ];
|
|
|
-
|
|
|
- // drawRegionMap.setStatusRegions(regions);
|
|
|
+ drawRegionMap.initMap(point, mapContainer.value, editable, true, true);
|
|
|
+ const regionData = route.query?.regionList || [];
|
|
|
+ if (regionData.length) {
|
|
|
+ varietyTabs.value = JSON.parse(regionData);
|
|
|
+ handleVarietyClick(varietyTabs.value[0], 0);
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
onActivated(() => {
|
|
|
@@ -132,40 +101,6 @@ onActivated(() => {
|
|
|
drawRegionMap.initMap(point, mapContainer.value, true, true, true);
|
|
|
}
|
|
|
|
|
|
- // 先绘制地块
|
|
|
- const polygonData = route.query.polygonData;
|
|
|
- const rawRangeWkt = route.query.rangeWkt;
|
|
|
- const rangeWkt = rawRangeWkt ? decodeURIComponent(rawRangeWkt) : null;
|
|
|
-
|
|
|
- if (rangeWkt) {
|
|
|
- let regions = [];
|
|
|
- try {
|
|
|
- const parsed = JSON.parse(rangeWkt);
|
|
|
- if (parsed && Array.isArray(parsed.geometryArr)) {
|
|
|
- regions = parsed.geometryArr.map((item) => ({
|
|
|
- geometry: item,
|
|
|
- status: "unresolved",
|
|
|
- updatedTime: route.query.updatedTime,
|
|
|
- }));
|
|
|
- } else if (typeof rangeWkt === "string" && rangeWkt.trim().length > 10) {
|
|
|
- regions = [{ geometry: rangeWkt.trim(), status: "unresolved", updatedTime: route.query.updatedTime }];
|
|
|
- }
|
|
|
- } catch (_) {
|
|
|
- if (typeof rangeWkt === "string" && rangeWkt.trim().length > 10) {
|
|
|
- regions = [{ geometry: rangeWkt.trim(), status: "unresolved", updatedTime: route.query.updatedTime }];
|
|
|
- }
|
|
|
- }
|
|
|
- if (regions.length) {
|
|
|
- drawRegionMap.setStatusRegions(regions);
|
|
|
- if (viewOnly.value && drawRegionMap.fitAllRegions) {
|
|
|
- drawRegionMap.fitAllRegions();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (!viewOnly.value && polygonData) {
|
|
|
- drawRegionMap.setAreaGeometry(JSON.parse(polygonData)?.geometryArr);
|
|
|
- }
|
|
|
-
|
|
|
// 查看模式下已通过 fitAllRegions 适配;编辑模式再设置地图中心
|
|
|
if (!viewOnly.value) {
|
|
|
drawRegionMap.setMapPosition(convertPointToArray(point));
|
|
|
@@ -216,40 +151,81 @@ const resetPolygon = () => {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
-const confirm = () => {
|
|
|
- // const polygonData = drawRegionMap.getAreaGeometry();
|
|
|
- // sessionStorage.setItem("drawRegionPolygonData", JSON.stringify(polygonData));
|
|
|
+const buildRegionsPayload = () => {
|
|
|
+ const regions = [];
|
|
|
+ varietyTabs.value.forEach((tab, index) => {
|
|
|
+ const draft = regionsDraftByIndex.value[index];
|
|
|
+ if (!draft?.geom) return;
|
|
|
+ regions.push({
|
|
|
+ regionId: tab.regionId,
|
|
|
+ typeId: tab.typeId,
|
|
|
+ regionName: tab.regionName,
|
|
|
+ geom: draft.geom,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ return regions;
|
|
|
+};
|
|
|
+
|
|
|
+const submitRegions = async () => {
|
|
|
+ if (submitting.value) return;
|
|
|
+ const regions = buildRegionsPayload();
|
|
|
+ if (regions.length === 0) {
|
|
|
+ ElMessage.warning("请先勾画地块后再确认");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ submitting.value = true;
|
|
|
+ try {
|
|
|
+ const res = await VE_API.basic_farm.saveBasicFarmInfoByExpertV3({
|
|
|
+ id: route.query.subjectId,
|
|
|
+ expertMiniUserId: '81881',
|
|
|
+ regions,
|
|
|
+ });
|
|
|
+ if (res?.code === 0) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ ElMessage.error(res?.msg || "保存失败");
|
|
|
+ return false;
|
|
|
+ } catch (e) {
|
|
|
+ ElMessage.error("保存失败");
|
|
|
+ return false;
|
|
|
+ } finally {
|
|
|
+ submitting.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const confirmArea = async () => {
|
|
|
+ // 先把当前品种的地块保存到草稿
|
|
|
+ const polygonData = drawRegionMap.getAreaGeometry?.();
|
|
|
+ const geometryArr = polygonData?.geometryArr;
|
|
|
+ if (!Array.isArray(geometryArr) || geometryArr.length === 0) {
|
|
|
+ ElMessage.warning("请先勾画地块后再确认");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // geom 后端一般期望 string;若勾画多个,则序列化为 JSON 数组
|
|
|
+ const geom = geometryArr.length === 1 ? geometryArr[0] : JSON.stringify(geometryArr);
|
|
|
+ regionsDraftByIndex.value[activeVariety.value] = { geomArr: geometryArr, geom };
|
|
|
|
|
|
- // 如果当前是第一个品种,则开启完整引导流程:每次确认都弹成功提示,直到最后一个才退出
|
|
|
+ // 从第一个品种开始时,进入引导流程(确认后弹提示,支持“下一步”)
|
|
|
if (activeVariety.value === 0) {
|
|
|
isGuidedFlow.value = true;
|
|
|
- showSuccessPopup.value = true;
|
|
|
- return;
|
|
|
}
|
|
|
|
|
|
- // 已经在引导流程中(从第一个品种开始勾选),后续品种确认也只弹成功提示,不直接跳走
|
|
|
+ // 每次确认都提交接口(携带目前已确认过的所有品种 regions)
|
|
|
+ const ok = await submitRegions();
|
|
|
+ if (!ok) return;
|
|
|
+
|
|
|
+ // 引导流程:弹成功提示,由弹窗控制“下一步/完成”
|
|
|
if (isGuidedFlow.value) {
|
|
|
showSuccessPopup.value = true;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 非引导流程(例如直接编辑单个非第一个品种),确认后直接返回上一页
|
|
|
+ // 非引导流程:确认后返回上一页
|
|
|
router.back();
|
|
|
};
|
|
|
|
|
|
const handleKnow = () => {
|
|
|
showSuccessPopup.value = false;
|
|
|
-
|
|
|
- const isLastVariety =
|
|
|
- varietyTabs.value.length > 0 && activeVariety.value === varietyTabs.value.length - 1;
|
|
|
-
|
|
|
- // 在引导流程中且还没到最后一个品种时,“我知道了”只关闭弹窗,不跳走
|
|
|
- if (isGuidedFlow.value && !isLastVariety) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 到达最后一个品种或本身就不是引导流程,才真正完成并返回
|
|
|
- isGuidedFlow.value = false;
|
|
|
router.back();
|
|
|
};
|
|
|
|
|
|
@@ -274,6 +250,32 @@ const handleSelectNextVariety = () => {
|
|
|
handleKnow();
|
|
|
}
|
|
|
};
|
|
|
+
|
|
|
+const handleEditRegion = () => {
|
|
|
+ // 从查看态切换到可勾画编辑态:移除查看标记并重建地图(editable=true)
|
|
|
+ const point = route.query.mapCenter || "POINT (113.6142086995688 23.585836479509055)";
|
|
|
+
|
|
|
+ const nextQuery = { ...route.query };
|
|
|
+ delete nextQuery.type;
|
|
|
+ delete nextQuery.viewOnly;
|
|
|
+ router.replace({ query: nextQuery });
|
|
|
+
|
|
|
+ nextTick(() => {
|
|
|
+ if (drawRegionMap.kmap) {
|
|
|
+ drawRegionMap.destroyMap();
|
|
|
+ }
|
|
|
+
|
|
|
+ drawRegionMap.initMap(point, mapContainer.value, true, true, true);
|
|
|
+
|
|
|
+ if (varietyTabs.value.length) {
|
|
|
+ drawRegionMap.setAreaGeometry([regionGeom.value],true);
|
|
|
+ }
|
|
|
+ // 切到编辑态后,统一自适应到所有区域,避免画面偏移
|
|
|
+ if (drawRegionMap.fitAllRegions) {
|
|
|
+ drawRegionMap.fitAllRegions();
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
@@ -362,7 +364,8 @@ const handleSelectNextVariety = () => {
|
|
|
background: #fff;
|
|
|
padding: 10px 12px 20px 12px;
|
|
|
box-sizing: border-box;
|
|
|
- &.confirm-btn-box{
|
|
|
+
|
|
|
+ &.confirm-btn-box {
|
|
|
justify-content: center;
|
|
|
}
|
|
|
|