1045 lines
33 KiB
Vue
1045 lines
33 KiB
Vue
|
|
<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>
|