148 lines
3.8 KiB
Vue
148 lines
3.8 KiB
Vue
<template>
|
|
<div class="AiEchartMap" v-resize="onDomResize">
|
|
<div class="chart-map" ref="dvMap"/>
|
|
<slot v-if="$slots.default"/>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import http from "dui/lib/js/request";
|
|
import {mapState} from "vuex";
|
|
import "../../lib/cdn/turf.min.js";
|
|
|
|
const assign = (target, source = {}) => {
|
|
Object.entries(source).forEach(([key, value]) => {
|
|
if (typeof value === 'object') {
|
|
if (target[key] && typeof target[key] === 'object') {
|
|
assign(target[key], value)
|
|
} else {
|
|
target[key] = value
|
|
}
|
|
} else {
|
|
target[key] = value
|
|
}
|
|
})
|
|
}
|
|
export default {
|
|
name: 'AiEchartMap',
|
|
props: {
|
|
geoJson: {type: [String, Object]},
|
|
data: Array,
|
|
ops: Object
|
|
},
|
|
data() {
|
|
return {
|
|
chart: null,
|
|
geo: null
|
|
}
|
|
},
|
|
directives: {
|
|
resize: {
|
|
bind(el, binding) {
|
|
let width = ''
|
|
let height = ''
|
|
|
|
function isResize() {
|
|
const style = document.defaultView.getComputedStyle(el)
|
|
if (width !== style.width || height !== style.height) {
|
|
binding.value({
|
|
width: style.width,
|
|
height: style.height
|
|
})
|
|
}
|
|
width = style.width
|
|
height = style.height
|
|
}
|
|
|
|
el.__vueSetInterval__ = setInterval(isResize, 300)
|
|
},
|
|
unbind(el) {
|
|
clearInterval(el.__vueSetInterval__)
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
...mapState(['user'])
|
|
},
|
|
mounted() {
|
|
this.$load(this.$refs.dvMap).then(() => this.initChart())
|
|
},
|
|
methods: {
|
|
onDomResize() {
|
|
this.$nextTick(() => {
|
|
this.chart.resize()
|
|
})
|
|
},
|
|
loadLibs() {
|
|
let getGeo
|
|
if (typeof this.geoJson === 'string') {
|
|
getGeo = this.getData(this.geoJson).then(res => this.geo = res?.data)
|
|
} else if (typeof this.geoJson === 'object') {
|
|
getGeo = Promise.resolve(this.geo = this.$copy(this.geoJson))
|
|
}
|
|
return Promise.all([getGeo])
|
|
},
|
|
handleMapOps(geoJson, ops) {
|
|
const {echarts, turf} = window
|
|
const boundary = geoJson.features?.length > 1 ? turf.union(geoJson) : this.$copy(geoJson.features[0])
|
|
boundary.properties = {...boundary.properties}
|
|
boundary.properties.name = "boundary"
|
|
geoJson.features.unshift(boundary)
|
|
echarts.registerMap('customMap', geoJson)
|
|
const option = {
|
|
geo: {
|
|
map: 'customMap', roam: true, emphasis: {disabled: true},
|
|
itemStyle: {areaColor: "transparent", borderColor: '#97CAE6'},
|
|
silent: true,
|
|
label: {show: true, color: '#fff'},
|
|
regions: [
|
|
{
|
|
name: "boundary", itemStyle: {
|
|
areaColor: "rgba(2,188,255,0.16)", shadowColor: "#02F0FF21", shadowOffsetY: 20, shadowBlur: 20,
|
|
borderColor: '#02F0FF', borderWidth: 3
|
|
}, label: {show: false}
|
|
}
|
|
],
|
|
},
|
|
}
|
|
assign(option, ops)
|
|
return option
|
|
},
|
|
initChart() {
|
|
const {echarts} = window
|
|
this.chart = echarts.init(this.$refs.dvMap)
|
|
this.chart.showLoading({
|
|
text: "数据加载中...", textColor: "#fff",
|
|
maskColor: 'rgba(0, 0, 0, 0.2)'
|
|
})
|
|
this.loadLibs().then(() => {
|
|
this.chart.setOption(this.handleMapOps(this.geo, this.ops))
|
|
}).finally(() => {
|
|
this.$emit('map', this.chart)
|
|
this.chart.hideLoading()
|
|
})
|
|
},
|
|
getData(url = `https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=${this.user.info.areaId?.substring(0, 6)}`) {
|
|
return http.post(`/app/appdvcpconfig/apiForward?url=${encodeURIComponent(url)}`)
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.AiEchartMap {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
height: 100%;
|
|
box-sizing: border-box;
|
|
position: relative;
|
|
|
|
.chart-map {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
</style>
|