263 lines
7.6 KiB
Vue
263 lines
7.6 KiB
Vue
|
|
<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>
|