WholeProcessPlatform/frontend/src/modules/yanchengshuiwenChangeMod/index.vue

586 lines
15 KiB
Vue
Raw Normal View History

2026-04-10 11:11:30 +08:00
<!-- SidePanelItem.vue -->
<template>
2026-05-20 08:44:31 +08:00
<SidePanelItem title="沿程水温变化" :prompt="prompts" :moreSelect="select" :datetimePicker="datetimePicker"
@update-values="handlePanelChange1">
<a-spin :spinning="loading" tip="加载中..." >
<div v-show="showemit && !loading" ref="chartRef" class="chart-container"></div>
<div v-show="!showemit && !loading" class="chart-container"> <a-empty /></div>
</a-spin>
2026-04-10 11:11:30 +08:00
</SidePanelItem>
2026-05-20 08:44:31 +08:00
2026-04-10 11:11:30 +08:00
</template>
<script lang="ts" setup>
2026-05-20 08:44:31 +08:00
import { ref, onMounted, onBeforeUnmount, watch, computed } from "vue";
import * as echarts from "echarts";
import type { ECharts } from "echarts";
import SidePanelItem from "@/components/SidePanelItem/index.vue";
2026-05-20 08:44:31 +08:00
import { getKendoListCust, wbsbGetKendoList } from "@/api/sw";
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
import { da } from "element-plus/es/locale/index.mjs";
import { f } from "vue-router/dist/router-CWoNjPRp.mjs";
2026-04-10 11:11:30 +08:00
// 定义组件名(便于调试和递归)
defineOptions({
name: "yanchengshuiwenChangeMod",
2026-04-10 11:11:30 +08:00
});
2026-05-20 08:44:31 +08:00
// 改为动态获取当前时间
const getCurrentHourTime = () => {
const now = new Date();
// 减去一小时
now.setHours(now.getHours() - 1);
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hour = String(now.getHours()).padStart(2, '0');
return `${year}-${month}-${day} ${hour}`;
};
const JidiSelectEventStore = useJidiSelectEventStore();
const baseid: any = ref(null);
const paramsOne = {
rvcd: '',
tm: []
}
const dataOne = ref('')
// 使用 computed 使 prompts 响应 dataOne.value 的变化
const prompts = computed(() => ({
show: true,
value: `注:最新数据时间为${dataOne.value || getCurrentHourTime()}`,
}));
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 showemit = ref(false)
const loading = ref(false)
// const selectOptions: any = ref([])
const optionsFmt = (options: any) =>
options.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}))
const chartRef = ref<HTMLElement | null>(null);
let chartInstance: ECharts | null = null;
// 静态数据 - 站点名称
const stationNames = ref([]);
// 静态数据 - 水温值 (°C),班多无数据设为 null
const waterTemperatures = ref([]);
// 使用 computed 使 currentTime 响应 dataOne.value 的变化
const currentTime = computed(() => dataOne.value || getCurrentHourTime());
2026-05-15 18:08:29 +08:00
// 选择器配置
const select = ref({
show: true,
2026-05-20 08:44:31 +08:00
value: '',
options: [],
picker: undefined,
format: undefined,
2026-05-15 18:08:29 +08:00
});
2026-04-10 11:11:30 +08:00
2026-05-15 18:08:29 +08:00
// 日期选择器配置
const datetimePicker = ref({
show: true,
2026-05-20 08:44:31 +08:00
value: computed(() => getCurrentHourTime()),
format: "YYYY-MM-DD HH",
picker: "date" as const,
options: [],
2026-05-15 18:08:29 +08:00
});
2026-04-10 11:11:30 +08:00
// 初始化图表
const initChart = () => {
if (!chartRef.value) return;
chartInstance = echarts.init(chartRef.value);
const option = {
title: {
text: "水温(°C)",
2026-04-10 11:11:30 +08:00
left: 5,
top: 0,
textStyle: {
color: "#000000",
2026-04-10 11:11:30 +08:00
fontSize: 12,
fontWeight: "normal",
},
2026-04-10 11:11:30 +08:00
},
2026-05-20 08:44:31 +08:00
dataZoom: [
{
type: 'inside',
start: 0,
end: 100,
zoomOnMouseWheel: true,
moveOnMouseMove: true,
filterMode: 'filter'
}
],
2026-04-10 11:11:30 +08:00
tooltip: {
trigger: "axis",
2026-04-10 11:11:30 +08:00
formatter: (params: any) => {
if (params && params.length > 0) {
const data = params[0];
// 过滤掉 null 值的数据点
if (data.value !== null && data.value !== undefined) {
2026-05-20 08:44:31 +08:00
return `${currentTime.value}<br/>${data.name}${data.value}°C`;
2026-04-10 11:11:30 +08:00
}
}
return "";
},
2026-04-10 11:11:30 +08:00
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
top: "15%",
containLabel: true,
2026-04-10 11:11:30 +08:00
},
xAxis: {
type: "category",
2026-04-10 11:11:30 +08:00
data: stationNames.value,
boundaryGap: true,
axisLine: {
show: true,
lineStyle: {
color: "#8f8f8f",
},
2026-04-10 11:11:30 +08:00
},
axisTick: {
show: false,
2026-04-10 11:11:30 +08:00
},
axisLabel: {
color: "#333",
2026-04-10 11:11:30 +08:00
fontSize: 12,
margin: 8,
interval: 0,
formatter: (value: string, index: number) => {
// 偶数索引0, 2, 4, 6的标签在上方
// 奇数索引1, 3, 5的标签在下方
// 通过添加空行实现上下错位
if (index % 2 === 0) {
return `${value}\n `; // 上方标签:文字 + 换行 + 空格占位
2026-04-10 11:11:30 +08:00
} else {
return ` \n${value}`; // 下方标签:空格占位 + 换行 + 文字
2026-04-10 11:11:30 +08:00
}
},
2026-04-10 11:11:30 +08:00
},
splitLine: {
show: true,
lineStyle: {
color: "#e0e0e0",
type: "solid",
},
},
2026-04-10 11:11:30 +08:00
},
yAxis: {
type: "value",
2026-04-10 11:11:30 +08:00
min: 0,
// max: 10,
2026-04-10 11:11:30 +08:00
interval: 2,
axisLine: {
show: true,
lineStyle: {
color: "#8f8f8f",
},
2026-04-10 11:11:30 +08:00
},
axisTick: {
show: true,
length: 3,
lineStyle: {
color: "#8f8f8f",
},
2026-04-10 11:11:30 +08:00
},
axisLabel: {
color: "#333",
fontSize: 12,
2026-04-10 11:11:30 +08:00
},
splitLine: {
show: true,
lineStyle: {
color: "#e0e0e0",
type: "solid",
},
},
2026-04-10 11:11:30 +08:00
},
series: [
{
name: "水温",
type: "line",
2026-04-10 11:11:30 +08:00
smooth: true,
symbol: "circle",
2026-04-10 11:11:30 +08:00
symbolSize: 6,
lineStyle: {
color: "#6ca4f7",
width: 2,
2026-04-10 11:11:30 +08:00
},
itemStyle: {
color: "#6ca4f7",
2026-04-10 11:11:30 +08:00
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(108, 164, 247, 0.3)",
2026-04-10 11:11:30 +08:00
},
{
offset: 1,
color: "rgba(108, 164, 247, 0.05)",
},
]),
2026-04-10 11:11:30 +08:00
},
data: waterTemperatures.value,
},
],
2026-04-10 11:11:30 +08:00
};
chartInstance.setOption(option);
};
// 处理窗口大小变化
const handleResize = () => {
chartInstance?.resize();
};
const init = async () => {
2026-05-20 08:44:31 +08:00
if (loading.value) return; // 防止重复请求
loading.value = true;
try {
const params = {
filter: {
logic: "and",
filters: [
{ field: "rvcd", operator: "eq", dataType: "string", value: paramsOne.rvcd },
{ field: "tm", operator: "gte", dataType: "date", value: paramsOne.tm[0] },
{ field: "tm", operator: "lte", dataType: "date", value: paramsOne.tm[1] },
],
},
sort: [{ field: "sort", dir: "asc" }],
};
let res = await getKendoListCust(params);
let data = res.data.data || res.data
if(data.length > 0){
showemit.value = true
}else{
showemit.value = false
}
stationNames.value = data
.filter((item: any) => item.sttp == "1")
.map((item: any) => item.stnm);
console.log(stationNames.value);
2026-05-20 08:44:31 +08:00
waterTemperatures.value = data
.filter((item: any) => item.sttp == "2")
.map((item: any) => item.temperature);
// waterTemperatures.value = res.data.data.map((item: any) => item.temperature);
console.log(waterTemperatures.value);
2026-05-20 08:44:31 +08:00
// 数据获取完成后,初始化或更新图表
setTimeout(() => {
if (!chartInstance) {
initChart();
} else {
// 如果图表已存在,只更新数据
chartInstance.setOption({
xAxis: {
data: stationNames.value,
},
2026-05-20 08:44:31 +08:00
series: [
{
data: waterTemperatures.value,
},
],
});
}
// 强制重绘,确保尺寸正确
setTimeout(() => {
chartInstance?.resize();
}, 100);
}, 50);
} catch (error) {
console.error('数据加载失败:', error);
showemit.value = false;
} finally {
loading.value = false;
}
};
//获取选择器配置参数
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', // contains
value: baseid.value
})
}
let data: any = {
filter: {
logic: 'and',
filters
}
// select: ['WBS_CODE', 'WBS_NAME']
}
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' },
],
2026-05-20 08:44:31 +08:00
groupResultFlat: true
}
}
2026-05-20 08:44:31 +08:00
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] }
})
// debugger
let dataMapNameArr: any = []
Object.keys(dataMapNameMap).forEach((item: any) => {
dataMapNameArr.push({
title: dataMapNameMap[item]?.[0]?.baseName,
value: item,
selectable: false,
// baseId:dataMapNameMap[item]?.[0]?.baseId,
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;
})
select.value.options = filterSelectOptions(dataMapNameArr)
if (baseid.value === 'all') {
select.value.value = 'SJLY1U'
} else if (filterSelectOptions(dataMapNameArr)[0]?.children) {
select.value.value = filterSelectOptions(dataMapNameArr)[0]?.children[0]?.value
} else if (filterSelectOptions(dataMapNameArr)[0]?.value) {
select.value.value = filterSelectOptions(dataMapNameArr)[0]?.value
} else {
select.value.value = ''
}
}
} catch (error) {
console.error('选择器配置加载失败:', error);
} finally {
loading.value = false;
}
}
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 []
}
//监听子组件的数据变化
const handlePanelChange1 = (data) => {
console.log('当前所有控件状态:', data);
if (data.moreSelect) {
paramsOne.rvcd = data.moreSelect
}
if (data.datetime) {
dataOne.value = data.datetime
const datetime = data.datetime;
// 解析日期和时间
const [datePart, hourPart] = datetime.split(' ');
const [year, month, day] = datePart.split('-').map(Number);
// 创建当前时间的 Date 对象
const currentDate = new Date(year, month - 1, day, parseInt(hourPart), 0, 0);
2026-05-20 08:44:31 +08:00
// 创建一个月前的 Date 对象
const previousDate = new Date(year, month - 2, day, 0, 0, 0);
// 格式化函数:将 Date 对象转为 "YYYY-MM-DD HH:mm:ss" 格式
function formatDate(date) {
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const d = String(date.getDate()).padStart(2, '0');
const h = String(date.getHours()).padStart(2, '0');
const min = String(date.getMinutes()).padStart(2, '0');
const s = String(date.getSeconds()).padStart(2, '0');
return `${y}-${m}-${d} ${h}:${min}:${s}`;
}
// 生成结果数组
const result = [
formatDate(currentDate), // "2026-05-15 15:00:00"
formatDate(previousDate) // "2026-04-15 00:00:00"
];
paramsOne.tm = result
console.log(paramsOne.tm, 'paramsOne.tm')
}
if (paramsOne.rvcd || paramsOne.tm.length > 0) {
init();
}
}
watch(
() => JidiSelectEventStore.selectedItem,
(newVal) => {
baseid.value = newVal.wbsCode;
getSelectConfig()
},
{ deep: true, immediate: true }
);
// 页面加载时执行的逻辑
onMounted(() => {
// 延迟初始化,确保 DOM 渲染完成
init();
window.addEventListener("resize", handleResize);
2026-04-10 11:11:30 +08:00
});
// 组件卸载前清理
onBeforeUnmount(() => {
window.removeEventListener("resize", handleResize);
2026-04-10 11:11:30 +08:00
chartInstance?.dispose();
});
</script>
<style lang="scss" scoped>
.chart-container {
width: 100%;
2026-05-20 08:44:31 +08:00
height: 252px ;
display: flex;
justify-content: center;
align-items: center;
}
:deep(.ant-spin-nested-loading ){
height: 252px !important;
2026-04-10 11:11:30 +08:00
}
</style>