272 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			272 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div class="AiDvMap" v-resize="onDomResize">
 | |
|     <div class="chart-map" ref="dvMap"/>
 | |
|     <div class="dialog" v-if="dialog" :style="dialogPos">
 | |
|       <div v-for="item in detail" :key="item.name" class="flex">
 | |
|         <div class="dot" :style="dotStyle(item.color)"/>
 | |
|         <div class="label fill" v-text="item.label"/>
 | |
|         <div v-text="item.value"/>
 | |
|       </div>
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import http from "dui/lib/js/request";
 | |
| import {mapState} from "vuex";
 | |
| 
 | |
| export default {
 | |
|   name: 'AiDvMap',
 | |
|   props: {
 | |
|     geoJson: String,
 | |
|     data: Array,
 | |
|     area: String
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       dialog: false,
 | |
|       chart: null,
 | |
|       detail: {},
 | |
|       dialogPos: {}
 | |
|     }
 | |
|   },
 | |
|   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())
 | |
|   },
 | |
|   watch: {
 | |
|     dialog(v) {
 | |
|       if (!v) {
 | |
|         this.detail = []
 | |
|         this.dialogPos = {}
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   methods: {
 | |
|     onDomResize() {
 | |
|       this.$nextTick(() => {
 | |
|         this.chart.resize()
 | |
|       })
 | |
|     },
 | |
|     initChart() {
 | |
|       const {echarts} = window
 | |
|       this.chart = echarts.init(this.$refs.dvMap)
 | |
|       this.getData(this.geoJson).then(res => {
 | |
|         if (res?.data) {
 | |
|           echarts.registerMap('customMap', res.data)
 | |
|           const option = {
 | |
|             geo: [
 | |
|               {
 | |
|                 map: "customMap",
 | |
|                 aspectScale: 1,
 | |
|                 zoom: 0.65,
 | |
|                 layoutCenter: ["50%", "50%"],
 | |
|                 layoutSize: "180%",
 | |
|                 show: true,
 | |
|                 roam: false,
 | |
|                 selectedMode: 'single',
 | |
|                 emphasis: {
 | |
|                   show: true,
 | |
|                   label: {
 | |
|                     textStyle: {
 | |
|                       color: "#FFFFFF"
 | |
|                     },
 | |
|                   },
 | |
|                   itemStyle: {
 | |
|                     areaColor: '#02C6DC'
 | |
|                   }
 | |
|                 },
 | |
|                 select: {
 | |
|                   label: {
 | |
|                     color: "#fff"
 | |
|                   },
 | |
|                   itemStyle: {
 | |
|                     areaColor: '#02bcff29'
 | |
|                   }
 | |
|                 },
 | |
|                 label: {
 | |
|                   show: true,
 | |
|                   color: '#fff',
 | |
|                   fontSize: 22
 | |
|                 },
 | |
|                 itemStyle: {
 | |
|                   borderColor: "rgba(2, 198, 220, 1)",
 | |
|                   borderWidth: 2,
 | |
|                   areaColor: "#02bcff29",
 | |
|                   shadowBlur: 120,
 | |
|                 }
 | |
|               },
 | |
|               // 重影
 | |
|               ...Array(3).fill(1).map((e, i) => {
 | |
|                 return {
 | |
|                   type: "map",
 | |
|                   map: "customMap",
 | |
|                   zlevel: -1,
 | |
|                   aspectScale: 1,
 | |
|                   zoom: 0.65,
 | |
|                   layoutCenter: ["50%", `${51 + i}%`],
 | |
|                   layoutSize: "180%",
 | |
|                   roam: false,
 | |
|                   silent: true,
 | |
|                   itemStyle: {
 | |
|                     normal: {
 | |
|                       borderWidth: 1,
 | |
|                       // borderColor:"rgba(17, 149, 216,0.6)",
 | |
|                       borderColor: `rgba(2, 198, 220, ${0.6 - i * 0.2})`,
 | |
|                       shadowColor: `rgba(2, 198, 220, ${0.6 - i * 0.2})`,
 | |
|                       shadowOffsetY: 5,
 | |
|                       shadowBlur: 15,
 | |
|                       areaColor: "transparent",
 | |
|                     },
 | |
|                   },
 | |
|                 }
 | |
|               })
 | |
|             ],
 | |
|             // geo3D: {
 | |
|             //   map: "customMap",
 | |
|             //   shading: 'color',
 | |
|             //   regionHeight: 8,
 | |
|             //   show: true,
 | |
|             //   emphasis: {
 | |
|             //     show: true,
 | |
|             //   },
 | |
|             //   label: {
 | |
|             //     show: true,
 | |
|             //     color: '#fff',
 | |
|             //     fontSize: 22
 | |
|             //   },
 | |
|             //   itemStyle: {
 | |
|             //     color: '#02bcff29',
 | |
|             //     borderColor: "rgba(2, 198, 220, 1)",
 | |
|             //     borderWidth: 2
 | |
|             //   },
 | |
|             //   viewControl: {
 | |
|             //     rotateSensitivity: 0,
 | |
|             //     zoomSensitivity: 0,
 | |
|             //     panMouseButton: 0,
 | |
|             //     distance: 250,
 | |
|             //     alpha:50,
 | |
|             //     center:[0,-60,0]
 | |
|             //   }
 | |
|             // },
 | |
|           }
 | |
|           this.chart.setOption(option)
 | |
|           this.chart.on('click', evt => {
 | |
|             const {name, event: {offsetX, offsetY}} = evt
 | |
|             this.dialog = true
 | |
|             this.detail = []
 | |
|             const item = this.data.find(e => e.name.includes(name))
 | |
|             for (const k in item) {
 | |
|               if ('name' != k) {
 | |
|                 this.detail.push({
 | |
|                   label: k, value: item[k], color: {
 | |
|                     高风险纠纷: "#FF6868",
 | |
|                     中风险纠纷: "#FFAB68",
 | |
|                     低风险纠纷: "#7FE89E",
 | |
|                   }[k]
 | |
|                 })
 | |
|               }
 | |
|             }
 | |
|             this.dialogPos = {left: offsetX + 'px', top: offsetY + 'px'}
 | |
|           })
 | |
|           this.chart.on('globalout', () => {
 | |
|             this.dialog = false
 | |
|           })
 | |
|         }
 | |
|       })
 | |
|     },
 | |
|     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)}`)
 | |
|     },
 | |
|     dotStyle(color) {
 | |
|       return {
 | |
|         background: color,
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| .AiDvMap {
 | |
|   display: flex;
 | |
|   align-items: center;
 | |
|   justify-content: center;
 | |
|   width: 100%;
 | |
|   height: 100%;
 | |
|   padding: 16px;
 | |
|   box-sizing: border-box;
 | |
|   position: relative;
 | |
| 
 | |
|   .chart-map {
 | |
|     width: 100%;
 | |
|     height: 100%;
 | |
|   }
 | |
| 
 | |
|   .dialog {
 | |
|     position: absolute;
 | |
|     transform: translate(-50%, -120%);
 | |
|     z-index: 20240327926;
 | |
|     padding: 16px 16px 24px;
 | |
|     background-color: rgba(9, 48, 69, 0.8);
 | |
|     backdrop-filter: blur(5px);
 | |
|     color: #fff;
 | |
|     font-size: 14px;
 | |
|     min-width: 200px;
 | |
|     border: 1px solid #02C6DC;
 | |
| 
 | |
|     &:after {
 | |
|       position: absolute;
 | |
|       bottom: 0;
 | |
|       left: 50%;
 | |
|       transform: translate(-50%, 50%) rotate(-135deg);
 | |
|       content: " ";
 | |
|       width: 10px;
 | |
|       height: 10px;
 | |
|       background: inherit;
 | |
|       border: inherit;
 | |
|       clip-path: polygon(0 0, 100% 0, 0 100%);
 | |
|     }
 | |
| 
 | |
|     .dot {
 | |
|       width: 14px;
 | |
|       height: 14px;
 | |
|       border-radius: 50%;
 | |
|       margin-right: 8px;
 | |
|       border: 3px solid rgba(9, 48, 69, .4);
 | |
|     }
 | |
| 
 | |
|     .label {
 | |
|       color: #9BB7D4;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </style>
 |