水温监测页面右侧组件完成
This commit is contained in:
parent
5695480021
commit
0a0433c3b8
@ -39,7 +39,7 @@ const initChart = () => {
|
|||||||
const option = {
|
const option = {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
trigger: 'item',
|
||||||
formatter: '{a} <br/>{b}: {c} ({d}%)',
|
formatter: '{a} {b}: {c} ({d}%)',
|
||||||
position: 'right'
|
position: 'right'
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
|
|||||||
424
frontend/src/modules/chuixiangshuiwenChangeMod/index.vue
Normal file
424
frontend/src/modules/chuixiangshuiwenChangeMod/index.vue
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
<!-- 垂向水温变化图 -->
|
||||||
|
<template>
|
||||||
|
<SidePanelItem title="垂向水温变化">
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<!-- 图例与翻页控制 -->
|
||||||
|
<div class="chart-header">
|
||||||
|
<div class="legend-container">
|
||||||
|
<div
|
||||||
|
v-for="item in currentLegendItems"
|
||||||
|
:key="item.name"
|
||||||
|
class="legend-item"
|
||||||
|
:class="{ inactive: legendInactiveSet.has(item.name) }"
|
||||||
|
@click="toggleLegend(item.name)"
|
||||||
|
>
|
||||||
|
<span class="legend-dot" :style="{ backgroundColor: legendInactiveSet.has(item.name) ? '#ccc' : item.color }"></span>
|
||||||
|
<span class="legend-text" :style="{ color: legendInactiveSet.has(item.name) ? '#ccc' : '#333' }">{{ item.name }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pagination">
|
||||||
|
<span class="page-btn" :class="{ disabled: currentPage === 1 }" @click="prevPage">◀</span>
|
||||||
|
<span class="page-info">{{ currentPage }}/{{ totalPages }}</span>
|
||||||
|
<span class="page-btn" :class="{ disabled: currentPage === totalPages }" @click="nextPage">▶</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 图表容器 -->
|
||||||
|
<div ref="chartRef" class="chart-container"></div>
|
||||||
|
</div>
|
||||||
|
</SidePanelItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import type { ECharts } from 'echarts';
|
||||||
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
|
|
||||||
|
// 定义组件名
|
||||||
|
defineOptions({
|
||||||
|
name: 'chuixiangshuiwenChangeMod'
|
||||||
|
});
|
||||||
|
|
||||||
|
const chartRef = ref<HTMLElement | null>(null);
|
||||||
|
let chartInstance: ECharts | null = null;
|
||||||
|
|
||||||
|
// 月份配置
|
||||||
|
const ITEMS_PER_PAGE = 5; // 每页显示5个月份
|
||||||
|
const currentPage = ref(1);
|
||||||
|
|
||||||
|
// 图例 inactive 状态集合
|
||||||
|
const legendInactiveSet = ref<Set<string>>(new Set());
|
||||||
|
|
||||||
|
// 12个月份的颜色配置(与设计稿一致)
|
||||||
|
const monthColors: Record<string, string> = {
|
||||||
|
'1月': '#5B9BD5',
|
||||||
|
'2月': '#70AD47',
|
||||||
|
'3月': '#7030A0',
|
||||||
|
'4月': '#ED7D31',
|
||||||
|
'5月': '#A5A5A5',
|
||||||
|
'6月': '#FFC000',
|
||||||
|
'7月': '#4472C4',
|
||||||
|
'8月': '#548235',
|
||||||
|
'9月': '#6F35A0',
|
||||||
|
'10月': '#C55A11',
|
||||||
|
'11月': '#8497B0',
|
||||||
|
'12月': '#7F7F7F'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 生成12个月份的图例数据
|
||||||
|
const allLegendItems = ref(
|
||||||
|
Object.keys(monthColors).map(month => ({
|
||||||
|
name: month,
|
||||||
|
color: monthColors[month]
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
// 计算总页数
|
||||||
|
const totalPages = computed(() => {
|
||||||
|
return Math.ceil(allLegendItems.value.length / ITEMS_PER_PAGE);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 当前页的图例项
|
||||||
|
const currentLegendItems = computed(() => {
|
||||||
|
const start = (currentPage.value - 1) * ITEMS_PER_PAGE;
|
||||||
|
const end = start + ITEMS_PER_PAGE;
|
||||||
|
return allLegendItems.value.slice(start, end);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 静态数据 - 深度数组
|
||||||
|
const depths = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
|
||||||
|
|
||||||
|
// 生成月份数据(模拟真实水温变化特征)
|
||||||
|
const generateMonthData = (monthIndex: number) => {
|
||||||
|
const baseSurfaceTemp = 2 + monthIndex * 2.2;
|
||||||
|
const deepWaterTemp = 3.5 + monthIndex * 0.3;
|
||||||
|
|
||||||
|
return depths.map((depth, index) => {
|
||||||
|
let temp;
|
||||||
|
|
||||||
|
if (depth <= 10) {
|
||||||
|
temp = baseSurfaceTemp - depth * 0.15 + Math.sin(index * 0.8) * 0.5;
|
||||||
|
} else if (depth <= 40) {
|
||||||
|
const middleFactor = (depth - 10) / 30;
|
||||||
|
temp = baseSurfaceTemp - 1.5 - middleFactor * (baseSurfaceTemp - deepWaterTemp) * 0.6;
|
||||||
|
} else {
|
||||||
|
temp = deepWaterTemp + Math.sin(index * 0.3) * 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(0, Math.round(temp * 100) / 100);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 生成所有月份的静态数据,格式为 [温度, 深度] 的二维数组
|
||||||
|
const monthData = ref(
|
||||||
|
Array.from({ length: 12 }, (_, i) => ({
|
||||||
|
month: `${i + 1}月`,
|
||||||
|
data: generateMonthData(i).map((temp, idx) => [temp, depths[idx]]) // [温度, 深度]
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
// 切换图例显示/隐藏
|
||||||
|
const toggleLegend = (name: string) => {
|
||||||
|
if (legendInactiveSet.value.has(name)) {
|
||||||
|
legendInactiveSet.value.delete(name);
|
||||||
|
} else {
|
||||||
|
legendInactiveSet.value.add(name);
|
||||||
|
}
|
||||||
|
updateChart();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上一页
|
||||||
|
const prevPage = () => {
|
||||||
|
if (currentPage.value > 1) {
|
||||||
|
currentPage.value--;
|
||||||
|
updateChart();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 下一页
|
||||||
|
const nextPage = () => {
|
||||||
|
if (currentPage.value < totalPages.value) {
|
||||||
|
currentPage.value++;
|
||||||
|
updateChart();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
const initChart = () => {
|
||||||
|
if (!chartRef.value) return;
|
||||||
|
|
||||||
|
if (chartRef.value.clientHeight === 0) {
|
||||||
|
setTimeout(() => initChart(), 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chartInstance = echarts.init(chartRef.value);
|
||||||
|
updateChart();
|
||||||
|
|
||||||
|
// 绑定图例点击事件 (如果需要与ECharts内部状态同步,虽然这里主要用自定义图例)
|
||||||
|
// chartInstance.on('legendselectchanged', (params: any) => { ... });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新图表
|
||||||
|
const updateChart = () => {
|
||||||
|
if (!chartInstance) return;
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
||||||
|
borderColor: '#ccc',
|
||||||
|
borderWidth: 1,
|
||||||
|
textStyle: {
|
||||||
|
color: '#333',
|
||||||
|
fontSize: 12
|
||||||
|
},
|
||||||
|
formatter: (params: any) => {
|
||||||
|
if (!params || !params.seriesName) return '';
|
||||||
|
|
||||||
|
const temperature = params.data[0]; // 温度值
|
||||||
|
const depth = params.data[1]; // 深度值
|
||||||
|
|
||||||
|
return `<div style="font-weight:bold;margin-bottom:8px;">${params.seriesName}</div>
|
||||||
|
<div>水温(°C):${temperature}</div>
|
||||||
|
<div>深度(m):${depth}</div>`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
show: true,
|
||||||
|
data: allLegendItems.value.map(item => ({
|
||||||
|
name: item.name,
|
||||||
|
icon: 'circle'
|
||||||
|
})),
|
||||||
|
selected: allLegendItems.value.reduce((acc, item) => {
|
||||||
|
acc[item.name] = !legendInactiveSet.value.has(item.name);
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, boolean>),
|
||||||
|
// 隐藏ECharts默认图例,使用自定义图例
|
||||||
|
top: -9999
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '70px',
|
||||||
|
right: '100px',
|
||||||
|
bottom: '60px',
|
||||||
|
top: '30px'
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'value',
|
||||||
|
position: 'top',
|
||||||
|
name: '水温(°C)',
|
||||||
|
nameLocation: 'end',
|
||||||
|
nameGap: 20,
|
||||||
|
nameTextStyle: {
|
||||||
|
color: '#666',
|
||||||
|
fontSize: 12,
|
||||||
|
align: 'right',
|
||||||
|
verticalAlign: 'top'
|
||||||
|
},
|
||||||
|
min: 0,
|
||||||
|
max: 8,
|
||||||
|
interval: null,
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#d0d0d0',
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: true,
|
||||||
|
length: 4,
|
||||||
|
inside: false,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#d0d0d0'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#666',
|
||||||
|
fontSize: 11,
|
||||||
|
margin: 6,
|
||||||
|
formatter: (value: number) => {
|
||||||
|
const showTicks = [0, 3, 6, 8];
|
||||||
|
if (showTicks.includes(value)) {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
position: 'left',
|
||||||
|
inverse: true,
|
||||||
|
min: 0,
|
||||||
|
max: 80,
|
||||||
|
interval: 20,
|
||||||
|
name: '水深(m)',
|
||||||
|
nameLocation: 'end',
|
||||||
|
nameGap: 25,
|
||||||
|
nameRotate: 0,
|
||||||
|
nameTextStyle: {
|
||||||
|
color: '#666',
|
||||||
|
fontSize: 12,
|
||||||
|
align: 'center',
|
||||||
|
verticalAlign: 'top'
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#d0d0d0',
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: true,
|
||||||
|
length: 3,
|
||||||
|
inside: false,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#d0d0d0'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#666',
|
||||||
|
fontSize: 11,
|
||||||
|
inside: false,
|
||||||
|
margin: 8
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#e5e5e5',
|
||||||
|
type: 'dashed',
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: monthData.value.map((monthItem: any) => ({
|
||||||
|
name: monthItem.month,
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 2,
|
||||||
|
lineStyle: {
|
||||||
|
width: 1,
|
||||||
|
color: monthColors[monthItem.month]
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: monthColors[monthItem.month]
|
||||||
|
},
|
||||||
|
data: monthItem.data.map((item: any) => [item[0], item[1]]),
|
||||||
|
connectNulls: false
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
|
||||||
|
chartInstance.setOption(option, { notMerge: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 组件挂载时初始化
|
||||||
|
onMounted(() => {
|
||||||
|
initChart();
|
||||||
|
|
||||||
|
// 监听窗口大小变化
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
chartInstance?.resize();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 组件卸载时清理
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
chartInstance?.dispose();
|
||||||
|
window.removeEventListener('resize', () => {
|
||||||
|
chartInstance?.resize();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-item.inactive {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-text {
|
||||||
|
font-size: 12px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
user-select: none;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-btn:hover:not(.disabled) {
|
||||||
|
border-color: #1890ff;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-btn.disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-info {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container {
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
240
frontend/src/modules/churukushuiwenMod/index.vue
Normal file
240
frontend/src/modules/churukushuiwenMod/index.vue
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
<!-- SidePanelItem.vue -->
|
||||||
|
<template>
|
||||||
|
<SidePanelItem title="出入库水温">
|
||||||
|
<div ref="chartContainer" class="chart-container"></div>
|
||||||
|
</SidePanelItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, onMounted, onUnmounted } from 'vue';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
|
|
||||||
|
// 定义组件名(便于调试和递归)
|
||||||
|
defineOptions({
|
||||||
|
name: 'churukushuiwenMod'
|
||||||
|
});
|
||||||
|
|
||||||
|
const chartContainer = ref<HTMLDivElement | null>(null);
|
||||||
|
let chartInstance: echarts.ECharts | null = null;
|
||||||
|
|
||||||
|
// 页面加载时执行的逻辑
|
||||||
|
onMounted(() => {
|
||||||
|
// 延迟初始化,确保 DOM 渲染完成
|
||||||
|
setTimeout(() => {
|
||||||
|
if (chartContainer.value) {
|
||||||
|
initChart();
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (chartInstance) {
|
||||||
|
chartInstance.dispose();
|
||||||
|
chartInstance = null;
|
||||||
|
}
|
||||||
|
window.removeEventListener('resize', handleResize);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleResize = () => {
|
||||||
|
if (chartInstance) {
|
||||||
|
chartInstance.resize();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initChart = () => {
|
||||||
|
if (!chartContainer.value) return;
|
||||||
|
|
||||||
|
// 检查容器实际高度,如果为 0 则延迟重试
|
||||||
|
const containerHeight = chartContainer.value.offsetHeight;
|
||||||
|
if (containerHeight === 0) {
|
||||||
|
setTimeout(() => initChart(), 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chartInstance = echarts.init(chartContainer.value);
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
backgroundColor: 'rgba(50, 50, 50, 0.9)',
|
||||||
|
borderColor: 'transparent',
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 14
|
||||||
|
},
|
||||||
|
axisPointer: {
|
||||||
|
type: 'line',
|
||||||
|
lineStyle: {
|
||||||
|
color: 'rgba(91, 143, 249, 0.15)',
|
||||||
|
width: 30,
|
||||||
|
type: 'solid'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
formatter: function(params: any) {
|
||||||
|
if (!params || params.length === 0) return '';
|
||||||
|
const date = params[0].name;
|
||||||
|
let result = `<div style="font-weight: bold; margin-bottom: 8px; font-size: 14px;">${date}</div>`;
|
||||||
|
params.forEach((item: any) => {
|
||||||
|
result += `<div style="display: flex; align-items: center; gap: 6px; margin: 4px 0; font-size: 14px;">
|
||||||
|
<span style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background-color: ${item.color};"></span>
|
||||||
|
<span>${item.seriesName}</span>
|
||||||
|
<span style="font-weight: bold; margin-left: auto;">${item.value}°C</span>
|
||||||
|
</div>`;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
text: '水温(°C)',
|
||||||
|
left: 17,
|
||||||
|
top: 13,
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#000000',
|
||||||
|
fontWeight: 'normal'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['入库水温', '出库水温'],
|
||||||
|
top: 13,
|
||||||
|
left: 'center',
|
||||||
|
itemWidth: 10,
|
||||||
|
itemHeight: 10,
|
||||||
|
itemGap: 20,
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#000000'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '10%',
|
||||||
|
right: '5%',
|
||||||
|
top: '15%',
|
||||||
|
bottom: '18%'
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: ['2026-04-01', '2026-04-02', '2026-04-03', '2026-04-04', '2026-04-05', '2026-04-06', '2026-04-07'],
|
||||||
|
boundaryGap: true,
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#000000'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#000000',
|
||||||
|
fontSize: 13,
|
||||||
|
margin: 10,
|
||||||
|
interval: 2
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#bfbfbf',
|
||||||
|
type: 'solid'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
type: 'inside',
|
||||||
|
start: 0,
|
||||||
|
end: 100,
|
||||||
|
minValueSpan: 2,
|
||||||
|
zoomOnMouseWheel: true,
|
||||||
|
moveOnMouseMove: true,
|
||||||
|
moveOnMouseWheel: false,
|
||||||
|
zoomLock: false,
|
||||||
|
throttle: 50
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
min: 5.2,
|
||||||
|
max: 5.9,
|
||||||
|
interval: 0.1,
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#000000',
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#000000',
|
||||||
|
width: 1
|
||||||
|
},
|
||||||
|
length: 4
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#000000',
|
||||||
|
fontSize: 12,
|
||||||
|
formatter: '{value}'
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#bfbfbf',
|
||||||
|
type: 'solid'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '入库水温',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 6,
|
||||||
|
lineStyle: {
|
||||||
|
width: 2,
|
||||||
|
color: '#4b79ab'
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: '#4b79ab'
|
||||||
|
},
|
||||||
|
data: [5.4, 5.3, 5.6, 5.4, 5.5, 5.6, 5.6]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '出库水温',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 6,
|
||||||
|
lineStyle: {
|
||||||
|
width: 2,
|
||||||
|
color: '#78c300'
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: '#78c300'
|
||||||
|
},
|
||||||
|
data: [5.8, 5.8, 5.8, 5.8, 5.8, 5.8, 5.8]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
chartInstance.setOption(option);
|
||||||
|
|
||||||
|
// 强制重绘,确保图表尺寸正确适配容器
|
||||||
|
setTimeout(() => {
|
||||||
|
if (chartInstance) {
|
||||||
|
chartInstance.resize();
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.chart-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 252px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,10 +1,9 @@
|
|||||||
<!-- SidePanelItem.vue -->
|
<!-- SidePanelItem.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div class="carousel-container">
|
|
||||||
<SidePanelItem title="典型设施介绍">
|
<SidePanelItem title="典型设施介绍">
|
||||||
<div v-if="carouselData.length > 0" class="carousel-wrapper">
|
<div v-if="carouselData.length > 0" class="carousel-wrapper">
|
||||||
<a-carousel v-model:current="currentIndex" autoplay class="tech-carousel"
|
<a-carousel v-model:current="currentIndex" class="tech-carousel" :dot-style="{ bottom: '0px' }">
|
||||||
:dot-style="{ bottom: '0px' }">
|
<!-- autoplay -->
|
||||||
<div v-for="(item, index) in carouselData" :key="index" class="carousel-item">
|
<div v-for="(item, index) in carouselData" :key="index" class="carousel-item">
|
||||||
<div class="image-container">
|
<div class="image-container">
|
||||||
<img :src="item.image" :alt="item.title" class="carousel-image" />
|
<img :src="item.image" :alt="item.title" class="carousel-image" />
|
||||||
@ -21,7 +20,6 @@
|
|||||||
<a-empty />
|
<a-empty />
|
||||||
</div>
|
</div>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -67,93 +65,64 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
|
||||||
.carousel-wrapper {
|
.carousel-wrapper {
|
||||||
width: 100%;
|
:deep(.slick-slide) {
|
||||||
|
text-align: center;
|
||||||
:deep(.ant-carousel) {
|
height: 250px;
|
||||||
width: 100%;
|
line-height: 160px;
|
||||||
|
background: #364d79;
|
||||||
.slick-slide {
|
|
||||||
height: auto !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slick-dots {
|
|
||||||
bottom: 0px !important;
|
|
||||||
margin: 0;
|
|
||||||
padding: 8px 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 6px;
|
|
||||||
|
|
||||||
li {
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
margin: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
|
|
||||||
button {
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
background-color: #005293;
|
|
||||||
opacity: 0.3;
|
|
||||||
border-radius: 50%;
|
|
||||||
transition: all 0.3s;
|
|
||||||
padding: 0;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.slick-active button {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
opacity: 1;
|
|
||||||
background-color: #005293;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-item {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container {
|
|
||||||
width: 100%;
|
|
||||||
background-color: #f5f0e1; // 米黄色背景
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-image {
|
:deep() {
|
||||||
width: 100%;
|
.ant-carousel .slick-dots li {
|
||||||
height: auto;
|
width: 5px !important;
|
||||||
display: block;
|
height: 5px !important;
|
||||||
object-fit: contain; // 保持图片比例,完整显示
|
border-radius: 50% !important;
|
||||||
|
background-color: #888e95;
|
||||||
|
|
||||||
|
}
|
||||||
|
.ant-carousel .slick-dots li button{
|
||||||
|
width: 5px !important;
|
||||||
|
height: 5px !important;
|
||||||
|
border-radius: 50% !important;
|
||||||
|
background-color: #888e95;
|
||||||
|
}
|
||||||
|
.ant-carousel .slick-dots li.slick-active{
|
||||||
|
background-color: #005293 !important;
|
||||||
|
}
|
||||||
|
.ant-carousel .slick-dots li.slick-active button{
|
||||||
|
background-color: #005293 !important;
|
||||||
|
}
|
||||||
|
.ant-carousel .slick-dots li :hover {
|
||||||
|
width: 5px !important;
|
||||||
|
height: 5px !important;
|
||||||
|
border-radius: 50% !important;
|
||||||
|
background-color: #ffffffcc;
|
||||||
|
|
||||||
|
}
|
||||||
|
.ant-carousel .slick-dots li button :hover{
|
||||||
|
width: 5px !important;
|
||||||
|
height: 5px !important;
|
||||||
|
border-radius: 50% !important;
|
||||||
|
background-color: #ffffffcc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.description-container {
|
.description-container {
|
||||||
padding: 12px 0 0 0;
|
height: 44px;
|
||||||
text-align: left;
|
width: 100%;
|
||||||
|
margin-top: 6px;
|
||||||
|
line-height: 22px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
word-break: break-all;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
text-indent: 0em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #1f1f1f;
|
|
||||||
margin: 0 0 8px 0;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-description {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #595959;
|
|
||||||
margin: 0;
|
|
||||||
line-height: 1.8;
|
|
||||||
text-align: justify;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -6,7 +6,7 @@
|
|||||||
<div v-for="facility in facilities" :key="facility.name" class="facility-card">
|
<div v-for="facility in facilities" :key="facility.name" class="facility-card">
|
||||||
<div style="width: 60px;height: 62px;display: flex;align-items: center;justify-content: center;">
|
<div style="width: 60px;height: 62px;display: flex;align-items: center;justify-content: center;">
|
||||||
<div class="facility-icon">
|
<div class="facility-icon">
|
||||||
<img width="18" height="14" :src="facility.icon ">
|
<img style="width: 18px;height: 14px;" :src="facility.icon ">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ onMounted(() => {
|
|||||||
flex-flow: wrap;
|
flex-flow: wrap;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-top: -7px;
|
margin-top: -8px;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
<!-- DataTable.vue -->
|
<!-- DataTable.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div class="data-table-container">
|
<div class="data-table-container">
|
||||||
<a-table :columns="columns" :data-source="tableData" :pagination="false" size="middle" :customRow="customRow" bordered
|
<a-table :columns="columns" :data-source="tableData" :pagination="false" size="middle" :customRow="customRow"
|
||||||
class="custom-table">
|
bordered class="custom-table">
|
||||||
</a-table>
|
</a-table>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -23,7 +23,7 @@ const columns: ColumnsType = [
|
|||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
width: 114,
|
width: 114.19,
|
||||||
align: 'left'
|
align: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -35,21 +35,21 @@ const columns: ColumnsType = [
|
|||||||
title: '总计',
|
title: '总计',
|
||||||
dataIndex: 'total',
|
dataIndex: 'total',
|
||||||
key: 'total',
|
key: 'total',
|
||||||
// // width: 76,
|
width: 76.64,
|
||||||
align: 'center'
|
align: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '已建',
|
title: '已建',
|
||||||
dataIndex: 'built',
|
dataIndex: 'built',
|
||||||
key: 'built',
|
key: 'built',
|
||||||
// width: 76,
|
width: 76.64,
|
||||||
align: 'center'
|
align: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '在建',
|
title: '在建',
|
||||||
dataIndex: 'building',
|
dataIndex: 'building',
|
||||||
key: 'building',
|
key: 'building',
|
||||||
// width: 76,
|
width: 68.25,
|
||||||
align: 'center'
|
align: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -215,6 +215,7 @@ onMounted(() => {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
// border: 1px solid #d5e2ed;
|
// border: 1px solid #d5e2ed;
|
||||||
border-top: 1px solid #d5e2ed;
|
border-top: 1px solid #d5e2ed;
|
||||||
|
|
||||||
.ant-table-thead {
|
.ant-table-thead {
|
||||||
>tr {
|
>tr {
|
||||||
>th {
|
>th {
|
||||||
@ -222,8 +223,10 @@ border-top: 1px solid #d5e2ed;
|
|||||||
color: #2f6b98;
|
color: #2f6b98;
|
||||||
// font-weight: 600;
|
// font-weight: 600;
|
||||||
// border: 1px solid #d5e2ed!important;
|
// border: 1px solid #d5e2ed!important;
|
||||||
padding: 4px 6px;
|
padding: 0px 6px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 31px;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
background-color: #e5eff8 !important;
|
background-color: #e5eff8 !important;
|
||||||
@ -247,8 +250,10 @@ border-top: 1px solid #d5e2ed;
|
|||||||
>tr {
|
>tr {
|
||||||
>td {
|
>td {
|
||||||
// border: 1px solid #d5e2ed;
|
// border: 1px solid #d5e2ed;
|
||||||
padding: 6px 6px;
|
padding: 0px 6px !important;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
line-height: 33px;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@ -262,55 +267,33 @@ border-top: 1px solid #d5e2ed;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-table-footer {
|
|
||||||
padding: 0;
|
|
||||||
background-color: #fafafa;
|
|
||||||
|
|
||||||
.table-footer {
|
|
||||||
.footer-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 12px 6px;
|
|
||||||
// border-top: 1px solid #d5e2ed;
|
|
||||||
background-color: #fafafa;
|
|
||||||
|
|
||||||
.footer-item {
|
|
||||||
flex: 1;
|
|
||||||
text-align: center;
|
|
||||||
// font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
flex: 0 0 140px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移除默认的 footer 单元格样式
|
// 移除默认的 footer 单元格样式
|
||||||
.ant-table-footer::before {
|
.ant-table-footer::before {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep() {
|
:deep() {
|
||||||
.ant-table-bordered .ant-table-tbody>tr>td {
|
.ant-table-bordered .ant-table-tbody>tr>td {
|
||||||
border-bottom: 1px solid #d5e2ed !important;
|
border-bottom: 1px solid #d5e2ed !important;
|
||||||
border-inline-end: 1px solid #d5e2ed !important;
|
border-inline-end: 1px solid #d5e2ed !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-table-container {
|
.ant-table-container {
|
||||||
border-inline-start: 1px solid #d5e2ed !important;
|
border-inline-start: 1px solid #d5e2ed !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-table-wrapper .ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>thead>tr:not(:last-child)>th {
|
.ant-table-wrapper .ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>thead>tr:not(:last-child)>th {
|
||||||
border-bottom: 1px solid #d5e2ed !important;
|
border-bottom: 1px solid #d5e2ed !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-table-wrapper .ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>thead>tr>th {
|
.ant-table-wrapper .ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>thead>tr>th {
|
||||||
border-inline-end: 1px solid #d5e2ed !important;
|
border-inline-end: 1px solid #d5e2ed !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-table-wrapper .ant-table-thead>tr>th {
|
.ant-table-wrapper .ant-table-thead>tr>th {
|
||||||
border-bottom: 0px solid #d5e2ed !important;
|
border-bottom: 1px solid #d5e2ed00 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,106 @@
|
|||||||
|
<!-- SidePanelItem.vue -->
|
||||||
|
<template>
|
||||||
|
<SidePanelItem title="水温监测工作开展情况">
|
||||||
|
<div class="facility-grid" >
|
||||||
|
<div v-for="facility in facilities" :key="facility.name" class="facility-card">
|
||||||
|
<div style="width: 60px;height: 62px;display: flex;align-items: center;justify-content: center;">
|
||||||
|
<div class="facility-icon">
|
||||||
|
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="facility-info">
|
||||||
|
<div class="facility-name">{{ facility.name }}</div>
|
||||||
|
<div style="font-size: 16px;"> <span class="facility-count">{{ facility.count }}</span><span>个</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SidePanelItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
|
|
||||||
|
// 定义组件名(便于调试和递归)
|
||||||
|
defineOptions({
|
||||||
|
name: 'shuiwenjiancegongzuokaizhangqingkuang'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 设施数据
|
||||||
|
const facilities = ref([
|
||||||
|
{
|
||||||
|
name: '表层水温',
|
||||||
|
count: 145,
|
||||||
|
icon: 'icon iconfont icon-shuizhijiancezhan'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '垂向水温',
|
||||||
|
count: 24,
|
||||||
|
icon: 'icon iconfont icon-diwenshuijianhuan'
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 页面加载时执行的逻辑
|
||||||
|
onMounted(() => {
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.facility-grid {
|
||||||
|
width: 406px;
|
||||||
|
flex-flow: wrap;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
||||||
|
}
|
||||||
|
|
||||||
|
.facility-card {
|
||||||
|
width: 200px;
|
||||||
|
height: 64px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 4px 0px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #e8e8e8;
|
||||||
|
border-radius: 2px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.facility-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
// margin-right: 8px;
|
||||||
|
background: #2f6b98;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.facility-info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.facility-name {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
// margin-bottom: 4px;
|
||||||
|
// font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.facility-count {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #2f6b98;
|
||||||
|
// font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
221
frontend/src/modules/yanchengshuiwenChangeMod/index.vue
Normal file
221
frontend/src/modules/yanchengshuiwenChangeMod/index.vue
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
<!-- SidePanelItem.vue -->
|
||||||
|
<template>
|
||||||
|
<SidePanelItem title="沿程水温变化" :prompt="prompts">
|
||||||
|
<div ref="chartRef" class="chart-container"></div>
|
||||||
|
</SidePanelItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import type { ECharts } from 'echarts';
|
||||||
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
|
|
||||||
|
// 定义组件名(便于调试和递归)
|
||||||
|
defineOptions({
|
||||||
|
name: 'yanchengshuiwenChangeMod'
|
||||||
|
});
|
||||||
|
|
||||||
|
const prompts = ref({
|
||||||
|
show: true,
|
||||||
|
value: '注:最新数据时间为2026-04-08 23',
|
||||||
|
});
|
||||||
|
|
||||||
|
const chartRef = ref<HTMLElement | null>(null);
|
||||||
|
let chartInstance: ECharts | null = null;
|
||||||
|
|
||||||
|
// 静态数据 - 站点名称
|
||||||
|
const stationNames = ref([
|
||||||
|
'班多',
|
||||||
|
'龙羊峡',
|
||||||
|
'拉西瓦',
|
||||||
|
'李家峡',
|
||||||
|
'公伯峡',
|
||||||
|
'苏只',
|
||||||
|
'积石峡'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 静态数据 - 水温值 (°C),班多无数据设为 null
|
||||||
|
const waterTemperatures = ref([
|
||||||
|
null,
|
||||||
|
5.7,
|
||||||
|
5.7,
|
||||||
|
6.5,
|
||||||
|
7.2,
|
||||||
|
7.8,
|
||||||
|
8.4
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 静态时间数据
|
||||||
|
const currentTime = '2026-04-08 23';
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
const initChart = () => {
|
||||||
|
if (!chartRef.value) return;
|
||||||
|
|
||||||
|
chartInstance = echarts.init(chartRef.value);
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: '水温(°C)',
|
||||||
|
left: 5,
|
||||||
|
top: 0,
|
||||||
|
textStyle: {
|
||||||
|
color: '#000000',
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 'normal',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
formatter: (params: any) => {
|
||||||
|
if (params && params.length > 0) {
|
||||||
|
const data = params[0];
|
||||||
|
// 过滤掉 null 值的数据点
|
||||||
|
if (data.value !== null && data.value !== undefined) {
|
||||||
|
return `${currentTime}<br/>${data.name}:${data.value}°C`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
top: '15%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: stationNames.value,
|
||||||
|
boundaryGap: true,
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#8f8f8f'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#333',
|
||||||
|
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 `; // 上方标签:文字 + 换行 + 空格占位
|
||||||
|
} else {
|
||||||
|
return ` \n${value}`; // 下方标签:空格占位 + 换行 + 文字
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#e0e0e0',
|
||||||
|
type: 'solid'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
min: 0,
|
||||||
|
max: 10,
|
||||||
|
interval: 2,
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#8f8f8f'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: true,
|
||||||
|
length: 3,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#8f8f8f'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#333',
|
||||||
|
fontSize: 12
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#e0e0e0',
|
||||||
|
type: 'solid'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '水温',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 6,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#6ca4f7',
|
||||||
|
width: 2
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: '#6ca4f7'
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgba(108, 164, 247, 0.3)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgba(108, 164, 247, 0.05)'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
},
|
||||||
|
data: waterTemperatures.value
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
chartInstance.setOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理窗口大小变化
|
||||||
|
const handleResize = () => {
|
||||||
|
chartInstance?.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面加载时执行的逻辑
|
||||||
|
onMounted(() => {
|
||||||
|
// 延迟初始化,确保 DOM 渲染完成
|
||||||
|
setTimeout(() => {
|
||||||
|
initChart();
|
||||||
|
// 强制重绘,确保尺寸正确
|
||||||
|
setTimeout(() => {
|
||||||
|
chartInstance?.resize();
|
||||||
|
}, 100);
|
||||||
|
}, 50);
|
||||||
|
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 组件卸载前清理
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('resize', handleResize);
|
||||||
|
chartInstance?.dispose();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.chart-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 252px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,5 +1,25 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
||||||
|
import RightDrawer from "@/components/RightDrawer/index.vue";
|
||||||
|
import ChuixiangshuiwenChangeMod from "@/modules/chuixiangshuiwenChangeMod/index.vue" // 垂向水温变化
|
||||||
|
import ChurukushuiwenMod from "@/modules/churukushuiwenMod/index.vue" // 出入库水温变化
|
||||||
|
import YanchengshuiwenChangeMod from "@/modules/yanchengshuiwenChangeMod/index.vue" // 沿程水温变化
|
||||||
|
import ShuiwenJCGZKZQK from "@/modules/shuiwenjiancegongzuokaizhangqingkuang/index.vue"
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="moduleContent">
|
||||||
<h2>水温监测</h2>
|
<div class="leftContent">
|
||||||
|
<JidiSelectorMod />
|
||||||
|
</div>
|
||||||
|
<div class="rightContent">
|
||||||
|
<RightDrawer>
|
||||||
|
<ShuiwenJCGZKZQK />
|
||||||
|
<YanchengshuiwenChangeMod />
|
||||||
|
<ChuixiangshuiwenChangeMod />
|
||||||
|
<ChurukushuiwenMod />
|
||||||
|
</RightDrawer>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user