grgw_vue_xz_2025/src/views/heating/heatanalysis/components/ZxtJX.vue

263 lines
7.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="wrap">
<div class="title">{{ headerText }}</div>
<a-tabs v-model:activeKey="activeTab" centered @change="onTabChange">
<a-tab-pane key="temp" tab="温度指标">
<div ref="tempChartRef" class="chart-box"></div>
</a-tab-pane>
<a-tab-pane key="press" tab="压力指标">
<div ref="pressChartRef" class="chart-box"></div>
</a-tab-pane>
<a-tab-pane key="heat" tab="热量指标">
<div ref="heatChartRef" class="chart-box"></div>
</a-tab-pane>
<a-tab-pane key="flow" tab="流量指标">
<div ref="flowChartRef" class="chart-box"></div>
</a-tab-pane>
</a-tabs>
</div>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineProps, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import { useMessage } from '/@/hooks/web/useMessage';
import {jxlist, list} from '/@/views/heating/history/HeatanalysisHistory.api';
const props = defineProps({});
const { createMessage } = useMessage();
const activeTab = ref('temp'); // 默认进入温度指标 tab
// 日期近7天含今天
const end = new Date();
end.setHours(23, 59, 59, 999);
const start = new Date(end);
start.setDate(end.getDate() - 6);
start.setHours(0, 0, 0, 0);
const pad = (n: number) => String(n).padStart(2, '0');
function formatDateTime(d: Date) {
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
}
const tempChartRef = ref<HTMLElement | null>(null);
const pressChartRef = ref<HTMLElement | null>(null);
const heatChartRef = ref<HTMLElement | null>(null);
const flowChartRef = ref<HTMLElement | null>(null);
let tempChart: echarts.ECharts | null = null;
let pressChart: echarts.ECharts | null = null;
let heatChart: echarts.ECharts | null = null;
let flowChart: echarts.ECharts | null = null;
let tempOption: any = null;
let pressOption: any = null;
let heatOption: any = null;
let flowOption: any = null;
const headerText = ref(''); // 页面顶部显示文本
function safeNum(v: any) {
if (v === null || v === undefined || v === '') return null;
const n = Number(v);
return Number.isNaN(n) ? null : n;
}
function buildHeader(records: any[], record_: any) {
const r = (records && records.length > 0) ? records[0] : record_;
const names = [r.view001Name, r.view002Name].filter(v => v && v !== '');
return names.join(' → ');
}
function initChartsOptions(records: any[]) {
// 按时间排序(优先 datatime再 view032
records.sort((a: any, b: any) => {
const ta = new Date(a.view032 || a.datatime || '').getTime();
const tb = new Date(b.view032 || b.datatime || '').getTime();
return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb);
});
const xAxis = records.map((r: any) => r.view032 || r.datatime || '');
// ⚡ 只改温度指标:根据每条记录的 fromFlow 判断取值
const tempSeries = [
{
name: '供水温度',
type: 'line',
showSymbol: false,
connectNulls: false,
data: records.map((r: any) => {
return safeNum(r.fromFlow == 1 ? r.view035 : r.view005);
}),
},
{
name: '回水温度',
type: 'line',
showSymbol: false,
connectNulls: false,
data: records.map((r: any) => {
return safeNum(r.fromFlow == 1 ? r.view036 : r.view006);
}),
},
];
// 压力指标(不变)
const pressSeries = [
{ name: '供水压力', key: 'view007' },
{ name: '回水压力', key: 'view008' },
].map(s => ({
name: s.name,
type: 'line',
showSymbol: false,
connectNulls: false,
data: records.map((r: any) => safeNum(r[s.key])),
}));
// 热量指标(不变)
const heatSeries = [
{ name: '瞬时热量', key: 'view041' },
{ name: '正累积热量', key: 'view042' },
].map(s => ({
name: s.name,
type: 'line',
showSymbol: false,
connectNulls: false,
data: records.map((r: any) => safeNum(r[s.key])),
}));
// 流量指标(不变)
const flowSeries = [
{ name: '瞬时流量', key: 'view037' },
{ name: '正累积流量', key: 'view038' },
].map(s => ({
name: s.name,
type: 'line',
showSymbol: false,
connectNulls: false,
data: records.map((r: any) => safeNum(r[s.key])),
}));
const baseOption = {
tooltip: { trigger: 'axis', axisPointer: { type: 'cross' } },
legend: { top: 36, left: 'center' },
grid: { left: '5%', right: '5%', bottom: 70, top: 70, containLabel: true },
xAxis: {
type: 'category',
data: xAxis,
boundaryGap: false,
},
yAxis: { type: 'value', scale: true },
};
tempOption = { ...baseOption, title: { text: '温度指标', left: 'center', top: 8 }, series: tempSeries };
pressOption = { ...baseOption, title: { text: '压力指标', left: 'center', top: 8 }, series: pressSeries };
heatOption = { ...baseOption, title: { text: '热量指标', left: 'center', top: 8 }, series: heatSeries };
flowOption = { ...baseOption, title: { text: '流量指标', left: 'center', top: 8 }, series: flowSeries };
}
let resizeAdded = false;
function ensureResizeListener() {
if (resizeAdded) return;
const onResize = () => {
tempChart?.resize();
pressChart?.resize();
heatChart?.resize();
flowChart?.resize();
};
window.addEventListener('resize', onResize);
onUnmounted(() => {
window.removeEventListener('resize', onResize);
});
resizeAdded = true;
}
function init(record_: any) {
const params = {
pageNo: 1,
pageSize: -1,
regionType: '乡镇',
view001: record_.view001,
view002: record_.view002,
view004: -1,
startDate: formatDateTime(start),
endDate: formatDateTime(end),
};
jxlist(params).then((res: any) => {
const records = (res && res.list) ? res.list : [];
headerText.value = buildHeader(records, record_);
initChartsOptions(records);
nextTick(() => {
// 初始化温度图表默认tab
if (tempChartRef.value) {
if (!tempChart) tempChart = echarts.init(tempChartRef.value);
tempChart.setOption(tempOption);
}
ensureResizeListener();
});
}).catch(err => {
console.error(err);
createMessage.error('获取数据失败');
});
}
// tab切换时第一次进来才 init对应图表
function onTabChange(key: string) {
nextTick(() => {
if (key === 'temp') {
if (!tempChart && tempChartRef.value) {
tempChart = echarts.init(tempChartRef.value);
tempChart.setOption(tempOption);
}
tempChart?.resize();
} else if (key === 'press') {
if (!pressChart && pressChartRef.value) {
pressChart = echarts.init(pressChartRef.value);
pressChart.setOption(pressOption);
}
pressChart?.resize();
} else if (key === 'heat') {
if (!heatChart && heatChartRef.value) {
heatChart = echarts.init(heatChartRef.value);
heatChart.setOption(heatOption);
}
heatChart?.resize();
} else if (key === 'flow') {
if (!flowChart && flowChartRef.value) {
flowChart = echarts.init(flowChartRef.value);
flowChart.setOption(flowOption);
}
flowChart?.resize();
}
});
}
defineExpose({ init });
onUnmounted(() => {
if (tempChart) { tempChart.dispose(); tempChart = null; }
if (pressChart) { pressChart.dispose(); pressChart = null; }
if (heatChart) { heatChart.dispose(); heatChart = null; }
if (flowChart) { flowChart.dispose(); flowChart = null; }
});
</script>
<style lang="less" scoped>
.wrap {
width: 80%;
margin: 0 auto;
}
.title {
text-align: center;
font-size: 16px;
font-weight: 600;
margin: 12px 0;
}
.chart-box {
width: 100%;
height: 60vh;
}
</style>