单独构建大屏ui库,避免引入混乱
This commit is contained in:
		
							
								
								
									
										270
									
								
								ui/dv/AiDvMap.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								ui/dv/AiDvMap.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,270 @@ | ||||
| <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 | ||||
|   }, | ||||
|   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> | ||||
		Reference in New Issue
	
	Block a user