mirror of
https://github.com/dataease/dataease.git
synced 2026-06-12 08:21:09 +08:00
feat(图表): 支持腾讯地图
This commit is contained in:
@@ -2064,7 +2064,8 @@ export default {
|
||||
map_type: 'Map Provider',
|
||||
map_type_gaode: 'Gaode Map',
|
||||
map_type_tianditu: 'Tianditu',
|
||||
map_type_baidu: 'Baidu Map'
|
||||
map_type_baidu: 'Baidu Map',
|
||||
map_type_tencent: 'QQ Map'
|
||||
},
|
||||
dataset: {
|
||||
field_value: 'Field Value',
|
||||
|
||||
@@ -2007,7 +2007,8 @@ export default {
|
||||
map_type: '地圖提供商',
|
||||
map_type_gaode: '高德地圖',
|
||||
map_type_tianditu: '天地圖',
|
||||
map_type_baidu: '百度地圖'
|
||||
map_type_baidu: '百度地圖',
|
||||
map_type_tencent: '騰訊地圖'
|
||||
},
|
||||
dataset: {
|
||||
field_value: '欄位值',
|
||||
|
||||
@@ -2013,7 +2013,8 @@ export default {
|
||||
map_type: '地图提供商',
|
||||
map_type_gaode: '高德地图',
|
||||
map_type_tianditu: '天地图',
|
||||
map_type_baidu: '百度地图'
|
||||
map_type_baidu: '百度地图',
|
||||
map_type_tencent: '腾讯地图'
|
||||
},
|
||||
dataset: {
|
||||
field_value: '字段值',
|
||||
|
||||
@@ -21,6 +21,7 @@ import { useMapStoreWithOut } from '@/store/modules/map'
|
||||
import { queryMapKeyApi } from '@/api/setting/sysParameter'
|
||||
import {
|
||||
gaodeMapStyleOptions,
|
||||
qqMapStyleOptions,
|
||||
tdtMapStyleOptions
|
||||
} from '@/views/chart/components/js/panel/charts/map/common'
|
||||
|
||||
@@ -292,6 +293,8 @@ const mapStyleOptions = computed(() => {
|
||||
switch (mapType.value) {
|
||||
case 'tianditu':
|
||||
return tdtMapStyleOptions
|
||||
case 'qq':
|
||||
return qqMapStyleOptions
|
||||
default:
|
||||
return gaodeMapStyleOptions
|
||||
}
|
||||
|
||||
@@ -72,6 +72,11 @@ export const tdtMapStyleOptions = [
|
||||
{ name: t('chart.map_style_darkblue'), value: 'indigo' }
|
||||
]
|
||||
|
||||
export const qqMapStyleOptions = [
|
||||
{ name: t('chart.map_style_normal'), value: 'normal' },
|
||||
{ name: t('commons.custom'), value: 'custom' }
|
||||
]
|
||||
|
||||
export declare type MapMouseEvent = MouseEvent & {
|
||||
feature: GeoJSON.Feature
|
||||
}
|
||||
|
||||
@@ -35,14 +35,16 @@ import type { Plot } from '@antv/g2plot'
|
||||
import type { PickOptions } from '@antv/g2plot/lib/core/plot'
|
||||
import { defaults, find } from 'lodash-es'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t: tI18n } = useI18n()
|
||||
import { isMobile } from '@/utils/utils'
|
||||
import { GaodeMap, TMap } from '@antv/l7-maps'
|
||||
import { GaodeMap, TMap, TencentMap } from '@antv/l7-maps'
|
||||
import {
|
||||
gaodeMapStyleOptions,
|
||||
qqMapStyleOptions,
|
||||
tdtMapStyleOptions
|
||||
} from '@/views/chart/components/js/panel/charts/map/common'
|
||||
|
||||
const { t: tI18n } = useI18n()
|
||||
|
||||
export function getPadding(chart: Chart): number[] {
|
||||
if (chart.drill) {
|
||||
return [0, 10, 22, 10]
|
||||
@@ -1242,38 +1244,55 @@ export function configL7Zoom(
|
||||
if (!scene?.getControlByName('zoom')) {
|
||||
if (!scene.map) {
|
||||
scene.once('loaded', () => {
|
||||
if (
|
||||
mapKey?.mapType === 'tianditu' &&
|
||||
scene.map?.defaultMapType?.name === 'TMAP_NORMAL_MAP'
|
||||
) {
|
||||
//天地图
|
||||
const initZoom = basicStyle.autoFit === false ? basicStyle.zoomLevel : scene.getZoom()
|
||||
const center =
|
||||
basicStyle.autoFit === false
|
||||
? [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude]
|
||||
: [scene.map.getCenter().getLng(), scene.map.getCenter().getLat()]
|
||||
const newZoomOptions = {
|
||||
initZoom: initZoom,
|
||||
center: center,
|
||||
buttonColor: basicStyle.zoomButtonColor,
|
||||
buttonBackground: basicStyle.zoomBackground
|
||||
} as any
|
||||
scene.addControl(new CustomZoom(newZoomOptions))
|
||||
} else {
|
||||
scene.map.on('complete', () => {
|
||||
const initZoom = basicStyle.autoFit === false ? basicStyle.zoomLevel : scene.getZoom()
|
||||
const center =
|
||||
basicStyle.autoFit === false
|
||||
? [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude]
|
||||
: [scene.map.getCenter().lng, scene.map.getCenter().lat]
|
||||
const newZoomOptions = {
|
||||
initZoom: initZoom,
|
||||
center: center,
|
||||
buttonColor: basicStyle.zoomButtonColor,
|
||||
buttonBackground: basicStyle.zoomBackground
|
||||
} as any
|
||||
scene.addControl(new CustomZoom(newZoomOptions))
|
||||
})
|
||||
switch (mapKey?.mapType) {
|
||||
case 'tianditu':
|
||||
//天地图
|
||||
{
|
||||
const initZoom = basicStyle.autoFit === false ? basicStyle.zoomLevel : scene.getZoom()
|
||||
const center =
|
||||
basicStyle.autoFit === false
|
||||
? [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude]
|
||||
: [scene.map.getCenter().getLng(), scene.map.getCenter().getLat()]
|
||||
const newZoomOptions = {
|
||||
initZoom: initZoom,
|
||||
center: center,
|
||||
buttonColor: basicStyle.zoomButtonColor,
|
||||
buttonBackground: basicStyle.zoomBackground
|
||||
} as any
|
||||
scene.addControl(new CustomZoom(newZoomOptions))
|
||||
}
|
||||
break
|
||||
case 'qq':
|
||||
{
|
||||
const initZoom = basicStyle.autoFit === false ? basicStyle.zoomLevel : scene.getZoom()
|
||||
const center =
|
||||
basicStyle.autoFit === false
|
||||
? [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude]
|
||||
: [scene.map.getCenter().lng, scene.map.getCenter().lat]
|
||||
const newZoomOptions = {
|
||||
initZoom: initZoom,
|
||||
center: center,
|
||||
buttonColor: basicStyle.zoomButtonColor,
|
||||
buttonBackground: basicStyle.zoomBackground
|
||||
} as any
|
||||
scene.addControl(new CustomZoom(newZoomOptions))
|
||||
}
|
||||
break
|
||||
default:
|
||||
scene.map.on('complete', () => {
|
||||
const initZoom = basicStyle.autoFit === false ? basicStyle.zoomLevel : scene.getZoom()
|
||||
const center =
|
||||
basicStyle.autoFit === false
|
||||
? [basicStyle.mapCenter.longitude, basicStyle.mapCenter.latitude]
|
||||
: [scene.map.getCenter().lng, scene.map.getCenter().lat]
|
||||
const newZoomOptions = {
|
||||
initZoom: initZoom,
|
||||
center: center,
|
||||
buttonColor: basicStyle.zoomButtonColor,
|
||||
buttonBackground: basicStyle.zoomBackground
|
||||
} as any
|
||||
scene.addControl(new CustomZoom(newZoomOptions))
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -1408,6 +1427,16 @@ export function getMapStyle(
|
||||
mapStyle = basicStyle.mapStyle
|
||||
}
|
||||
break
|
||||
case 'qq':
|
||||
if (
|
||||
!find(qqMapStyleOptions, s => s.value === basicStyle.mapStyle) ||
|
||||
basicStyle.mapStyle === 'normal'
|
||||
) {
|
||||
mapStyle = 'normal'
|
||||
} else {
|
||||
mapStyle = basicStyle.mapStyleUrl
|
||||
}
|
||||
break
|
||||
default:
|
||||
if (!find(gaodeMapStyleOptions, s => s.value === basicStyle.mapStyle)) {
|
||||
basicStyle.mapStyle = 'normal'
|
||||
@@ -1457,6 +1486,14 @@ export async function getMapScene(
|
||||
}
|
||||
|
||||
scene.map.showLabel = !(basicStyle.showLabel === false)
|
||||
if (mapKey.mapType === 'qq') {
|
||||
scene.map.setBaseMap({
|
||||
//底图设置(参数为:VectorBaseMap对象)
|
||||
type: 'vector', //类型:失量底图
|
||||
features: basicStyle.showLabel === false ? ['base', 'building2d'] : undefined
|
||||
//仅渲染:道路及底面(base) + 2d建筑物(building2d),以达到隐藏文字的效果
|
||||
})
|
||||
}
|
||||
}
|
||||
if (basicStyle.autoFit === false) {
|
||||
scene.setZoomAndCenter(basicStyle.zoomLevel, center)
|
||||
@@ -1465,6 +1502,15 @@ export async function getMapScene(
|
||||
mapRendering(container)
|
||||
scene.once('loaded', () => {
|
||||
mapRendered(container)
|
||||
if (mapKey.mapType === 'qq') {
|
||||
scene.map.setBaseMap({
|
||||
//底图设置(参数为:VectorBaseMap对象)
|
||||
type: 'vector', //类型:失量底图
|
||||
features: basicStyle.showLabel === false ? ['base', 'building2d'] : undefined
|
||||
//仅渲染:道路及底面(base) + 2d建筑物(building2d),以达到隐藏文字的效果
|
||||
})
|
||||
scene.setMapStyle(mapStyle)
|
||||
}
|
||||
// 去除天地图自己的缩放按钮
|
||||
if (mapKey.mapType === 'tianditu') {
|
||||
if (mapStyle === 'normal') {
|
||||
@@ -1526,6 +1572,18 @@ export function getMapObject(
|
||||
preserveDrawingBuffer: true
|
||||
}
|
||||
})
|
||||
case 'qq':
|
||||
return new TencentMap({
|
||||
token: mapKey?.key ?? undefined,
|
||||
style: mapStyle,
|
||||
pitch: miscStyle.mapPitch,
|
||||
center,
|
||||
zoom: basicStyle.autoFit === false ? basicStyle.zoomLevel : 12,
|
||||
showLabel: !(basicStyle.showLabel === false),
|
||||
WebGLParams: {
|
||||
preserveDrawingBuffer: true
|
||||
}
|
||||
})
|
||||
default:
|
||||
return new GaodeMap({
|
||||
token: mapKey?.key ?? undefined,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<el-option value="gaode" :label="t('chart.map_type_gaode')" />
|
||||
<el-option value="tianditu" :label="t('chart.map_type_tianditu')" />
|
||||
<!-- <el-option value="baidu" :label="t('chart.map_type_baidu')" />-->
|
||||
<el-option value="qq" :label="t('chart.map_type_tencent')" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="map-item">
|
||||
@@ -54,6 +55,11 @@
|
||||
v-if="!mapLoading && mapLoaded && mapEditor.key && mapEditor.mapType === 'tianditu'"
|
||||
:map-key="mapEditor.key"
|
||||
/>
|
||||
<OnlineMapQQ
|
||||
v-if="!mapLoading && mapLoaded && mapEditor.key && mapEditor.mapType === 'qq'"
|
||||
:map-key="mapEditor.key"
|
||||
:security-code="mapEditor.securityCode"
|
||||
/>
|
||||
<EmptyBackground
|
||||
v-if="!mapLoaded"
|
||||
img-type="noneWhite"
|
||||
@@ -71,6 +77,7 @@ import { ElMessage } from 'element-plus-secondary'
|
||||
import EmptyBackground from '@/components/empty-background/src/EmptyBackground.vue'
|
||||
import OnlineMapTdt from './OnlineMapTdt.vue'
|
||||
import OnlineMapGaode from './OnlineMapGaode.vue'
|
||||
import OnlineMapQQ from './OnlineMapQQ.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
const mapEditor = reactive({
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
|
||||
const domId = ref('de-map-container')
|
||||
const mapInstance = ref(null)
|
||||
const mapReloading = ref(false)
|
||||
|
||||
const props = defineProps<{
|
||||
mapKey: string
|
||||
securityCode?: string
|
||||
}>()
|
||||
|
||||
const loadMap = () => {
|
||||
if (!props.mapKey) {
|
||||
return
|
||||
}
|
||||
const mykey = props.mapKey
|
||||
const url = `https://map.qq.com/api/gljs?v=1.exp&key=${mykey}`
|
||||
|
||||
loadScript(url)
|
||||
.then(() => {
|
||||
if (mapInstance.value) {
|
||||
mapInstance.value?.destroy()
|
||||
mapInstance.value = null
|
||||
mapReloading.value = true
|
||||
setTimeout(() => {
|
||||
domId.value = domId.value + '-de-'
|
||||
mapReloading.value = false
|
||||
nextTick(() => {
|
||||
createMapInstance()
|
||||
})
|
||||
}, 1500)
|
||||
|
||||
return
|
||||
}
|
||||
createMapInstance()
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
if (mapInstance.value) {
|
||||
mapInstance.value.destroy()
|
||||
mapInstance.value = null
|
||||
}
|
||||
})
|
||||
}
|
||||
const createMapInstance = () => {
|
||||
if (window.TMap) {
|
||||
const center = new window.TMap.LatLng(39.90923, 116.397428)
|
||||
mapInstance.value = new window.TMap.Map(document.getElementById(domId.value), {
|
||||
viewMode: '2D',
|
||||
zoom: 11,
|
||||
center: center
|
||||
})
|
||||
mapInstance.value?.removeControl(window.TMap.constants.DEFAULT_CONTROL_ID.ZOOM)
|
||||
mapInstance.value?.removeControl(window.TMap.constants.DEFAULT_CONTROL_ID.ROTATION)
|
||||
mapInstance.value?.removeControl(window.TMap.constants.DEFAULT_CONTROL_ID.SCALE)
|
||||
}
|
||||
}
|
||||
const loadScript = (url: string) => {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const scriptId = 'de-qq-script-id'
|
||||
let dom = document.getElementById(scriptId)
|
||||
if (dom) {
|
||||
dom.parentElement?.removeChild(dom)
|
||||
dom = null
|
||||
window.TMap = null
|
||||
}
|
||||
const script = document.createElement('script')
|
||||
|
||||
script.id = scriptId
|
||||
script.onload = function () {
|
||||
return resolve(null)
|
||||
}
|
||||
script.onerror = function () {
|
||||
return reject(new Error('Load script from '.concat(url, ' failed')))
|
||||
}
|
||||
script.src = url
|
||||
const head = document.head || document.getElementsByTagName('head')[0]
|
||||
;(document.body || head).appendChild(script)
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadMap()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
const scriptId = 'de-qq-script-id'
|
||||
let dom = document.getElementById(scriptId)
|
||||
if (dom) {
|
||||
dom.parentElement?.removeChild(dom)
|
||||
dom = null
|
||||
window.TMap = null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="de-map-container" v-if="!mapReloading" :id="domId" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
.de-map-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
@@ -58,7 +58,7 @@ const createMapInstance = () => {
|
||||
}
|
||||
const loadScript = (url: string) => {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const scriptId = 'de-gaode-script-id'
|
||||
const scriptId = 'de-tdt-script-id'
|
||||
let dom = document.getElementById(scriptId)
|
||||
if (dom) {
|
||||
dom.parentElement?.removeChild(dom)
|
||||
@@ -84,7 +84,7 @@ onMounted(() => {
|
||||
loadMap()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
const scriptId = 'de-gaode-script-id'
|
||||
const scriptId = 'de-tdt-script-id'
|
||||
let dom = document.getElementById(scriptId)
|
||||
if (dom) {
|
||||
dom.parentElement?.removeChild(dom)
|
||||
|
||||
Reference in New Issue
Block a user