From c6159b0a5a424250adeca1bc2b475da5324fe038 Mon Sep 17 00:00:00 2001 From: web <candymxq888@outlook.com> Date: 星期五, 18 四月 2025 17:16:30 +0800 Subject: [PATCH] fix:对接报表数据 --- src/views/screen/temperature/graphic/index.vue | 449 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 447 insertions(+), 2 deletions(-) diff --git a/src/views/screen/temperature/graphic/index.vue b/src/views/screen/temperature/graphic/index.vue index 5efa2d0..235ce02 100644 --- a/src/views/screen/temperature/graphic/index.vue +++ b/src/views/screen/temperature/graphic/index.vue @@ -1,13 +1,458 @@ <script setup> +import {ref, onMounted, watch} from "vue"; +import * as echarts from 'echarts/core'; +import {getTemperaturePointList} from '@/api/screen/index.js' +import Quarter from "@/components/Quarter"; +import moment from "moment"; +import { getGraphicData } from '@/api/screen/graphic/index.js' + + +const menuList = ref([]) +const timeType = ref(1) //时间类型 1日 2周 3月 4季 5年 +const showTime = ref(moment().format('YYYY-MM-DD')); //展示时间 +const timeValue = ref(moment().format('YYYY-MM-DD')) //处理后得时间 +const searchVal = ref() +const graphicRef = ref(null) +const chartsRef = ref([]) //动态生成图表ref +const chartData = ref([]) +let charts = [] + +// 动态设置ref +const setChartsRef = (el, index) => { + if (el) { + chartsRef.value[index] = el + charts[index] = 'charts' + index + } +} + +// 获取图表配置 +const getChartsOptions = (data, unit) => { + let xdata = []; + let Hdata = []; + let Adata = []; + let Ldata = []; + if (data) { + data.dataVOList.forEach(item => { + xdata.push(item.dataTime) + Hdata.push(item.maxValue); + Adata.push(item.avgValue); + Ldata.push(item.minValue); + }) + } + return { + title: { + text: data.pointName, + left: '3%', + textStyle: { + color: '#fff', + } + }, + tooltip: { + trigger: 'axis', + }, + color: ['#D4B3E3FF', '#00DDFFFF', '#ABFA97FF'], + legend: { + top: 0, + data: ['最高水温', '平均水温', '最低水温'], + textStyle: { + color: '#fff' + } + }, + grid: { + left: '4%', + right: '5%', + bottom: '3%', + containLabel: true + }, + xAxis: { + type: 'category', + boundaryGap: false, + data: xdata, + axisLabel: { + color: '#fff', + fontSize: '1rem' + } + }, + yAxis: { + type: 'value', + name: unit, + max: 40, + min: 0, + nameTextStyle: { + color: '#fff', + fontSize: '1rem' + }, + axisLabel: { + color: '#fff', + fontSize: '1rem' + } + }, + series: [ + { + name: '最高水温', + data: Hdata, + type: 'line', + areaStyle: { + opacity: 0.8, + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { + offset: 0, + color: 'rgb(212,179,227)' + }, + { + offset: 1, + color: 'rgba(212,179,227,0)' + } + ]) + }, + }, + { + name: '平均水温', + data: Adata, + type: 'line', + areaStyle: { + opacity: 0.8, + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { + offset: 0, + color: 'rgb(0, 221, 255)' + }, + { + offset: 1, + color: 'rgba(0,221,255,0)' + } + ]) + }, + }, + { + name: '最低水温', + data: Ldata, + type: 'line', + areaStyle: { + opacity: 0.8, + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { + offset: 0, + color: 'rgb(171,250,151)' + }, + { + offset: 1, + color: 'rgba(171,250,151,0)' + } + ]) + }, + } + ] + } +} + +// 选择时间类型 +const changeType = (type) => { + timeType.value = type; + showTime.value = '' +} + +// 初始化图表 +const initCharts = () => { + chartData.value.forEach((item, index) => { + if (chartsRef.value[index]) { + charts[index] = echarts.init(chartsRef.value[index]) + const option = getChartsOptions(item, '℃') + charts[index].setOption(option) + } + }) +} + +// 全屏操作 +const handleFullScreen = () => { + graphicRef.value.requestFullscreen() +} + +// 一键导出 +const handleExport = () => { + charts?.forEach((chart, index) => { + const imgData = chart.getDataURL({ + type: 'png', // 也可以是 'jpeg' + pixelRatio: 2, // 提高导出图片的分辨率 + backgroundColor: 'rgba(23, 108, 229, 0.3)' + }); + + // 创建下载链接 + const link = document.createElement('a'); + link.href = imgData; + link.download = `chart_${index + 1}.png`; + link.click(); + }) +} + +// 获取时间 +const getTime = (value) => { + const momentValue = moment(value) + const time = momentValue.format('YYYY-MM-DD') + let data = '' + switch (timeType.value) { + case 1: + data = '' + break; + case 2: + data = momentValue.add(1, 'week').format('YYYY-MM-DD') + break; + case 3: + data = momentValue.add(1, 'month').format('YYYY-MM-DD') + break; + case 4: + data = momentValue.add(1, 'quarter').format('YYYY-MM-DD') + break; + case 5: + data = momentValue.add(1, 'year').format('YYYY-MM-DD') + break; + default: + break; + } + if(data) { + timeValue.value = time + '~' + data + } else { + timeValue.value = time + } +} + +// 获取水温监控点菜单 +const getTempMonitor = () => { + getTemperaturePointList().then(res => { + menuList.value = res.data + }) +} + +// 获取报表数据 +const getChartData = (point = '') => { + const data = { + type: timeType.value, + pointId: point, + pointName: searchVal.value, + dataTime: timeValue.value, + } + getGraphicData(data).then(async res => { + chartData.value = res.data + await nextTick() + initCharts() + }) +} + +onMounted(() => { + getTempMonitor() + getChartData() +}) </script> <template> - <div> - 图形分析 + <div class="graphic"> + <div class="graphic-menu"> + <div class="menu-t">监测点列表</div> + <el-menu class="el-menu" @select="getChartData"> + <template v-for="(item, index) in menuList" :key="index+1"> + <template v-if="item?.childrenList?.length === 0"> + <el-menu-item :index="item.id">{{ item.pointName }}</el-menu-item> + </template> + <template v-else> + <el-sub-menu :index="item.id"> + <template #title> + <span>{{ item.pointName }}</span> + </template> + <el-menu-item v-for="(child, cidx) in item.childrenList" :key="cidx" :index="child.id"> + {{ child.pointName }} + </el-menu-item> + </el-sub-menu> + </template> + </template> + </el-menu> + </div> + <div class="graphic-info"> + <div class="graphic-tool"> + <div class="tool-l"> + <div class="name">类型</div> + <el-button-group class="ml-4"> + <el-button :type="timeType === 1 ? 'primary' : ''" @click="changeType(1)">日 + </el-button> + <el-button :type="timeType === 2 ? 'primary' : ''" @click="changeType(2)">周 + </el-button> + <el-button :type="timeType === 3 ? 'primary' : ''" @click="changeType(3)">月 + </el-button> + <el-button :type="timeType === 4 ? 'primary' : ''" @click="changeType(4)">季 + </el-button> + <el-button :type="timeType === 5 ? 'primary' : ''" @click="changeType(5)">年 + </el-button> + </el-button-group> + <el-date-picker + v-if="timeType === 1" + v-model="showTime" + type="date" + placeholder="选择时间" + style="width: 15rem" + @change="getTime" + /> + <el-date-picker + v-if="timeType === 2" + v-model="showTime" + type="week" + format="YYYY年 ww[周]" + placeholder="选择时间" + style="width: 15rem" + @change="getTime" + /> + <el-date-picker + v-if="timeType === 3" + v-model="showTime" + type="month" + placeholder="选择时间" + style="width: 15rem" + @change="getTime" + /> + <Quarter + v-if="timeType === 4" + placeholder="选择时间" + :default-value="showTime" + clearable + style="width: 15rem" + @change="getTime" + /> + <el-date-picker + v-if="timeType === 5" + v-model="showTime" + type="year" + placeholder="选择时间" + style="width: 15rem" + @change="getTime" + /> + <el-input v-model="searchVal" style="width: 15rem" clearable placeholder="请输入监测点名称"/> + <el-button @click="() => getChartData()"> + <el-icon> + <Search/> + </el-icon> + 搜索 + </el-button> + <el-button type="success" @click="handleExport">一键导出</el-button> + </div> + <div class="tool-r" @click="handleFullScreen"> + <img src="@/assets/images/flow/fullscreen.png"/> + 全屏 + </div> + </div> + <div class="graphic-box" ref="graphicRef"> + <div class="chartList"> + <div class="chartItem" v-for="(item, index) in chartData"> + <div class="charts" :ref="el => setChartsRef(el, index)"></div> + </div> + </div> + </div> + </div> </div> </template> <style scoped lang="scss"> +.graphic { + height: 100%; + display: flex; + &-menu { + flex-shrink: 0; + width: 20%; + height: 100%; + padding: 10px 0; + background: linear-gradient(135deg, #91BDDB 0%, #9EC2DB 99%); + overflow-y: scroll; + + &::-webkit-scrollbar { + display: none; + } + + .menu-t { + height: 40px; + line-height: 40px; + padding-left: 20px; + font-size: 26px; + color: #fff; + background: url("@/assets/images/flow/monitor-title-bg.png") no-repeat; + background-size: 100% 100%; + } + + .el-menu { + background-color: transparent; + border-right: none; + + :deep(.el-menu) { + background-color: transparent; + } + + :deep(.el-sub-menu__title:hover) { + background-color: rgba(0, 0, 0, 0.06); + } + + :deep(.el-menu-item.is-active) { + color: #fff; + } + } + } + + .graphic-info { + flex-shrink: 0; + width: 80%; + height: 100%; + + .graphic-tool { + width: 100%; + height: 60px; + padding: 0 30px; + background: linear-gradient(90deg, #91BDDB 0%, #DADFE3 100%); + display: flex; + align-items: center; + justify-content: space-between; + + .tool-l { + display: flex; + align-items: center; + gap: 1rem; + + .name { + font-size: 1.1rem; + } + } + + .tool-r { + display: flex; + align-items: center; + + img { + width: 25px; + margin-right: 10px; + } + } + } + + .graphic-box { + height: calc(100% - 60px); + padding: 10px 30px; + background: linear-gradient(180deg, #91BDDB 0%, rgba(102, 102, 102, 0.5) 100%); + + .chartList { + height: 100%; + display: flex; + flex-wrap: wrap; + gap: 20px; + + .chartItem { + width: 100%; + min-height: 48%; + background: rgba(23, 108, 229, 0.3); + border: 1px solid #176CE5; + border-radius: 8px; + + .charts { + height: 100%; + } + } + } + } + } +} </style> \ No newline at end of file -- Gitblit v1.9.3