|
@@ -1,7 +1,21 @@
|
|
|
<template>
|
|
|
<div class="business">
|
|
|
- <ShipFilterCom class="ship-filter" :map="map" :mapFunc="mapFunc"/>
|
|
|
- <ShipInfoCom class="ship-info" :map="map" :mapFunc="mapFunc"/>
|
|
|
+ <ShipFilterCom class="ship-filter" :map="map" :mapFunc="mapFunc" @getShipFilter="handleShipFilter"/>
|
|
|
+ <TrackListCom class="track-list" :map="map" :mapFunc="mapFunc"/>
|
|
|
+ <div class="hover-info" ref="ref_shipHover">
|
|
|
+ <div class="hover-info-head">
|
|
|
+ <span>{{ shipHoverInfo?.isHistory ? '历史' : '实时'}}</span>
|
|
|
+ </div>
|
|
|
+ <div class="hover-info-close __hover" @click="shipHover.setPosition(undefined)">
|
|
|
+ <img src="@/components/easyMap/images/close.png" alt=""/>
|
|
|
+ </div>
|
|
|
+ <div class="hover-main" v-if="shipHoverInfo?.data">
|
|
|
+ <div class="hover-item">
|
|
|
+ <div class="hover-item-label">名称:</div>
|
|
|
+ <div class="hover-item-value">{{shipHoverInfo.data}}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -16,34 +30,414 @@ import {
|
|
|
getCurrentInstance,
|
|
|
ComponentInternalInstance,
|
|
|
toRefs,
|
|
|
- nextTick
|
|
|
+ nextTick, onUnmounted
|
|
|
} from 'vue'
|
|
|
import {useStore} from 'vuex'
|
|
|
import {useRouter, useRoute} from 'vue-router'
|
|
|
import {ElMessage, ElMessageBox} from "element-plus";
|
|
|
import ShipFilterCom from "./ship-filter.vue";
|
|
|
-import ShipInfoCom from "./ship-info.vue";
|
|
|
+import TrackListCom from "./track-list.vue";
|
|
|
+import * as source from "ol/source";
|
|
|
+import * as layer from "ol/layer";
|
|
|
+import ShipStyle from "@/views/ship-test/business/shipStyle";
|
|
|
+import * as format from "ol/format";
|
|
|
+import * as ol from "ol";
|
|
|
|
|
|
export default defineComponent({
|
|
|
name: '',
|
|
|
components: {
|
|
|
ShipFilterCom,
|
|
|
- ShipInfoCom
|
|
|
+ TrackListCom
|
|
|
},
|
|
|
props: {
|
|
|
- map: {},
|
|
|
- mapFunc: {},
|
|
|
+ map: <any>{},
|
|
|
+ mapFunc: <any>{},
|
|
|
},
|
|
|
setup(props, {emit}) {
|
|
|
const store = useStore();
|
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
|
const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
|
|
|
- const state = reactive({})
|
|
|
+ const state = reactive({
|
|
|
+ zoomWMS: true,
|
|
|
+ wsMap: new Map(),
|
|
|
+ wsLayer: <any>null,
|
|
|
+ shipFilter: {
|
|
|
+ cql: null,
|
|
|
+ config: <any>{}
|
|
|
+ },
|
|
|
+ trackMap: new Map(),
|
|
|
+ shipHover: <any>null,
|
|
|
+ shipHoverInfo: <any>{}
|
|
|
+ })
|
|
|
+ const ref_shipHover = ref()
|
|
|
+ const initMap = () => {
|
|
|
+ props.map?.on('moveend', (e) => {
|
|
|
+ const zoom = e.map.getView().getZoom()
|
|
|
+ if (zoom > 13) {
|
|
|
+ state.zoomWMS = false
|
|
|
+ initWebSocketShip()
|
|
|
+ } else {
|
|
|
+ state.zoomWMS = true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ props.map?.on('singleclick', (e) => {
|
|
|
+ if (!store.state.easyMap.isDrawing) {
|
|
|
+ let isFeature = false
|
|
|
+ e.map.forEachFeatureAtPixel(e.pixel, (f) => {
|
|
|
+ if (!isFeature) {
|
|
|
+ if (f.get('_trackId') && !state.trackMap.has(f.get('_trackId'))) {
|
|
|
+ isFeature = true
|
|
|
+ if (f.get('featureType') === 'ship') {
|
|
|
+ handleShipClick(f)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ hitTolerance: 0,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ props.map?.on('pointermove', (e) => {
|
|
|
+ if (!store.state.easyMap.isDrawing) {
|
|
|
+ let isFeature = false
|
|
|
+ e.map.forEachFeatureAtPixel(e.pixel, (f) => {
|
|
|
+ if (!isFeature) {
|
|
|
+ if (['ship', 'shipPoint'].includes(f.get('featureType'))) {
|
|
|
+ isFeature = true
|
|
|
+ state.shipHover.setPosition(f.getGeometry().getCoordinates())
|
|
|
+ state.shipHoverInfo = f.get('_hover')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ hitTolerance: 0,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ state.shipHover = new ol.Overlay({
|
|
|
+ id: 'shipHover',
|
|
|
+ element: ref_shipHover.value,
|
|
|
+ autoPan: false,
|
|
|
+ offset: [0, -30],
|
|
|
+ positioning: 'bottom-center',
|
|
|
+ stopEvent: true,
|
|
|
+ autoPanAnimation: {
|
|
|
+ duration: 250
|
|
|
+ }
|
|
|
+ })
|
|
|
+ props.map.addOverlay(state.shipHover)
|
|
|
+ }
|
|
|
+ const handleShipClick = (clickFeat) => {
|
|
|
+ const color = `rgb(${that.$util.randomNum(0, 255)}, ${that.$util.randomNum(0, 255)}, ${that.$util.randomNum(0, 255)})`
|
|
|
+ const trackLayer: any = new layer.VectorImage({
|
|
|
+ zIndex: 10
|
|
|
+ })
|
|
|
+ props.map.addLayer(trackLayer)
|
|
|
+ const trackId = clickFeat.get('_trackId')
|
|
|
+ const rWs = new WebSocket(clickFeat.get('_wsUrl'))
|
|
|
+ state.trackMap.set(trackId, {
|
|
|
+ color: color,
|
|
|
+ webSocket: rWs,
|
|
|
+ layer: trackLayer,
|
|
|
+ historyData: [],
|
|
|
+ realData: [],
|
|
|
+ sourceId: clickFeat.get('_sourceId')
|
|
|
+ })
|
|
|
+ initWebSocketShip()
|
|
|
+ const hWs = new WebSocket(clickFeat.get('_historyWsUrl'))
|
|
|
+ hWs.onopen = (e) => {
|
|
|
+ const str = {
|
|
|
+ ...clickFeat.get('_historyWsOtherParams'),
|
|
|
+ endTime: that.$util.YMDHms(new Date().getTime() + 1000 * 60 * 10),
|
|
|
+ shipId: trackId,
|
|
|
+ startTime: that.$util.YMDHms(new Date().getTime() - 1000 * 60 * 60 * 4)
|
|
|
+ }
|
|
|
+ hWs.send(JSON.stringify(str))
|
|
|
+ }
|
|
|
+ hWs.onmessage = (e) => {
|
|
|
+ try {
|
|
|
+ const json = JSON.parse(e.data)
|
|
|
+ const s = 'json' + clickFeat.get('_historyWsDataFlag')
|
|
|
+ const data = eval(s)
|
|
|
+ state.trackMap.get(trackId).historyData = data
|
|
|
+ } catch (e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rWs.onopen = (e) => {
|
|
|
+ const str = {
|
|
|
+ cql: `${clickFeat.get('_trackKey')} = '${trackId}'`
|
|
|
+ }
|
|
|
+ rWs.send(JSON.stringify(str))
|
|
|
+ }
|
|
|
+ rWs.onmessage = (e) => {
|
|
|
+ try {
|
|
|
+ const json = JSON.parse(e.data)
|
|
|
+ const s = 'json' + clickFeat.get('_wsDataFlag')
|
|
|
+ const data = eval(s)
|
|
|
+ const features: any = []
|
|
|
+ // 实时船舶
|
|
|
+ const DATA = data?.[0]
|
|
|
+ if (DATA) {
|
|
|
+ try {
|
|
|
+ const getKeyData = (key) => {
|
|
|
+ if (clickFeat.get(key)) {
|
|
|
+ return eval(clickFeat.get(key))
|
|
|
+ } else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const feat: any = new format.WKT().readFeature(getKeyData('trackWktKey'))
|
|
|
+ feat.set('featureType', 'ship')
|
|
|
+ feat.setId(getKeyData('trackPointKey'))
|
|
|
+ feat.set('_hover', {
|
|
|
+ data: DATA,
|
|
|
+ config: clickFeat.get('_config'),
|
|
|
+ isHistory: false
|
|
|
+ })
|
|
|
+ feat.setStyle(ShipStyle.ShipNormalStyle({
|
|
|
+ course: clickFeat.get('_course'),
|
|
|
+ speed: clickFeat.get('_speed'),
|
|
|
+ head: clickFeat.get('_head'),
|
|
|
+ color: color
|
|
|
+ }))
|
|
|
+ features.push(feat)
|
|
|
+ state.trackMap.get(trackId).realData.push(DATA)
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 轨迹线
|
|
|
+ const lineArr: any = []
|
|
|
+ state.trackMap.get(trackId).historyData.forEach(DATA => {
|
|
|
+ DATA.isHistory = true
|
|
|
+ const getKeyData = (key) => {
|
|
|
+ if (clickFeat.get(key)) {
|
|
|
+ return eval(clickFeat.get(key))
|
|
|
+ } else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lineArr.push(getKeyData('historyTrackWktKey'))
|
|
|
+ })
|
|
|
+ state.trackMap.get(trackId).realData.forEach(DATA => {
|
|
|
+ DATA.isHistory = false
|
|
|
+ const getKeyData = (key) => {
|
|
|
+ if (clickFeat.get(key)) {
|
|
|
+ return eval(clickFeat.get(key))
|
|
|
+ } else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lineArr.push(getKeyData('trackWktKey'))
|
|
|
+ })
|
|
|
+ if (lineArr.length > 0) {
|
|
|
+ const lineWkt = that.$easyMap.formatPosition.wptTwl(lineArr)
|
|
|
+ const feat: any = new format.WKT().readFeature(lineWkt)
|
|
|
+ feat.set('trackPointList', [...state.trackMap.get(trackId).historyData, ...state.trackMap.get(trackId).realData])
|
|
|
+ feat.set('featureType', 'shipTrack')
|
|
|
+ feat.setStyle((f, r) => ShipStyle.trackStyle(f, r, props.map, color, (s, pointList) => {
|
|
|
+ const pointFeatures: any = []
|
|
|
+ pointList.forEach(DATA => {
|
|
|
+ try {
|
|
|
+ const getKeyData = (key) => {
|
|
|
+ if (clickFeat.get(key)) {
|
|
|
+ return eval(clickFeat.get(key))
|
|
|
+ } else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const feat: any = new format.WKT().readFeature(DATA.isHistory ? getKeyData('historyTrackWktKey') : getKeyData('trackWktKey'))
|
|
|
+ feat.set('featureType', 'shipPoint')
|
|
|
+ feat.set('_hover', {
|
|
|
+ data: DATA,
|
|
|
+ config: clickFeat.get('_config'),
|
|
|
+ isHistory: DATA.isHistory
|
|
|
+ })
|
|
|
+ feat.setStyle(ShipStyle.trackPointNormalStyle(color))
|
|
|
+ pointFeatures.push(feat)
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ trackLayer.getSource().addFeatures(pointFeatures)
|
|
|
+ return s
|
|
|
+ }))
|
|
|
+ features.push(feat)
|
|
|
+ }
|
|
|
+ const vectorSource = new source.Vector({
|
|
|
+ features: features,
|
|
|
+ wrapX: false
|
|
|
+ });
|
|
|
+ trackLayer.setSource(vectorSource)
|
|
|
+ } catch (e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const handleShipFilter = ({cql, shipParams}) => {
|
|
|
+ state.shipFilter.cql = cql
|
|
|
+ state.shipFilter.config = shipParams
|
|
|
+ console.log(state.shipFilter.config)
|
|
|
+ refreshMap()
|
|
|
+ }
|
|
|
+ const refreshMap = () => {
|
|
|
+ if (state.shipFilter.config) {
|
|
|
+ if (state.zoomWMS) {
|
|
|
+ initWMSShip()
|
|
|
+ } else {
|
|
|
+ const hasLayer = props.map.getLayers().getArray().filter(v => v.get('layerName') === 'WMSShip')?.[0]
|
|
|
+ if (hasLayer) {
|
|
|
+ props.map.removeLayer(hasLayer)
|
|
|
+ }
|
|
|
+ initWebSocketShip()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const initWMSShip = () => {
|
|
|
+ if (state.wsLayer) {
|
|
|
+ state.wsLayer.getSource().clear()
|
|
|
+ }
|
|
|
+ for (let key of state.wsMap.keys()) {
|
|
|
+ state.wsMap.get(key).close()
|
|
|
+ state.wsMap.delete(key)
|
|
|
+ }
|
|
|
+ const hasLayer = props.map.getLayers().getArray().filter(v => v.get('layerName') === 'WMSShip')?.[0]
|
|
|
+ if (hasLayer) {
|
|
|
+ props.map.removeLayer(hasLayer)
|
|
|
+ }
|
|
|
+ const p:any = {
|
|
|
+ 'FORMAT': 'image/png8',
|
|
|
+ 'VERSION': '1.1.1',
|
|
|
+ "LAYERS": state.shipFilter.config.tileName,
|
|
|
+ "exceptions": 'application/vnd.ogc.se_inimage',
|
|
|
+ refresh: new Date().getTime()
|
|
|
+ }
|
|
|
+ if (state.shipFilter.cql) {
|
|
|
+ p.CQL_FILTER = state.shipFilter.cql
|
|
|
+ }
|
|
|
+ const _tileWMS = new source.TileWMS({
|
|
|
+ url: state.shipFilter.config.tileUrl,
|
|
|
+ params: p
|
|
|
+ })
|
|
|
+ const layerTile = new layer.Tile({
|
|
|
+ source: _tileWMS,
|
|
|
+ zIndex: 3,
|
|
|
+ })
|
|
|
+ layerTile.set('layerName', 'WMSShip')
|
|
|
+ props.map.addLayer(layerTile)
|
|
|
+ }
|
|
|
+ const initWebSocketShip = () => {
|
|
|
+ const str = {
|
|
|
+ cql: <any>null
|
|
|
+ }
|
|
|
+ str.cql = `(BBOX(location, ${props.mapFunc.getBBOX().join(',')}) and ${state.shipFilter.cql})`
|
|
|
+ let ids: any = []
|
|
|
+ state.trackMap.forEach((value, key) => {
|
|
|
+ if (value.sourceId === state.shipFilter.config.id) {
|
|
|
+ ids.push(`'${key}'`)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ if (ids.length > 0) {
|
|
|
+ str.cql += ` and (${state.shipFilter.config.track.trackKey.split('DATA.')[1]} not in (${ids.join(',')}))`
|
|
|
+ }
|
|
|
+ if (state.wsMap.has(state.shipFilter.config.id)) {
|
|
|
+ if (state.wsMap.get(state.shipFilter.config.id).readyState === 1) {
|
|
|
+ state.wsMap.get(state.shipFilter.config.id).send(JSON.stringify(str))
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ const ws = new WebSocket(state.shipFilter.config.wsUrl)
|
|
|
+ state.wsMap.set(state.shipFilter.config.id, ws)
|
|
|
+ ws.onopen = (e) => {
|
|
|
+ ws.send(JSON.stringify(str))
|
|
|
+ }
|
|
|
+ ws.onmessage = (e) => {
|
|
|
+ try {
|
|
|
+ const json = JSON.parse(e.data)
|
|
|
+ const s = 'json' + state.shipFilter.config.wsDataFlag
|
|
|
+ const data = eval(s)
|
|
|
+ initShip(data)
|
|
|
+ } catch (e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const initShip = (data) => {
|
|
|
+ if (!state.wsLayer) {
|
|
|
+ state.wsLayer = new layer.VectorImage({
|
|
|
+ zIndex: 10,
|
|
|
+ style: (f) => {
|
|
|
+ return ShipStyle.ShipNormalStyle({
|
|
|
+ course: f.get('_course'),
|
|
|
+ speed: f.get('_speed'),
|
|
|
+ head: f.get('_head')
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ state.wsLayer.set('layerName', 'WSShip')
|
|
|
+ props.map.addLayer(state.wsLayer)
|
|
|
+ }
|
|
|
+ const ships = data
|
|
|
+ // 动态拼接数据的唯一标识DATA,不可修改
|
|
|
+ const features = ships.map(DATA => {
|
|
|
+ try {
|
|
|
+ const getKeyData = (key) => {
|
|
|
+ if (state.shipFilter.config.track[key]) {
|
|
|
+ return eval(state.shipFilter.config.track[key])
|
|
|
+ } else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const feat: any = new format.WKT().readFeature(getKeyData('trackWktKey'))
|
|
|
+ feat.set('featureType', 'ship')
|
|
|
+ feat.setId(getKeyData('trackPointKey'))
|
|
|
+ feat.set('_trackId', getKeyData('trackKey'))
|
|
|
+ feat.set('_trackKey', state.shipFilter.config.track.trackKey.split('DATA.')[1])
|
|
|
+ feat.set('_course', getKeyData('trackCourseKey'))
|
|
|
+ feat.set('_speed', getKeyData('trackSpeedKey'))
|
|
|
+ feat.set('_head', getKeyData('trackDeadKey'))
|
|
|
+ feat.set('_wsDataFlag', state.shipFilter.config.wsDataFlag)
|
|
|
+ feat.set('_wsUrl', state.shipFilter.config.wsUrl)
|
|
|
+ feat.set('_sourceId', state.shipFilter.config.id)
|
|
|
+ feat.set('_historyWsUrl', state.shipFilter.config.historyWsUrl)
|
|
|
+ feat.set('_historyWsDataFlag', state.shipFilter.config.historyWsDataFlag)
|
|
|
+ feat.set('_historyWsOtherParams', JSON.parse(state.shipFilter.config.historyWsOtherParams))
|
|
|
+ feat.set('_config', state.shipFilter.config)
|
|
|
+ feat.set('_hover', {
|
|
|
+ data: DATA,
|
|
|
+ config: feat.get('_config'),
|
|
|
+ isHistory: false
|
|
|
+ })
|
|
|
+ for (let [key, value] of Object.entries(state.shipFilter.config.track)) {
|
|
|
+ feat.set(key, value)
|
|
|
+ }
|
|
|
+ return feat
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const vectorSource = new source.Vector({
|
|
|
+ features: features,
|
|
|
+ wrapX: false
|
|
|
+ });
|
|
|
+ state.wsLayer.setSource(vectorSource)
|
|
|
+ }
|
|
|
+ watch(() => state.zoomWMS, () => {
|
|
|
+ refreshMap()
|
|
|
+ })
|
|
|
onMounted(() => {
|
|
|
+ initMap()
|
|
|
+ })
|
|
|
+ onUnmounted(() => {
|
|
|
+ for (let key of state.wsMap.keys()) {
|
|
|
+ state.wsMap.get(key).close()
|
|
|
+ }
|
|
|
+ for (let key of state.trackMap.keys()) {
|
|
|
+ state.trackMap.get(key).webSocket.close()
|
|
|
+ }
|
|
|
})
|
|
|
return {
|
|
|
...toRefs(state),
|
|
|
+ ref_shipHover,
|
|
|
+ handleShipFilter
|
|
|
}
|
|
|
},
|
|
|
})
|
|
@@ -56,10 +450,89 @@ export default defineComponent({
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
}
|
|
|
- .ship-info {
|
|
|
+ .track-list {
|
|
|
position: fixed;
|
|
|
top: 0;
|
|
|
right: 0;
|
|
|
}
|
|
|
}
|
|
|
+.hover-info {
|
|
|
+ $footH: 10px;
|
|
|
+ width: 300px;
|
|
|
+ background: linear-gradient(180deg, #3874C9 0%, #0043C4 100%);
|
|
|
+ border-radius: 0px 4px 4px 4px;
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ &:after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ bottom: -$footH;
|
|
|
+ border-top: $footH solid #0043C4;
|
|
|
+ border-left: $footH solid transparent;
|
|
|
+ border-right: $footH solid transparent;
|
|
|
+ }
|
|
|
+ .hover-info-head {
|
|
|
+ min-width: 68px;
|
|
|
+ height: 18px;
|
|
|
+ position: absolute;
|
|
|
+ top: -18px;
|
|
|
+ left: 0;
|
|
|
+ font-size: 12px;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #FFFFFF;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ line-height: 8px;
|
|
|
+ &:before {
|
|
|
+ z-index: -1;
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(180deg, #3874C9 0%, #0043C4 100%);
|
|
|
+ border-radius: 2px 2px 0 0;/* 设置圆角 */
|
|
|
+ transform: perspective(20px)rotateX(4deg);
|
|
|
+ /* 镜头距离元素表面的位置为8px,x轴为1.1倍y轴为1.3倍,绕x轴旋转5度 */
|
|
|
+ transform-origin: bottom left;
|
|
|
+ /* bottom left = left bottom = 0 100% 中心点偏移量*/
|
|
|
+ }
|
|
|
+ >span {
|
|
|
+ margin-left: 10px;
|
|
|
+ }
|
|
|
+ >img {
|
|
|
+ margin: 0 4px 0 6px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .hover-info-close {
|
|
|
+ position: absolute;
|
|
|
+ right: 0;
|
|
|
+ top: -16px;
|
|
|
+ }
|
|
|
+ .hover-main {
|
|
|
+ width: 100%;
|
|
|
+ height: auto;
|
|
|
+ padding: 10px;
|
|
|
+ .hover-item {
|
|
|
+ display: flex;
|
|
|
+ .hover-item-label {
|
|
|
+ width: 42px;
|
|
|
+ font-size: 14px;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #08FFFF;
|
|
|
+ line-height: 20px;
|
|
|
+ }
|
|
|
+ .hover-item-value {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 14px;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #FFFFFF;
|
|
|
+ line-height: 20px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|