Files
dvcp_v2_webapp/ui/packages/tools/AiEchartMap.vue
2024-09-19 14:50:31 +08:00

144 lines
3.8 KiB
Vue

<template>
<div class="AiEchartMap" v-resize="onDomResize">
<div class="chart-map" ref="dvMap"/>
</div>
</template>
<script>
import http from "dui/lib/js/request";
import {mapState} from "vuex";
import "../../lib/cdn/turf.min.js";
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])
},
initChart() {
const {echarts, turf} = window
this.chart = echarts.init(this.$refs.dvMap)
this.chart.showLoading({
text: "数据加载中...", textColor: "#fff",
maskColor: 'rgba(0, 0, 0, 0.2)'
})
this.loadLibs().then(() => {
const geoJson = this.geo
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}
}
],
},
}
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
}
})
}
assign(option, this.ops)
this.chart.setOption(option)
}).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>