WholeProcessPlatform/frontend/src/modules/monthlyAvgWaterTemCompareHistory/TwoLayers/monthlyAverageMaxModal.vue

1045 lines
33 KiB
Vue
Raw Normal View History

2026-05-28 08:36:32 +08:00
<template>
<div class="water-temp-compare-modal">
<!-- 搜索区域 -->
<a-row>
<a-col>
<a-form-item label="测站选择">
<a-tree-select
v-model:value="selectValue"
v-model:tree-expanded-keys="treeExpandedKeys"
:tree-data="processedSelectOptions"
placeholder="请选择测站"
style="width: 200px;margin-right: 10px;"
:loading="loading"
@change="handleSelectChange"
:field-names="{ label: 'title', value: 'value', children: 'children' }"
tree-node-filter-prop="title"
show-search
popup-class-name="no-wrap-tree-select"
@select="handleTreeSelect" />
</a-form-item>
</a-col>
<a-col>
<a-form-item label="日期选择">
<a-month-picker
v-model:value="dateValue"
format="YYYY-MM"
placeholder="请选择月份"
style="width: 200px;margin-right: 10px;"
@change="handleDateChange"
:disabled-date="disabledMonthDate" />
</a-form-item>
</a-col>
<a-col>
<a-button type="primary" @click="handleSearch" :loading="loading">
查询
</a-button>
<a-button style="margin-left: 8px" @click="handleReset">
重置
</a-button>
</a-col>
</a-row>
<!-- 图表区域 -->
<a-spin :spinning="loading" tip="加载中...">
<div v-show="!loading && showChart" class="water-temp-compare-chart" ref="chartRef"></div>
<div v-show="!loading && !showChart" class="water-temp-compare-chart">
<a-empty description="暂无数据" />
</div>
</a-spin>
<!-- 数据点详情弹框 -->
<a-modal v-model:open="detailModalVisible" :title="'月均水温对比'" width="1536px" :footer="null" @cancel="handleDetailModalClose">
<div v-if="detailModalData" >
<MonthlyAverage
:tm="detailModalData.date ? dayjs(detailModalData.date).format('YYYY-MM') + '-01 00:00:00' : dayjs().format('YYYY-MM') + '-01 23:59:59'"
:dataDimensionVal="detailModalData.baseid"
:rvcd="detailModalData.rvcd"
:stcd="detailModalData.stcd"
:jdList="jiDiList" />
</div>
</a-modal>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, computed, nextTick } from 'vue'
import * as echarts from 'echarts'
import { wbsbGetKendoList, avgMonGetKendoListCust } from "@/api/sw";
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
import dayjs from 'dayjs';
import { ZoomInOutlined } from '@ant-design/icons-vue';
import type { Dayjs } from 'dayjs';
import MonthlyAverage from '../monthlyAverage.vue';
defineOptions({
name: 'MonthlyAverageMaxModal'
});
// Props 定义 - 双向绑定模式
const props = defineProps<{
modelValue?: {
selectValue: string;
dateValue: string | Dayjs;
}
visible?: boolean; // 弹框可见状态
}>();
const emit = defineEmits(['update:modelValue']);
const JidiSelectEventStore = useJidiSelectEventStore();
const chartRef = ref<HTMLElement | null>(null)
let chartInstance: echarts.ECharts | null = null
const unit = '°C'
const baseid: any = ref(null);
const loading = ref(false);
const showChart = ref(true);
// 详情弹框相关状态
const detailModalVisible = ref(false);
const detailModalData = ref<any>(null);
// 基地列表(与父组件保持一致)
const jiDiList: any = ref([
{
"baseid": "all",
"basename": "当前全部",
"id": "9BFEC848-83EA-AD22-6DE2-10E969476693"
},
{
"baseid": "01",
"basename": "金沙江干流",
"id": "A33040B7-8977-D9F1-5E02-D7F0241AB8AA"
},
{
"baseid": "02",
"basename": "雅砻江干流",
"id": "C63D6020-995D-FE97-2F4A-F619A7142C79"
},
{
"baseid": "03",
"basename": "大渡河干流",
"id": "CCB0766B-F1D4-7DD6-650F-5C556B7231B3"
},
{
"baseid": "04",
"basename": "乌江干流",
"id": "E8A66641-B4F4-CC85-0815-38C5B2F93DBD"
},
{
"baseid": "05",
"basename": "长江上游干流",
"id": "E02C11E9-CEA5-A030-202F-3BFE84465D03"
},
{
"baseid": "10",
"basename": "湘西",
"id": "B1D1D52D-CEEF-6DC4-27DF-9990EB572F8D"
},
{
"baseid": "08",
"basename": "黄河上游干流",
"id": "BC6AF135-263D-09A9-D5CA-C99B2598FE6E"
},
{
"baseid": "09",
"basename": "黄河中游干流",
"id": "60EEEC28-128F-A2A8-44F3-6EAAC8FD8BB6"
},
{
"baseid": "06",
"basename": "南盘江-红水河",
"id": "7BB9A8F4-34B5-42B4-A7FC-CE910AD7F203"
},
{
"baseid": "12",
"basename": "东北",
"id": "47F8EF06-924E-E161-FCAF-62A66BBF252D"
},
{
"baseid": "07",
"basename": "澜沧江干流",
"id": "A966A4C9-278C-B0DA-2B97-2D10B7A6E96A"
},
{
"baseid": "13",
"basename": "怒江干流",
"id": "FA89E8CB-67A8-76DA-DC1E-23AE4C54F9E4"
},
{
"baseid": "11",
"basename": "闽浙赣",
"id": "CD98F995-EEB2-1021-D807-DA1B1AD9E49A"
},
{
"baseid": "other",
"basename": "其他",
"id": "AFBDFC67-B955-4EFD-959A-014CFB59EBFC"
}
]);
// 选择器相关 - 内部状态管理
const selectValue = ref('');
const selectOptions = ref<any[]>([]);
// 树形选择器展开状态管理
const treeExpandedKeys = ref<string[]>([])
const nodeMap = new Map<string, { node: any; parentKey: string | null }>()
/**
* 递归处理树数据为父节点添加 selectable: false
* @param data 原始树数据
* @returns 处理后的树数据
*/
const processTreeData = (data: any[]): any[] => {
if (!data || !Array.isArray(data)) return [];
return data.map(item => {
const newItem = { ...item };
// 如果有子项,标记为不可选中
if (newItem.children && newItem.children.length > 0) {
newItem.selectable = false;
// 递归处理子项
newItem.children = processTreeData(newItem.children);
} else {
// 叶子节点默认可选中(显式声明更清晰)
newItem.selectable = true;
}
return newItem;
});
};
// 计算属性:处理后的树数据
const processedSelectOptions = computed(() => {
return processTreeData(selectOptions.value || []);
});
/**
* 构建树节点映射建立父子关系
* @param treeData 树形数据
* @param parentKey 父节点key
*/
const buildNodeMap = (treeData: any[], parentKey: string | null = null) => {
if (!treeData || !Array.isArray(treeData)) return
treeData.forEach(node => {
// 存储当前节点及其父节点信息
nodeMap.set(node.value, {
node,
parentKey
})
// 递归处理子节点
if (node.children && node.children.length > 0) {
buildNodeMap(node.children, node.value)
}
})
}
/**
* 获取目标节点的所有父节点keys
* @param targetValue 目标节点value
* @returns 父节点keys数组从根到直接父节点
*/
const getParentKeys = (targetValue: string): string[] => {
const parentKeys: string[] = []
let currentKey: string | null = targetValue
// 向上追溯所有父节点
while (currentKey !== null && currentKey !== undefined) {
const nodeInfo = nodeMap.get(currentKey)
// 如果节点不存在或已到达根节点,停止追溯
if (!nodeInfo || nodeInfo.parentKey === null || nodeInfo.parentKey === undefined) {
break
}
// 将父节点插入到数组开头(保持从根到叶的顺序)
parentKeys.unshift(nodeInfo.parentKey)
currentKey = nodeInfo.parentKey
}
return parentKeys
}
// 日期选择器相关 - 内部状态管理Dayjs 对象)
const dateValue = ref<Dayjs | null>(null);
/**
* 禁用未来月份
* @param current 当前日期对象
* @returns 是否禁用
*/
const disabledMonthDate = (current: Dayjs) => {
if (!current) return false
const now = dayjs()
// 禁用大于当前年月的日期
return current.isAfter(now, 'month')
}
/**
* 处理树节点选择事件
* @param selectedKeys 选中的键值
* @param info 节点信息
*/
const handleTreeSelect = (selectedKeys: string | string[], info: any) => {
let selectedValue: string;
if (typeof selectedKeys === 'string') {
selectedValue = selectedKeys;
} else if (Array.isArray(selectedKeys)) {
selectedValue = selectedKeys[0];
} else {
selectedValue = info?.value || '';
}
selectValue.value = selectedValue;
};
const filterSelectOptions = (selectOptions: any) => {
if (selectOptions?.length === 1 && selectOptions?.[0]?.children?.length === 1) {
return [{ ...selectOptions?.[0]?.children?.[0], isLeaf: true }]
} else if (selectOptions.length) {
return selectOptions.map((e) => {
if (e?.children?.length > 1) {
return { ...e, isLeaf: false, selectable: true, children: e.children.map((item) => ({ ...item, isLeaf: true })) }
} else {
return { ...e.children[0], isLeaf: true }
}
})
}
return []
}
// 监听 props.modelValue 变化,同步到内部状态
watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
// 同步 selectValue
if (newVal.selectValue !== undefined && newVal.selectValue !== selectValue.value) {
selectValue.value = newVal.selectValue;
}
// 同步 dateValue兼容 string 和 Dayjs 类型)
if (newVal.dateValue !== undefined) {
const newDateValue = typeof newVal.dateValue === 'string'
? dayjs(newVal.dateValue, 'YYYY-MM')
: newVal.dateValue;
if (!dateValue.value || !newDateValue.isSame(dateValue.value)) {
dateValue.value = newDateValue;
}
}
}
},
{ deep: true, immediate: true }
);
// 监听内部状态变化emit 给父组件(添加防循环机制)
watch(selectValue, (newVal) => {
// 只有当父组件传入的值与当前值不同时才 emit
if (props.modelValue?.selectValue !== newVal) {
emit('update:modelValue', {
selectValue: newVal,
dateValue: dateValue.value ? dateValue.value.format('YYYY-MM') : ''
});
}
});
watch(dateValue, (newVal) => {
const formattedDate = newVal ? newVal.format('YYYY-MM') : '';
// 只有当父组件传入的值与当前值不同时才 emit
if (props.modelValue?.dateValue !== formattedDate) {
emit('update:modelValue', {
selectValue: selectValue.value,
dateValue: formattedDate
});
}
});
// 监听弹框 visible 状态变化,每次打开时重新查询数据
watch(
() => props.visible,
(newVal) => {
if (newVal === true) {
// 弹框打开时,确保使用最新的父组件传入值
console.log('弹框打开,重新查询数据');
// 优先使用父组件传入的值进行查询
const querySelectValue = props.modelValue?.selectValue || selectValue.value;
const queryDateValue = props.modelValue?.dateValue || dateValue.value;
console.log('查询参数 - selectValue:', querySelectValue, 'dateValue:', queryDateValue);
// 如果父组件传入了新值,先同步到内部状态
if (props.modelValue?.selectValue && props.modelValue.selectValue !== selectValue.value) {
selectValue.value = props.modelValue.selectValue;
}
if (props.modelValue?.dateValue) {
const newDateValue = typeof props.modelValue.dateValue === 'string'
? dayjs(props.modelValue.dateValue, 'YYYY-MM')
: props.modelValue.dateValue;
if (!dateValue.value || !newDateValue.isSame(dateValue.value)) {
dateValue.value = newDateValue;
}
}
// 使用同步后的值查询数据
getEchartsData();
}
}
);
//获取选择器配置参数
const getSelectConfig = async () => {
loading.value = true;
try {
let obj: any = {}
if (baseid.value === 'all') {
obj = { rstcdStepSort: 'asc', siteStepSort: 'asc' }
} else {
obj = { siteStepSort: 'asc' }
}
const filters = [
{
field: 'wbsType',
operator: 'eq',
value: 'PSB_RVCD'
}
]
if (baseid.value && baseid.value !== 'all') {
filters.push({
field: 'objId',
operator: 'eq',
value: baseid.value
})
}
let data: any = {
filter: {
logic: 'and',
filters
}
}
if (obj) {
data.sort = [obj]
} else {
data = {
...data,
group: [
{ dir: 'asc', field: 'orderIndex' },
{ dir: 'asc', field: 'wbsCode' },
{ dir: 'asc', field: 'wbsName' },
{ dir: 'asc', field: 'objid' },
],
groupResultFlat: true
}
}
let res = await wbsbGetKendoList(data)
let dataOne = res?.data?.data || res?.data
if (dataOne.length > 0) {
let dataMapNameMap: any = {}
let jiDiListMap: any = {}
jiDiList.value.forEach((item: any) => {
jiDiListMap[item.baseid] = item.basename
})
dataOne.map((item: any, index: number) => {
const { stcd, stnm, objId } = item
if (dataMapNameMap[objId]) {
dataMapNameMap[objId].push({ ...item, baseName: jiDiListMap[objId], baseId: objId })
} else {
dataMapNameMap[objId] = [{ ...item, baseName: jiDiListMap[objId], baseId: objId }]
}
return { label: item.wbsName, value: item.wbsCode, baseId: objId, baseName: jiDiListMap[objId] }
})
let dataMapNameArr: any = []
Object.keys(dataMapNameMap).forEach((item: any) => {
dataMapNameArr.push({
title: dataMapNameMap[item]?.[0]?.baseName,
value: item,
selectable: false,
children: dataMapNameMap[item].map((item2: any) => {
return {
title: item2.wbsName,
value: item2.wbsCode
}
})
})
})
dataMapNameArr = dataMapNameArr.sort((a: any, b: any) => {
const indexA = jiDiList.value.findIndex(item => item.baseid === a.value);
const indexB = jiDiList.value.findIndex(item => item.baseid === b.value);
return indexA - indexB;
})
// 构建树节点映射,用于自动展开
buildNodeMap(dataMapNameArr)
// 先设置原始数据
selectOptions.value = filterSelectOptions(dataMapNameArr)
// 保存父组件传入的值(如果有)
const parentSelectValue = props.modelValue?.selectValue;
// 确定最终要选中的值
// 只在没有外部传入值时才设置默认值
if (!parentSelectValue) {
if (baseid.value === 'all') {
selectValue.value = 'SJLY176'
} else if (selectOptions.value[0]?.children) {
selectValue.value = selectOptions.value[0]?.children[0]?.value
} else if (selectOptions.value[0]?.value) {
selectValue.value = selectOptions.value[0]?.value
} else {
selectValue.value = ''
}
} else {
// 如果有父组件传入的值,使用父组件的值
selectValue.value = parentSelectValue;
}
// 自动展开选中节点的父节点
if (selectValue.value) {
nextTick(() => {
const parentKeys = getParentKeys(selectValue.value);
treeExpandedKeys.value = parentKeys;
});
}
}
// 只在没有外部传入日期值时才设置默认值
if (!props.modelValue?.dateValue) {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
dateValue.value = dayjs(`${year}-${month}`, 'YYYY-MM');
} else {
// 如果有父组件传入的日期值,使用父组件的值
const newDateValue = typeof props.modelValue.dateValue === 'string'
? dayjs(props.modelValue.dateValue, 'YYYY-MM')
: props.modelValue.dateValue;
dateValue.value = newDateValue;
}
// 不在这里调用 getEchartsData(),等待弹框打开时再查询
// 但如果是在 onMounted 或 Store watch 首次加载时,且弹框已经打开,则需要查询
if (props.visible) {
// 如果弹框已经是打开状态,立即查询数据
setTimeout(() => {
getEchartsData();
}, 50);
}
} catch (error) {
console.error('选择器配置加载失败:', error);
} finally {
loading.value = false;
}
}
//获取图表配置
const getEchartsData = async () => {
if (loading.value) return; // 防止重复请求
loading.value = true;
try {
// 根据 dateValue 解析年月
const dateValueStr = dateValue.value ? dateValue.value.format('YYYY-MM') : '';
if (!dateValueStr || !selectValue.value) {
showChart.value = false;
loading.value = false;
return;
}
const [yearStr, monthStr] = dateValueStr.split('-');
const year = parseInt(yearStr);
const month = parseInt(monthStr);
// 计算该月的第一天和最后一天
const firstDay = `${dateValueStr}-01 00:00:00`;
// 创建下个月1号然后减去1天得到本月最后一天
const nextMonth = month === 12 ? 1 : month + 1;
const nextYear = month === 12 ? year + 1 : year;
const lastDate = new Date(nextYear, nextMonth - 1, 1);
lastDate.setDate(lastDate.getDate() - 1);
const lastDay = `${year}-${String(month).padStart(2, '0')}-${String(lastDate.getDate()).padStart(2, '0')} 23:59:59`;
const params = {
"filter": {
"logic": "and",
"filters": [
{
"field": "rvcd",
"operator": "eq",
"dataType": "string",
"value": selectValue.value
},
{
"field": "tm",
"operator": "gte",
"dataType": "date",
"value": firstDay
},
{
"field": "tm",
"operator": "lte",
"dataType": "date",
"value": lastDay
},
{
"field": "year",
"operator": "eq",
"dataType": "string",
"value": year
},
{
"field": "month",
"operator": "eq",
"dataType": "string",
"value": month
}
]
}
}
let res = await avgMonGetKendoListCust(params)
console.log('接口返回数据:', res)
let data = res?.data?.data || res?.data || []
if (data.length === 0) {
showChart.value = false
return
}
showChart.value = true
// 筛选 sttp === "1" 的数据作为 X 轴站点名称
const stationData = data.filter((item: any) => item.sttp === "1")
const xData = stationData.map((item: any) => ({
value: item.stnm,
stnm: item.stnm,
stcd: item.stcd // 保留站点编码用于点击事件
}))
// 筛选 sttp === "2" 的数据作为图表系列数据
const tempData = data.filter((item: any) => item.sttp === "2")
// 按照站点顺序提取三个系列的数据,包装为对象格式以保留元信息
const actualData = tempData.map((item: any) => ({
value: item.actualTemp,
stcd: item.stcd,
stnm: item.stnm
}))
const lastData = tempData.map((item: any) => ({
value: item.lastTemp,
stcd: item.stcd,
stnm: item.stnm
}))
const naturalData = stationData.map((item: any) => ({
value: item.naturalTemp,
stcd: item.stcd,
stnm: item.stnm
}))
console.log('X轴数据:', xData)
console.log('实测值:', actualData)
console.log('去年同期:', lastData)
console.log('天然值:', naturalData)
// 初始化或更新图表 - 每次都重新初始化以避免显示异常
setTimeout(() => {
// 总是调用 initChart 重新创建图表实例,避免旧实例残留导致的双重显示问题
initChart(xData, actualData, lastData, naturalData)
// 强制重绘,确保尺寸正确
setTimeout(() => {
chartInstance?.resize()
}, 100)
}, 50)
} catch (error) {
console.error('图表数据加载失败:', error)
showChart.value = false
} finally {
loading.value = false;
}
}
const initChart = (xData: any[], actualData: any[], lastData: any[], naturalData: any[]) => {
if (!chartRef.value) return
// 如果图表实例已存在,先销毁再重新创建,避免重复绑定事件和显示异常
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
chartInstance = echarts.init(chartRef.value)
const legendData = ['实测值', '去年同期', '天然']
// 计算Y轴范围最小值向下取整最大值向上取整
const allData = [...actualData, ...lastData, ...naturalData].map(item => item.value).filter(val => val !== null && val !== undefined)
const dataMin = allData.length > 0 ? Math.min(...allData) : 0
const dataMax = allData.length > 0 ? Math.max(...allData) : 10
const yAxisMin = Math.floor(dataMin)
const yAxisMax = Math.ceil(dataMax)
// 完全按照原始React代码中的options配置
const options: any = {
noShowToolbox: true,
yAxisSplit: 5,
xData,
dataZoom: [
{
type: 'inside',
show: false
},
{
type: 'slider',
show: false
}
],
tooltip: {
show: true,
trigger: 'axis',
confine: true,
formatter: (params: any) => {
const label = xData.filter((item: any) => item.value === params[0].axisValueLabel)?.[0]?.stnm
let elm = ``
for (const item of params) {
const value = item.data?.value ?? item.value;
elm += `
<div>
${item.marker}
<span>${item.seriesName}:</span>
<span>${value === null || value === undefined ? '-' : value}${unit}</span>
</div>
`
}
return `<div>${label}</div>` + elm
}
},
legend: {
data: legendData
},
grid: {
top: 30,
bottom: 50,
right: 15,
left: 30
},
xAxis: {
axisPointer: {
type: 'shadow',
lineStyle: {
color: '#007aff1a',
width: 1,
}
},
axisLine: {
show: true,
lineStyle: {
color: '#8f8f8f'
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#000000',
fontSize: 12,
interval: xData.length < 5 ? 0 : 2,
rotate: 0,
formatter: (value: any) => {
const label = xData.filter((item: any) => item.value === value)?.[0]?.stnm
return `{a|${label.substring(0, 6)}}` + (label.length > 6 ? '...\n{b|}' : '\n{b|}')
},
rich: {
a: {
height: 30,
align: 'center'
},
b: {
height: 30,
align: 'center'
}
}
},
data: xData,
splitLine: {
show: false
}
},
yAxis: [
{
type: 'value',
name: `水温(${unit})`,
min: yAxisMin,
max: yAxisMax,
nameTextStyle: {
fontSize: 12,
color: '#000000'
},
lineStyle: {
color: '#6ca4f7',
width: 2
},
axisLine: {
show: true,
lineStyle: {
color: '#bfbfbf'
}
},
axisTick: {
show: true,
length: 3,
lineStyle: {
color: '#8f8f8f'
}
},
axisLabel: {
color: '#333',
fontSize: 12
},
splitLine: {
show: true,
lineStyle: {
color: '#bfbfbf',
type: 'solid'
}
}
}
],
series: [
{
name: legendData[0],
data: actualData,
type: 'line',
connectNulls: true,
smooth: true
},
{
name: legendData[1],
data: lastData,
type: 'line',
connectNulls: true,
smooth: true
},
{
name: legendData[2],
data: naturalData,
type: 'line',
connectNulls: true,
smooth: true
}
]
}
// 颜色配置 - 对应 getColorByCodeAndType(['Other'], ['ACTUALTEMP', 'LASTTEMP', 'NATURALTEMP'])
// 根据图片:实测值(蓝)、去年同期(紫)、天然(绿)
options.color = ['#5470c6', '#9b59b6', '#91cc75']
chartInstance.setOption(options)
// 绑定点击事件 - 移植自 index.vue打开详情弹框
chartInstance.on('click', (params: any) => {
console.log('图表数据点被点击:', params);
// 获取点击的数据点信息
const dataPoint = params.data;
const stcd = dataPoint?.stcd || '';
const stnm = dataPoint?.stnm || '';
// 设置弹框数据
detailModalData.value = {
baseid: baseid.value,
rvcd: selectValue.value,
date: dateValue.value ? dateValue.value.format('YYYY-MM') : dayjs().format('YYYY-MM'),
stcd: stcd,
stnm: stnm
};
// 打开详情弹框
detailModalVisible.value = true;
});
}
// 选择器变化处理
const handleSelectChange = (value: string) => {
console.log('选择器变化:', value);
// 自动展开父节点
if (value && nodeMap.size > 0) {
const parentKeys = getParentKeys(value)
treeExpandedKeys.value = parentKeys
console.log('自动展开父节点:', parentKeys)
} else {
treeExpandedKeys.value = []
}
// 自动查询
getEchartsData();
};
// 日期变化处理
const handleDateChange = (date: Dayjs | null, dateString: string) => {
console.log('日期变化:', dateString);
// 自动查询
getEchartsData();
};
// 详情弹框关闭处理
const handleDetailModalClose = () => {
detailModalVisible.value = false;
detailModalData.value = null;
};
// 查询按钮点击
const handleSearch = () => {
// 手动查询
getEchartsData();
};
// 重置按钮点击
const handleReset = () => {
// 恢复到组件内部默认值(根据当前 baseid 重新计算)
if (baseid.value === 'all') {
selectValue.value = 'SJLY176';
} else if (selectOptions.value[0]?.children) {
selectValue.value = selectOptions.value[0]?.children[0]?.value;
} else if (selectOptions.value[0]?.value) {
selectValue.value = selectOptions.value[0]?.value;
} else {
selectValue.value = '';
}
// 重置日期为当前月份
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
dateValue.value = dayjs(`${year}-${month}`, 'YYYY-MM');
// 重新加载数据
getEchartsData();
};
// 图表放大展示 - 打开弹框
const handleChartZoomIn = () => {
// TODO: 如果需要进一步放大,可以在此添加逻辑
console.log('图表放大展示');
};
watch(
() => JidiSelectEventStore.selectedItem,
(newVal) => {
baseid.value = newVal.wbsCode;
getSelectConfig()
},
{ deep: true, immediate: true }
);
// 监听树数据变化,重新构建映射
watch(() => processedSelectOptions.value, (newData) => {
console.log('树数据变化,重新构建映射')
if (newData && newData.length > 0) {
// 清空旧映射
nodeMap.clear()
// 重新构建映射
buildNodeMap(newData)
// 数据加载完成后,如果已有默认值,重新触发一次
if (selectValue.value) {
nextTick(() => {
const parentKeys = getParentKeys(selectValue.value)
treeExpandedKeys.value = parentKeys
console.log('数据加载后自动展开父节点:', parentKeys)
})
}
}
}, { deep: true })
// 监听 selectValue 变化(包括默认值和用户选择)
watch(() => selectValue.value, (newValue) => {
console.log('selectValue 变化:', newValue)
if (newValue && nodeMap.size > 0) {
// 只有当 nodeMap 已构建时才执行
const parentKeys = getParentKeys(newValue)
treeExpandedKeys.value = parentKeys
console.log('自动展开父节点:', parentKeys)
} else {
treeExpandedKeys.value = []
}
}, { immediate: true })
onMounted(() => {
// 延迟初始化,确保容器尺寸已就绪
setTimeout(() => {
getSelectConfig()
}, 100)
window.addEventListener('resize', () => {
chartInstance?.resize()
})
})
onBeforeUnmount(() => {
chartInstance?.dispose()
window.removeEventListener('resize', () => {
chartInstance?.resize()
})
})
</script>
<style scoped>
.water-temp-compare-modal {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.search-card {
/* margin-bottom: 16px; */
}
.water-temp-compare-chart {
width: 100%;
height: 602px;
display: flex;
justify-content: center;
align-items: center;
}
.water_bottom {
width: 100%;
display: flex;
justify-content: end;
align-items: center;
color: #2f6b96;
cursor: pointer;
padding: 8px 0;
}
:deep(.ant-spin-nested-loading) {
flex: 1;
display: flex;
flex-direction: column;
}
:deep(.ant-spin-container) {
flex: 1;
display: flex;
flex-direction: column;
}
</style>