| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- <template>
- <el-dialog
- :model-value="modelValue"
- title="选择存放点位"
- width="920px"
- align-center
- append-to-body
- destroy-on-close
- class="select-location-dialog"
- @update:model-value="emit('update:modelValue', $event)"
- @opened="handleOpened"
- @closed="handleClosed"
- >
- <div v-loading="loading" class="map-wrap">
- <div ref="mapRef" class="map-el"></div>
- <div v-if="!loading && regionCount === 0" class="map-empty">暂无区域数据</div>
- <div class="map-tip">点击地图放置存放位置</div>
- </div>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="close">取消</el-button>
- <el-button type="primary" @click="handleConfirm">确认</el-button>
- </div>
- </template>
- </el-dialog>
- </template>
- <script setup>
- import { getCurrentInstance, nextTick, ref } from "vue";
- import { ElMessage } from "element-plus";
- import { wktCastGeom } from "@/common/ol_common";
- import LocationSelectMap from "./locationSelectMap";
- const props = defineProps({
- modelValue: {
- type: Boolean,
- default: false,
- },
- farmId: {
- type: [String, Number],
- default: 101532,
- },
- /** 已选点位 WKT,编辑回显 */
- locationWkt: {
- type: String,
- default: "",
- },
- });
- const emit = defineEmits(["update:modelValue", "confirm"]);
- const { proxy } = getCurrentInstance();
- const mapRef = ref(null);
- const loading = ref(false);
- const regionCount = ref(0);
- let locationMap = null;
- const close = () => emit("update:modelValue", false);
- const handleOpened = async () => {
- await nextTick();
- if (!mapRef.value) return;
- if (!locationMap) {
- locationMap = new LocationSelectMap();
- }
- const initLocation =
- props.locationWkt || "POINT(113.61448114737868 23.585550924763083)";
- locationMap.init(mapRef.value, initLocation);
- await loadRegions();
- locationMap.updateSize();
- };
- const loadRegions = async () => {
- loading.value = true;
- regionCount.value = 0;
- try {
- const res = await proxy.VE_API.farm.blueRegionList({
- farmId: props.farmId,
- regionId: "",
- });
- const list = Array.isArray(res?.data) ? res.data : [];
- regionCount.value = list.length;
- locationMap?.setRegions(list);
- // 等 fit 完成后再放点,避免先出现在默认位置再消失
- await nextTick();
- requestAnimationFrame(() => {
- if (props.locationWkt) {
- try {
- const coord = wktCastGeom(props.locationWkt).getFirstCoordinate();
- locationMap?.setPoint(coord);
- } catch (e) {
- locationMap?.setPointToCenter();
- }
- } else {
- locationMap?.setPointToCenter();
- }
- });
- if (!list.length && res?.msg) {
- ElMessage.warning(res.msg);
- }
- } catch (e) {
- console.error(e);
- ElMessage.error("区域数据加载失败");
- } finally {
- loading.value = false;
- nextTick(() => locationMap?.updateSize());
- }
- };
- const handleConfirm = () => {
- const point = locationMap?.getPoint();
- if (!point) {
- ElMessage.warning("请在地图上选择存放点位");
- return;
- }
- emit("confirm", point);
- close();
- };
- const handleClosed = () => {
- locationMap?.destroy();
- locationMap = null;
- regionCount.value = 0;
- };
- </script>
- <style lang="scss" scoped>
- .map-wrap {
- position: relative;
- width: 100%;
- height: 520px;
- background: #d3d7d8;
- border-radius: 4px;
- overflow: hidden;
- cursor: pointer;
- }
- .map-el {
- width: 100%;
- height: 100%;
- }
- .map-empty {
- position: absolute;
- inset: 0;
- display: flex;
- align-items: center;
- justify-content: center;
- color: #999;
- pointer-events: none;
- z-index: 2;
- }
- .map-tip {
- position: absolute;
- left: 16px;
- bottom: 16px;
- z-index: 3;
- padding: 6px 12px;
- border-radius: 4px;
- background: rgba(0, 0, 0, 0.55);
- color: #fff;
- font-size: 13px;
- pointer-events: none;
- }
- .dialog-footer {
- display: flex;
- justify-content: center;
- gap: 16px;
- padding-bottom: 4px;
- }
- </style>
- <style lang="scss">
- .select-location-dialog {
- .el-dialog__body {
- padding: 12px 20px 8px;
- }
- }
- </style>
|