123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- <template>
- <div class="search-layout">
- <el-input
- v-model="keyword"
- :placeholder="$t('sceneHome.nameSearch')"
- style="width: 350px"
- clearable
- @change="onSearch"
- >
- <template #append>
- <el-button @click="onSearch(keyword)" :icon="Search" />
- </template>
- </el-input>
- <div class="rrr">
- <div class="search-result" v-show="keyword">
- <div
- class="search-list"
- v-for="(item, index) in keywordList"
- @click="hanleItem(item)"
- >
- {{ item.name||item.formatted_address }}
- </div>
- <div v-if="issearch && keywordList && keywordList.length == 0" class="noData search-list">{{$t('sys.unSearchData')}}</div>
- </div>
- <!-- <div class="search-sh" v-show="keyword">
- <el-button style="width: 100%" @click="showSearch = !showSearch">
- {{ showSearch ? "收起" : "展开" }}搜索结果
- </el-button>
- </div> -->
- </div>
- </div>
- <div class="def-select-map-layout">
- <div class="def-select-map" id="mapEl" ref="mapEl"></div>
- </div>
- <div class="def-map-info" v-if="searchInfo">
- <p><span>{{$t('coord.lat')}}</span>{{ searchInfo.lat }}</p>
- <p><span>{{$t('coord.lng')}}</span>{{ searchInfo.lng }}</p>
- <!-- <p><span>缩放级别</span>{{ info.zoom }}</p> -->
- </div>
- </template>
- <script setup lang="ts">
- import AMapLoader from "@amap/amap-jsapi-loader";
- import { Search } from "@element-plus/icons-vue";
- import { wgs84_to_gcj02 } from "./map";
- import { getTipsList, getGaoDeGaoDeList, getTipsNames, getCaseInfo } from "@/store/case";
- import { ref, watchEffect, onMounted, computed } from "vue";
- import { QuiskExpose } from "@/helper/mount";
- import { ElMessage, ElMessageBox, genFileId } from "element-plus";
- import { ui18n } from "@/i18n";
- import { debounce } from "@/util";
- import html2canvas from "html2canvas";
- import L from "leaflet";
- import "./leaflet.ChineseTmsProviders.js";
- import "leaflet/dist/leaflet.css";
- import { router } from "@/router";
- export type MapImage = { blob: Blob | null; search: MapInfo | null };
- type MapInfo = {
- lat: number;
- lng: number;
- zoom: number;
- text: string;
- address: string;
- id: string;
- };
- // const layer = L.tileLayer('http://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}')
- // const layer = L.tileLayer("http://a.map.jms.gd/tile/osm/{z}/{x}/{y}.png");
- // const layer = L.tileLayer('http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=6&x={x}&y={y}&z={z}&token=YOUR_API_KEY')
- var normalMap = L.tileLayer.chinaProvider("Google.Normal.Map", {
- maxZoom: 18,
- minZoom: 5,
- });
- var Gaode = L.tileLayer.chinaProvider("GaoDe.Normal.Map", {
- maxZoom: 18,
- minZoom: 5,
- });
- var baseLayers = {
- [ui18n.t("coord.edit.gmap")]: Gaode,
- };
- let map: any = {};
- const issearch = ref(false);
- let clickMarker;
- const keyword = ref("");
- const showSearch = ref(true);
- const isGoogle = ref(true);
- const info = ref<MapInfo>();
- const caseInfoData = ref<any>(null);
- const searchInfo = ref<MapInfo>();
- const mapEl = ref<HTMLDivElement>();
- const keywordList = ref([]);
- watchEffect(() => {
- if (keyword.value) {
- showSearch.value = true;
- }
- });
- const caseId = computed(() => {
- const caseId = router.currentRoute.value.params.caseId;
- if (caseId) {
- return Number(caseId);
- }
- });
- function detectProxy() {
- return new Promise(resolve => {
- const img = new Image();
- img.onload = () => resolve(false);
- img.onerror = () => resolve(true);
- img.src = `https://www.google.com/images/searchbox/desktop_searchbox_sprites318_hr.webp?t=${Date.now()}`;
- // 设置超时
- setTimeout(() => resolve(true), 1000);
- });
- }
- onMounted(async () => {
- isGoogle.value = await detectProxy();
- if(!isGoogle.value){
- baseLayers[ui18n.t("coord.edit.ggmap")] = normalMap
- }
- caseInfoData.value = await getCaseInfo(caseId.value);
- let center = [22.363947, 113.598948];
- if (caseInfoData.value?.latAndLong) {
- center = caseInfoData.value.latAndLong.split(",");
- }
- console.log("caseInfoData", caseInfoData.value.latAndLong, center);
- // 'map'为HTML节点id
- map = L.map(mapEl.value, {
- center: center, //中心坐标
- zoom: 14, //缩放级别
- zoomControl: true, //缩放组件
- attributionControl: false, //去掉右下角logol
- layers: [Gaode], //图层
- // center: [51.505, -0.09],
- // zoom: 13
- });
- if (caseInfoData.value?.latAndLong) {
- clickMarker = L.marker([center[0], center[1]], {
- position: [center[0], center[1]],
- title: "点击位置",
- });
- clickMarker.addTo(map);
- }
- console.log("baseLayers", baseLayers);
- L.control.layers(baseLayers, null).addTo(map);
- map.on("click", async function (e) {
- // 获取点击位置的经纬度坐标
- console.log("click", e);
- var latitude = e.latlng.lat;
- var longitude = e.latlng.lng;
- console.log("click", e, [longitude, latitude]);
- let ress = await getGaoDeGaoDeList(`${longitude},${latitude}`, 2)
- let data = ress.data && JSON.parse(ress.data) || {};
- console.log("click",data, ress);
- let formatted_address = data.regeocode && data.regeocode.formatted_address || "";
- searchInfo.value = {
- text: formatted_address.length ? formatted_address : "",
- lat: latitude,
- lng: longitude,
- zoom: 0,
- };
- clickMarker && clickMarker.remove();
- clickMarker = null;
- // 在地图上添加标记
- clickMarker = L.marker([latitude, longitude], {
- position: [latitude, longitude],
- title: "点击位置",
- });
- clickMarker.addTo(map);
- map.panTo([latitude, longitude]);
- // map.add(clickMarker);
- });
- });
- const resultEl = ref<HTMLDivElement>();
- const searchAMap = ref<any>();
- watchEffect(async (onCleanup) => {
- if (!mapEl.value || !resultEl.value) {
- return;
- }
- //绑定地图移动与缩放事件
- map.on("moveend", () => {
- info.value = getMapInfo();
- });
- map.on("zoomend", () => {
- info.value = getMapInfo();
- });
- searchAMap.value = placeSearch;
- onCleanup(() => {
- searchAMap.value = null;
- map.destroy();
- });
- });
- const placeSearch = async () => {
- // let res = await
- }
- const getMapInfo = (): MapInfo => {
- var zoom = map.getZoom(); //获取当前地图级别
- var center = map.getCenter();
- return {
- text: "",
- zoom,
- lat: center.lat,
- lng: center.lng,
- };
- };
- const onSearch = (val) => {
- issearch.value = true;
- getGaoDeGaoDeList(val).then((res) => {
- let data = res.data && JSON.parse(res.data);
- keywordList.value = data.pois;
- keyword.value = val;
- console.log("getTipsList",data, keywordList.value, keyword.value);
- // if(data && data.geocodes && data.geocodes.length > 0) {
- // let item = data.geocodes[0].location.split(",");
- // console.log("item", item);
- // // 在地图上添加标记
- // clickMarker = L.marker([item[1], item[0]], {
- // position: [item[1], item[0]],
- // title: "点击位置",
- // // icon,
- // });
- // clickMarker.addTo(map);
- // map.panTo([item[1], item[0]]);
- // }
- }).catch((err) => {
- ElMessage.error(ui18n.t("err.disconnect"));
- });
- console.log("onSearch", val, "keyword.value", keyword.value);
- };
- const hanleItem = async (item) => {
- let res = item
- console.log("hanleItem", item);
- if(item.location) {
- res.lng = item.location.split(",")[0];
- res.lat = item.location.split(",")[1];
- res.name = res.name || item.formatted_address
- }else{
- let ress = await getTipsNames(item.name);
- res = ress.data;
- }
- keyword.value = "";
- searchInfo.value = {
- ...res,
- text: res.name,
- };
- clickMarker && clickMarker.remove();
- // let icon = L.icon({
- // iconUrl: require('./icon.svg'),
- // iconSize: [25, 30],
- // iconAnchor: [12, 30]
- // });
- clickMarker = null;
- // 在地图上添加标记
- clickMarker = L.marker([res.lat, res.lng], {
- position: [res.lat, res.lng],
- title: "点击位置",
- // icon,
- });
- clickMarker.addTo(map);
- map.panTo([res.lat, res.lng]);
- // keyword.value = item.name;
- // getTipsNames(name).then((ress) => {
- // let res = ress.data;
- // // longlat = wgs84_to_gcj02(Number(res.lng),Number(res.lat))
-
- // });
- // onSearch(item.name);
- };
- var dataURLtoBlob = function (dataurl) {
- var arr = dataurl.split(","),
- mime = arr[0].match(/:(.*?);/)[1],
- bstr = atob(arr[1]),
- n = bstr.length,
- u8arr = new Uint8Array(n);
- while (n--) {
- u8arr[n] = bstr.charCodeAt(n);
- }
- return new Blob([u8arr], { type: mime });
- };
- const search = debounce((keyword: string) => {
- searchAMap.value.search(keyword);
- }, 1000);
- watchEffect(() => {
- searchAMap.value && search(keyword.value);
- });
- defineExpose<QuiskExpose>({
- submit() {
- return new Promise<MapImage>((resolve) => {
- console.log("searchInfo", searchInfo.value, mapEl.value);
- if (mapEl.value) {
- const canvas = mapEl.value.querySelector("canvas") as HTMLCanvasElement;
- console.log(canvas, "canvas");
- canvas &&
- canvas.toBlob((blob) => resolve({ blob, search: searchInfo.value! })); // || resolve({ search: searchInfo.value! });
- if (!canvas) {
- //div内容生成图片
- html2canvas(mapEl.value, {
- useCORS: true, // 添加这个选项以解决跨域问题
- }).then((canvas) => {
- let imgUrl = canvas.toDataURL("image/png");
- let blob = dataURLtoBlob(imgUrl);
- resolve({ blob, search: searchInfo.value! });
- });
- }
- } else {
- resolve({ blob: null, search: null });
- }
- });
- },
- });
- </script>
- <style lang="scss" scoped>
- .search-layout {
- display: inline-block;
- position: relative;
- margin-bottom: 15px;
- z-index: 2;
- }
- .rrr {
- position: absolute;
- left: 0;
- right: 0;
- z-index: 1;
- }
- .search-sh,
- .search-result {
- overflow: hidden;
- &.show {
- max-height: 450px;
- overflow-y: auto;
- }
- .search-list {
- background: #1B1B1C;
- padding-left: 10px;
- line-height: 36px;
- cursor: pointer;
- }
- }
- .def-map-info {
- margin-top: 10px;
- p {
- font-size: 14px;
- color: rgba(0, 0, 0, 0.85);
- display: inline;
- &:not(:last-child)::after {
- content: ",";
- margin-right: 6px;
- }
- }
- span::after {
- content: ":";
- }
- }
- .def-select-map-layout {
- --scale: 1.5;
- width: 100%;
- padding-top: calc((390 / 540) * 100%);
- position: relative;
- z-index: 1;
- }
- .def-select-map {
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- }
- </style>
|