|
|
@@ -10,22 +10,24 @@
|
|
|
<div class="stat-item">
|
|
|
<div class="stat-label">新安江流域平均降雨量</div>
|
|
|
<div class="stat-value-row">
|
|
|
- <span class="stat-value">累计降雨 <b>1393.4mm</b></span>
|
|
|
- <span class="stat-compare less">较多年平均 -3.20%</span>
|
|
|
+ <span class="stat-value">累计降雨 <b>{{ rainfallStat.drp }}mm</b></span>
|
|
|
+ <span class="stat-compare" :class="rainfallStat.drp > rainfallStat.dnpj ? 'more' : 'less'">
|
|
|
+ 较多年平均 {{ rainfallStat.dnpj > 0 ? ((rainfallStat.drp - rainfallStat.dnpj) / rainfallStat.dnpj * 100).toFixed(2) : 0 }}%
|
|
|
+ </span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="stat-item">
|
|
|
<div class="stat-label">新安江水库罗桐埠断面</div>
|
|
|
<div class="stat-value-row">
|
|
|
- <span class="stat-value">实际下泄量 <b>56.85亿m³</b></span>
|
|
|
- <span class="stat-compare">年度计划 <b>77.90亿m³</b></span>
|
|
|
+ <span class="stat-value">实际下泄量 <b>{{ luotongbuStat.ww.toFixed(2) }}亿m³</b></span>
|
|
|
+ <span class="stat-compare">年度计划 <b>{{ luotongbuStat.wwSchema.toFixed(2) }}亿m³</b></span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="stat-item">
|
|
|
<div class="stat-label">浙皖省界接口断面</div>
|
|
|
<div class="stat-value-row">
|
|
|
- <span class="stat-value">实际下泄量 <b>55.99亿m³</b></span>
|
|
|
- <span class="stat-compare more">年度计划 <b>42.00亿m³</b></span>
|
|
|
+ <span class="stat-value">实际下泄量 <b>{{ jiekouStat.ww.toFixed(2) }}亿m³</b></span>
|
|
|
+ <span class="stat-compare" :class="jiekouStat.ww > jiekouStat.wwSchema ? 'more' : 'less'">年度计划 <b>{{ jiekouStat.wwSchema.toFixed(2) }}亿m³</b></span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -79,10 +81,78 @@
|
|
|
</el-tab-pane>
|
|
|
|
|
|
<el-tab-pane label="开发利用情况" name="utilization">
|
|
|
- <div class="utilization-placeholder">
|
|
|
- <el-icon :size="48" color="#c0c4cc"><DataLine /></el-icon>
|
|
|
- <p>开发利用情况数据展示区域</p>
|
|
|
- <el-empty description="暂无开发利用数据" />
|
|
|
+ <div class="utilization-wrapper">
|
|
|
+ <div class="utilization-map-container" id="utilization-map"></div>
|
|
|
+
|
|
|
+ <!-- 开发利用统计面板 -->
|
|
|
+ <div class="stats-panel utilization-stats">
|
|
|
+ <div class="panel-title">开发利用统计情况</div>
|
|
|
+ <div class="stat-item">
|
|
|
+ <div class="stat-label">工业自备水源</div>
|
|
|
+ <div class="stat-value-row">
|
|
|
+ <span class="stat-value">个数 <b>{{ wiuSummary.industrial.cnt }}</b></span>
|
|
|
+ <span class="stat-compare">当年取水量 <b>{{ wiuSummary.industrial.ww.toFixed(2) }}万m³</b></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-item">
|
|
|
+ <div class="stat-label">公共供水企业</div>
|
|
|
+ <div class="stat-value-row">
|
|
|
+ <span class="stat-value">个数 <b>{{ wiuSummary.publicSupply.cnt }}</b></span>
|
|
|
+ <span class="stat-compare">当年取水量 <b>{{ wiuSummary.publicSupply.ww.toFixed(2) }}万m³</b></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-item">
|
|
|
+ <div class="stat-label">服务业自备水源</div>
|
|
|
+ <div class="stat-value-row">
|
|
|
+ <span class="stat-value">个数 <b>{{ wiuSummary.service.cnt }}</b></span>
|
|
|
+ <span class="stat-compare">当年取水量 <b>{{ wiuSummary.service.ww.toFixed(2) }}万m³</b></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-item" style="border-bottom: none;">
|
|
|
+ <div class="stat-label">合计</div>
|
|
|
+ <div class="stat-value-row">
|
|
|
+ <span class="stat-value">个数 <b>{{ wiuSummary.total.cnt }}</b></span>
|
|
|
+ <span class="stat-compare">当年取水量 <b>{{ wiuSummary.total.ww.toFixed(2) }}万m³</b></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 取水户图例 -->
|
|
|
+ <div class="legend-panel legend-left utilization-legend">
|
|
|
+ <div class="legend-title">取水户类型</div>
|
|
|
+ <div class="legend-item">
|
|
|
+ <span class="legend-dot" style="background: #e6a23c;"></span>
|
|
|
+ <span class="legend-text">工业自备水源</span>
|
|
|
+ </div>
|
|
|
+ <div class="legend-item">
|
|
|
+ <span class="legend-dot" style="background: #67c23a;"></span>
|
|
|
+ <span class="legend-text">公共供水企业</span>
|
|
|
+ </div>
|
|
|
+ <div class="legend-item">
|
|
|
+ <span class="legend-dot" style="background: #f56c6c;"></span>
|
|
|
+ <span class="legend-text">服务业自备水源</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 悬浮提示 -->
|
|
|
+ <div v-if="wiuTooltipData.visible" class="map-tooltip wiu-tooltip" :style="wiuTooltipStyle">
|
|
|
+ <!-- 区县悬浮 -->
|
|
|
+ <template v-if="wiuTooltipData.type === 'county'">
|
|
|
+ <div class="tooltip-title">{{ wiuTooltipData.name }}</div>
|
|
|
+ <div class="tooltip-row">工业自备水源:<b>{{ wiuTooltipData.industrial.cnt }}</b>个,取水量 <b>{{ wiuTooltipData.industrial.ww.toFixed(2) }}</b>万m³</div>
|
|
|
+ <div class="tooltip-row">公共供水企业:<b>{{ wiuTooltipData.publicSupply.cnt }}</b>个,取水量 <b>{{ wiuTooltipData.publicSupply.ww.toFixed(2) }}</b>万m³</div>
|
|
|
+ <div class="tooltip-row">服务业自备水源:<b>{{ wiuTooltipData.service.cnt }}</b>个,取水量 <b>{{ wiuTooltipData.service.ww.toFixed(2) }}</b>万m³</div>
|
|
|
+ <div class="tooltip-divider"></div>
|
|
|
+ <div class="tooltip-row">合计:<b>{{ wiuTooltipData.total.cnt }}</b>个,取水量 <b>{{ wiuTooltipData.total.ww.toFixed(2) }}</b>万m³</div>
|
|
|
+ </template>
|
|
|
+ <!-- 取水户悬浮 -->
|
|
|
+ <template v-if="wiuTooltipData.type === 'wiu'">
|
|
|
+ <div class="tooltip-title">{{ wiuTooltipData.name }}</div>
|
|
|
+ <div class="tooltip-row">社会信用代码:{{ wiuTooltipData.uscc }}</div>
|
|
|
+ <div class="tooltip-row">取水户类型:{{ wiuTooltipData.tradTp }}</div>
|
|
|
+ <div class="tooltip-row">区县:{{ wiuTooltipData.county }}</div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</el-tab-pane>
|
|
|
</el-tabs>
|
|
|
@@ -150,7 +220,8 @@ import * as echarts from 'echarts'
|
|
|
import { DataLine, Search, DataAnalysis } from '@element-plus/icons-vue'
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
import { xajfqGeoJson } from '@/assets/mapJSON/xajfq_geojson'
|
|
|
-import { listMapStations, getLatestData, listData } from '@/api/xajgl/station'
|
|
|
+import { xajCountyJson } from '@/assets/mapJSON/xaj_mapdata'
|
|
|
+import { listMapStations, getLatestData, getLatestDataByBiz, listData, getRainfallStat, getDischargeStat, getWiuCountyStat, getWiuList } from '@/api/xajgl/station'
|
|
|
|
|
|
const props = defineProps({
|
|
|
active: { type: Boolean, default: false }
|
|
|
@@ -161,6 +232,25 @@ const emit = defineEmits(['open-station-dialog'])
|
|
|
const activeTab = ref('situation')
|
|
|
const mapContainer = ref(null)
|
|
|
|
|
|
+// 降雨统计数据
|
|
|
+const rainfallStat = ref({
|
|
|
+ drp: 0,
|
|
|
+ dnpj: 0
|
|
|
+})
|
|
|
+
|
|
|
+// 断面下泄量统计数据
|
|
|
+const luotongbuStat = ref({
|
|
|
+ ww: 0,
|
|
|
+ dnww: 0,
|
|
|
+ wwSchema: 0
|
|
|
+})
|
|
|
+
|
|
|
+const jiekouStat = ref({
|
|
|
+ ww: 0,
|
|
|
+ dnww: 0,
|
|
|
+ wwSchema: 0
|
|
|
+})
|
|
|
+
|
|
|
// 历史数据弹框相关
|
|
|
const historyDialogVisible = ref(false)
|
|
|
const historyDialogTitle = ref('')
|
|
|
@@ -171,25 +261,50 @@ const currentStation = ref(null)
|
|
|
const historyChartRef = ref(null)
|
|
|
let historyChart = null
|
|
|
|
|
|
-// 站点类型对应的业务域配置
|
|
|
-const STATION_BIZ_CONFIG = {
|
|
|
- DRP: { bizCode: 'AH_SL_YL', columns: ['stnm', 'tm', 'drp', 'prov', 'city', 'county'], historyChart: ['drp'] },
|
|
|
- ZZ: { bizCode: 'AH_SL_JL', columns: ['stnm', 'tm', 'z', 'q', 'prov', 'city', 'county'], historyChart: ['z', 'q'] },
|
|
|
- DYP: { bizCode: 'AH_SL_ZF', columns: ['stnm', 'tm', 'dyp', 'prov', 'city', 'county'], historyChart: ['dyp'] },
|
|
|
- SK: { bizCode: 'FD_XAJ', columns: ['stnm', 'tm', 'z', 'dwz', 'inq', 'outq'], historyChart: ['z', 'inq', 'outq'] }
|
|
|
+// bizCode对应的列显示配置
|
|
|
+const BIZ_CODE_COLUMNS = {
|
|
|
+ 'AH_SL_YL': ['stnm', 'tm', 'drp'], // 安徽省雨量
|
|
|
+ 'ZJ_SL_YL': ['stnm', 'tm', 'drp'], // 浙江省雨量
|
|
|
+ 'AH_SL_JL': ['stnm', 'tm', 'z', 'q'], // 安徽省水文
|
|
|
+ 'ZJ_SL_JL': ['stnm', 'tm', 'z', 'q'], // 浙江省水文
|
|
|
+ 'TBA_SW_XAJ': ['stnm', 'tm', 'q'], // 太湖局水文
|
|
|
+ 'AH_SL_ZF': ['stnm', 'tm', 'dyp'], // 安徽省蒸发
|
|
|
+ 'DW_XAJ_ST': ['stnm', 'tm', 'z', 'inq', 'outq'], // 单位新安江站点
|
|
|
+ 'FD_XAJ': ['stnm', 'tm', 'z', 'dwz', 'inq', 'outq'], // 水库
|
|
|
+ 'HS_SK_XAJ': ['stnm', 'tm','ww'], // 黄山水库
|
|
|
+ 'CA_SK_XAJ': ['stnm', 'tm', 'ww'] // 常山水库
|
|
|
+}
|
|
|
+
|
|
|
+// bizCode对应的图表字段配置
|
|
|
+const BIZ_CODE_CHART = {
|
|
|
+ 'AH_SL_YL': ['drp'],
|
|
|
+ 'ZJ_SL_YL': ['drp'],
|
|
|
+ 'AH_SL_JL': ['z', 'q'],
|
|
|
+ 'ZJ_SL_JL': ['z', 'q'],
|
|
|
+ 'TBA_SW_XAJ': ['q'],
|
|
|
+ 'AH_SL_ZF': ['dyp'],
|
|
|
+ 'DW_XAJ_ST': ['z', 'inq', 'outq'],
|
|
|
+ 'FD_XAJ': ['z', 'dwz', 'inq', 'outq'],
|
|
|
+ 'HS_SK_XAJ': ['ww'],
|
|
|
+ 'CA_SK_XAJ': ['ww']
|
|
|
}
|
|
|
|
|
|
// 历史数据列配置
|
|
|
const historyColumns = [
|
|
|
- { prop: 'stnm', label: '站点名称', width: 150, fixed: 'left' },
|
|
|
- { prop: 'tm', label: '时间', width: 150, formatter: fmtDateTime },
|
|
|
- { prop: 'z', label: '水位(m)', width: 100 },
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 120, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '监测时间', width: 150, formatter: fmtDateTime },
|
|
|
+ { prop: 'z', label: '水位/坝上水位(m)', width: 140 },
|
|
|
{ prop: 'dwz', label: '坝下水位(m)', width: 110 },
|
|
|
- { prop: 'q', label: '流量(m³/s)', width: 110 },
|
|
|
+ { prop: 'q', label: '流量(m³/s)', width: 100 },
|
|
|
{ prop: 'inq', label: '入库流量(m³/s)', width: 120 },
|
|
|
{ prop: 'outq', label: '出库流量(m³/s)', width: 120 },
|
|
|
- { prop: 'drp', label: '降雨量(mm)', width: 110 },
|
|
|
- { prop: 'dyp', label: '蒸发量(mm)', width: 110 }
|
|
|
+ { prop: 'ww', label: '下泄水量(万m³)', width: 120 },
|
|
|
+ { prop: 'w', label: '蓄水量(万m³)', width: 110 },
|
|
|
+ { prop: 'drp', label: '降雨量(mm)', width: 100 },
|
|
|
+ { prop: 'dyp', label: '蒸发量(mm)', width: 100 },
|
|
|
+ { prop: 'prov', label: '省份', width: 80 },
|
|
|
+ { prop: 'city', label: '地市', width: 80 },
|
|
|
+ { prop: 'county', label: '区县', width: 80 }
|
|
|
]
|
|
|
|
|
|
const stationColorMap = {
|
|
|
@@ -221,8 +336,29 @@ let baseLayer = null
|
|
|
let labelLayer = null
|
|
|
let resizeObserver = null
|
|
|
let currentHoverStcd = null
|
|
|
+let countyLayer = null
|
|
|
+let wiuLayer = null
|
|
|
const currentLayer = ref('vec')
|
|
|
|
|
|
+// 开发利用相关状态
|
|
|
+const wiuCountyStats = ref([])
|
|
|
+const wiuList = ref([])
|
|
|
+const wiuTooltipData = reactive({
|
|
|
+ visible: false,
|
|
|
+ type: '', // 'county' 或 'wiu'
|
|
|
+ name: '',
|
|
|
+ // 区县悬浮信息
|
|
|
+ industrial: { cnt: 0, ww: 0 },
|
|
|
+ publicSupply: { cnt: 0, ww: 0 },
|
|
|
+ service: { cnt: 0, ww: 0 },
|
|
|
+ total: { cnt: 0, ww: 0 },
|
|
|
+ // 取水户悬浮信息
|
|
|
+ uscc: '',
|
|
|
+ tradTp: '',
|
|
|
+ county: ''
|
|
|
+})
|
|
|
+const wiuTooltipStyle = ref({})
|
|
|
+
|
|
|
// 天地图图层配置
|
|
|
const layerConfig = {
|
|
|
vec: {
|
|
|
@@ -317,11 +453,24 @@ function switchLayer(type) {
|
|
|
function loadAreaGeoJson() {
|
|
|
const source = areaLayer.getSource()
|
|
|
try {
|
|
|
+ // 处理GeoJSON数据,清理坐标中的多余维度(原数据有4个值,需要清理为2个值)
|
|
|
+ const geoJsonData = JSON.parse(JSON.stringify(xajfqGeoJson))
|
|
|
+ if (geoJsonData.features) {
|
|
|
+ geoJsonData.features.forEach(feature => {
|
|
|
+ if (feature.geometry && feature.geometry.coordinates) {
|
|
|
+ feature.geometry.coordinates = cleanCoordinates(feature.geometry.coordinates)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
const format = new GeoJSON()
|
|
|
- const features = format.readFeatures(xajfqGeoJson, {
|
|
|
- dataProjection: 'EPSG:4490',
|
|
|
+ const features = format.readFeatures(geoJsonData, {
|
|
|
+ dataProjection: 'EPSG:4326',
|
|
|
featureProjection: 'EPSG:3857'
|
|
|
})
|
|
|
+
|
|
|
+ console.log('加载子流域features数量:', features.length)
|
|
|
+
|
|
|
features.forEach(f => {
|
|
|
const name = f.get('name') || ''
|
|
|
f.setStyle(new Style({
|
|
|
@@ -342,6 +491,17 @@ function loadAreaGeoJson() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 清理坐标数据,移除多余维度
|
|
|
+function cleanCoordinates(coords) {
|
|
|
+ if (!Array.isArray(coords)) return coords
|
|
|
+ // 如果是坐标点 [lng, lat, ...],只保留前两个值
|
|
|
+ if (typeof coords[0] === 'number') {
|
|
|
+ return [coords[0], coords[1]]
|
|
|
+ }
|
|
|
+ // 如果是数组的数组,递归处理
|
|
|
+ return coords.map(item => cleanCoordinates(item))
|
|
|
+}
|
|
|
+
|
|
|
async function loadStations() {
|
|
|
try {
|
|
|
const res = await listMapStations()
|
|
|
@@ -349,6 +509,8 @@ async function loadStations() {
|
|
|
const rows = (res.rows || []).filter(s =>
|
|
|
['DRP', 'SK', 'ZZ', 'DYP'].includes(s.tp) && s.lgtd && s.lttd
|
|
|
)
|
|
|
+ // 批量获取所有站点的最新数据
|
|
|
+ await loadAllLatestData(rows)
|
|
|
renderStations(rows)
|
|
|
}
|
|
|
} catch (e) {
|
|
|
@@ -356,6 +518,88 @@ async function loadStations() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 批量加载所有站点的最新数据
|
|
|
+async function loadAllLatestData() {
|
|
|
+ try {
|
|
|
+ // 使用所有业务域编码获取最新数据(使用MAX方法)
|
|
|
+ const bizCodes = [
|
|
|
+ 'AH_SL_JL', // 安徽省水文
|
|
|
+ 'AH_SL_ZF', // 安徽省蒸发
|
|
|
+ 'ZJ_SL_JL', // 浙江省水文
|
|
|
+ 'TBA_SW_XAJ', // 太湖局水文
|
|
|
+ 'AH_SL_YL', // 安徽省雨量
|
|
|
+ 'ZJ_SL_YL', // 浙江省雨量
|
|
|
+ 'DW_XAJ_ST', // 单位新安江站点
|
|
|
+ 'FD_XAJ', // 水库
|
|
|
+ 'HS_SK_XAJ', // 黄山水库
|
|
|
+ 'CA_SK_XAJ' // 常山水库
|
|
|
+ ]
|
|
|
+ const promises = bizCodes.map(bizCode => getLatestDataByBiz(bizCode))
|
|
|
+ const results = await Promise.all(promises)
|
|
|
+
|
|
|
+ // 将结果存入缓存(同一站点可能有多个业务域的数据,保留最新的)
|
|
|
+ results.forEach(res => {
|
|
|
+ if (res.code === 200 && res.data) {
|
|
|
+ res.data.forEach(item => {
|
|
|
+ if (item.stcd) {
|
|
|
+ const existing = latestDataCache[item.stcd]
|
|
|
+ // 如果没有缓存或者新数据时间更新,则更新缓存
|
|
|
+ if (!existing || (item.tm && existing.tm && new Date(item.tm) > new Date(existing.tm))) {
|
|
|
+ latestDataCache[item.stcd] = item
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载最新数据失败', e)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 加载降雨统计数据
|
|
|
+async function loadRainfallStat() {
|
|
|
+ try {
|
|
|
+ const res = await getRainfallStat()
|
|
|
+ if (res.code === 200 && res.data) {
|
|
|
+ rainfallStat.value = {
|
|
|
+ drp: res.data.drp || 0,
|
|
|
+ dnpj: res.data.dnpj || 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载降雨统计数据失败', e)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 加载断面下泄量统计数据
|
|
|
+async function loadDischargeStats() {
|
|
|
+ try {
|
|
|
+ // 并行查询两个断面的数据
|
|
|
+ const [luotongbuRes, jiekouRes] = await Promise.all([
|
|
|
+ getDischargeStat('70112100'), // 罗桐埠断面
|
|
|
+ getDischargeStat('70111400') // 街口断面
|
|
|
+ ])
|
|
|
+
|
|
|
+ if (luotongbuRes.code === 200 && luotongbuRes.data) {
|
|
|
+ luotongbuStat.value = {
|
|
|
+ ww: luotongbuRes.data.ww || 0,
|
|
|
+ dnww: luotongbuRes.data.dnww || 0,
|
|
|
+ wwSchema: luotongbuRes.data.wwSchema || 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (jiekouRes.code === 200 && jiekouRes.data) {
|
|
|
+ jiekouStat.value = {
|
|
|
+ ww: jiekouRes.data.ww || 0,
|
|
|
+ dnww: jiekouRes.data.dnww || 0,
|
|
|
+ wwSchema: jiekouRes.data.wwSchema || 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载断面下泄量数据失败', e)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
function renderStations(stations) {
|
|
|
const source = stationLayer.getSource()
|
|
|
stations.forEach(station => {
|
|
|
@@ -369,18 +613,6 @@ function renderStations(stations) {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-async function getLatestDataWithCache(stcd) {
|
|
|
- if (latestDataCache[stcd]) return latestDataCache[stcd]
|
|
|
- try {
|
|
|
- const res = await getLatestData(stcd)
|
|
|
- const data = res.data && res.data.length > 0 ? res.data[0] : null
|
|
|
- latestDataCache[stcd] = data
|
|
|
- return data
|
|
|
- } catch (e) {
|
|
|
- return null
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
function buildLatestValues(tp, data) {
|
|
|
const values = []
|
|
|
if (tp === 'DRP') {
|
|
|
@@ -427,10 +659,12 @@ function formatDate(date) {
|
|
|
|
|
|
// 计算当前历史数据列配置
|
|
|
const currentHistoryColumns = computed(() => {
|
|
|
- if (!currentStation.value) return historyColumns
|
|
|
- const config = STATION_BIZ_CONFIG[currentStation.value.tp]
|
|
|
- if (!config) return historyColumns
|
|
|
- return historyColumns.filter(col => config.columns.includes(col.prop))
|
|
|
+ if (!currentStation.value) return historyColumns.slice(0, 2) // 至少显示站名和时间
|
|
|
+ const bizCode = currentStation.value.bizCode
|
|
|
+ if (!bizCode) return historyColumns.slice(0, 2)
|
|
|
+ const columns = BIZ_CODE_COLUMNS[bizCode]
|
|
|
+ if (!columns) return historyColumns.slice(0, 2)
|
|
|
+ return historyColumns.filter(col => columns.includes(col.prop))
|
|
|
})
|
|
|
|
|
|
function handleMapClick(event) {
|
|
|
@@ -456,7 +690,14 @@ function openHistoryDialog(station) {
|
|
|
historyDateRange.value = [formatDate(start), formatDate(end)]
|
|
|
historyData.value = []
|
|
|
historyDialogVisible.value = true
|
|
|
- loadHistoryData()
|
|
|
+ // 销毁旧的echart实例
|
|
|
+ if (historyChart) {
|
|
|
+ historyChart.dispose()
|
|
|
+ historyChart = null
|
|
|
+ }
|
|
|
+ nextTick(() => {
|
|
|
+ loadHistoryData()
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
// 加载历史数据
|
|
|
@@ -464,9 +705,10 @@ function loadHistoryData() {
|
|
|
if (!currentStation.value || !historyDateRange.value || historyDateRange.value.length !== 2) return
|
|
|
historyLoading.value = true
|
|
|
const [startTm, endTm] = historyDateRange.value
|
|
|
- const config = STATION_BIZ_CONFIG[currentStation.value.tp]
|
|
|
- const bizCode = config ? config.bizCode : null
|
|
|
- listData(currentStation.value.stcd, startTm, endTm, bizCode).then(res => {
|
|
|
+ // 从站点基础信息中获取stcd和bizCode
|
|
|
+ const stcd = currentStation.value.stcd
|
|
|
+ const bizCode = currentStation.value.bizCode || null
|
|
|
+ listData(stcd, startTm, endTm, bizCode).then(res => {
|
|
|
if (res.code === 200) {
|
|
|
historyData.value = res.data || []
|
|
|
} else {
|
|
|
@@ -480,9 +722,46 @@ function loadHistoryData() {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+// 字段类型分组:用于y轴分配
|
|
|
+const Y_AXIS_LEFT_FIELDS = ['z', 'dwz'] // 水位类,左y轴
|
|
|
+const Y_AXIS_RIGHT_FIELDS = ['q', 'inq', 'outq', 'ww', 'w', 'drp', 'dyp'] // 流量/水量/雨量类,右y轴
|
|
|
+
|
|
|
+// 水位类字段(使用折线图)
|
|
|
+const LINE_FIELDS = ['z', 'dwz']
|
|
|
+// 流量/水量类字段(使用柱状图)
|
|
|
+const BAR_FIELDS = ['q', 'inq', 'outq', 'ww', 'w', 'drp', 'dyp']
|
|
|
+
|
|
|
+// 获取字段的图表类型
|
|
|
+function getChartType(field) {
|
|
|
+ if (LINE_FIELDS.includes(field)) return 'line'
|
|
|
+ if (BAR_FIELDS.includes(field)) return 'bar'
|
|
|
+ return 'line'
|
|
|
+}
|
|
|
+
|
|
|
+// 获取字段的y轴索引
|
|
|
+function getYAxisIndex(field) {
|
|
|
+ if (Y_AXIS_LEFT_FIELDS.includes(field)) return 0
|
|
|
+ if (Y_AXIS_RIGHT_FIELDS.includes(field)) return 1
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+// 获取字段的单位
|
|
|
+function getFieldUnit(field) {
|
|
|
+ const units = {
|
|
|
+ 'z': 'm', 'dwz': 'm',
|
|
|
+ 'q': 'm³/s', 'inq': 'm³/s', 'outq': 'm³/s',
|
|
|
+ 'ww': '万m³', 'w': '万m³',
|
|
|
+ 'drp': 'mm', 'dyp': 'mm'
|
|
|
+ }
|
|
|
+ return units[field] || ''
|
|
|
+}
|
|
|
+
|
|
|
// 初始化历史数据图表
|
|
|
function initHistoryChart() {
|
|
|
- if (!historyChartRef.value) return
|
|
|
+ if (!historyChartRef.value) {
|
|
|
+ console.warn('historyChartRef is not ready')
|
|
|
+ return
|
|
|
+ }
|
|
|
if (!historyChart) {
|
|
|
historyChart = echarts.init(historyChartRef.value)
|
|
|
}
|
|
|
@@ -490,39 +769,94 @@ function initHistoryChart() {
|
|
|
historyChart.clear()
|
|
|
return
|
|
|
}
|
|
|
- const config = STATION_BIZ_CONFIG[currentStation.value.tp]
|
|
|
- if (!config || !config.historyChart || config.historyChart.length === 0) {
|
|
|
+ if (!currentStation.value) {
|
|
|
+ historyChart.clear()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const bizCode = currentStation.value.bizCode
|
|
|
+ if (!bizCode) {
|
|
|
historyChart.clear()
|
|
|
return
|
|
|
}
|
|
|
- const chartFields = config.historyChart
|
|
|
+ const chartFields = BIZ_CODE_CHART[bizCode]
|
|
|
+ if (!chartFields || chartFields.length === 0) {
|
|
|
+ historyChart.clear()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断是否需要双y轴
|
|
|
+ const hasLeftAxis = chartFields.some(f => Y_AXIS_LEFT_FIELDS.includes(f))
|
|
|
+ const hasRightAxis = chartFields.some(f => Y_AXIS_RIGHT_FIELDS.includes(f))
|
|
|
+ const useDualAxis = hasLeftAxis && hasRightAxis
|
|
|
+
|
|
|
const sortedData = [...historyData.value].sort((a, b) => new Date(a.tm) - new Date(b.tm))
|
|
|
const xData = sortedData.map(d => fmtDateTime(null, null, d.tm))
|
|
|
+
|
|
|
const series = chartFields.map(field => {
|
|
|
const col = historyColumns.find(c => c.prop === field)
|
|
|
- return {
|
|
|
+ const chartType = getChartType(field)
|
|
|
+ const baseConfig = {
|
|
|
name: col ? col.label : field,
|
|
|
- type: 'line',
|
|
|
- data: sortedData.map(d => d[field] ?? null),
|
|
|
- smooth: true,
|
|
|
- symbol: 'circle',
|
|
|
- symbolSize: 4,
|
|
|
- lineStyle: { width: 2 }
|
|
|
+ type: chartType,
|
|
|
+ yAxisIndex: useDualAxis ? getYAxisIndex(field) : 0,
|
|
|
+ data: sortedData.map(d => d[field] ?? null)
|
|
|
+ }
|
|
|
+ // 折线图额外配置
|
|
|
+ if (chartType === 'line') {
|
|
|
+ return {
|
|
|
+ ...baseConfig,
|
|
|
+ smooth: true,
|
|
|
+ symbol: 'circle',
|
|
|
+ symbolSize: 4,
|
|
|
+ lineStyle: { width: 2 }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 柱状图额外配置
|
|
|
+ return {
|
|
|
+ ...baseConfig,
|
|
|
+ barMaxWidth: 30
|
|
|
}
|
|
|
})
|
|
|
+
|
|
|
+ // 获取左右y轴的单位
|
|
|
+ const leftFields = chartFields.filter(f => Y_AXIS_LEFT_FIELDS.includes(f))
|
|
|
+ const rightFields = chartFields.filter(f => Y_AXIS_RIGHT_FIELDS.includes(f))
|
|
|
+ const leftUnit = leftFields.length > 0 ? getFieldUnit(leftFields[0]) : ''
|
|
|
+ const rightUnit = rightFields.length > 0 ? getFieldUnit(rightFields[0]) : ''
|
|
|
+
|
|
|
+ const yAxis = useDualAxis ? [
|
|
|
+ {
|
|
|
+ type: 'value',
|
|
|
+ position: 'left',
|
|
|
+ name: leftUnit,
|
|
|
+ axisLabel: { formatter: '{value}' }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'value',
|
|
|
+ position: 'right',
|
|
|
+ name: rightUnit,
|
|
|
+ axisLabel: { formatter: '{value}' }
|
|
|
+ }
|
|
|
+ ] : {
|
|
|
+ type: 'value',
|
|
|
+ name: getFieldUnit(chartFields[0]) || ''
|
|
|
+ }
|
|
|
+
|
|
|
const option = {
|
|
|
tooltip: { trigger: 'axis' },
|
|
|
legend: { data: series.map(s => s.name), bottom: 0 },
|
|
|
- grid: { left: '10%', right: '5%', top: '10%', bottom: '15%' },
|
|
|
+ grid: { left: '10%', right: '10%', top: '10%', bottom: '15%' },
|
|
|
xAxis: {
|
|
|
type: 'category',
|
|
|
data: xData,
|
|
|
axisLabel: { rotate: 30, fontSize: 11 }
|
|
|
},
|
|
|
- yAxis: { type: 'value' },
|
|
|
+ yAxis,
|
|
|
series
|
|
|
}
|
|
|
historyChart.setOption(option, true)
|
|
|
+ // 调整图表大小
|
|
|
+ historyChart.resize()
|
|
|
}
|
|
|
|
|
|
function handlePointerMove(event) {
|
|
|
@@ -545,11 +879,17 @@ function handlePointerMove(event) {
|
|
|
tooltipData.stnm = station.stnm
|
|
|
tooltipData.stcd = station.stcd
|
|
|
tooltipData.unit = station.unit || '-'
|
|
|
- tooltipData.tm = ''
|
|
|
- tooltipData.values = []
|
|
|
- tooltipData.loading = true
|
|
|
+ // 直接从缓存获取数据,不需要查询数据库
|
|
|
+ const data = latestDataCache[station.stcd]
|
|
|
+ if (data) {
|
|
|
+ tooltipData.tm = fmtDate(data.tm)
|
|
|
+ tooltipData.values = buildLatestValues(station.tp, data)
|
|
|
+ } else {
|
|
|
+ tooltipData.tm = '暂无数据'
|
|
|
+ tooltipData.values = []
|
|
|
+ }
|
|
|
+ tooltipData.loading = false
|
|
|
tooltipData.visible = true
|
|
|
- loadTooltipData(station)
|
|
|
} else {
|
|
|
tooltipData.visible = true
|
|
|
}
|
|
|
@@ -562,19 +902,6 @@ function handlePointerMove(event) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-async function loadTooltipData(station) {
|
|
|
- const data = await getLatestDataWithCache(station.stcd)
|
|
|
- if (currentHoverStcd !== station.stcd) return
|
|
|
- if (data) {
|
|
|
- tooltipData.tm = fmtDate(data.tm)
|
|
|
- tooltipData.values = buildLatestValues(station.tp, data)
|
|
|
- } else {
|
|
|
- tooltipData.tm = '暂无数据'
|
|
|
- tooltipData.values = []
|
|
|
- }
|
|
|
- tooltipData.loading = false
|
|
|
-}
|
|
|
-
|
|
|
onMounted(() => {
|
|
|
nextTick(() => {
|
|
|
if (mapContainer.value) initMap()
|
|
|
@@ -587,6 +914,10 @@ onMounted(() => {
|
|
|
resizeObserver.observe(mapContainer.value)
|
|
|
}
|
|
|
})
|
|
|
+ // 加载降雨统计数据
|
|
|
+ loadRainfallStat()
|
|
|
+ // 加载断面下泄量统计数据
|
|
|
+ loadDischargeStats()
|
|
|
})
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
@@ -609,7 +940,243 @@ watch(() => props.active, (val) => {
|
|
|
watch(activeTab, (val) => {
|
|
|
if (val === 'situation') {
|
|
|
nextTick(() => { if (olMap) olMap.updateSize() })
|
|
|
+ } else if (val === 'utilization') {
|
|
|
+ initUtilizationMap()
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// ============ 开发利用情况相关函数 ============
|
|
|
+
|
|
|
+// 初始化开发利用地图
|
|
|
+function initUtilizationMap() {
|
|
|
+ nextTick(async () => {
|
|
|
+ const container = document.getElementById('utilization-map')
|
|
|
+ if (!container) return
|
|
|
+ // 如果已经初始化过,更新尺寸
|
|
|
+ if (container._olMap) {
|
|
|
+ container._olMap.updateSize()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 创建新的地图实例
|
|
|
+ const utilBaseLayer = new TileLayer({ source: new XYZ({ url: layerConfig.vec.base }) })
|
|
|
+ const utilLabelLayer = new TileLayer({ source: new XYZ({ url: layerConfig.vec.label }) })
|
|
|
+
|
|
|
+ const utilMap = new OlMap({
|
|
|
+ target: container,
|
|
|
+ view: new View({
|
|
|
+ center: fromLonLat([119.05, 29.5]),
|
|
|
+ zoom: 9,
|
|
|
+ minZoom: 8,
|
|
|
+ maxZoom: 18
|
|
|
+ }),
|
|
|
+ layers: [utilBaseLayer, utilLabelLayer]
|
|
|
+ })
|
|
|
+ container._olMap = utilMap
|
|
|
+
|
|
|
+ // 加载区县图层
|
|
|
+ countyLayer = new VectorLayer({ source: new VectorSource() })
|
|
|
+ wiuLayer = new VectorLayer({ source: new VectorSource() })
|
|
|
+ utilMap.addLayer(countyLayer)
|
|
|
+ utilMap.addLayer(wiuLayer)
|
|
|
+
|
|
|
+ // 加载数据
|
|
|
+ await loadWiuData()
|
|
|
+ renderCountyLayer()
|
|
|
+ renderWiuLayer()
|
|
|
+
|
|
|
+ // 监听鼠标移动
|
|
|
+ utilMap.on('pointermove', handleWiuPointerMove)
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 加载取水户数据
|
|
|
+async function loadWiuData() {
|
|
|
+ try {
|
|
|
+ const [statRes, listRes] = await Promise.all([
|
|
|
+ getWiuCountyStat(),
|
|
|
+ getWiuList()
|
|
|
+ ])
|
|
|
+ if (statRes.code === 200) wiuCountyStats.value = statRes.data || []
|
|
|
+ if (listRes.code === 200) wiuList.value = listRes.data || []
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载取水户数据失败', e)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 渲染区县图层
|
|
|
+function renderCountyLayer() {
|
|
|
+ if (!countyLayer) return
|
|
|
+ const source = countyLayer.getSource()
|
|
|
+ source.clear()
|
|
|
+ try {
|
|
|
+ const geoJsonData = JSON.parse(JSON.stringify(xajCountyJson))
|
|
|
+ // 清理坐标
|
|
|
+ if (geoJsonData.features) {
|
|
|
+ geoJsonData.features.forEach(feature => {
|
|
|
+ if (feature.geometry && feature.geometry.coordinates) {
|
|
|
+ feature.geometry.coordinates = cleanCoordinates(feature.geometry.coordinates)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ const format = new GeoJSON()
|
|
|
+ const features = format.readFeatures(geoJsonData, {
|
|
|
+ dataProjection: 'EPSG:4326',
|
|
|
+ featureProjection: 'EPSG:3857'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 按区县统计数据
|
|
|
+ const statsMap = {}
|
|
|
+ wiuCountyStats.value.forEach(s => {
|
|
|
+ if (!statsMap[s.county]) {
|
|
|
+ statsMap[s.county] = { industrial: { cnt: 0, ww: 0 }, publicSupply: { cnt: 0, ww: 0 }, service: { cnt: 0, ww: 0 }, total: { cnt: 0, ww: 0 } }
|
|
|
+ }
|
|
|
+ const item = { cnt: s.cnt || 0, ww: Number(s.yearWw) || 0 }
|
|
|
+ statsMap[s.county].total.cnt += item.cnt
|
|
|
+ statsMap[s.county].total.ww += item.ww
|
|
|
+ if (s.tradTp === '1') statsMap[s.county].industrial = item
|
|
|
+ else if (s.tradTp === '2') statsMap[s.county].service = item
|
|
|
+ else if (s.tradTp === '3') statsMap[s.county].publicSupply = item
|
|
|
+ })
|
|
|
+
|
|
|
+ // 随机颜色数组
|
|
|
+ const colors = [
|
|
|
+ 'rgba(28, 151, 231, 0.25)', 'rgba(23, 194, 199, 0.25)', 'rgba(103, 194, 58, 0.25)',
|
|
|
+ 'rgba(230, 162, 60, 0.25)', 'rgba(245, 108, 108, 0.25)', 'rgba(144, 147, 153, 0.25)',
|
|
|
+ 'rgba(28, 109, 231, 0.25)', 'rgba(22, 174, 237, 0.25)'
|
|
|
+ ]
|
|
|
+
|
|
|
+ features.forEach((f, i) => {
|
|
|
+ const name = f.get('NAME99') || ''
|
|
|
+ f.set('_stats', statsMap[name] || null)
|
|
|
+ f.setStyle(new Style({
|
|
|
+ fill: new Fill({ color: colors[i % colors.length] }),
|
|
|
+ stroke: new Stroke({ color: 'rgba(28, 151, 231, 0.8)', width: 1.5 }),
|
|
|
+ text: name ? new TextStyle({
|
|
|
+ text: name,
|
|
|
+ font: 'bold 12px Microsoft YaHei',
|
|
|
+ fill: new Fill({ color: '#303133' }),
|
|
|
+ stroke: new Stroke({ color: '#fff', width: 3 }),
|
|
|
+ overflow: true
|
|
|
+ }) : undefined
|
|
|
+ }))
|
|
|
+ })
|
|
|
+ source.addFeatures(features)
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载区县GeoJSON失败', e)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 渲染取水户点位
|
|
|
+function renderWiuLayer() {
|
|
|
+ if (!wiuLayer) return
|
|
|
+ const source = wiuLayer.getSource()
|
|
|
+ source.clear()
|
|
|
+
|
|
|
+ const tradTpMap = { '1': '#e6a23c', '2': '#f56c6c', '3': '#67c23a' }
|
|
|
+
|
|
|
+ wiuList.value.forEach(wiu => {
|
|
|
+ if (!wiu.lgtd || !wiu.lttd) return
|
|
|
+ const coord = fromLonLat([Number(wiu.lgtd), Number(wiu.lttd)])
|
|
|
+ const feature = new Feature({
|
|
|
+ geometry: new Point(coord),
|
|
|
+ wiuData: wiu
|
|
|
+ })
|
|
|
+ const color = tradTpMap[wiu.tradTp] || '#1c97e7'
|
|
|
+ feature.setStyle(new Style({
|
|
|
+ image: new CircleStyle({
|
|
|
+ radius: 5,
|
|
|
+ fill: new Fill({ color }),
|
|
|
+ stroke: new Stroke({ color: '#fff', width: 1.5 })
|
|
|
+ })
|
|
|
+ }))
|
|
|
+ source.addFeature(feature)
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 处理开发利用地图鼠标移动
|
|
|
+function handleWiuPointerMove(e) {
|
|
|
+ const container = e.target.getTarget()
|
|
|
+ if (!container) return
|
|
|
+
|
|
|
+ const pixel = e.pixel
|
|
|
+ let found = false
|
|
|
+
|
|
|
+ // 先检查取水户点
|
|
|
+ e.target.forEachFeatureAtPixel(pixel, (feature) => {
|
|
|
+ if (found) return
|
|
|
+ const wiuData = feature.get('wiuData')
|
|
|
+ if (wiuData) {
|
|
|
+ found = true
|
|
|
+ const tradTpNames = { '1': '工业自备水源', '2': '服务业自备水源', '3': '公共供水企业' }
|
|
|
+ wiuTooltipData.visible = true
|
|
|
+ wiuTooltipData.type = 'wiu'
|
|
|
+ wiuTooltipData.name = wiuData.stnm || ''
|
|
|
+ wiuTooltipData.uscc = wiuData.uscc || '-'
|
|
|
+ wiuTooltipData.tradTp = tradTpNames[wiuData.tradTp] || wiuData.tradTp || '-'
|
|
|
+ wiuTooltipData.county = wiuData.county || '-'
|
|
|
+ wiuTooltipStyle.value = {
|
|
|
+ left: (pixel[0] + 15) + 'px',
|
|
|
+ top: (pixel[1] - 10) + 'px'
|
|
|
+ }
|
|
|
+ container.style.cursor = 'pointer'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 再检查区县面
|
|
|
+ if (!found) {
|
|
|
+ e.target.forEachFeatureAtPixel(pixel, (feature) => {
|
|
|
+ if (found) return
|
|
|
+ const name = feature.get('NAME99')
|
|
|
+ if (name) {
|
|
|
+ found = true
|
|
|
+ const stats = feature.get('_stats')
|
|
|
+ wiuTooltipData.visible = true
|
|
|
+ wiuTooltipData.type = 'county'
|
|
|
+ wiuTooltipData.name = name
|
|
|
+ if (stats) {
|
|
|
+ wiuTooltipData.industrial = stats.industrial
|
|
|
+ wiuTooltipData.publicSupply = stats.publicSupply
|
|
|
+ wiuTooltipData.service = stats.service
|
|
|
+ wiuTooltipData.total = stats.total
|
|
|
+ } else {
|
|
|
+ wiuTooltipData.industrial = { cnt: 0, ww: 0 }
|
|
|
+ wiuTooltipData.publicSupply = { cnt: 0, ww: 0 }
|
|
|
+ wiuTooltipData.service = { cnt: 0, ww: 0 }
|
|
|
+ wiuTooltipData.total = { cnt: 0, ww: 0 }
|
|
|
+ }
|
|
|
+ wiuTooltipStyle.value = {
|
|
|
+ left: (pixel[0] + 15) + 'px',
|
|
|
+ top: (pixel[1] - 10) + 'px'
|
|
|
+ }
|
|
|
+ container.style.cursor = 'pointer'
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!found) {
|
|
|
+ wiuTooltipData.visible = false
|
|
|
+ container.style.cursor = ''
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 计算开发利用统计汇总
|
|
|
+const wiuSummary = computed(() => {
|
|
|
+ const summary = {
|
|
|
+ industrial: { cnt: 0, ww: 0 },
|
|
|
+ publicSupply: { cnt: 0, ww: 0 },
|
|
|
+ service: { cnt: 0, ww: 0 },
|
|
|
+ total: { cnt: 0, ww: 0 }
|
|
|
}
|
|
|
+ wiuCountyStats.value.forEach(s => {
|
|
|
+ const cnt = s.cnt || 0
|
|
|
+ const ww = Number(s.yearWw) || 0
|
|
|
+ summary.total.cnt += cnt
|
|
|
+ summary.total.ww += ww
|
|
|
+ if (s.tradTp === '1') { summary.industrial.cnt += cnt; summary.industrial.ww += ww }
|
|
|
+ else if (s.tradTp === '2') { summary.service.cnt += cnt; summary.service.ww += ww }
|
|
|
+ else if (s.tradTp === '3') { summary.publicSupply.cnt += cnt; summary.publicSupply.ww += ww }
|
|
|
+ })
|
|
|
+ return summary
|
|
|
})
|
|
|
</script>
|
|
|
|
|
|
@@ -620,6 +1187,9 @@ watch(activeTab, (val) => {
|
|
|
flex-direction: column;
|
|
|
padding: 16px;
|
|
|
overflow: hidden;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ min-height: 0;
|
|
|
}
|
|
|
|
|
|
.xaj-tabs {
|
|
|
@@ -869,20 +1439,30 @@ watch(activeTab, (val) => {
|
|
|
font-style: italic;
|
|
|
}
|
|
|
|
|
|
-.utilization-placeholder {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
+.utilization-wrapper {
|
|
|
+ position: relative;
|
|
|
height: 100%;
|
|
|
- min-height: 400px;
|
|
|
- background: #fff;
|
|
|
border-radius: 8px;
|
|
|
+ overflow: hidden;
|
|
|
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
|
|
}
|
|
|
|
|
|
-.utilization-placeholder p {
|
|
|
- color: #909399;
|
|
|
- margin: 12px 0;
|
|
|
+.utilization-map-container {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ min-height: 500px;
|
|
|
+}
|
|
|
+
|
|
|
+.utilization-stats {
|
|
|
+ width: 300px;
|
|
|
+}
|
|
|
+
|
|
|
+.utilization-legend {
|
|
|
+ bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.wiu-tooltip {
|
|
|
+ min-width: 220px;
|
|
|
}
|
|
|
|
|
|
@media (max-width: 768px) {
|