grgw_vue_2025/src/views/screen/components/ZxtCQ.vue

293 lines
8.0 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>
<span class="close-btn2" @click="closeModal"><span style="color: white;">×</span></span>
</div>
<div class="wrap">
<!-- 页面顶部中间显示 公司/锅炉房/换热站 -->
<div class="title">{{ headerText }}</div>
<!-- Tabs -->
<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-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 { list } from '/@/views/heating/history/HeatanalysisHistory.api';
const emit = defineEmits(['close']);
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);
let tempChart: echarts.ECharts | null = null;
let pressChart: echarts.ECharts | null = null;
let tempOption: any = null;
let pressOption: 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, r.view004Name].filter(v => v && v !== '');
// 用箭头连接
return names.join(' → ');
}
function initChartsOptions(records: any[]) {
records.sort((a: any, b: any) => new Date(a.datatime).getTime() - new Date(b.datatime).getTime());
const xAxis = records.map((r: any) => r.datatime);
const tempSeries = [
{ name: '一次供水温度', key: 'view005', color: '#00c6ff' }, // 直接使用颜色而不是渐变
{ name: '一次回水温度', key: 'view006', color: '#ff6a00' },
{ name: '二次供水温度', key: 'view009', color: '#ff007f' },
{ name: '二次回水温度', key: 'view010', color: '#6a5acd' },
].map(s => ({
name: s.name,
type: 'line',
showSymbol: false,
connectNulls: false,
lineStyle: { width: 2 }, // 设置线条的宽度
itemStyle: {
color: s.color, // 设置折线的颜色
},
data: records.map((r: any) => safeNum(r[s.key])),
}));
const pressSeries = [
{ name: '一次供水压力', key: 'view007', color: '#00c6ff' },
{ name: '一次回水压力', key: 'view008', color: '#ff6a00' },
{ name: '二次供水压力', key: 'view011', color: '#ff007f' },
{ name: '二次回水压力', key: 'view012', color: '#6a5acd' },
].map(s => ({
name: s.name,
type: 'line',
showSymbol: false,
connectNulls: false,
lineStyle: { width: 2 }, // 设置线条的宽度
itemStyle: {
color: s.color, // 设置折线的颜色
},
data: records.map((r: any) => safeNum(r[s.key])),
}));
const baseOption = {
tooltip: { trigger: 'axis', axisPointer: { type: 'cross' } },
legend: { top: 36, left: 'center', textStyle: { color: '#ffffff' } }, // 设置折线图legend文字为白色
grid: { left: '5%', right: '5%', bottom: 70, top: 70, containLabel: true },
xAxis: {
type: 'category',
data: xAxis,
boundaryGap: false,
axisLabel: {
interval: 0,
formatter: (val: string) => val.replace(' ', '\n'),
color: '#ffffff' // 设置x轴文字颜色为白色
},
},
yAxis: { type: 'value', scale: true, axisLabel: { color: '#ffffff' } }, // 设置y轴文字颜色为白色
};
tempOption = { ...baseOption, title: { text: '温度指标', left: 'center', top: 8, textStyle: { color: '#ffffff' } }, series: tempSeries };
pressOption = { ...baseOption, title: { text: '压力指标', left: 'center', top: 8, textStyle: { color: '#ffffff' } }, series: pressSeries };
}
let resizeAdded = false;
function ensureResizeListener() {
if (resizeAdded) return;
const onResize = () => {
tempChart?.resize();
pressChart?.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: record_.view004 || -1,
SDateStr: formatDateTime(start),
EDateStr: formatDateTime(end),
};
list(params).then((res: any) => {
const records = (res && res.records) ? res.records : [];
headerText.value = buildHeader(records, record_);
initChartsOptions(records);
nextTick(() => {
// 初始化温度图表默认tab
if (tempChartRef.value) {
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();
}
});
}
function closeModal() {
emit('close')
}
defineExpose({ init });
onUnmounted(() => {
if (tempChart) { tempChart.dispose(); tempChart = null; }
if (pressChart) { pressChart.dispose(); pressChart = null; }
});
</script>
<style lang="less" scoped>
.close-btn2 {
position: absolute;
top: 10px;
right: 10px;
float: right;
color: white;
cursor: pointer;
z-index: 299;
}
.wrap {
width: 100%;
margin: 0 auto;
background: linear-gradient(135deg, rgba(20, 35, 55, 0.85), rgba(0, 20, 40, 0.7));
/* 渐变背景色 */
padding: 20px;
border-radius: 15px;
/* 增加圆角 */
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
/* 添加阴影 */
backdrop-filter: blur(10px);
/* 背景模糊效果 */
}
.title {
text-align: center;
font-size: 24px;
font-weight: 700;
margin: 20px 0;
color: #ffffff;
background: linear-gradient(135deg, #66d9ff, #ff8c00);
/* 渐变文字 */
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.5);
/* 增加文字的荧光效果 */
}
.chart-box {
width: 100%;
height: 60vh;
background-color: rgba(0, 0, 0, 0.3);
/* 深色背景让图表突出 */
border-radius: 12px;
/* 圆角效果 */
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
/* 给图表增加阴影 */
overflow: hidden;
}
a-tabs {
background-color: rgba(0, 0, 0, 0.5);
/* Tab 背景色 */
border-radius: 8px;
}
a-tab-pane {
background-color: rgba(255, 255, 255, 0.836);
/* Tab 选项卡背景 */
border-radius: 8px;
}
a-tab-pane .ant-tabs-tab {
font-size: 16px;
font-weight: bold;
color: #ffffff;
/* 确保未选中的 Tab 文字为白色 */
padding: 10px 20px;
}
a-tab-pane .ant-tabs-tab-active {
background-color: #ff8c00;
/* 激活的Tab颜色 */
color: #ffffff;
}
a-tab-pane .ant-tabs-tab:hover {
color: #ffffff;
/* hover时也为白色 */
}
:deep .ant-tabs-tab-btn {
color: white;
}
</style>