|
@@ -1,20 +1,225 @@
|
|
|
<template>
|
|
|
- <div class="main">
|
|
|
- asdasd
|
|
|
+ <div class="chart-main" ref="ref_main">
|
|
|
+ <div class="chart-ref" ref="ref_chart"/>
|
|
|
+ <div class="map-bg">
|
|
|
+ <img src="./map-bg.png"/>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import {getCurrentInstance, reactive} from "vue";
|
|
|
+import {getCurrentInstance, reactive, ref, onMounted, watch, nextTick} from "vue";
|
|
|
+import * as echarts from 'echarts';
|
|
|
+import mockData from './res.json'
|
|
|
+import {getCenter, getHainanMapJson} from "@/views/screen/components/map/tool";
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ data: {},
|
|
|
+})
|
|
|
|
|
|
const {proxy} = getCurrentInstance()
|
|
|
-const state: any = reactive({})
|
|
|
+const state = reactive({
|
|
|
+ resizeObserver: <any>null,
|
|
|
+ chart: <any>null
|
|
|
+})
|
|
|
+const ref_chart = ref();
|
|
|
+const ref_main = ref();
|
|
|
+const initChart = () => {
|
|
|
+ echarts.dispose(ref_chart.value)
|
|
|
+ const chart = echarts.init(ref_chart.value);
|
|
|
+ echarts.registerMap('海南', getHainanMapJson())
|
|
|
+ const _regions: any = []
|
|
|
+ mockData.data.forEach(v => {
|
|
|
+ const goodPer = Number(v.availability.replace('%', ''))
|
|
|
+ const obj = {
|
|
|
+ name: v.areacode,
|
|
|
+ itemStyle: {
|
|
|
+ borderWidth: 2,
|
|
|
+ borderColor: 'rgba(2, 162, 255, 1)'
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ label: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ borderWidth: 2,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (goodPer < 70) {
|
|
|
+ obj.emphasis.itemStyle.borderColor = 'rgba(255, 32, 69, 1)'
|
|
|
+ obj.emphasis.itemStyle.areaColor = 'rgba(255, 32, 69, 0.6)'
|
|
|
+ } else if (goodPer < 90) {
|
|
|
+ obj.emphasis.itemStyle.borderColor = 'rgba(255, 136, 20, 1)'
|
|
|
+ obj.emphasis.itemStyle.areaColor = 'rgba(255, 136, 20, 0.7)'
|
|
|
+ } else {
|
|
|
+ obj.emphasis.itemStyle.borderColor = 'rgba(55, 164, 230, 1)'
|
|
|
+ obj.emphasis.itemStyle.areaColor = 'rgba(55, 164, 230, 0.7)'
|
|
|
+ }
|
|
|
+ _regions.push(obj)
|
|
|
+ })
|
|
|
+ const option = {
|
|
|
+ geo: {
|
|
|
+ map: '海南',
|
|
|
+ aspectScale: 1,
|
|
|
+ itemStyle: {
|
|
|
+ borderWidth: 2,
|
|
|
+ borderColor: 'rgba(2, 162, 255, 1)',
|
|
|
+ areaColor: 'transparent',
|
|
|
+ },
|
|
|
+ regions: _regions,
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ "backgroundColor": "rgba(50,50,50,0.7)",
|
|
|
+ "borderColor": "#333",
|
|
|
+ "borderWidth": 0,
|
|
|
+ "padding": 0,
|
|
|
+ formatter: (p) => {
|
|
|
+ let h = [`<div style="background-color: rgba(0, 0, 0, 0.7);border: 2px solid ${Number(p.data.availability.replace('%', '')) < 70 ? 'rgba(255, 32, 69, 1)' : (Number(p.data.availability.replace('%', '')) < 90 ? 'rgba(255, 136, 20, 1)' : 'rgba(55, 164, 230, 1)')};">`, '', '</div>']
|
|
|
+ if (Number(p.data.availability.replace('%', '')) < 70) {
|
|
|
+ h[1] += `
|
|
|
+ <div style="background: linear-gradient(90deg, rgba(255, 32, 69, 1) 0%, rgba(255, 32, 69, 0) 100%);font-size: 16px;display: flex; align-items: center;padding: 7px 12px 8px 12px;color: #ffffff;">
|
|
|
+ <img src="./system/attachment/download/file?id=TJ7f383b9fd1e14345acabf03ee89fdb" style="margin-right: 7px;"/>
|
|
|
+ <span>完好率已低于70%!</span>
|
|
|
+ </div>
|
|
|
+ `
|
|
|
+ }
|
|
|
+ h[1] += `
|
|
|
+ <div style="display: grid;grid-template-columns: 1fr 1fr;color: #C4D1E6;padding: 12px 13px 10px 14px;grid-row-gap: 10px;grid-column-gap: 6px;line-height: 1;">
|
|
|
+ <div style="grid-column: 1/3;display: flex; align-items: end;font-size: 16px;">总数:<div style="margin-left: 4px;font-family: Bebas;color: #33dcfc;font-size: 20px;">${p.data['dev_amount']}</div></div>
|
|
|
+ <div style="font-size: 16px;">在线数:${p.data['online_amount']}</div>
|
|
|
+ <div style="font-size: 16px;">异常数:${p.data['abnormal']}</div>
|
|
|
+ <div style="font-size: 16px;">在线率:${p.data['online_rate']}</div>
|
|
|
+ <div style="font-size: 16px;">完好率:${p.data['availability']}</div>
|
|
|
+ </div>
|
|
|
+ `
|
|
|
+ return h.join('')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '海南地图',
|
|
|
+ type: 'map',
|
|
|
+ geoIndex: 0,
|
|
|
+ label: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ select: {
|
|
|
+ disabled: true
|
|
|
+ },
|
|
|
+ data: mockData.data.map(v => {
|
|
|
+ v.name = v.areacode
|
|
|
+ return v
|
|
|
+ })
|
|
|
+ },
|
|
|
+ {
|
|
|
+ geoIndex: 0,
|
|
|
+ name: "散点层",
|
|
|
+ label: {
|
|
|
+ "formatter": "{b}",
|
|
|
+ "fontSize": 20,
|
|
|
+ "fontWeight": "normal",
|
|
|
+ "color": "#fff",
|
|
|
+ "show": true,
|
|
|
+ "position": "right",
|
|
|
+ "alignTo": "none",
|
|
|
+ "edgeDistance": 20,
|
|
|
+ "overflow": "none",
|
|
|
+ "ellipsis": "...",
|
|
|
+ "distance": 5,
|
|
|
+ "offset": [
|
|
|
+ 0,
|
|
|
+ 0
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ "borderWidth": 0,
|
|
|
+ "borderType": "solid",
|
|
|
+ "shadowBlur": 0,
|
|
|
+ "shadowColor": "#000",
|
|
|
+ "borderRadius": [
|
|
|
+ 0,
|
|
|
+ 0,
|
|
|
+ 0,
|
|
|
+ 0
|
|
|
+ ],
|
|
|
+ "color": "rgba(244, 62, 17, 1)"
|
|
|
+ },
|
|
|
+ type: "scatter",
|
|
|
+ symbol: "arrow",
|
|
|
+ symbolSize: 40,
|
|
|
+ coordinateSystem: "geo",
|
|
|
+ "data": mockData.data.map(v => {
|
|
|
+ v.name = v.areacode
|
|
|
+ v.value = [...getCenter(v.name), Number(v.abnormal)]
|
|
|
+ const goodPer = Number(v.availability.replace('%', ''))
|
|
|
+ v.symbolSize = 20
|
|
|
+ if (goodPer < 70) {
|
|
|
+ v.itemStyle = {
|
|
|
+ color: 'rgba(255, 32, 69, 1)'
|
|
|
+ }
|
|
|
+ } else if (goodPer < 90) {
|
|
|
+ v.itemStyle = {
|
|
|
+ color: 'rgba(255, 136, 20, 1)'
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ v.itemStyle = {
|
|
|
+ color: 'rgba(87, 220, 255, 1)'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return v
|
|
|
+ })
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ chart.setOption(option);
|
|
|
+ state.resizeObserver = new ResizeObserver((entries) => {
|
|
|
+ for (const entry of entries) {
|
|
|
+ chart && chart.resize()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ state.resizeObserver.observe(ref_main.value);
|
|
|
+ return chart
|
|
|
+}
|
|
|
+watch(() => props.data, () => {
|
|
|
+ state.chart = initChart()
|
|
|
+})
|
|
|
+onMounted(() => {
|
|
|
+ nextTick(() => {
|
|
|
+ state.chart = initChart()
|
|
|
+ })
|
|
|
+ return () => {
|
|
|
+ state.resizeObserver?.unobserve(ref_main?.value)
|
|
|
+ state.resizeObserver?.disconnect()
|
|
|
+ }
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.main {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- background-color: #2E81FF;
|
|
|
+.chart-main {
|
|
|
+ margin: auto;
|
|
|
+ flex: 1;
|
|
|
+ width: 800px;
|
|
|
+ height: 800px;
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ .chart-ref {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ .map-bg {
|
|
|
+ position: absolute;
|
|
|
+ z-index: -1;
|
|
|
+ top: 107px;
|
|
|
+ left: 8px;
|
|
|
+ width: 781px;
|
|
|
+ height: 587px;
|
|
|
+ >img {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|