| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- <template>
- <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)"
- >
- {{ v.regionName }}
- </div>
- </div>
- <div class="edit-map-content">
- <div class="edit-map-tip" v-if="!viewOnly">操作提示:拖动圆点,即可调整地块边界</div>
- <div class="map-container" ref="mapContainer"></div>
- <div class="edit-map-footer">
- <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>
- </div>
- </div>
- <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"
- />
- </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 { useStore } from "vuex";
- import DrawRegionMap from "../../interactionList/map/drawRegionMap.js";
- import { useRouter, useRoute } from "vue-router";
- import { convertPointToArray } from "@/utils/index";
- import { ElMessage, ElMessageBox } from "element-plus";
- const store = useStore();
- const router = useRouter();
- const route = useRoute();
- const mapContainer = ref(null);
- const drawRegionMap = new DrawRegionMap();
- const showSuccessPopup = ref(false);
- // 是否从第一个品种开始的引导流程(需要全部品种都确认后再退出)
- const isGuidedFlow = 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 handleVarietyClick = (tab, index) => {
- activeVariety.value = index;
- farmIdData.value = tab.farmId;
- };
- const activeVarietyName = computed(() => {
- const current = varietyTabs.value[activeVariety.value];
- return current?.regionName || "";
- });
- const viewOnly = computed(() => route.query.viewOnly === "1" || route.query.viewOnly === "true");
- 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);
- });
- onActivated(() => {
- const point = route.query.mapCenter || "POINT (113.6142086995688 23.585836479509055)";
- // 从编辑态进入仅查看时,需重新初始化为不可编辑
- if (viewOnly.value && drawRegionMap.kmap && drawRegionMap.editable) {
- drawRegionMap.destroyMap();
- drawRegionMap.initMap(point, mapContainer.value, false, true, false);
- }
- // 从仅查看进入勾画(编辑)时,需重新初始化为可编辑
- if (!viewOnly.value && drawRegionMap.kmap && !drawRegionMap.editable) {
- drawRegionMap.destroyMap();
- 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));
- }
- });
- onDeactivated(() => {
- activeVariety.value = 0;
- drawRegionMap.clearLayer()
- })
- const goBack = () => {
- // drawRegionMap.clearLayer()
- router.back()
- };
- const resetPolygon = () => {
- ElMessageBox.confirm(
- "确认要重置当前地块吗?重置后将恢复到进入页面时的区域形状。",
- "重置确认",
- {
- confirmButtonText: "确认重置",
- cancelButtonText: "取消",
- type: "warning",
- }
- )
- .then(() => {
- // 只清空当前可编辑多边形,不影响只读状态图层
- if (drawRegionMap.kmap && drawRegionMap.kmap.polygonLayer && drawRegionMap.kmap.polygonLayer.source) {
- drawRegionMap.kmap.polygonLayer.source.clear();
- }
- // 使用进入页面时路由上带的 polygonData 作为“初始形状”进行回显
- const polygonDataStr = route.query.polygonData;
- if (polygonDataStr) {
- try {
- const parsed = JSON.parse(polygonDataStr);
- if (parsed && Array.isArray(parsed.geometryArr) && parsed.geometryArr.length) {
- drawRegionMap.setAreaGeometry(parsed.geometryArr);
- }
- } catch (_) {
- // 解析失败则不做处理,仅相当于清空重画
- }
- }
- ElMessage.success("地块已重置");
- })
- .catch(() => {
- // 用户取消重置,不做任何操作
- });
- };
- const confirm = () => {
- // const polygonData = drawRegionMap.getAreaGeometry();
- // sessionStorage.setItem("drawRegionPolygonData", JSON.stringify(polygonData));
- // 如果当前是第一个品种,则开启完整引导流程:每次确认都弹成功提示,直到最后一个才退出
- if (activeVariety.value === 0) {
- isGuidedFlow.value = true;
- showSuccessPopup.value = true;
- 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();
- };
- const handleSelectNextVariety = () => {
- if (varietyTabs.value.length === 0) {
- handleKnow();
- return;
- }
- const nextIndex = activeVariety.value + 1;
- if (nextIndex < varietyTabs.value.length) {
- const nextTab = varietyTabs.value[nextIndex];
- // 勾画当前品种完成后,先用统一的 clearLayer 方法重置图层,再切换到下一个品种
- if (drawRegionMap && typeof drawRegionMap.clearLayer === "function") {
- drawRegionMap.clearLayer();
- }
- handleVarietyClick(nextTab, nextIndex);
- showSuccessPopup.value = false;
- } else {
- // 如果已经是最后一个品种,则直接返回上一页
- handleKnow();
- }
- };
- </script>
- <style lang="scss" scoped>
- .edit-map {
- width: 100%;
- height: 100vh;
- overflow: hidden;
- .variety-tabs {
- display: flex;
- align-items: center;
- gap: 8px;
- padding: 10px 12px 0;
- overflow-x: auto;
- overflow-y: hidden;
- flex-wrap: nowrap;
- -webkit-overflow-scrolling: touch;
- .variety-tab {
- padding: 4px 12px;
- border-radius: 2px;
- color: #767676;
- background: #fff;
- border: 0.5px solid rgba(174, 174, 174, 0.8);
- white-space: nowrap;
- }
- .variety-tab--active {
- background: #2199F8;
- color: #ffffff;
- }
- }
- .edit-map-content {
- width: 100%;
- margin-top: 10px;
- height: calc(100% - 58px);
- position: relative;
- .edit-map-tip {
- position: absolute;
- top: 23px;
- left: calc(50% - 256px / 2);
- z-index: 1;
- font-size: 12px;
- color: #fff;
- padding: 9px 20px;
- background: rgba(0, 0, 0, 0.5);
- border-radius: 20px;
- }
- .map-container {
- width: 100%;
- height: 100%;
- }
- .edit-map-footer {
- position: absolute;
- bottom: 110px;
- left: 12px;
- width: calc(100% - 24px);
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- .footer-back {
- padding: 6px 7px 9px;
- background: #fff;
- border-radius: 8px;
- margin-bottom: 12px;
- .back-icon {
- width: 20px;
- height: 18px;
- }
- }
- .edit-map-footer-btn {
- display: flex;
- justify-content: space-between;
- align-items: center;
- width: 100%;
- position: fixed;
- bottom: 0;
- left: 0;
- background: #fff;
- padding: 10px 12px 20px 12px;
- box-sizing: border-box;
- &.confirm-btn-box{
- justify-content: center;
- }
- div {
- width: 100px;
- text-align: center;
- color: #666666;
- font-size: 14px;
- padding: 8px 0;
- border-radius: 25px;
- border: 0.5px solid rgba(153, 153, 153, 0.5);
- }
- .btn-confirm {
- background: #2199F8;
- color: #fff;
- border: 1px solid #2199F8;
- }
- }
- }
- }
- }
- </style>
|