From 87e3d52c62233ad44bd7bac3f43e5348a2de4e94 Mon Sep 17 00:00:00 2001
From: luohairen <3399054449@qq.com>
Date: 星期一, 25 十一月 2024 10:36:16 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 src/views/components/Map/index.vue |  585 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 585 insertions(+), 0 deletions(-)

diff --git a/src/views/components/Map/index.vue b/src/views/components/Map/index.vue
new file mode 100644
index 0000000..38f61f6
--- /dev/null
+++ b/src/views/components/Map/index.vue
@@ -0,0 +1,585 @@
+<template>
+    <div :id="id" ref="contentRef" style="height: 100%; width: 100%">
+        <div
+            v-if="isShowControl"
+            :class="controlPosition"
+            class="control-container bottom-right"
+        >
+            <div
+                v-for="item in controlMapping"
+                :key="item.id"
+                class="control-content"
+            >
+                <template v-if="item.children">
+                    <div
+                        v-for="child in item.children"
+                        :key="child.id"
+                        class="control-item"
+                        @click="child.event"
+                    >
+                        <img :src="child.img" />
+                    </div>
+                </template>
+                <template v-else>
+                    <div class="control-item" @click="item.event">
+                        <img :src="item.img" />
+                    </div>
+                </template>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import Location from "@/assets/images/location.png";
+import FileImg from "@/assets/images/file1.png";
+import MinusImg from "@/assets/images/minus.png";
+import PlusImg from "@/assets/images/plus.png";
+import FullScreenImg from "@/assets/images/fullScreen.png";
+import PositionImg from "@/assets/images/position.png";
+export default {
+    data() {
+        return {
+            zoom: 15,
+            map: null,
+            contentRef: {},
+            infoWin: {},
+            defaultMaskInfo: {},
+            mapKey: "ffb871cd7ca48883db3b04cfd00d469f",
+            controlMapping: [
+                {
+                    id: "瀹氫綅",
+                    img: PositionImg,
+                    event: this.getCurrentPosition,
+                },
+                {
+                    id: "缂╂斁",
+                    children: [
+                        {
+                            id: "鏀惧ぇ",
+                            img: PlusImg,
+                            event: this.zoomIn,
+                        },
+                        {
+                            id: "缂╁皬",
+                            img: MinusImg,
+                            event: this.zoomOut,
+                        },
+                    ],
+                },
+                {
+                    id: "鍏ㄥ睆",
+                    img: FullScreenImg,
+                    event: this.fullScreen,
+                },
+            ],
+        };
+    },
+    props: {
+        id: String,
+        mapList: Array,
+        listType: Boolean,
+        isShowControl: Boolean,
+        controlPosition: Object,
+        isImmediateLoad: { type: Boolean, default: true },
+        mapType: Boolean,
+    },
+
+    created() {
+        this.defaultMaskInfo = {
+            lon: this.$props.mapList[0]?.lon
+                ? this.$props.mapList[0].lon
+                : "105.37281",
+            lat: this.$props.mapList[0]?.lat
+                ? this.$props.mapList[0].lat
+                : "30.87145",
+            name: this.$props.mapList[0]?.name ? this.$props.mapList[0].name : "鍒涘缓",
+        };
+        if (this.$props.isImmediateLoad) this.onLoad();
+    },
+    methods: {
+        async onLoad() {
+            const scripts = document.body.querySelectorAll("script");
+            if (!this.mapKey) {
+                // const res = await getDicts('map_key')
+                // mapKey = res[0].dictLabel
+                this.mapKey = "ffb871cd7ca48883db3b04cfd00d469f";
+            }
+
+            const scriptSrc = `http://api.tianditu.gov.cn/api?v=4.0&tk=${this.mapKey}`;
+            const mapScript = Array.from(scripts).find((item) => {
+                return item.getAttribute("src") === scriptSrc;
+            });
+
+            if (!mapScript) {
+                // 鍒涘缓script鏍囩
+                const script = document.createElement("script");
+                // 璁剧疆API鐨刄RL
+                script.src = scriptSrc;
+                script.type = "text/javascript";
+                // 灏唖cript鏍囩娣诲姞鍒癏TML涓�
+                document.body.appendChild(script);
+                script.onload = () => {
+                    this.initTianMap();
+                };
+            } else {
+                this.initTianMap();
+            }
+        },
+
+        initTianMap() {
+            var T = window.T;
+            setTimeout(async () => {
+                // this.map = new T.Map(this.id, {
+                //     projection: "EPSG:4326",
+                // });
+                this.map = new T.Map(this.id);
+                this.map.centerAndZoom(
+                    new T.LngLat(this.defaultMaskInfo.lon, this.defaultMaskInfo.lat),
+                    this.zoom
+                );
+                if (!this.$props.listType) {
+                    // 娓呴櫎涔嬪墠鐨勬爣璁�
+                    // map && map.clearOverLays()
+                    //form琛ㄥ崟涓槸鍚︽湁鍧愭爣锛屾湁鍒欏畾浣嶅埌瀵瑰簲浣嶇疆锛屾病鏈夊垯浣跨敤榛樿鐨�
+                    // 104.65417 28.75572 娴嬭瘯鏁版嵁
+                    // 鍥涘窛鐪佸疁瀹惧競缈犲睆鍖哄ぇ瑙傛ゼ琛楅亾澶栧崡琛�71
+                    if (this.$props.mapList[0].addr) {
+                        const { lng: lon, lat } = await this.getGeocode(
+                            this.$props.mapList[0].addr
+                        );
+                        this.defaultMaskInfo.lon = String(lon);
+                        this.defaultMaskInfo.lat = String(lat);
+                    }
+
+                    this.map && this.makeDefaultMask(this.defaultMaskInfo);
+                    this.addEvent(this.map, "click", (e) => this.mapClick(e));
+                } else {
+                    this.$props.mapList.length && this.makeAllMask(this.$props.mapList);
+                }
+            }, 1500);
+        },
+
+        zoomIn() {
+            this.map && this.map.zoomIn();
+        },
+
+        zoomOut() {
+            this.map && this.map.zoomOut();
+        },
+
+        fullScreen() {
+            this.map && this.contentRef?.requestFullscreen();
+        },
+
+        getCurrentPosition() {
+            if (navigator.geolocation) {
+                ElMessage.warning("璇ュ姛鑳芥殏鏈紑鍙�");
+                // TODO 鍦板浘瀹氫綅
+                // navigator.geolocation.getCurrentPosition(function (position) {
+                //   var latitude = position.coords.latitude
+                //   var longitude = position.coords.longitude
+                //
+                //   moveTo(String(longitude), String(latitude))
+                // })
+            } else {
+                ElMessage.warning("褰撳墠娴忚鍣ㄤ笉鏀寔瀹氫綅鍔熻兘");
+            }
+        },
+
+        moveTo(lon, lat) {
+            this.map && this.map.panTo(new T.LngLat(lon, lat));
+        },
+
+        // 榛樿鐨勭偣鏍囪
+        makeDefaultMask(mapInfo) {
+            const { name, lon, lat } = mapInfo
+            const option = {
+                text: name,
+                offset: [-35, -45],
+                labelBg: "#3369FF",
+                labelColor: "#fff",
+                labelClick,
+            };
+            // 娓呴櫎涔嬪墠鐨勬爣璁�
+            this.map && this.map.clearOverLays();
+            this.map.panTo(new T.LngLat(lon, lat));
+            this.makeMask(lon, lat, { labelOptions: option });
+        },
+
+        // 鍦板浘鐐瑰嚮浜嬩欢
+        mapClick(e) {
+            e.originalEvent.stopPropagation();
+
+            const { lat, lng: lon } = e.lnglat;
+
+            this.makeDefaultMask({
+                ...defaultMaskInfo,
+                lon: String(lon),
+                lat: String(lat),
+            });
+            this.getReverseGeocode(e).then((addr) => {
+                this.$emit("mapClick", { e, addr });
+            });
+            console.log("鐐瑰嚮浜嬩欢", e);
+        },
+
+        // 閫嗗湴鐞嗙紪鐮� 鑾峰彇鍦板潃
+        getReverseGeocode(e) {
+            return new Promise((resolve) => {
+                const geocode = new T.Geocoder();
+                geocode.getLocation(e.lnglat, (result) => {
+                    if (result.status === "0") {
+                        resolve(result.getAddress());
+                    }
+                });
+            });
+        },
+
+        // 鍦扮悊缂栫爜
+        getGeocode(addr) {
+            return new Promise((resolve) => {
+                const geocoder = new T.Geocoder();
+                geocoder.getPoint(addr, (result) => {
+                    if (result.status === "0") {
+                        resolve(result.getLocationPoint());
+                    }
+                });
+            });
+        },
+
+        // 鐢熸垚鐐逛綅鍐呭
+        // 鐢熸垚鐐逛綅鍐呭
+        generateContent(row, random) {
+            if (row) {
+                return `
+    <div class="map-window-info">
+      <div class='title-block'>
+        <div class="title truncate-content">
+          ${row.projectName ?? "鏆傛棤鏁版嵁"}
+        </div>
+        <div class='close-btn close-btn-${random}'>
+          脳
+        </div>
+      </div>
+      <div class="detail-info">
+        <span class="truncate-content">鎬绘姇璧勶細${row.totalMoney ?? "鏆傛棤鏁版嵁"
+                    }</span>
+        <span class="truncate-content">
+          椤圭洰鐘舵�侊細
+        </span>
+         <span class="truncate-content">
+          椤圭洰鍦板潃锛�${row.projectAddr ?? "鏆傛棤鏁版嵁"}
+        </span>
+      </div>
+    </div>`;
+            } else {
+                return `<div style="display: flex; justify-content:center; align-items:center; opacity: 0;">
+
+    </div>`;
+            }
+        },
+
+        // 鍞竴鏍囪瘑
+        getUniqueId() {
+            return Math.random().toString(36).substr(2) + Date.now();
+        },
+
+        markerMouseover(_e, infoWin, info, random) {
+            // 鐐逛綅鏍囪绉诲叆鏄剧ず涓嶅悓鍐呭
+            if (this.$props.isShowControl) {
+                infoWin.setContent(this.generateContent(info, random));
+                const contentWrapper = document.querySelector(
+                    ".tdt-infowindow-content-wrapper"
+                );
+                if (contentWrapper) {
+                    contentWrapper.style.opacity = "1";
+                }
+                // 鏌ユ壘鍒伴偅涓猧nfo 鐣岄潰
+                // const allCloseBtn = document.querySelectorAll(`.close-btn-${random}`);
+                // allCloseBtn[allCloseBtn.length - 1].onclick = (_e) => {
+                //   infoWin.setContent(generateContent());
+                // };
+            }
+        },
+
+        markerMouseout(_e, infoWin) {
+            infoWin.setContent(this.generateContent());
+            const contentWrapper = document.querySelector(
+                ".tdt-infowindow-content-wrapper"
+            );
+            if (contentWrapper) {
+                contentWrapper.style.opacity = "0";
+            }
+        },
+
+        // 鎵撴爣璁�
+        makeMask(lon, lat, options) {
+
+            const { markerOptions, labelOptions } = options;
+            console.log("options", markerOptions, labelOptions);
+            const icon = new T.Icon({
+                iconUrl: Location,
+                iconSize: new T.Point(19, 27),
+                iconAnchor: new T.Point(10, 25),
+            });
+            var marker = new T.Marker(new T.LngLat(lon, lat), {
+                icon,
+                id: markerOptions?.id,
+            });
+
+            this.map && this.map.addOverLay(marker);
+            const label = new T.Label({
+                text: labelOptions.text,
+                position: new T.LngLat(lon, lat),
+                offset: new T.Point(...labelOptions.offset),
+                id: labelOptions?.id,
+            });
+
+            labelOptions.labelBg && label.setBackgroundColor(labelOptions.labelBg);
+            labelOptions.labelColor && label.setFontColor(labelOptions.labelColor);
+            //鍒涘缓鍦板浘鏂囨湰瀵硅薄
+            if (!this.$props.mapType) {
+                this.map && this.map.addOverLay(label);
+            }
+            markerOptions?.markerClick &&
+                this.addEvent(marker, "click", (e) => markerOptions.markerClick(label, e));
+            labelOptions?.labelClick &&
+                this.addEvent(label, "click", (e) => labelOptions.labelClick(label, e));
+
+            const lnglat = new T.LngLat(lon, lat);
+            const infoWin = new T.InfoWindow(this.generateContent(), {
+                id: markerOptions?.id,
+                offset: new T.Point(0, -15),
+                closeButton: false,
+            });
+
+            infoWin.setLngLat(lnglat);
+            // 鍚戝湴鍥句笂娣诲姞淇℃伅绐楀彛
+            if (this.$props.mapType) {
+                this.map && this.map.addOverLay(infoWin);
+            }
+
+            this.addEvent(marker, "mouseover", (e) =>
+                markerMouseover(e, infoWin, labelOptions, getUniqueId())
+            );
+            this.addEvent(marker, "mouseout", (e) => markerMouseout(e, infoWin));
+        },
+
+        // 鏍囪鎵�鏈夌偣
+        makeAllMask(mapList) {
+            var _this = this;
+            this.mapList.map((item) => {
+                const config = {
+                    markerOptions: {
+                        id: item.id,
+                        markerClick: _this.markerClick,
+                    },
+                    labelOptions: {
+                        text: item.name,
+                        offset: [-45, -45],
+                        id: item.id,
+                        markerClick: _this.labelClick,
+                    },
+                };
+                _this.makeMask(item.lon, item.lat, config);
+            });
+        },
+
+        // 閫氱敤娣诲姞浜嬩欢鐨勬柟娉�
+        addEvent(component, name, func) {
+            // 绉诲嚭浜嬩欢
+            this.removeEvent(component, name, func);
+            // 娣诲姞浜嬩欢
+            component.addEventListener(name, func);
+        },
+
+        // 閫氱敤绉诲嚭浜嬩欢鐨勬柟娉�
+        removeEvent(component, name, func) {
+            component.removeEventListener(name, func);
+        },
+
+        //鏍囪鐐瑰嚮浜嬩欢
+        markerClick(currentLabel, e) {
+            const id = e.target.options.id;
+            currentLabelStyleChange(currentLabel);
+            console.log("鐐瑰嚮浜嬩欢", e, currentLabel);
+            this.getReverseGeocode(e).then((addr) => {
+                this.$emit(
+                    "markClick",
+                    id
+                        ? this.$props.mapList?.find((item) => item.id === id)
+                        : { e, addr: addr }
+                );
+            });
+        },
+
+        // label鐐瑰嚮浜嬩欢
+        labelClick(currentLabel, e) {
+            const id = e.target.options.id;
+            currentLabelStyleChange(currentLabel);
+            getReverseGeocode(e).then((addr) => {
+                this.$emit(
+                    "labelClick",
+                    id
+                        ? this.$props.mapList?.find((item) => {
+                            return String(item.id) === String(id);
+                        })
+                        : { e, addr: addr }
+                );
+            });
+        },
+
+        currentLabelStyleChange(currentLabel) {
+            this.$emit("currentLabelStyleChange", currentLabel);
+        },
+
+        resizeMap() {
+            this.map.checkResize();
+        },
+    },
+    watch: {
+        listType: {
+            handler(val) {
+                if (val) {
+                    this.map && this.map.clearOverLays();
+                    if (this.$props.mapList.length && T) {
+                        this.makeAllMask(this.$props.mapList);
+                    }
+                }
+            },
+        },
+    },
+    beforeUnmount() {
+        this.map = null;
+    },
+};
+
+// const emits = defineEmits<{
+//   (e: 'labelClick', value: any): void;
+//   (e: 'markClick', value: any): void;
+//   (e: 'mapClick', value: any): void;
+//   (e: 'currentLabelStyleChange', value: any): void;
+// }>();
+</script>
+<style lang="scss" scoped>
+:deep(.tdt-label) {
+    border-radius: 15px;
+    color: var(--el-color-primary);
+    cursor: pointer;
+}
+
+// #53547f
+:deep(.tdt-bar a, .tdt-bar a:hover) {
+    border-bottom: 0;
+    color: #53547f;
+}
+
+:deep(.tdt-touch .tdt-control-zoom-in) {
+    font-size: 18px;
+}
+
+:deep(.tdt-bar) {
+    border-radius: 3px;
+    box-shadow: 5px 0px 12px 0px rgb(0 0 0 / 0.03);
+}
+
+.tdt-bar a.tdt-disabled,
+.tdt-bar a:hover {
+    background-color: #f4f4f4;
+}
+
+.control-container {
+    position: absolute;
+    display: flex;
+    flex-direction: column;
+    gap: 10px;
+    z-index: 999;
+}
+
+.top-left {
+    top: 10px;
+    left: 10px;
+}
+
+.top-right {
+    top: 10px;
+    right: 10px;
+}
+
+.bottom-left {
+    bottom: 10px;
+    left: 10px;
+}
+
+.bottom-right {
+    bottom: 10px;
+    right: 10px;
+}
+
+.control-content {
+    border-radius: 3px;
+    box-shadow: 5px 0px 12px 0px rgb(0 0 0 / 0.03);
+    background-color: #fff;
+}
+
+.control-item {
+    box-sizing: border-box;
+    width: 30px;
+    height: 30px;
+    line-height: 28px;
+    padding: 0 9px;
+
+    img {
+        display: inline-block;
+    }
+}
+
+.control-item:hover {
+    background-color: #f4f4f4;
+}
+</style>
+<style lang="scss">
+.map-window-info {
+    padding: 0 20px;
+    width: 300px;
+    cursor: default;
+
+    .title {
+        color: #3369ff;
+        font-size: 18px;
+        margin-bottom: 13px;
+    }
+
+    .detail-info {
+        display: flex;
+        flex-direction: column;
+        color: #7e809c;
+        font-size: 12px;
+        gap: 8px;
+    }
+}
+
+.title-block {
+    display: flex;
+    justify-content: space-between;
+
+    .close-btn {
+        font-size: 18px;
+        color: #d8dde6;
+        cursor: pointer;
+        z-index: 999999;
+    }
+}
+
+//.tdt-control-copyright {
+//  display: none;
+//}
+
+.tdt-infowindow-tip-container {
+    opacity: 0;
+}
+
+.tdt-infowindow-content-wrapper {
+    opacity: 0;
+}
+</style>

--
Gitblit v1.8.0