web
7 天以前 9631059731ceb3e119101de3f7e27f6dd76da324
src/views/screen/temperature/graphic/index.vue
@@ -1,4 +1,247 @@
<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>
@@ -6,20 +249,102 @@
    <div class="graphic">
        <div class="graphic-menu">
            <div class="menu-t">监测点列表</div>
            <el-menu class="el-menu">
                <el-sub-menu index="1">
                    <template #title>
                        <span>可移动监测点</span>
            <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>
                    <el-menu-item index="1-1">水电站流量监测点</el-menu-item>
                </el-sub-menu>
                <el-sub-menu index="2">
                    <template #title>
                        <span>固定位监测点</span>
                    <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>
                    <el-menu-item index="2-1">新扎口流量监测点</el-menu-item>
                </el-sub-menu>
                </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>
@@ -28,6 +353,7 @@
.graphic {
    height: 100%;
    display: flex;
    &-menu {
        flex-shrink: 0;
        width: 20%;
@@ -67,5 +393,66 @@
            }
        }
    }
    .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>