This commit is contained in:
扈兆增 2026-06-17 11:22:17 +08:00
commit 826261a7a2
18 changed files with 4716 additions and 1109 deletions

View File

@ -2,7 +2,7 @@ import request from '@/utils/request';
//生态流量达标情况
export function qgcetQgcStaticData(data: any) {
return request({
url: '/api/wmp-eng-server/eng/eq/interval/qgc/getQgcStaticData',
url: '/eq/interval/qgc/getQgcStaticData',
method: 'post',
data
});
@ -10,7 +10,7 @@ export function qgcetQgcStaticData(data: any) {
//tabs 日
export function dayGetKendoListCust(data: any) {
return request({
url: '/api/wmp-eng-server/eng/eq/interval/qgc/day/GetKendoListCust',
url: '/eq/interval/qgc/day/GetKendoListCust',
method: 'post',
data
});
@ -18,7 +18,7 @@ export function dayGetKendoListCust(data: any) {
//tabs 小时
export function hourGetKendoListCust(queryParams: any) {
return request({
url: '/api/wmp-eng-server/eng/eq/interval/qgc/hour/GetKendoListCust',
url: '/eq/interval/qgc/hour/GetKendoListCust',
method: 'post',
data: queryParams
});
@ -26,7 +26,7 @@ export function hourGetKendoListCust(queryParams: any) {
//接入过生态流量数据的电站
export function evnmAutoMonitorGetKendoListCust(queryParams: any) {
return request({
url: '/api/dec-lygk-base-server/base/evnmAutoMonitor/GetKendoListCust',
url: '/eq/evnmAutoMonitor/GetKendoListCust',
method: 'post',
data: queryParams
});
@ -34,15 +34,63 @@ export function evnmAutoMonitorGetKendoListCust(queryParams: any) {
//获取电站
export function vmsstbprptGetKendoList(queryParams: any) {
return request({
url: '/api/dec-lygk-base-server/base/vmsstbprpt/GetKendoList',
url: '/eq/vmsstbprpt/GetKendoList',
method: 'post',
data: queryParams
});
}
//生态流量达标情况 /api/wmp-eng-server/eng/eq/qecRateCount
//生态流量达标情况
export function eqqecRateCount(queryParams: any) {
return request({
url: '/api/wmp-eng-server/eng/eq/qecRateCount',
url: '/eq/qecRateCount',
method: 'post',
data: queryParams
});
}
// 获取生态流量达标率按基地
export function intervalGetKendoListCust(queryParams: any) {
return request({
url: '/eq/interval/GetKendoListCust',
method: 'post',
data: queryParams
});
}
// 获取生态流量达标率按性能
export function eqGetKendoListCust(queryParams: any) {
return request({
url: '/api/wmp-eng-server/eng/to/eq/GetKendoListCust',
method: 'post',
data: queryParams
});
}
//生态流量沿程变化
export function qgcHourVGetKendoListCust(queryParams: any) {
return request({
url: '/eq/engalong/statistics/qgcHourV/GetKendoListCust',
method: 'post',
data: queryParams
});
}
//根据流域获取电站
export function wbsbGetKendoList(queryParams: any) {
return request({
url: '/eq/wbsb/GetKendoList',
method: 'post',
data: queryParams
});
}
//生态流量泄放方式
export function msstbprptGetKendoList(queryParams: any) {
return request({
url: '/eq/msstbprpt/GetKendoList',
method: 'post',
data: queryParams
});
}
//根据流域获取电站
export function qgcgetEngLimit(queryParams: any) {
return request({
url: '/api/wmp-eng-server/eng/engalong/statistics/qgc/getEngLimit',
method: 'post',
data: queryParams
});

View File

@ -994,22 +994,22 @@ const wtPointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '建成日期',
filed: 'jcdt',
@ -1070,22 +1070,22 @@ const FhWpPointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '建成日期',
filed: 'jcdt',
@ -1259,22 +1259,22 @@ const FhZQPointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '建成日期',
filed: 'jcdt',
@ -1328,22 +1328,22 @@ const FPPointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '开工日期',
@ -1507,22 +1507,22 @@ const FPPointColumns1: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '开工日期',
@ -1766,22 +1766,22 @@ const FPPointColumns2: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '开工日期',
@ -1971,22 +1971,22 @@ const FPPointColumns4: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '开工日期',
@ -2190,22 +2190,22 @@ const FPPointColumns5: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '开工日期',
@ -2254,22 +2254,22 @@ const FBPointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '开工日期',
@ -2420,22 +2420,22 @@ const VaPointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '开工日期',
@ -2551,22 +2551,22 @@ const VPPointColumns: Array<any> = [
format: 'YYYY-MM-DD',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '建成日期',
filed: 'jcdt',
@ -2644,22 +2644,22 @@ const wePointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '',
filed: '',
@ -2684,22 +2684,22 @@ const waPointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '监测方式',
filed: 'mwayName',
@ -2759,22 +2759,22 @@ const StinfoAiVidoPointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '监控点地址',
filed: 'stlc',
@ -2822,22 +2822,22 @@ const DwPointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '所属电站',
filed: 'ennm',
@ -3006,22 +3006,22 @@ const DwFivePointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '所属电站',
filed: 'ennm',
@ -3176,22 +3176,22 @@ const DwSixPointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '所属电站',
filed: 'ennm',
@ -3325,22 +3325,22 @@ const DwOnePointColumns: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '所属电站',
filed: 'ennm',
@ -3486,22 +3486,22 @@ const EQPointColumns2: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '所属电站',
filed: 'ennm',
@ -3619,22 +3619,22 @@ const EQPointColumns5: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '所属电站',
filed: 'ennm',
@ -3723,22 +3723,22 @@ const EQPointColumns3: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '所属电站',
filed: 'ennm',
@ -3857,22 +3857,22 @@ const EQPointColumns4: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '所属电站',
filed: 'ennm',
@ -3990,22 +3990,22 @@ const EQPointColumns1: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '所属电站',
filed: 'ennm',
@ -4123,22 +4123,22 @@ const EQPointColumns7: Array<any> = [
type: 'select',
url: ''
},
{
name: '经度(°)',
filed: 'lgtd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
{
name: '纬度(°)',
filed: 'lttd',
visible: true,
type: 'number',
toFixed: 6,
url: ''
},
// {
// name: '经度(°)',
// filed: 'lgtd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
// {
// name: '纬度(°)',
// filed: 'lttd',
// visible: true,
// type: 'number',
// toFixed: 6,
// url: ''
// },
{
name: '所属电站',
filed: 'ennm',

View File

@ -683,9 +683,11 @@ const handleFocus = () => {
// Handle focus
};
const filterOption = (input: string, option?: { value: string }) => {
const filterOption = (input: string, option?: { label: string; value: string }) => {
if (!option) return false;
return option.value.toLowerCase().includes(input.toLowerCase());
const label = option.label?.toLowerCase() || '';
const value = option.value?.toLowerCase() || '';
return label.includes(input.toLowerCase()) || value.includes(input.toLowerCase());
};
//
@ -725,6 +727,16 @@ const emitAllValues = () => {
selectedNodeExtra: selectedNodeExtra.value
};
//
if (datetimeValue.value) {
// 使 format picker
const format =
props.datetimePicker.format ||
getDefaultFormat(props.datetimePicker.picker);
payload.datetime = datetimeValue.value.format(format);
} else {
payload.datetime = null;
}
//
if (datetimeValue.value) {
// 使 format picker

View File

@ -88,7 +88,7 @@
</div>
<!-- 详情弹窗 -->
<a-modal v-model:open="detailModalVisible" :title="`${detailData.stnm || ''} 详细信息`" width="80%" :footer="null"
<a-modal v-model:open="detailModalVisible" :title="`${detailData.stnm || ''} 详细信息`" width="1536px" :footer="null"
@cancel="handleDetailModalClose">
<HJMZDTwoLays :tc="{
stcd: detailData.stcd || '',

View File

@ -63,7 +63,7 @@ const customTransform = (res: any) => {
//
const handleViewDetail = (record: any) => {
modelStore.modalVisible = true;
modelStore.params.sttp = "VD_FBFM";
modelStore.params.sttp = record.sttpCode;
modelStore.title = record.stnm ;
modelStore.params.stcd = record.stcd;
}

View File

@ -1,9 +1,19 @@
<!-- SidePanelItem.vue -->
<template>
<div>
<SidePanelItem title="生态流量限值沿程变化" :select="select" :datetimePicker="datetimePicker" >
<SidePanelItem
title="生态流量限值沿程变化"
:select="select"
:datetimePicker="datetimePicker"
@update-values="handlePanelChange1"
>
<!-- 图表容器 -->
<div ref="chartRef" style="width: 100%; height: 400px;"></div>
<div class="chart-container">
<a-spin :spinning="loading" tip="加载中...">
<div ref="chartRef" class="chart-wrapper" :class="{ 'has-data': chartData.length > 0 }"></div>
<a-empty v-if="!loading && chartData.length === 0" description="暂无数据" />
</a-spin>
</div>
</SidePanelItem>
</div>
</template>
@ -13,55 +23,42 @@ import { ref, onMounted, computed, watch, onBeforeUnmount } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import dayjs from 'dayjs';
import { wbsbGetKendoList, qgcgetEngLimit } from '@/api/stll';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { useModelStore } from '@/store/modules/model';
const modelStore = useModelStore();
//
defineOptions({
name: 'xieFangFenBu'
});
const JidiSelectEventStore = useJidiSelectEventStore();
let wbsCode = ref('');
const select = ref({
show: true,
value: undefined,
options: [
]
options: [],
picker: undefined,
format: undefined
});
const datetimePicker = ref({
show: true,
value: undefined,
value: dayjs().format('YYYY-MM'), //
format: 'YYYY-MM', //YYYY-MM-DD HH
picker: 'month' //date | week | month | quarter | year
picker: 'month', //date | week | month | quarter | year
options: [] // options
});
//
const chartData = ref([
{ stnm: '站点A001', qecLimit: 120.5 },
{ stnm: '站点B002', qecLimit: 135.8 },
{ stnm: '站点C003', qecLimit: 98.3 },
{ stnm: '站点D004', qecLimit: 142.6 },
{ stnm: '站点E005', qecLimit: 115.2 },
{ stnm: '站点F006', qecLimit: 128.9 },
{ stnm: '站点G007', qecLimit: 105.4 },
{ stnm: '站点H008', qecLimit: 138.7 },
{ stnm: '站点I009', qecLimit: 122.1 },
{ stnm: '站点J010', qecLimit: 145.3 },
{ stnm: '站点K011', qecLimit: 110.6 },
{ stnm: '站点L012', qecLimit: 132.4 },
{ stnm: '站点M013', qecLimit: 118.9 },
{ stnm: '站点N014', qecLimit: 140.2 },
{ stnm: '站点O015', qecLimit: 125.7 }
]);
//
const chartData = ref([]);
//
const loading = ref(false);
//
const flowUnit = ref('m³/s');
//
const generateModerateColor = () => {
const hue = Math.floor(Math.random() * 360);
const saturation = 50 + Math.floor(Math.random() * 30); // 50-80%
const lightness = 45 + Math.floor(Math.random() * 20); // 45-65%
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
};
//
const chartOption = computed<EChartsOption>(() => {
const dataLength = chartData.value.length;
@ -99,7 +96,8 @@ const chartOption = computed<EChartsOption>(() => {
interval: dataLength > 12 ? 2 : 0,
rotate: 0,
formatter: (value: string, index: number) => {
const displayText = value.substring(0, 6) + (value.length > 6 ? '...' : '');
const displayText =
value.substring(0, 6) + (value.length > 6 ? '...' : '');
if (dataLength === 2) {
return `{a|${displayText}}`;
@ -126,10 +124,12 @@ const chartOption = computed<EChartsOption>(() => {
show: false
}
},
yAxis: [{
yAxis: [
{
type: 'value',
name: `流量(${flowUnit.value})`
}],
}
],
dataZoom: [
{
type: 'inside',
@ -144,13 +144,23 @@ const chartOption = computed<EChartsOption>(() => {
{
name: '生态流量限值',
type: 'line',
data: chartData.value.map((item: any) => item.qecLimit),
data: chartData.value.map((item: any) => ({
value: item.qecLimit,
stcd: item.stcd,
stnm: item.stnm
})),
smooth: false,
showSymbol: true,
symbolSize: 6
symbolSize: 6,
itemStyle: {
color: '#f7a737'
},
lineStyle: {
color: '#f7a737'
}
}
],
color: [generateModerateColor()]
color: ['#f7a737']
};
});
@ -158,6 +168,20 @@ const chartOption = computed<EChartsOption>(() => {
let chartInstance: echarts.ECharts | null = null;
const chartRef = ref<HTMLDivElement>();
//
const handleChartClick = (params: any) => {
// debugger
console.log('点击数据点:', params);
const { name, value, data } = params;
modelStore.modalVisible = true;
modelStore.params.sttp ='ENG';
modelStore.title = name ;
modelStore.params.stcd = data?.stcd
modelStore.params.eqtp = 'QEC';
// data
console.log(`站点: ${name}, 流量: ${value} ${flowUnit.value}, stcd: ${data?.stcd}`);
};
//
const initChart = () => {
if (!chartRef.value) {
@ -168,6 +192,10 @@ const initChart = () => {
console.log('开始初始化图表...');
chartInstance = echarts.init(chartRef.value);
chartInstance.setOption(chartOption.value);
//
chartInstance.on('click', handleChartClick);
console.log('图表初始化完成');
//
@ -180,13 +208,22 @@ const handleResize = () => {
};
//
watch(chartOption, (newOption) => {
watch(chartOption, newOption => {
if (chartInstance) {
chartInstance.setOption(newOption, true);
}
});
onMounted(() => {
//
watch(chartData, (newData) => {
if (chartInstance && newData.length === 0) {
chartInstance.clear();
}
});
onMounted(async () => {
await selectdata();
await getEchartsData();
initChart();
});
@ -195,9 +232,118 @@ onBeforeUnmount(() => {
chartInstance?.dispose();
chartInstance = null;
});
const selectdata = async () => {
try {
let params = {
filter: {
logic: 'and',
filters: [
{
field: 'wbsType',
operator: 'eq',
dataType: 'string',
value: 'PSB_RVCD'
},
{
field: 'objId',
operator: 'eq',
dataType: 'string',
value: wbsCode.value
}
]
},
group: [
{
dir: 'asc',
field: 'orderIndex'
},
{
dir: 'asc',
field: 'wbsCode'
},
{
dir: 'asc',
field: 'wbsName'
}
],
groupResultFlat: 'true'
};
const res = await wbsbGetKendoList(params);
if (res.data?.data && res.data.data.length > 0) {
select.value.options = res.data.data.map((item: any) => {
return {
value: item.wbsCode,
label: item.wbsName
};
});
select.value.value = res.data.data[0].wbsCode;
}
} catch (error) {
console.error('获取站点数据失败:', error);
}
};
const getEchartsData = async () => {
loading.value = true;
try {
if (!select.value.value) {
console.warn('未选择站点,无法获取图表数据');
chartData.value = [];
return;
}
let params = {
date: dayjs(datetimePicker.value.value).format('YYYY-MM-DD HH:mm:ss'),
rvcd: select.value.value
};
let res = await qgcgetEngLimit(params);
if (res.data && Array.isArray(res.data)) {
chartData.value = res.data;
} else {
console.warn('获取到的图表数据为空或格式不正确');
chartData.value = [];
}
} catch (error) {
console.error('获取图表数据失败:', error);
chartData.value = [];
} finally {
loading.value = false;
}
};
watch(
() => JidiSelectEventStore.selectedItem,
async (newVal) => {
console.log('流域切换:', newVal);
if (newVal?.wbsCode) {
wbsCode.value = newVal.wbsCode;
await selectdata();
}
},
{ deep: true, immediate: true }
);
const handlePanelChange1 = async (data: any) => {
console.log('当前所有控件状态:', data);
if (data.select && data.datetime) {
await getEchartsData();
}
};
</script>
<style lang="scss" scoped>
.chart-container {
width: 100%;
height: 400px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.chart-wrapper {
width: 100%;
height: 100%;
&.has-data {
min-height: 0;
}
}
</style>

View File

@ -0,0 +1,879 @@
<template>
<div class="stlldbqk-container">
<!-- 搜索表单 -->
<a-form layout="inline" class="search-form">
<a-form-item label="基地选择">
<a-select
v-model:value="params.qid"
placeholder="请选择基地"
style="width: 200px; margin-right: 10px"
show-search
:filter-option="filterOption"
:options="jidiOptions"
@change="handleJidiChange"
/>
<a-select
v-model:value="params.rstcd"
placeholder="请选择电站"
style="width: 200px"
show-search
:filter-option="filterOption"
:options="rstcdOptions"
/>
</a-form-item>
<a-form-item>
<a-space>
<a-button type="primary" @click="handleSearch">查询</a-button>
</a-space>
</a-form-item>
</a-form>
<!-- Tabs 标签页 -->
<a-tabs
v-if="tabList.length > 0"
v-model:activeKey="ecoFlowType"
class="tab-style"
@change="fetchTableData"
>
<a-tab-pane v-for="item in tabList" :key="item.key" :tab="item.label" />
</a-tabs>
<div class="body_zhengti">
<div class="echarts">
<a-spin :spinning="dataLoading">
<div v-if="pieData.length > 0" ref="chartRef" class="pie-chart"></div>
<a-empty
v-if="!dataLoading && pieData.length === 0"
description="暂无数据"
/>
</a-spin>
</div>
<div class="table_1">
<BasicTable
ref="tableRef"
:columns="columns"
:scrollY="380"
:scrollX="100"
:list-url="vmsstbprptGetKendoList"
:search-params="searchParams"
:transform-data="customTransform"
:enable-sort="true"
@sort-change="handleSortChange"
>
<template #stnm="{ record }">
<a-button
type="link"
size="small"
@click="handleView(record, 'EQ')"
>{{ record.stnm }}</a-button
>
</template>
<template #ennm="{ record }">
<a-button
type="link"
size="small"
@click="handleView(record, 'ENG')"
>{{ record.ennm }}</a-button
>
</template>
</BasicTable>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import dayjs from 'dayjs';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import {
dayGetKendoListCust,
vmsstbprptGetKendoList,
msstbprptGetKendoList
} from '@/api/stll';
import BasicTable from '@/components/BasicTable/index.vue';
import { useModelStore } from '@/store/modules/model';
import { NullableDateType } from 'ant-design-vue/es/vc-picker/interface';
const modelStore = useModelStore();
const props = defineProps<{
basicId?: string;
sttpCodekey: string;
}>();
const JidiSelectEventStore = useJidiSelectEventStore();
// ==================== ====================
// Tab
const columnsConfig = {
EQ_6: [
{
key: 'stnm',
title: '设施名称',
dataIndex: 'stnm',
slots: { customRender: 'stnm' },
fixed: 'left' ,
width: '120px',
sorter: true
},
{
key: 'ennm',
title: '所属电站',
dataIndex: 'ennm',
slots: { customRender: 'ennm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'ttpwr',
title: '装机容量',
dataIndex: 'ttpwr',
width: '160px',
sorter: true
},
{
key: 'stjzysq',
title: '生态机组额定流量(m³/s)',
dataIndex: 'stjzysq',
width: '200px',
sorter: true
}
],
EQ_5: [
{
key: 'stnm',
title: '设施名称',
dataIndex: 'stnm',
slots: { customRender: 'stnm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'ennm',
title: '所属电站',
dataIndex: 'ennm',
slots: { customRender: 'ennm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'jhfdgk',
title: '基荷发电工况',
dataIndex: 'jhfdgk',
width: '100px',
sorter: true
},
{
key: 'fdll',
title: '发电量(MKW)',
dataIndex: 'fdll',
width: '120px',
sorter: true
},
{
key: 'blprdName',
title: '所属建设阶段',
dataIndex: 'blprdName',
width: '160px',
sorter: true
}
],
default: [
{
key: 'stnm',
title: '设施名称',
dataIndex: 'stnm',
slots: { customRender: 'stnm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'ennm',
title: '所属电站',
dataIndex: 'ennm',
slots: { customRender: 'ennm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'ddzgq',
title: '死水位时保证流量(m³/s)',
dataIndex: 'ddzgq',
width: '190px',
sorter: true
},
{
key: 'flkq',
title: '最大泄放流量(m³/s)',
dataIndex: 'flkq',
sorter: true,
width: '160px'
},
{
key: 'jskgc',
title: '进水口底版高程(m)',
dataIndex: 'jskgc',
sorter: true,
width: '160px'
},
{
key: 'outflrelev',
title: '出水口底版高程(m)',
dataIndex: 'outflrelev',
sorter: true,
width: '160px'
},
{
key: 'flksz',
title: '孔口尺寸(m)',
dataIndex: 'flksz',
sorter: true,
width: '120px'
},
{
key: 'frntwlltyp',
title: '结构形式',
dataIndex: 'frntwlltyp',
sorter: true,
width: '160px'
},
{
key: 'blprdName',
title: '所属建设阶段',
dataIndex: 'blprdName',
sorter: true,
width: '160px'
}
]
};
// Tab
const columns = computed(() => {
const type = ecoFlowType.value;
if (type === 'EQ_6') return columnsConfig.EQ_6;
if (type === 'EQ_5') return columnsConfig.EQ_5;
return columnsConfig.default;
});
const tableRef = ref();
//
const sortInfo = ref<{ field: string; order: string | null }>({
field: '',
order: null
});
const sort2 = ref([
{
field: 'baseStepSort',
dir: 'asc'
},
{
field: 'rvcdStepSort',
dir: 'asc'
},
{
field: 'rstcdStepSort',
dir: 'asc'
},
{
field: 'siteStepSort',
dir: 'asc'
}
]);
//
const searchParams = computed(() => {
let baseSort;
//
if (sortInfo.value.field && sortInfo.value.order) {
baseSort = [
{
field: sortInfo.value.field,
dir: sortInfo.value.order === 'ascend' ? 'asc' : 'desc'
}
];
} else {
// 使
baseSort = sort2.value;
}
return {
sort: baseSort,
group: [],
select: [],
groupResultFlat: false
};
});
//
const handleSortChange = (info: {
field: string;
order: 'ascend' | 'descend' | null;
}) => {
sortInfo.value.field = info.field || '';
sortInfo.value.order = info.order || null;
// DOM
nextTick(() => {
fetchTableData();
});
};
const params = ref({
qid: props.basicId || 'all',
rstcd: ''
});
// 使 handleView
const activeSTime = ref('');
const activeETime = ref('');
// Tab
const tabList = ref<any[]>([]);
const ecoFlowType = ref<string>(props.sttpCodekey || '');
const loading = ref<boolean>(false);
const jidiOptions = computed(() => {
return [
...JidiSelectEventStore.jidiData.map((item: any) => ({
value: item.wbsCode,
label: item.wbsName
}))
];
});
const filterOption = (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
};
// ==================== ====================
const chartRef = ref<HTMLDivElement | null>(null);
let chartInstance: echarts.ECharts | null = null;
const pieData = ref<any[]>([]); //
const dataLoading = ref<boolean>(false);
const pieCode = ref<string[]>([]); //
//
const themeecLists = [];
const jdColor = [
'#4b79ab',
'#78c300',
'#9556a4',
'#df91ab',
'#7399c6',
'#dbb629',
'#56c2e3',
'#f56a06',
'#cdba75',
'#76523b',
'#df75b6',
'#00a050',
'#f5a644',
'#4b79ab',
'#78c300',
'#9556a4',
'#df91ab',
'#7399c6',
'#dbb629',
'#56c2e3',
'#f56a06',
'#cdba75',
'#76523b',
'#df75b6',
'#00a050',
'#f5a644'
];
//
const fetchPieData = async () => {
dataLoading.value = true;
try {
const { qid, rstcd } = params.value;
let obj = {
filter: {
logic: 'and',
filters: [
qid != 'all'
? {
field: 'baseId',
operator: 'contains',
dataType: 'string',
value: qid
}
: null,
{
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: ecoFlowType.value
},
{
field: 'baseName',
operator: 'isnotnull',
dataType: 'string'
},
rstcd
? {
field: 'rstcd',
operator: 'eq',
dataType: 'string',
value: rstcd
}
: null
].filter(Boolean)
},
group: [
{
dir: 'asc',
field: 'baseStepSort'
},
{
dir: 'asc',
field: 'baseId'
},
{
dir: 'desc',
field: 'baseName'
},
{
dir: 'desc',
field: 'sttpCode'
}
],
groupResultFlat: 'true'
};
let res = await vmsstbprptGetKendoList(obj);
if (res?.data?.data) {
const dataSource = res.data.data.map((el: any) => ({
id: el.baseId,
name: el.baseName,
value: el.count_baseId,
key: el.baseId
}));
pieData.value = dataSource;
pieCode.value = []; //
// DOM
await nextTick();
initOrUpdateChart();
} else {
pieData.value = [];
}
} catch (error) {
console.error('获取饼图数据失败:', error);
pieData.value = [];
} finally {
dataLoading.value = false;
}
};
//
const initOrUpdateChart = () => {
if (!chartRef.value) return;
//
if (!chartInstance) {
chartInstance = echarts.init(chartRef.value);
//
chartInstance.on('legendselectchanged', handleLegendSelectChanged);
}
updateChart();
};
//
const updateChart = () => {
if (!chartInstance) return;
const total =
pieData.value.reduce((pre: number, cur: any) => pre + cur.value, 0) || 0;
//
const colors = pieData.value.map((item: any, index: number) => {
const matched = themeecLists.find((i: any) => i.name === item.name);
return matched?.color || jdColor[index % jdColor.length];
});
const option: EChartsOption = {
color: colors,
tooltip: {
trigger: 'item',
formatter: '{b}: {c} (座) ({d}%)'
},
legend: {
orient: 'vertical',
right: 20,
top: 80,
type: 'scroll',
textStyle: {
width: 100, //
overflow: 'truncate', //
ellipsis: '...' //
}
},
title: [
{
text: total.toString(),
left: '34%',
top: '44%',
textAlign: 'center',
textStyle: {
fontSize: 24,
fontWeight: 'bold',
color: '#333'
}
},
{
text: '电站总数量',
left: '34%',
top: '51%',
textAlign: 'center',
textStyle: {
fontSize: 14,
color: '#666'
}
},
{
text: '(座)',
left: '34%',
top: '55%',
textAlign: 'center',
textStyle: {
fontSize: 12,
color: '#999'
}
}
],
series: [
{
name: '电站总数量',
type: 'pie',
radius: ['31%', '40%'],
center: ['35%', '50%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: true,
formatter: function (params) {
const maxLen = 8; //
let name = params.name;
if (name.length > maxLen) {
return name.substring(0, maxLen) + '...';
}
return name;
}
},
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
}
},
data: pieData.value
}
]
};
chartInstance.setOption(option, true);
};
//
const handleLegendSelectChanged = (params: any) => {
const selected = params.selected;
const trueRivers = Object.keys(selected).filter(key => selected[key]);
const allFalse = Object.values(selected).every(value => value === false);
const selectedKeys = pieData.value
.filter((item: any) => trueRivers.includes(item.name))
.map((item: any) => item.key);
pieCode.value = allFalse ? ['0'] : selectedKeys;
//
fetchTableData();
};
//
const customTransform = (res: any) => {
return {
records: res?.data?.data || [],
total: res?.data?.total || 0
};
};
// Tab
const fetchTabList = async () => {
loading.value = true;
try {
const { qid, rstcd } = params.value;
let obj = {
filter: {
logic: 'and',
filters: [
qid != 'all'
? {
field: 'baseId',
operator: 'contains',
dataType: 'string',
value: qid
}
: null,
{
field: 'sttpFullPath',
operator: 'contains',
dataType: 'string',
value: 'ENV,ENVP,EQ,'
},
{
field: 'sttpFullPath',
operator: 'neq',
dataType: 'string',
value: 'ENV,ENVP,EQ,'
},
{
field: 'baseName',
operator: 'isnotnull',
dataType: 'string'
},
rstcd
? {
field: 'rstcd',
operator: 'eq',
dataType: 'string',
value: rstcd
}
: null
].filter(Boolean)
},
group: [
{
dir: 'desc',
field: 'sttpCode'
}
]
};
let res = await msstbprptGetKendoList(obj);
if (res?.data?.data?.length > 0) {
const resData = res.data.data;
tabList.value = resData.map(item => ({
key: item.key,
value: item.key,
label: `${item.keyName}(${item.count}个)`
}));
// ""
// ecoFlowType.value = tabList.value[0].key;
//
fetchPieData();
//
fetchTableData();
} else {
tabList.value = [];
}
} catch (error) {
console.error('获取 Tab 列表失败:', error);
tabList.value = [];
} finally {
loading.value = false;
}
};
const handleView = (record: any, type: 'ENG' | 'EQ') => {
modelStore.modalVisible = true;
modelStore.params.sttp = type == 'EQ' ? record.sttpCode :'ENG';
modelStore.title = type === 'ENG' ? record.ennm : record.stnm;
modelStore.params.stcd = type === 'ENG' ? record.rstcd : record.stcd;
modelStore.params.eqtp = record.eqtp;
modelStore.filter.rangeTm = [activeSTime.value, activeETime.value];
};
//table
const fetchTableData = async () => {
//
const { qid, rstcd } = params.value;
const filters: any[] = [
{
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: ecoFlowType.value
},
{
field: 'baseName',
operator: 'isnotnull',
dataType: 'string'
},
qid != 'all'
? {
field: 'baseId',
operator: 'contains',
dataType: 'string',
value: qid
}
: null,
rstcd
? {
field: 'rstcd',
operator: 'eq',
dataType: 'string',
value: rstcd
}
: null
].filter(Boolean);
//
if (pieCode.value.length > 0) {
if (qid === 'all') {
filters.push({
field: 'baseId',
operator: 'in',
dataType: 'string',
value: pieCode.value
});
} else {
filters.push({
field: 'hbrvcd',
operator: 'in',
dataType: 'string',
value: pieCode.value
});
}
}
const filter = {
logic: 'and',
filters
};
tableRef.value?.getList(filter);
};
// ecoFlowType
watch(ecoFlowType, () => {
fetchPieData();
});
const handleSearch = () => {
// Tab
fetchTabList();
};
//
let rstcdOptions: any = ref([]);
const rstcdOption = async () => {
let obj = {
filter: {
logic: 'and',
filters: [
params.value.qid != 'all'
? {
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: 'ENG'
}
: null
].filter(Boolean)
},
sort: [
{
field: 'ttpwr',
dir: 'desc'
}
],
select: ['stcd', 'stnm']
};
let res = await vmsstbprptGetKendoList(obj);
rstcdOptions.value = res.data.data.map((item: any) => {
return {
value: item.stcd,
label: item.stnm
};
});
};
const handleJidiChange = (value: string) => {
rstcdOption();
};
onMounted(() => {
fetchTabList();
rstcdOption();
//
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
//
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
window.removeEventListener('resize', handleResize);
});
//
const handleResize = () => {
chartInstance?.resize();
};
</script>
<style scoped lang="scss">
.stlldbqk-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
background-color: #ffffff;
box-sizing: border-box;
// padding: 16px;
}
.body_zhengti {
width: 100%;
display: flex;
justify-content: space-between;
flex: 1;
.echarts {
width: 35%;
height: 482px;
// position: relative;
min-width: 521px;
.pie-chart {
width: 100%;
height: 100%;
}
:deep(.ant-spin-nested-loading) {
width: 100%;
height: 100%;
}
:deep(.ant-spin-container) {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.table_1 {
width: 65%;
height: 482px;
// overflow: auto;
// max-width: 500px;
}
}
</style>

View File

@ -2,35 +2,61 @@
<template>
<div class="xie-fang-fang-shi-container">
<SidePanelItem title="生态流量泄放方式">
<div ref="chartRef" class="pie-chart"></div>
<!-- Loading 状态 -->
<a-spin v-if="loading" :spinning="true" style="width: 100%; height: 350px; display: flex; justify-content: center; align-items: center;" />
<!-- 空状态提示 -->
<a-empty v-else-if="!loading && pieData.length === 0" description="暂无数据" style="height: 350px; display: flex; justify-content: center; align-items: center;flex-direction: column;text-indent:0em" />
<!-- 图表容器 -->
<div v-else ref="chartRef" class="pie-chart"></div>
</SidePanelItem>
<!-- 详情弹框 -->
<a-modal
v-model:open="modalVisible"
:title="'生态流量泄放方式'"
width="1536px"
@cancel="handleModalCancel"
>
<STLLXFFS
v-if="modalVisible"
:basicId="wbsCode"
:sttpCodekey ="selectedData.sttpCode"
/>
</a-modal>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
import * as echarts from 'echarts';
import type { ECharts } from 'echarts';
import { msstbprptGetKendoList } from '@/api/stll';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import STLLXFFS from './TwoLayer/STLLXFFS.vue'
// 便
defineOptions({
name: 'xieFangFangShi'
});
const JidiSelectEventStore = useJidiSelectEventStore();
const chartRef = ref<HTMLElement | null>(null);
let chartInstance: ECharts | null = null;
let wbsCode = ref('');
//
const pieData = [
{ value: 44.83, name: '基荷发电' },
{ value: 19.31, name: '泄洪设施' },
{ value: 8.28, name: '生态机组' },
{ value: 8.96, name: '生态放流管' },
{ value: 9.65, name: '生态放流闸' },
{ value: 5.52, name: '生态放流孔' },
{ value: 3.45, name: '生态放流洞' }
];
// Loading
const loading = ref(false);
//
const pieData = ref<any[]>([]);
const totalCount = ref(0);
const apiRawData = ref<any[]>([]); // API
//
const modalVisible = ref(false);
const modalTitle = ref('');
const selectedData = ref<any>(null);
//
const colors = [
@ -121,7 +147,7 @@ const initChart = () => {
show: true // 线
}
},
data: pieData.map((item, index) => ({
data: pieData.value.map((item, index) => ({
...item,
itemStyle: { color: colors[index % colors.length] },
labelLine: {
@ -134,7 +160,7 @@ const initChart = () => {
],
//
title: {
text: '145',
text: totalCount.value.toString(),
subtext: '泄放设施总数量\n(个)',
left: 'center',
top: 'center',
@ -154,6 +180,43 @@ const initChart = () => {
};
chartInstance.setOption(option);
//
chartInstance.on('click', handleChartClick);
};
/**
* 图表点击事件
*/
const handleChartClick = (params: any) => {
//
const clickedData = params.data;
if (clickedData) {
selectedData.value = {
name: clickedData.name,
value: clickedData.value,
sttpCode: clickedData.sttpCode,
count:
apiRawData.value.find(
(item: any) => item.sttpCode === clickedData.sttpCode
)?.count_sttpName || 0,
...apiRawData.value.find(
(item: any) => item.sttpCode === clickedData.sttpCode
) //
};
modalTitle.value = `${clickedData.name} - 详细信息`;
modalVisible.value = true;
}
};
/**
* 弹框取消事件
*/
const handleModalCancel = () => {
modalVisible.value = false;
selectedData.value = null;
};
//
@ -172,6 +235,11 @@ onMounted(() => {
}, 200);
}, 50);
window.addEventListener('resize', handleResize);
//
if (wbsCode.value) {
getecharts();
}
});
//
@ -179,6 +247,109 @@ onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize);
chartInstance?.dispose();
});
const getecharts = async () => {
loading.value = true;
let params = {
filter: {
logic: 'and',
filters: [
wbsCode.value != 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: wbsCode.value
}
: null,
{
field: 'sttpFullPath',
operator: 'contains',
dataType: 'string',
value: 'ENV,ENVP,EQ,'
},
{
field: 'sttpFullPath',
operator: 'neq',
dataType: 'string',
value: 'ENV,ENVP,EQ,'
},
{
field: 'baseName',
operator: 'isnotnull',
dataType: 'string'
}
].filter(Boolean)
},
group: [
{
dir: 'desc',
field: 'sttpCode'
},
{
dir: 'desc',
field: 'sttpName'
}
],
groupResultFlat: 'true'
};
try {
let res = await msstbprptGetKendoList(params);
//
if (!res || !res.data || !res.data.data || !Array.isArray(res.data.data)) {
console.warn('未获取到有效的泄放设施数据:', res);
pieData.value = [];
totalCount.value = 0;
return;
}
const apiData = res.data.data;
//
apiRawData.value = apiData;
//
const total = apiData.reduce((sum: number, item: any) => {
return sum + (item.count_sttpName || 0);
}, 0);
totalCount.value = total;
//
pieData.value = apiData.map((item: any) => ({
name: item.sttpName,
value:
total > 0
? Number(((item.count_sttpName / total) * 100).toFixed(2))
: 0,
sttpCode: item.sttpCode // sttpCode
}));
//
setTimeout(() => {
initChart();
}, 100);
} catch (error) {
console.error('获取泄放设施数据失败:', error);
pieData.value = [];
totalCount.value = 0;
} finally {
loading.value = false;
}
};
watch(
() => JidiSelectEventStore.selectedItem,
newVal => {
console.log('流域切换:', newVal);
if (newVal?.wbsCode) {
wbsCode.value = newVal.wbsCode;
getecharts();
}
},
{ deep: true, immediate: true }
);
</script>
<style lang="scss" scoped>

View File

@ -0,0 +1,737 @@
<template>
<div class="xffs-fb-container">
<!-- 搜索表单 -->
<a-form layout="inline" class="search-form">
<a-form-item label="基地选择">
<a-select
v-model:value="params.JiDi"
placeholder="请选择基地"
style="width: 200px; margin-right: 10px"
show-search
:filter-option="filterOption"
:options="jidiOptions"
/>
</a-form-item>
<a-form-item label="生态流量泄放方式">
<a-select
v-model:value="params.XFFS"
placeholder="请选择泄放方式"
style="width: 200px; margin-right: 10px"
show-search
:filter-option="filterOption"
:options="xffsOptions"
/>
</a-form-item>
<a-form-item>
<a-input
v-model:value="params.stnm"
placeholder="请输入电站或设施名称"
style="width: 200px; margin-right: 10px"
allow-clear
/>
</a-form-item>
<a-form-item>
<a-space>
<a-button type="primary" @click="handleSearch">查询</a-button>
</a-space>
</a-form-item>
</a-form>
<!-- 图表和表格布局 -->
<div class="body-content">
<!-- 左侧饼图 -->
<div class="chart-section">
<a-spin :spinning="chartLoading">
<div v-if="pieData.length > 0" ref="chartRef" class="pie-chart"></div>
<a-empty
v-if="!chartLoading && pieData.length === 0"
description="暂无数据"
/>
</a-spin>
</div>
<!-- 右侧表格 -->
<div class="table-section">
<BasicTable
ref="tableRef"
:columns="columns"
:scrollY="385"
:scrollX="100"
:list-url="vmsstbprptGetKendoList"
:search-params="searchParams"
:transform-data="customTransform"
:enable-sort="true"
@sort-change="handleSortChange"
>
<template #stnm="{ record }">
<a-button
type="link"
size="small"
@click="handleView(record, 'EQ')"
>
{{ record.stnm }}
</a-button>
</template>
<template #ennm="{ record }">
<a-button
type="link"
size="small"
@click="handleView(record, 'ENG')"
>
{{ record.ennm }}
</a-button>
</template>
</BasicTable>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import { msstbprptGetKendoList, vmsstbprptGetKendoList } from '@/api/stll';
import BasicTable from '@/components/BasicTable/index.vue';
import { useModelStore } from '@/store/modules/model';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
const modelStore = useModelStore();
const JidiSelectEventStore = useJidiSelectEventStore();
// ==================== Props ====================
const props = defineProps<{
dataDimensionVal?: string | number | boolean;
defaultJidiInfo?: Record<string, string | number | boolean> | null;
jidiName?: string;
selectData?: string;
jiDiList?: (Record<string, string | number | boolean> | null)[];
}>();
// ==================== ====================
const columnsConfig = {
EQ_6: [
{
key: 'stnm',
title: '设施名称',
dataIndex: 'stnm',
slots: { customRender: 'stnm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'ennm',
title: '所属电站',
dataIndex: 'ennm',
slots: { customRender: 'ennm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'ttpwr',
title: '装机容量',
dataIndex: 'ttpwr',
width: '160px',
sorter: true
},
{
key: 'stjzysq',
title: '生态机组额定流量(m³/s)',
dataIndex: 'stjzysq',
width: '200px',
sorter: true
}
],
EQ_5: [
{
key: 'stnm',
title: '设施名称',
dataIndex: 'stnm',
slots: { customRender: 'stnm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'ennm',
title: '所属电站',
dataIndex: 'ennm',
slots: { customRender: 'ennm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'jhfdgk',
title: '基荷发电工况',
dataIndex: 'jhfdgk',
width: '100px',
sorter: true
},
{
key: 'fdll',
title: '发电量(MKW)',
dataIndex: 'fdll',
width: '120px',
sorter: true
},
{
key: 'blprdName',
title: '所属建设阶段',
dataIndex: 'blprdName',
width: '160px',
sorter: true
}
],
default: [
{
key: 'stnm',
title: '设施名称',
dataIndex: 'stnm',
slots: { customRender: 'stnm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'ennm',
title: '所属电站',
dataIndex: 'ennm',
slots: { customRender: 'ennm' },
fixed: 'left',
width: '120px',
sorter: true
},
{
key: 'ddzgq',
title: '死水位时保证流量(m³/s)',
dataIndex: 'ddzgq',
width: '190px',
sorter: true
},
{
key: 'flkq',
title: '最大泄放流量(m³/s)',
dataIndex: 'flkq',
sorter: true,
width: '160px'
},
{
key: 'jskgc',
title: '进水口底版高程(m)',
dataIndex: 'jskgc',
sorter: true,
width: '160px'
},
{
key: 'outflrelev',
title: '出水口底版高程(m)',
dataIndex: 'outflrelev',
sorter: true,
width: '160px'
},
{
key: 'flksz',
title: '孔口尺寸(m)',
dataIndex: 'flksz',
sorter: true,
width: '120px'
},
{
key: 'frntwlltyp',
title: '结构形式',
dataIndex: 'frntwlltyp',
sorter: true,
width: '160px'
},
{
key: 'blprdName',
title: '所属建设阶段',
dataIndex: 'blprdName',
sorter: true,
width: '160px'
}
]
};
//
const columns = computed(() => {
const xffsName = params.value.XFFS;
if (xffsName === '生态机组') return columnsConfig.EQ_6;
if (xffsName === '基荷发电') return columnsConfig.EQ_5;
return columnsConfig.default;
});
const tableRef = ref();
//
const sortInfo = ref<{ field: string; order: string | null }>({
field: '',
order: null
});
const sort2 = ref([
{
field: 'rvcdStepSort',
dir: 'asc'
},
{
field: 'rstcdStepSort',
dir: 'asc'
}
]);
//
const searchParams = computed(() => {
let baseSort;
if (sortInfo.value.field && sortInfo.value.order) {
baseSort = [
{
field: sortInfo.value.field,
dir: sortInfo.value.order === 'ascend' ? 'asc' : 'desc'
}
];
} else {
baseSort = sort2.value;
}
return {
sort: baseSort,
group: [],
select: [],
groupResultFlat: false
};
});
//
const handleSortChange = (info: {
field: string;
order: 'ascend' | 'descend' | null;
}) => {
sortInfo.value.field = info.field || '';
sortInfo.value.order = info.order || null;
nextTick(() => {
fetchTableData();
});
};
// ==================== ====================
const params = ref({
JiDi: props.jidiName || '',
XFFS: props.selectData || '',
stnm: ''
});
//
const jidiOptions = computed(() => {
return (props.jiDiList || []).map((item: any) => ({
value: item?.wbsCode,
label: item?.wbsName
}));
});
//
const xffsOptions = computed(() => {
return echartData.value.map((item: any) => ({
value: item.dataIndex,
label: item.name
}));
});
const filterOption = (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
};
// ==================== ====================
const chartRef = ref<HTMLDivElement | null>(null);
let chartInstance: echarts.ECharts | null = null;
const pieData = ref<any[]>([]);
const chartLoading = ref<boolean>(false);
const pieCode = ref<string[]>([]); //
//
const jdColor = [
'#4b79ab',
'#78c300',
'#9556a4',
'#df91ab',
'#7399c6',
'#dbb629',
'#56c2e3',
'#f56a06',
'#cdba75',
'#76523b',
'#df75b6',
'#00a050',
'#f5a644'
];
//
const echartData = computed(() => {
const v = (eqtp: string) => {
const index = pieData.value.findIndex((item: any) => item.name === eqtp);
if (index !== -1) {
return pieData.value[index]?.value || 0;
}
return 0;
};
return [
{ dataIndex: 'EQ_1', value: v('EQ_1'), name: '生态放流孔' },
{ dataIndex: 'EQ_2', value: v('EQ_2'), name: '生态放流闸' },
{ dataIndex: 'EQ_3', value: v('EQ_3'), name: '生态放流洞' },
{ dataIndex: 'EQ_4', value: v('EQ_4'), name: '生态放流管' },
{ dataIndex: 'EQ_5', value: v('EQ_5'), name: '基荷发电' },
{ dataIndex: 'EQ_6', value: v('EQ_6'), name: '生态机组' },
{ dataIndex: 'EQ_7', value: v('EQ_7'), name: '泄洪设施' }
];
});
//
const fetchPieData = async () => {
chartLoading.value = true;
try {
let obj = {
filter: {
logic: 'and',
filters: [
params.value.JiDi !== 'all'
? {
field: 'baseId',
operator: 'contains',
dataType: 'string',
value: params.value.JiDi
}
: null,
params.value.XFFS
? {
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: params.value.XFFS
}
: null
].filter(Boolean)
},
group: [
{
dir: 'desc',
field: 'sttpCode'
},
{
dir: 'desc',
field: 'sttpName'
}
],
groupResultFlat: 'true'
};
const res = await msstbprptGetKendoList(obj);
if (res?.data?.data) {
const dataSource = res.data.data.map((el: any) => ({
name: el.sttpName,
value: el.count_sttpCode
}));
pieData.value = dataSource;
pieCode.value = []; //
// DOM
await nextTick();
initOrUpdateChart();
} else {
pieData.value = [];
}
} catch (error) {
console.error('获取饼图数据失败:', error);
pieData.value = [];
} finally {
chartLoading.value = false;
}
};
//
const initOrUpdateChart = () => {
if (!chartRef.value) return;
if (!chartInstance) {
chartInstance = echarts.init(chartRef.value);
chartInstance.on('legendselectchanged', handleLegendSelectChanged);
}
updateChart();
};
//
const updateChart = () => {
if (!chartInstance) return;
const total =
pieData.value.reduce((pre: number, cur: any) => pre + cur.value, 0) || 0;
const colors = pieData.value.map((item: any, index: number) => {
return jdColor[index % jdColor.length];
});
const option: EChartsOption = {
color: colors,
tooltip: {
trigger: 'item',
formatter: '{b}: {c} 个 ({d}%)'
},
legend: {
orient: 'vertical',
right: 20,
top: 80,
type: 'scroll',
textStyle: {
width: 100,
overflow: 'truncate',
ellipsis: '...'
}
},
title: [
{
text: total.toString(),
left: '34%',
top: '44%',
textAlign: 'center',
textStyle: {
fontSize: 24,
fontWeight: 'bold',
color: '#333'
}
},
{
text: '电站总数',
left: '34%',
top: '51%',
textAlign: 'center',
textStyle: {
fontSize: 14,
color: '#666'
}
},
{
text: '(个)',
left: '34%',
top: '55%',
textAlign: 'center',
textStyle: {
fontSize: 12,
color: '#999'
}
}
],
series: [
{
name: '电站总数量',
type: 'pie',
radius: ['31%', '40%'],
center: ['35%', '50%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: true,
formatter: function (params) {
const maxLen = 8;
let name = params.name;
if (name.length > maxLen) {
return name.substring(0, maxLen) + '...';
}
return name;
}
},
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
}
},
data: pieData.value
}
]
};
chartInstance.setOption(option, true);
};
//
const handleLegendSelectChanged = (params: any) => {
const selected = params.selected;
const trueRivers = Object.keys(selected).filter(key => selected[key]);
const allFalse = Object.values(selected).every(value => value === false);
const selectedKeys = pieData.value
.filter((item: any) => trueRivers.includes(item.name))
.map((item: any) => item.name);
pieCode.value = allFalse ? [] : selectedKeys;
//
fetchTableData();
};
//
const customTransform = (res: any) => {
return {
records: res?.data?.data || [],
total: res?.data?.total || 0
};
};
//
const fetchTableData = async () => {
const filters: any[] = [
params.value.XFFS
? {
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: params.value.XFFS
}
: null,
params.value.JiDi
? {
field: 'baseId',
operator: 'contains',
dataType: 'string',
value: params.value.JiDi
}
: null,
params.value.stnm
? {
logic: 'or',
filters: [
{
field: 'stnm',
operator: 'contains',
value: '12'
},
{
field: 'ennm',
operator: 'contains',
value: '12'
}
]
}
: null
].filter(Boolean);
//
if (pieCode.value.length > 0) {
filters.push({
field: 'sttpName',
operator: 'in',
dataType: 'string',
value: pieCode.value
});
}
const filter = {
logic: 'and',
filters
};
tableRef.value?.getList(filter);
};
//
const handleView = (record: any, type: 'ENG' | 'EQ') => {
modelStore.modalVisible = true;
modelStore.params.sttp = type === 'EQ' ? record.sttpCode : 'ENG';
modelStore.title = type === 'ENG' ? record.ennm : record.stnm;
modelStore.params.stcd = type === 'ENG' ? record.rstcd : record.stcd;
modelStore.params.eqtp = record.eqtp;
};
//
const handleSearch = () => {
fetchPieData();
fetchTableData();
};
//
const handleResize = () => {
chartInstance?.resize();
};
onMounted(() => {
fetchPieData();
fetchTableData()
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
window.removeEventListener('resize', handleResize);
});
</script>
<style scoped lang="scss">
.xffs-fb-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
background-color: #ffffff;
box-sizing: border-box;
}
.search-form {
padding: 16px;
border-bottom: 1px solid #f0f0f0;
}
.body-content {
width: 100%;
display: flex;
justify-content: space-between;
flex: 1;
padding: 16px;
.chart-section {
width: 35%;
height: 482px;
min-width: 521px;
.pie-chart {
width: 100%;
height: 100%;
}
:deep(.ant-spin-nested-loading) {
width: 100%;
height: 100%;
}
:deep(.ant-spin-container) {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.table-section {
width: 65%;
height: 482px;
}
}
</style>

View File

@ -1,386 +1,479 @@
<!-- SidePanelItem.vue -->
<template>
<div>
<SidePanelItem title="泄放方式分布情况">
<div class="chart-container">
<!-- 自定义图例区域 -->
<div class="legend-container">
<div class="legend-items">
<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-color" :style="{ backgroundColor: item.color }"></span>
<span class="legend-text">{{ item.name }}</span>
</div>
</div>
<!-- 分页控制 -->
<div class="legend-pagination" v-if="totalPages > 1">
<span
class="pagination-btn"
:class="{ disabled: currentPage === 1 }"
@click="prevPage"
>
</span>
<span class="pagination-text">{{ currentPage }}/{{ totalPages }}</span>
<span
class="pagination-btn"
:class="{ disabled: currentPage === totalPages }"
@click="nextPage"
>
</span>
</div>
</div>
<!-- ECharts 图表容器 -->
<div ref="chartRef" class="chart"></div>
</div>
<div ref="chartRef" class="bar-chart-container"></div>
<!-- 空状态提示 -->
<a-empty v-if="showEmpty" description="暂无数据" />
</SidePanelItem>
</div>
<!-- 详情弹框 -->
<a-modal
v-model:open="modalVisible"
title="泄放方式分布情况"
width="1536px"
:footer="null"
@cancel="handleModalCancel"
>
<FBQKTwolayer
v-if="modalVisible"
:selectData="selectData"
:jidiName="jidiName"
:jiDiList="JidiSelectEventStore.jidiData"
></FBQKTwolayer>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, onMounted, computed, watch, onBeforeUnmount } from 'vue';
import {
ref,
onMounted,
onBeforeUnmount,
watch,
computed,
nextTick
} from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import type { ECharts } from 'echarts';
import { vmsstbprptGetKendoList } from '@/api/stll';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import FBQKTwolayer from './TwoLayer/FenBuQingKuangTwoLayer.vue';
//
defineOptions({
name: 'xieFangFenBu'
name: 'XieFangFenBu'
});
//
const JidiSelectEventStore = useJidiSelectEventStore();
// DOM
const chartRef = ref<HTMLElement | null>(null);
let chartInstance: echarts.ECharts | null = null;
let chartInstance: ECharts | null = null;
//
const ITEMS_PER_PAGE = 4; // 4
const currentPage = ref(1); //
//
const loading = ref(false);
const data = ref<any[]>([]);
const echartsXData = ref<string[]>([]);
const wbsCode = ref('');
// 8
const allLegendItems = ref([
{ name: '生态放流孔', color: '#7cb342' },
{ name: '生态放流闸', color: '#ce93d8' },
{ name: '生态放流洞', color: '#64b5f6' },
{ name: '生态放流管', color: '#ffd54f' },
{ name: '生态放流口', color: '#ff8a65' },
{ name: '生态放流道', color: '#4db6ac' },
{ name: '生态放流渠', color: '#ba68c8' },
{ name: '生态放流站', color: '#a1887f' }
]);
//
const modalVisible = ref(false);
const selectData = ref(''); //
const jidiName = ref(''); //
//
const totalPages = computed(() => {
return Math.ceil(allLegendItems.value.length / ITEMS_PER_PAGE);
//
const typeName = [
{ label: '生态放流孔', eqtp: 'EQ_1' },
{ label: '生态放流闸', eqtp: 'EQ_2' },
{ label: '生态放流洞', eqtp: 'EQ_3' },
{ label: '生态放流管', eqtp: 'EQ_4' },
{ label: '基荷发电', eqtp: 'EQ_5' },
{ label: '生态机组', eqtp: 'EQ_6' },
{ label: '泄洪设施', eqtp: 'EQ_7' }
];
// getUnitConfigByCode 使
const defaultColors = [
'#9556a4', // EQ_1 -
'#30b7b9', // EQ_2 - 绿
'#4b79ab', // EQ_3 -
'#dbb629', // EQ_4 -
'#df91ab', // EQ_5 -
'#78c300', // EQ_6 - 绿
'#7399c6' // EQ_7 -
];
//
const showEmpty = computed(() => {
return !loading.value && (!data.value || data.value.length === 0);
});
//
const currentLegendItems = computed(() => {
const start = (currentPage.value - 1) * ITEMS_PER_PAGE;
const end = start + ITEMS_PER_PAGE;
return allLegendItems.value.slice(start, end);
});
// inactive
const legendInactiveSet = ref<Set<string>>(new Set());
// /
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--;
}
};
//
const nextPage = () => {
if (currentPage.value < totalPages.value) {
currentPage.value++;
}
};
// - API
const xData = ref([
'金沙江干流',
'雅砻江干流',
'大渡河干流',
'乌江干流',
'湘西',
'黄河上游干流',
'东北',
'闽浙赣',
'其他'
]);
// 8
const seriesData = ref([
{ name: '生态放流孔', data: [2, 1, 3, 1, 2, 1, 0, 1, 5] },
{ name: '生态放流闸', data: [3, 2, 4, 2, 3, 1, 1, 2, 8] },
{ name: '生态放流洞', data: [5, 2, 6, 3, 4, 2, 1, 2, 9] },
{ name: '生态放流管', data: [15, 0, 12, 18, 4, 0, 0, 0, 21] },
{ name: '生态放流口', data: [0, 0, 0, 0, 0, 0, 0, 0, 0] },
{ name: '生态放流道', data: [0, 0, 0, 0, 0, 0, 0, 0, 0] },
{ name: '生态放流渠', data: [0, 0, 0, 0, 0, 0, 0, 0, 0] },
{ name: '生态放流站', data: [0, 0, 0, 0, 0, 0, 0, 0, 0] }
]);
//
const calculateTotal = (index: number) => {
return seriesData.value
.filter(series => !legendInactiveSet.value.has(series.name)) //
.reduce((sum, series) => {
return sum + (series.data[index] || 0);
}, 0);
};
//
const updateChart = () => {
if (!chartInstance) return;
const option: EChartsOption = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: (params: any) => {
let result = `${params[0].name}<br/>`;
params.forEach((param: any) => {
// active
if (!legendInactiveSet.value.has(param.seriesName)) {
result += `${param.marker} ${param.seriesName}: ${param.value}<br/>`;
}
/**
* 手写 omit 函数替代 lodash.omit
*/
const omit = (obj: any, keys: string[]) => {
const result = { ...obj };
keys.forEach(key => {
delete result[key];
});
return result;
}
},
grid: {
left: '3%',
right: '4%',
bottom: '15%',
top: '10%',
containLabel: true
},
xAxis: {
type: 'category',
data: xData.value,
axisLabel: {
rotate: 45, // X 45
interval: 0 //
},
axisTick: {
alignWithLabel: true
}
},
yAxis: {
type: 'value',
min: 0,
// Y
axisLabel: {
formatter: '{value}'
}
},
series: seriesData.value.map((series, index) => {
//
const legendItem = allLegendItems.value.find(item => item.name === series.name);
const color = legendItem?.color;
//
const isHidden = legendInactiveSet.value.has(series.name);
return {
name: series.name,
type: 'bar',
stack: 'total',
barWidth: '60%',
// null使
data: isHidden ? series.data.map(() => null) : series.data,
//
itemStyle: {
color: color
},
// -
label: {
show: index === seriesData.value.length - 1, //
position: 'top',
fontSize: 12,
color: '#333',
formatter: (params: any) => {
//
const total = calculateTotal(params.dataIndex);
return total > 0 ? total.toString() : '';
}
},
//
emphasis: {
itemStyle: {
shadowBlur: 0,
shadowColor: 'rgba(0, 0, 0, 0)'
}
}
};
})
};
chartInstance.setOption(option, true);
};
//
/**
* 获取颜色配置模拟 getUnitConfigByCode
* TODO: 如果项目中有等效实现请替换此处逻辑
*/
const getColorByType = (type: string): string => {
// getUnitConfigByCode
// const config = getUnitConfigByCode('Other', type);
// return config?.lineColor || config?.pieColor;
// 使
const index = typeName.findIndex(item => item.eqtp === type);
return defaultColors[index] || '#999999';
};
/**
* 初始化图表
*/
const initChart = () => {
if (!chartRef.value) return;
//
//
if (chartRef.value.clientHeight === 0) {
setTimeout(() => {
chartInstance = echarts.init(chartRef.value);
updateChart();
//
setTimeout(() => {
chartInstance?.resize();
initChart();
}, 100);
}, 50);
return;
}
if (!chartInstance) {
chartInstance = echarts.init(chartRef.value);
}
const option = buildChartOption();
chartInstance.setOption(option, true);
//
chartInstance.off('click');
chartInstance.on('click', handleChartClick);
};
//
/**
* 构建图表配置
*/
const buildChartOption = () => {
//
const countSums: Record<string, number> = {};
data.value.forEach(item => {
const baseid = item.baseid;
const count = Number(item.count) || 0;
if (countSums[baseid]) {
countSums[baseid] += count;
} else {
countSums[baseid] = count;
}
});
const values = Object.values(countSums);
const maxValue = values.length > 0 ? Math.max(...values) : 0;
//
const totalData: number[] = [];
const uniqueBaseNames = [...new Set(echartsXData.value)];
uniqueBaseNames.forEach((basename, index) => {
let total = 0;
data.value.forEach(item => {
if (item.basename === basename) {
total += Number(item.count) || 0;
}
});
totalData[index] = total;
});
// series
const seriesData = typeName.map(type => {
return uniqueBaseNames.map(basename => {
const found = data.value.find(
item => item.eqtp === type.eqtp && item.basename === basename
);
return found ? Number(found.count) || 0 : 0;
});
});
//
const colors = typeName.map(type => getColorByType(type.eqtp));
const option: any = {
tooltip: {
trigger: 'axis',
confine: true,
formatter: (params: any) => {
const content = params
.map((item: any) => {
let value = item.value || 0;
if (item.seriesName === '总计') {
value = totalData[item.dataIndex];
}
return `<div>${item.marker}${item.seriesName}: &nbsp;&nbsp;&nbsp;&nbsp;<span style="float:right">${value} 个</span></div>`;
})
.join('');
return `<h3>${params[0].name}</h3>${content}`;
},
axisPointer: {
type: 'line'
}
},
grid: {
left: '8%',
right: '4%',
bottom: '20%',
top: '20%'
},
legend: {
type: 'scroll',
icon: 'rect',
orient: 'horizontal',
itemWidth: 12,
itemHeight: 12,
textStyle: {
fontSize: 12,
color: '#6A93B9',
height: 8
},
data: typeName.map(item => item.label)
},
xAxis: {
show: true,
type: 'category',
axisLine: { show: true },
axisLabel: {
fontSize: 12,
color: '#686868',
rotate: 37
},
axisTick: {
alignWithLabel: true
},
data: uniqueBaseNames
},
yAxis: {
max: maxValue,
type: 'value',
barWidth: 10,
name: '数量(个)',
nameTextStyle: {
fontSize: 12,
color: '#848484',
align: 'center'
},
axisTick: { show: false },
axisLabel: {
fontSize: 12,
color: '#343434',
fontFamily: 'Bebas'
}
},
series: [
...typeName.map((type, index) => ({
name: type.label,
type: 'bar' as const,
stack: 'total',
barCategoryGap: '50%',
data: seriesData[index]
})),
{
name: '总计',
type: 'bar' as const,
stack: 'total',
label: {
show: true,
position: 'top',
formatter: (params: any) => {
return String(totalData[params.dataIndex]);
}
},
itemStyle: {
color: 'transparent'
},
data: Array(totalData.length).fill(0)
}
],
color: colors
};
return option;
};
/**
* 图表点击事件
*/
const handleChartClick = (params: any) => {
// sttpCode (eqtp)
const typeConfig = typeName.find(item => item.label === params.seriesName);
selectData.value = typeConfig ? typeConfig.eqtp : '';
// wbsCode
const jidiInfo = JidiSelectEventStore.jidiData.find(
(item: any) => item.wbsName === params.name
);
jidiName.value = jidiInfo ? jidiInfo.wbsCode : params.name;
modalVisible.value = true;
};
/**
* 弹框取消事件
*/
const handleModalCancel = () => {
modalVisible.value = false;
selectData.value = '';
jidiName.value = '';
};
/**
* 获取数据
*/
const fetchData = async () => {
if (!wbsCode.value) return;
loading.value = true;
try {
//
let params: any = {
filter: {
logic: 'and',
filters: [
wbsCode.value !== 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: wbsCode.value
}
: null,
{
field: 'sttpFullPath',
operator: 'contains',
dataType: 'string',
value: 'ENV,ENVP,EQ,'
}
].filter(Boolean)
},
group: [
{
dir: 'asc',
field: 'baseStepSort'
},
{
dir: 'asc',
field: 'baseId'
},
{
dir: 'desc',
field: 'sttpCode'
}
],
groupResultFlat: 'true'
};
// baseId
if (wbsCode.value === 'all') {
params = omit(params, ['filter']);
params.filter = {
logic: 'and',
filters: [
{
field: 'sttpFullPath',
operator: 'contains',
dataType: 'string',
value: 'ENV,ENVP,EQ,'
}
]
};
}
const res = await vmsstbprptGetKendoList(params);
if (res.data && res.data.data) {
const apiData = res.data.data;
//
const list: any[] = [];
apiData.forEach((it: any) => {
list.push({
key: it.baseId,
count: it.count_sttpCode,
eqtp: it.sttpCode
});
});
// 使 JidiSelectEventStore.jidiData
const processedData = list.map((item: any) => {
// jidiData
const jidiInfo = JidiSelectEventStore.jidiData.find(
(jidi: any) => jidi.wbsCode === item.key
);
return {
baseid: item.key,
basename: jidiInfo ? jidiInfo.wbsName : item.key, // 使 wbsName使 baseId
count: item.count,
eqtp: item.eqtp
};
});
data.value = processedData;
// debugger
// X
echartsXData.value = [
...new Set(processedData.map(item => item.basename))
];
//
await nextTick();
initChart();
} else {
data.value = [];
echartsXData.value = [];
}
} catch (error) {
console.error('获取泄放方式分布数据失败:', error);
data.value = [];
echartsXData.value = [];
} finally {
loading.value = false;
}
};
/**
* 处理窗口大小变化
*/
const handleResize = () => {
chartInstance?.resize();
};
//
watch([currentPage, legendInactiveSet], () => {
updateChart();
}, { deep: true });
//
//
onMounted(() => {
// DOM
setTimeout(() => {
initChart();
setTimeout(() => {
chartInstance?.resize();
}, 200);
}, 50);
window.addEventListener('resize', handleResize);
//
if (wbsCode.value) {
fetchData();
}
});
//
onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize);
chartInstance?.dispose();
chartInstance = null;
});
//
const refreshData = (newXData: string[], newSeriesData: any[]) => {
xData.value = newXData;
seriesData.value = newSeriesData;
updateChart();
};
//
const setLegendData = (legendData: Array<{ name: string; color: string }>) => {
allLegendItems.value = legendData;
currentPage.value = 1; //
legendInactiveSet.value.clear();
};
// 使
defineExpose({
refreshData,
setLegendData
});
//
watch(
() => JidiSelectEventStore.selectedItem,
newVal => {
console.log('流域切换:', newVal);
if (newVal?.wbsCode) {
wbsCode.value = newVal.wbsCode;
fetchData();
}
},
{ deep: true, immediate: true }
);
</script>
<style lang="scss" scoped>
.chart-container {
width: 100%;
.legend-container {
display: flex;
justify-content: space-between;
align-items: center;
.legend-items {
display: flex;
gap: 10px; //
flex-wrap: nowrap; //
flex: 1; //
min-width: 0; //
.legend-item {
display: flex;
align-items: center;
cursor: pointer;
transition: opacity 0.3s;
flex-shrink: 0; //
&:hover {
opacity: 0.8;
}
&.inactive {
opacity: 0.5;
}
.legend-color {
width: 12px;
height: 12px;
border-radius: 2px;
margin-right: 4px;
flex-shrink: 0;
}
.legend-text {
font-size: 12px; //
color: #333;
white-space: nowrap;
}
}
}
.legend-pagination {
display: flex;
align-items: center;
flex-shrink: 0;
margin-left: 5px; //
.pagination-btn {
cursor: pointer;
font-size: 14px;
color: #666;
user-select: none;
transition: color 0.3s;
&:hover:not(.disabled) {
color: #409eff;
}
&.disabled {
cursor: not-allowed;
color: #ccc;
}
}
.pagination-text {
font-size: 13px;
color: #666;
min-width: 30px;
text-align: center;
}
}
}
.chart {
.bar-chart-container {
width: 100%;
height: 350px;
}
}
</style>

View File

@ -295,7 +295,7 @@ const handleChange = async () => {
select: ['stcd', 'stnm']
};
let res = await vmsstbprptGetKendoList(params);
if (res?.data?.success && res?.data?.data) {
if ( res?.data?.data) {
let data = res.data.data;
stcdOptions.value = data.map((item: any) => ({
value: item.stcd,

View File

@ -36,7 +36,7 @@
v-model:value="dateRange"
:allow-clear="false"
format="YYYY-MM-DD"
style="width: 360px"
style="width: 260px"
/>
</a-form-item>
@ -70,11 +70,11 @@
/>
</a-spin>
</div>
<div class="table">
<div class="table1">
<BasicTable
ref="tableRef"
:columns="columns"
:scrollY="380"
:scrollY="400"
:list-url="
activeTimeType == 'day' ? dayGetKendoListCust : hourGetKendoListCust
"
@ -952,7 +952,7 @@ const handleResize = () => {
align-items: center;
}
}
.table {
.table1 {
width: 65%;
height: 482px;
}

View File

@ -0,0 +1,812 @@
<template>
<div class="stlldbqk-container">
<!-- 搜索表单 -->
<a-form layout="inline" class="search-form">
<a-form-item label="基地选择">
<a-select
v-model:value="params.qid"
placeholder="请选择基地"
style="width: 200px"
show-search
:filter-option="filterOption"
:options="jidiOptions"
/>
</a-form-item>
<!-- <a-form-item label=" "> -->
<a-input
v-model:value="params.ennm"
placeholder=" "
style="width: 200px; margin-right: 15px"
/>
<!-- </a-form-item> -->
<a-form-item label="日期范围">
<a-range-picker
v-model:value="dateRange"
:allow-clear="false"
format="YYYY-MM-DD"
style="width: 360px"
/>
</a-form-item>
<a-form-item>
<a-space>
<a-button type="primary" @click="handleSearch">查询</a-button>
</a-space>
</a-form-item>
</a-form>
<!-- Tabs 选择器仅在 type === 'left' 时显示 -->
<a-spin :spinning="tabsLoading" tip="加载中...">
<a-tabs
v-if="props.type === 'left' && tabOptions.length > 0"
v-model:activeKey="activeTab"
@change="handleTabChange"
class="stll-tabs"
>
<a-tab-pane
v-for="item in tabOptions"
:key="item.qecPerformance"
:tab="`${item.qecPerformanceName} (${
item.qecRate !== null &&
item.qecRate !== undefined &&
item.qecRate !== ''
? Number(item.qecRate).toFixed(2) + '%'
: '-%'
})`"
/>
</a-tabs>
<div class="body_zhengti">
<div class="echarts">
<a-spin :spinning="dataLoading">
<div
v-show="pieData.length > 0"
ref="chartRef"
class="pie-chart"
></div>
<a-empty
v-show="!dataLoading && pieData.length === 0"
description="暂无数据"
/>
</a-spin>
</div>
<div class="table">
<BasicTable
ref="tableRef"
:columns="columns"
:scrollY="'450px'"
:list-url="
props.type == 'top'
? intervalGetKendoListCust
: eqGetKendoListCust
"
:search-params="searchParams"
:transform-data="customTransform"
:enable-sort="true"
@sort-change="handleSortChange"
>
<template #ennm="{ column, record }">
<a-button type="link" size="small" @click="handleView(record)">{{
record.ennm
}}</a-button>
</template>
</BasicTable>
</div>
</div>
</a-spin>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import dayjs from 'dayjs';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import BasicTable from '@/components/BasicTable/index.vue';
import { useModelStore } from '@/store/modules/model';
import {
vmsstbprptGetKendoList,
intervalGetKendoListCust,
eqqecRateCount,
eqGetKendoListCust
} from '@/api/stll';
const modelStore = useModelStore();
const props = defineProps<{
type?: string;
basicId?: string;
qecPerformance?: any;
}>();
const JidiSelectEventStore = useJidiSelectEventStore();
const columns = [
props.type == 'left'
? {
key: 'baseName',
title: '所属基地',
dataIndex: 'baseName',
sorter: true //
}
: null,
{
key: 'ennm',
title: '电站名称',
dataIndex: 'ennm',
slots: { customRender: 'action' },
sorter: true //
},
{
key: 'addvcdName',
title: '行政区',
dataIndex: 'addvcdName',
sorter: true //
},
{
key: 'hbrvcdName',
title: '所在河段',
dataIndex: 'hbrvcdName',
width: '300px'
},
{
key: 'qecRate',
title: `生态流量达标率(%)`,
dataIndex: 'qecRate',
sorter: true, //
width: '160px',
customRender: ({ text }: any) => {
if (text === null || text === undefined || text === '' || text === '-')
return '-';
return Number(text).toFixed(2);
}
},
{
key: 'beforeQecRate',
title: '去年同期达标率(%)',
dataIndex: 'beforeQecRate',
width: '160px',
sorter: true, //
customRender: ({ text }: any) => {
if (text === null || text === undefined || text === '' || text === '-')
return '-';
return Number(text).toFixed(2);
}
}
].filter(Boolean);
const tableRef = ref();
//
const sortInfo = ref<{ field: string; order: string | null }>({
field: '',
order: null
});
const defaultSort = ref([
{
field: 'baseId',
dir: 'asc'
},
{
field: 'rvcdStepSort',
dir: 'asc'
},
{
field: 'siteStepSort',
dir: 'asc'
},
{
field: 'qecRate',
dir: 'asc'
}
]);
//
const searchParams = computed(() => {
let baseSort;
//
if (sortInfo.value.field && sortInfo.value.order) {
baseSort = [
{
field: sortInfo.value.field,
dir: sortInfo.value.order === 'ascend' ? 'asc' : 'desc'
}
];
} else {
// 使
baseSort = defaultSort.value;
}
return {
sort: baseSort
};
});
//
const handleSortChange = (info: {
field: string;
order: 'ascend' | 'descend' | null;
}) => {
sortInfo.value.field = info.field || '';
sortInfo.value.order = info.order || null;
// DOM
nextTick(() => {
fetchTableData();
});
};
//
const initDateRange = () => {
const today = dayjs();
const lastMonthSameDay = today.subtract(1, 'month');
return [lastMonthSameDay, today];
};
const dateRange = ref(initDateRange());
const params = ref({
qid: props.basicId || 'all',
ennm: '',
sTime: '',
eTime: ''
});
const jidiOptions = computed(() => {
return [
...JidiSelectEventStore.jidiData.map((item: any) => ({
value: item.wbsCode,
label: item.wbsName
}))
];
});
const filterOption = (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
};
// ==================== Tabs ====================
const activeTab = ref<string>(props.qecPerformance || ''); // tab key
const tabOptions = ref<any[]>([]); // tabs
const tabsLoading = ref<boolean>(false); // tabs
// Tabs
const fetchTabOptions = async () => {
if (props.type !== 'left') return;
tabsLoading.value = true;
try {
const res = await eqqecRateCount({
filter: {
logic: 'and',
filters: [
params.value.qid !== 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: params.value.qid
}
: null,
{
field: 'type',
operator: 'eq',
dataType: 'string',
value: 'DAY'
},
{
field: 'RGCP_CODE',
operator: 'in',
dataType: 'string',
value: ['1']
},
{
field: 'tm',
operator: 'gte',
dataType: 'date',
value:
params.value.sTime ||
dayjs().subtract(1, 'month').format('YYYY-MM-DD 00:00:00')
},
{
field: 'tm',
operator: 'lte',
dataType: 'date',
value: params.value.eTime || dayjs().format('YYYY-MM-DD 23:59:59')
}
].filter(Boolean)
},
group: [{ dir: 'asc', field: 'qecPerformance' }]
});
if (res?.data?.data && res.data.data.length > 0) {
tabOptions.value = res.data.data;
//
activeTab.value =props.qecPerformance || res.data.data[0].qecPerformance;
} else {
tabOptions.value = [];
activeTab.value = '';
}
} catch (error) {
console.error('获取tabs选项失败:', error);
tabOptions.value = [];
activeTab.value = '';
} finally {
tabsLoading.value = false;
}
};
// Tab
const handleTabChange = (key: string) => {
activeTab.value = key;
//
fetchPieData();
fetchTableData();
};
// ==================== ====================
const chartRef = ref<HTMLDivElement | null>(null);
let chartInstance: echarts.ECharts | null = null;
const pieData = ref<any[]>([]); //
const dataLoading = ref<boolean>(false);
const pieCode = ref<string[]>([]); //
//
const themeecLists = [];
const jdColor = [
'#4b79ab',
'#78c300',
'#9556a4',
'#df91ab',
'#7399c6',
'#dbb629',
'#56c2e3',
'#f56a06',
'#cdba75',
'#76523b',
'#df75b6',
'#00a050',
'#f5a644',
'#4b79ab',
'#78c300',
'#9556a4',
'#df91ab',
'#7399c6',
'#dbb629',
'#56c2e3',
'#f56a06',
'#cdba75',
'#76523b',
'#df75b6',
'#00a050',
'#f5a644'
];
//
const fetchPieData = async () => {
if (!params.value.sTime || !params.value.eTime) return;
dataLoading.value = true;
try {
const { sTime, eTime, qid, ennm } = params.value;
let obj = {
filter: {
logic: 'and',
filters: [
{
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: 'ENG'
},
{
field: 'prsc',
operator: 'in',
dataType: 'string',
value: [1, 2, 3]
},
qid != 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: qid
}
: null,
{
field: 'bldstt',
operator: 'in',
dataType: 'string',
value: [1, 10, 11]
},
props.type != 'left'
? {
field: 'dtinEnv',
operator: 'in',
dataType: 'string',
value: [1, 2]
}
: {
field: 'RGCP_CODE',
operator: 'in',
dataType: 'string',
value: [activeTab.value]
}
].filter(Boolean)
},
group: [
{
dir: 'asc',
field: 'rvcdStepSort'
},
{
dir: 'asc',
field: 'hbrvcd'
},
{
dir: 'asc',
field: 'hbrvcdName'
}
],
groupResultFlat: true
};
// TODO: API -
const res = await vmsstbprptGetKendoList(obj);
if (res?.data?.data) {
const dataSource = res.data.data.map((el: any) => ({
id: el.hbrvcd,
name: el.hbrvcdName,
value: el.count_hbrvcd,
key: el.hbrvcd
}));
pieData.value = dataSource;
pieCode.value = []; //
// DOM
await nextTick();
initOrUpdateChart();
} else {
pieData.value = [];
}
} catch (error) {
console.error('获取饼图数据失败:', error);
pieData.value = [];
} finally {
dataLoading.value = false;
}
};
//
const initOrUpdateChart = () => {
if (!chartRef.value) return;
//
if (!chartInstance) {
chartInstance = echarts.init(chartRef.value);
//
chartInstance.on('legendselectchanged', handleLegendSelectChanged);
}
updateChart();
};
//
const updateChart = () => {
if (!chartInstance) return;
const total =
pieData.value.reduce((pre: number, cur: any) => pre + cur.value, 0) || 0;
//
const colors = pieData.value.map((item: any, index: number) => {
const matched = themeecLists.find((i: any) => i.name === item.name);
return matched?.color || jdColor[index % jdColor.length];
});
const option: EChartsOption = {
color: colors,
tooltip: {
trigger: 'item',
formatter: '{b}: {c} (座) ({d}%)'
},
legend: {
orient: 'vertical',
right: 20,
top: 80,
type: 'scroll',
textStyle: {
width: 100, //
overflow: 'truncate', //
ellipsis: '...' //
}
},
title: [
{
text: total.toString(),
left: '34%',
top: '44%',
textAlign: 'center',
textStyle: {
fontSize: 24,
fontWeight: 'bold',
color: '#333'
}
},
{
text: '电站总数量',
left: '34%',
top: '51%',
textAlign: 'center',
textStyle: {
fontSize: 14,
color: '#666'
}
},
{
text: '(座)',
left: '34%',
top: '55%',
textAlign: 'center',
textStyle: {
fontSize: 12,
color: '#999'
}
}
],
series: [
{
name: '电站总数量',
type: 'pie',
radius: ['31%', '40%'],
center: ['35%', '50%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: true,
formatter: function (params) {
const maxLen = 8; //
let name = params.name;
if (name.length > maxLen) {
return name.substring(0, maxLen) + '...';
}
return name;
}
},
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
}
},
data: pieData.value
}
]
};
chartInstance.setOption(option, true);
};
//
const handleLegendSelectChanged = (params: any) => {
const selected = params.selected;
const trueRivers = Object.keys(selected).filter(key => selected[key]);
const allFalse = Object.values(selected).every(value => value === false);
const selectedKeys = pieData.value
.filter((item: any) => trueRivers.includes(item.name))
.map((item: any) => item.key);
pieCode.value = allFalse ? ['0'] : selectedKeys;
//
fetchTableData();
};
//
const customTransform = (res: any) => {
return {
records: res?.data?.data || [],
total: res?.data?.total || 0
};
};
const handleView = (record: any) => {
modelStore.modalVisible = true;
modelStore.params.sttp = 'ENG';
modelStore.title = record.ennm;
modelStore.params.stcd = record.stcd;
modelStore.params.eqtp = record.eqtp;
};
//
const fetchTableData = async () => {
const { sTime, eTime, qid, ennm } = params.value;
// TODO: -
const filters = [
qid != 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: qid
}
: null,
{
field: 'dtinEnv',
operator: 'in',
dataType: 'string',
value: [1, 2]
},
{
field: 'tm',
operator: 'gte',
dataType: 'date',
value: sTime
},
{
field: 'tm',
operator: 'lte',
dataType: 'date',
value: eTime
},
ennm
? {
field: 'ennm',
operator: 'contains',
dataType: 'string',
value: ennm
}
: null,
props.type == 'left'
? {
field: 'rgcpCode',
operator: 'eq',
dataType: 'string',
value: activeTab.value
}
: null,
props.type == 'left'
? {
field: 'type',
operator: 'eq',
dataType: 'string',
value: 'DAY'
}
: null
].filter(Boolean);
const filter = {
logic: 'and',
filters
};
tableRef.value?.getList(filter);
};
const handleSearch = () => {
// params
if (dateRange.value && dateRange.value.length === 2) {
params.value.sTime = dateRange.value[0].format('YYYY-MM-DD 00:00:00');
params.value.eTime = dateRange.value[1].format('YYYY-MM-DD 23:59:59');
}
// type === 'left' tabs
if (props.type === 'left') {
fetchTabOptions().then(() => {
// tabs
fetchPieData();
fetchTableData();
});
} else {
//
fetchPieData();
fetchTableData();
}
};
onMounted(() => {
//
if (dateRange.value && dateRange.value.length === 2) {
params.value.sTime = dateRange.value[0].format('YYYY-MM-DD 00:00:00');
params.value.eTime = dateRange.value[1].format('YYYY-MM-DD 23:59:59');
// type === 'left' tabs
if (props.type === 'left') {
fetchTabOptions().then(() => {
// tabs
console.log(JidiSelectEventStore.jidiData);
fetchPieData();
fetchTableData();
});
} else {
//
console.log(JidiSelectEventStore.jidiData);
fetchPieData();
fetchTableData();
}
}
//
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
//
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
window.removeEventListener('resize', handleResize);
});
//
const handleResize = () => {
chartInstance?.resize();
};
</script>
<style scoped lang="scss">
.stlldbqk-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
background-color: #ffffff;
box-sizing: border-box;
// padding: 16px;
}
.stll-tabs {
margin-top: 16px;
margin-bottom: 16px;
:deep(.ant-tabs-nav) {
margin-bottom: 0;
}
}
.body_zhengti {
width: 100%;
display: flex;
justify-content: space-between;
flex: 1;
margin-top: 25px;
.echarts {
width: 35%;
height: 482px;
position: relative;
.pie-chart {
width: 100%;
height: 100%;
}
:deep(.ant-spin-nested-loading) {
width: 100%;
height: 100%;
}
:deep(.ant-spin-container) {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.table {
width: 65%;
height: 482px;
}
}
</style>

View File

@ -7,7 +7,9 @@
-->
<template #click-action-content>
<div v-if="titleData.cnt" style="max-width: 300px; line-height: 1.6">
<p>1时间{{ getdate().startDate1 }} {{ getdate().endDate1 }}</p>
<p>
1时间{{ getdate().startDate1 }} {{ getdate().endDate1 }}
</p>
<p>
2范围接入过生态流量数据的电站<span
style="color: #5989ad; cursor: pointer"
@ -39,6 +41,21 @@
>
<ModalYkzhbzdjcgz v-if="huanbaoModalVisible" :titleData="titleData" />
</a-modal>
<!-- 生态流量达标率详情弹框 -->
<a-modal
v-model:open="detailModalVisible"
:title="detailModalTitle"
width="1536px"
:footer="null"
>
<STLLXFFS
v-if="detailModalVisible"
:type="mode"
:basicId="detailData[0]?.baseId"
:qecPerformance=detailData[0].qecPerformance
/>
</a-modal>
</template>
<script lang="ts" setup>
@ -47,15 +64,11 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
import * as echarts from 'echarts';
import { eqqecRateCount, evnmAutoMonitorGetKendoListCust } from '@/api/stll';
import ModalYkzhbzdjcgz from '../shengtaidabiaoMod/TwoLayer/ModalYkzhbzdjcgz.vue';
import STLLXFFS from './TwoLayer/STLLXFFS.vue'
// 便
defineOptions({
name: 'shengtaidabiaoMod'
});
const obj = {
show: true,
value:
'1、统计电站范围接入过生态流量数据的电站2、当来水不足时生态流量不小于入库流量判定为达标3、"≥95% 座数"表示统计电站范围内时段达标率大于等于 95% 的电站数量'
};
const mode = ref('top');
const spinning = ref(false);
const chartRef = ref<HTMLElement | null>(null);
@ -66,45 +79,20 @@ const chartData = ref<{
categories: string[];
currentData: number[];
lastYearData: number[];
baseIds: (string | number)[];
qecPerformances: (string | number)[];
}>({
categories: [],
currentData: [],
lastYearData: []
lastYearData: [],
baseIds: [],
qecPerformances: []
});
const huanbaoModalVisible = ref(false);
//
const handleStationClick = () => {
huanbaoModalVisible.value = true;
};
//
const baseData = {
categories: [
'金沙江干流',
'雅砻江干流',
'大渡河干流',
'乌江干流',
'长江上游干流',
'湘西',
'黄河上游干流',
'黄河中游干流',
'南盘江 - 红水河',
'东北',
'澜沧江干流',
'闽浙赣',
'其他'
],
currentData: [98, 100, 99.5, 99.8, 100, 98.5, 100, 100, 100, 97, 100, 93, 98],
lastYearData: [92, 100, 99, 100, 100, 98, 100, 100, 100, 100, 100, 88, 93]
};
//
const performanceData = {
categories: ['多年调节', '年调节', '季调节', '周调节', '其他'],
currentData: [95, 92, 88, 85, 90],
lastYearData: [93, 90, 85, 82, 88]
};
//
const loadData = async () => {
spinning.value = true;
@ -303,11 +291,48 @@ const initChart = () => {
chartInstance.setOption(option);
//
chartInstance.off('click');
chartInstance.on('click', (params: any) => {
handleChartClick(params);
});
//
setTimeout(() => {
chartInstance?.resize();
}, 0);
};
//
const handleChartClick = (params: any) => {
const categoryName = params.name;
const currentIndex = params.dataIndex;
// debugger
//
detailModalTitle.value =
mode.value === 'top'
? `生态流量达标率(按基地统计) `
: `生态流量达标率(按调节性能统计)`;
//
const baseId = mode.value === 'top' ? chartData.value.baseIds[currentIndex] : undefined;
const qecPerformance = mode.value === 'left' ? chartData.value.qecPerformances[currentIndex] : undefined;
// debugger
const currentItem = {
baseId: baseId,
baseName: mode.value === 'top' ? categoryName :'',
qecPerformance: qecPerformance,
qecPerformanceName: mode.value === 'left' ? categoryName : '',
qecRate: chartData.value.currentData[currentIndex],
beforeQecRate: chartData.value.lastYearData[currentIndex]
};
detailData.value = [currentItem];
detailModalVisible.value = true;
};
const getdate = () => {
const now = new Date();
const oneMonthAgo = new Date(now);
@ -409,7 +434,9 @@ const getEcharts = async () => {
),
lastYearData: uniqueData.map((item: any) =>
item.beforeQecRate != null ? Number(item.beforeQecRate) : 0
)
),
baseIds: uniqueData.map((item: any) => item.baseId),
qecPerformances: []
};
} else {
//
@ -420,7 +447,9 @@ const getEcharts = async () => {
),
lastYearData: apiData.map((item: any) =>
item.beforeQecRate != null ? Number(item.beforeQecRate) : 0
)
),
baseIds: [],
qecPerformances: apiData.map((item: any) => item.qecPerformance || '')
};
}
} else {
@ -429,7 +458,9 @@ const getEcharts = async () => {
chartData.value = {
categories: [],
currentData: [],
lastYearData: []
lastYearData: [],
baseIds: [],
qecPerformances: []
};
}
} catch (error) {
@ -438,7 +469,9 @@ const getEcharts = async () => {
chartData.value = {
categories: [],
currentData: [],
lastYearData: []
lastYearData: [],
baseIds: [],
qecPerformances: []
};
}
};
@ -484,6 +517,34 @@ onMounted(() => {
});
});
//
const detailModalVisible = ref(false);
const detailModalTitle = ref('');
const detailData = ref<any[]>([]);
const detailColumns = ref([
{
title: mode.value === 'top' ? '基地名称' : '调节性能',
dataIndex: mode.value === 'top' ? 'baseName' : 'qecPerformanceName',
key: mode.value === 'top' ? 'baseName' : 'qecPerformanceName',
width: 150,
fixed: 'left'
},
{
title: '当前达标率',
dataIndex: 'qecRate',
key: 'qecRate',
width: 120,
align: 'right'
},
{
title: '去年同期达标率',
dataIndex: 'beforeQecRate',
key: 'beforeQecRate',
width: 150,
align: 'right'
}
]);
// mode
watch(mode, () => {
loadData();
@ -523,4 +584,8 @@ watch(mode, () => {
height: 449px;
// padding: 10px;
}
.detail-content {
padding: 16px 0;
}
</style>

View File

@ -0,0 +1,614 @@
<template>
<div>
<SidePanelItem
title="生态流量沿程变化"
:iconmap="iconmap"
:select="select"
:datetimePicker="datetimePicker"
@update-values="handlePanelChange"
>
<!-- 加载状态 -->
<div v-if="dataLoading" class="chart-loading">
<a-spin tip="加载中..." />
</div>
<!-- 无数据提示 -->
<a-empty
v-if="!chartData.length && !dataLoading"
description="暂无数据"
class="chart-empty"
/>
<!-- 图表容器使用 display 控制避免 v-if 销毁 DOM-->
<div
ref="chartRef"
class="chart-container"
:style="{
display: chartData.length && !dataLoading ? 'block' : 'none'
}"
></div>
</SidePanelItem>
</div>
</template>
<script lang="ts" setup>
import { ref, watch, nextTick, onBeforeUnmount } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
// import { wbsbGetKendoList } from '@/api/sz';
import * as echarts from 'echarts';
import dayjs from 'dayjs';
// TODO: API
import { qgcHourVGetKendoListCust, wbsbGetKendoList } from '@/api/stll';
import { useModelStore } from '@/store/modules/model';
//
defineOptions({
name: 'StllyanchengChangeMod'
});
// ==================== ====================
//
const iconmap = ref({
show: true,
value:
'入库流量是基于库容曲线和水量平衡的推算值,非实测数据。出库流量是基于机组出力特征曲线和闸门开度的推算值,非实测数据。',
icon: 'iconfont icon-time'
});
//
const datetimePicker = ref({
show: true,
value: dayjs().format('YYYY-MM-DD HH:mm'), //
format: 'YYYY-MM-DD HH:mm',
picker: 'date',
timeFormat: 'HH:mm',
options: []
});
//
const select = ref({
show: true,
value: '',
options: [],
picker: undefined,
format: undefined
});
const modelStore = useModelStore();
//
const wbsCode = ref(''); //
const selectData = ref(''); //
const chartData = ref<any[]>([]); //
const dataLoading = ref(false); //
const latestTime = ref(''); //
const hasTimeData = ref(false); //
//
const chartRef = ref<HTMLElement | null>(null);
let chartInstance: echarts.ECharts | null = null;
//
const modalVisible = ref(false);
const modalData = ref<any>({
stcd: '',
stnm: '',
titleName: ''
});
// Store
const JidiSelectEventStore = useJidiSelectEventStore();
// ==================== ====================
/**
* 获取河段列表
*/
const getSelect = async () => {
if (!wbsCode.value) {
console.warn('wbsCode 为空,无法获取河段数据');
return;
}
let params = {
filter: {
logic: 'and',
filters: [
{
field: 'objId',
operator: 'eq',
value: wbsCode.value
},
{
field: 'wbsType',
operator: 'eq',
value: 'PSB_RVCD'
}
]
},
group: [
{
dir: 'asc',
field: 'orderIndex'
},
{
dir: 'asc',
field: 'wbsCode'
},
{
dir: 'asc',
field: 'wbsName'
},
{
dir: 'asc',
field: 'objid'
}
],
groupResultFlat: 'true'
};
try {
let res = await wbsbGetKendoList(params);
//
let data;
if (res && res.data && res.data.data) {
if (Array.isArray(res.data.data)) {
data = res.data.data;
} else if (res.data.data.data && Array.isArray(res.data.data.data)) {
data = res.data.data.data;
} else {
console.warn('无法解析河段数据:', res);
return;
}
} else {
console.warn('未获取到河段数据');
return;
}
if (data && data.length > 0) {
// debugger;
select.value.value = data[0].wbsCode;
selectData.value = data[0].wbsCode; //
select.value.options = data.map(item => ({
value: item.wbsCode,
label: item.wbsName
}));
//
await loadChartData();
} else {
console.warn('河段数据为空');
select.value.value = '';
select.value.options = [];
}
} catch (error) {
console.error('获取河段数据失败:', error);
}
};
/**
* 获取生态流量数据预留 API 位置
*/
const getList = async (rvcd: string, sDate: string) => {
// TODO: API
// React
// - baseId: JidiSelectEventStore.selectedItem
// - rvcd:
// - tm: 1
const currentTime = dayjs(sDate);
const startTime = currentTime.subtract(1, 'month');
let params = {
filter: {
logic: 'and',
filters: [
{
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: wbsCode.value
},
{
field: 'rvcd',
operator: 'eq',
dataType: 'string',
value: rvcd
},
{
field: 'tm',
operator: 'gte',
dataType: 'date',
value: startTime.format('YYYY-MM-DD HH:mm:ss')
},
{
field: 'tm',
operator: 'lte',
dataType: 'date',
value: currentTime.format('YYYY-MM-DD HH:mm:ss')
}
]
},
sort: [
{
field: 'sort',
dir: 'asc'
}
]
};
// TODO: API FAA
const res = await qgcHourVGetKendoListCust(params);
//
if (!res || !res.data || !res.data.data || !Array.isArray(res.data.data)) {
console.warn('未获取到有效的生态流量数据:', res);
return [];
}
//
return res.data.data.map((item: any) => ({
TM: dayjs(item.tm).format('YYYY-MM-DD H时'),
stnm: item.stnm,
stcd: item.stcd,
qec: item.qec, //
qecLimit: item.qecLimit, //
qi: item.qi //
}));
};
/**
* 加载图表数据
*/
const loadChartData = async () => {
if (!selectData.value || !datetimePicker.value.value) {
return;
}
dataLoading.value = true;
try {
const data = await getList(selectData.value, datetimePicker.value.value);
if (data && data.length > 0) {
chartData.value = data;
hasTimeData.value = true;
//
if (data[0]?.TM) {
latestTime.value = data[0].TM;
}
//
await nextTick();
initChart();
} else {
chartData.value = [];
hasTimeData.value = false;
latestTime.value = '';
//
if (chartInstance) {
chartInstance.clear();
}
}
} catch (error) {
console.error('加载图表数据失败:', error);
chartData.value = [];
} finally {
dataLoading.value = false;
}
};
/**
* 初始化 ECharts 图表
*/
const initChart = () => {
if (!chartRef.value) {
console.warn('图表容器未准备好');
return;
}
//
if (chartInstance) {
chartInstance.dispose();
}
//
chartInstance = echarts.init(chartRef.value);
//
const xData: string[] = [];
const inData: (number | string)[] = []; //
const outData: (number | string)[] = []; //
const limitData: (number | string)[] = []; //
let hasValidData = false; //
chartData.value.forEach(item => {
xData.push(item.stnm);
const qecValue = item.qec ?? '-';
const qiValue = item.qi ?? '-';
const qecLimitValue = item.qecLimit ?? '-';
outData.push(qecValue);
inData.push(qiValue);
limitData.push(qecLimitValue);
//
if (qecValue !== '-' || qiValue !== '-' || qecLimitValue !== '-') {
hasValidData = true;
}
});
//
if (!hasValidData && chartData.value.length > 0) {
chartData.value = [];
if (chartInstance) {
chartInstance.clear();
}
return;
}
//
const option: echarts.EChartsOption = {
tooltip: {
trigger: 'axis',
confine: true,
formatter: function (params: any) {
const datum = chartData.value.find(
(el: any) => el.stnm === params[0].name
);
const unit = 'm³/s'; // TODO:
const content = params
.map((item: any) => {
const value = item.value ?? '-';
return `<div>${item.marker}${item.seriesName}: &nbsp;&nbsp;&nbsp;&nbsp;<span style="float:right">${value} ${unit}</span></div>`;
})
.join('');
return `<h3 style="color:white">${params[0].name}<br/>${
datum?.TM || ''
}</h3>${content}`;
},
axisPointer: {
type: 'line'
}
},
legend: {
data: ['入库流量', '生态流量', '环评要求限值'],
icon: 'roundRect',
top: 10
},
grid: {
left: 10,
right: 10,
bottom: 10,
top: 70,
containLabel: true
},
xAxis: {
type: 'category',
data: xData,
axisLine: {
lineStyle: {
color: '#505050'
}
},
splitLine: {
show: true,
lineStyle: {
color: '#8f8f8f',
type: 'solid'
}
},
axisLabel: {
interval: xData.length > 12 ? 2 : 0,
rotate: 0,
formatter: (value: string, index: number) => {
const shortValue =
value.substring(0, 6) + (value.length > 6 ? '...' : '');
if (index % 2 !== 0) {
return `{a|${shortValue}}`;
} else {
return `\n{b|}${shortValue}`;
}
},
rich: {
a: {
height: 20,
align: 'center'
},
b: {
height: 30,
align: 'center'
}
}
}
},
yAxis: {
type: 'value',
name: '流量(m³/s)', // TODO:
minInterval: 1,
axisLine: {
lineStyle: {
color: '#505050'
}
},
splitLine: {
show: true,
lineStyle: {
color: '#8f8f8f',
type: 'solid'
}
}
},
dataZoom: [
{
type: 'inside',
xAxisIndex: 0,
start: 0,
end: 100,
zoomOnMouseWheel: true,
moveOnMouseMove: true
}
],
series: [
{
name: '入库流量',
data: inData,
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 6,
connectNulls: true,
color: '#5470c6' // TODO:
},
{
name: '生态流量',
data: outData,
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 6,
connectNulls: true,
color: '#91cc75' // TODO:
},
{
name: '环评要求限值',
data: limitData,
type: 'bar',
barMaxWidth: 10,
color: '#fac858' // TODO:
}
]
};
chartInstance.setOption(option);
//
chartInstance.on('click', handleChartClick);
//
window.addEventListener('resize', handleResize);
};
/**
* 图表点击事件
*/
const handleChartClick = (params: any) => {
const datum = chartData.value.find((item: any) => item.stnm === params.name);
if (datum) {
const currentTime = dayjs(datetimePicker.value.value);
const startTime = currentTime.subtract(1, 'month');
modalVisible.value = true;
modelStore.modalVisible = true;
modelStore.params.sttp = 'ENG';
modelStore.title = datum.stnm;
modelStore.params.stcd = datum.stcd;
modelStore.params.eqtp = 'QEC';
modelStore.filter.rangeTm = [startTime, currentTime];
modelStore.filter.stllgzlx = 'qecInterval';
modelStore.filter.stllTmType = 'day';
}
};
/**
* 窗口大小改变时重新调整图表
*/
const handleResize = () => {
if (chartInstance) {
chartInstance.resize();
}
};
/**
* 弹窗取消事件
*/
const handleModalCancel = () => {
modalVisible.value = false;
modalData.value = {
stcd: '',
stnm: '',
titleName: ''
};
};
/**
* 面板数据变化处理
*/
const handlePanelChange = async (data: any) => {
console.log('当前所有控件状态:', data);
//
if (data.select) {
select.value.value = data.select;
selectData.value = data.select;
}
if (data.datetime) {
datetimePicker.value.value = data.datetime;
}
//
if (data.select || data.datetime) {
await loadChartData();
}
};
// ==================== ====================
//
watch(
() => JidiSelectEventStore.selectedItem,
newVal => {
console.log('流域切换:', newVal);
if (newVal?.wbsCode) {
wbsCode.value = newVal.wbsCode;
getSelect();
}
},
{ deep: true, immediate: true }
);
//
onBeforeUnmount(() => {
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
window.removeEventListener('resize', handleResize);
});
</script>
<style lang="scss" scoped>
.chart-loading {
display: flex;
justify-content: center;
align-items: center;
height: 424px;
}
.chart-empty {
display: flex;
align-items: center;
height: 424px;
flex-direction: column;
/* align-content: center; */
justify-content: center;
text-align: center !important;
:deep(.ant-empty-description) {
text-align: center !important;
text-indent: 0;
width: 100%;
}
}
.chart-container {
width: 406px;
height: 424px;
}
.time-tip {
text-align: right;
font-size: 12px;
color: #8e8e8e;
padding: 8px 0;
margin-top: 4px;
}
</style>

View File

@ -34,7 +34,7 @@ service.interceptors.request.use(
config.headers._sysid = '10EC2E0B-AEA9-4757-83A2-201BA1BC54E9';
config.headers.authorization =
'bearer 3c424544-50d5-4787-9453-97bc18e44427';
'bearer 0952e56d-8a77-4c43-abe4-a44367a22d73';
config.baseURL = '/';
} else {
const user = useUserStoreHook();

View File

@ -1,8 +1,22 @@
<script setup lang="ts">
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
import RightDrawer from "@/components/RightDrawer/index.vue";
import ShengtaidabiaoMod from '@/modules/shengtaidabiaoMod/index.vue' // -
import ShengtaidabiaoTwoMod from '@/modules/shengtaidabiaoTwoMod/index.vue'
import JidiSelectorMod from '@/modules/jidiSelectorMod.vue';
import RightDrawer from '@/components/RightDrawer/index.vue';
import ShengtaidabiaoMod from '@/modules/shengtaidabiaoMod/index.vue'; // -
import ShengtaidabiaoTwoMod from '@/modules/shengtaidabiaoTwoMod/index.vue';
import StllyanchengChangeMod from '@/modules/stllyanchengChangeMod/index.vue' // -沿
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { ref, onMounted, watch } from 'vue';
const JidiSelectEventStore = useJidiSelectEventStore();
const baseid = ref('');
watch(
() => JidiSelectEventStore.selectedItem,
newVal => {
if (newVal && newVal.wbsCode) {
baseid.value = newVal.wbsCode;
}
},
{ deep: true, immediate: true }
);
</script>
<template>
@ -13,7 +27,8 @@ import ShengtaidabiaoTwoMod from '@/modules/shengtaidabiaoTwoMod/index.vue'
<div class="rightContent">
<RightDrawer>
<ShengtaidabiaoMod />
<ShengtaidabiaoTwoMod />
<ShengtaidabiaoTwoMod v-if="baseid == 'all'" />
<StllyanchengChangeMod v-if="baseid != 'all'" />
</RightDrawer>
</div>
</div>

View File

@ -1,9 +1,23 @@
<script setup lang="ts">
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
import RightDrawer from "@/components/RightDrawer/index.vue";
import XFFS from "@/modules/shengTaiLiuLiangXieFangSheShiMod/xieFangFangShi/index.vue" //
import XFFB from "@/modules/shengTaiLiuLiangXieFangSheShiMod/xieFangFenBu/index.vue" //
import { ref, watch } from 'vue';
import JidiSelectorMod from '@/modules/jidiSelectorMod.vue';
import RightDrawer from '@/components/RightDrawer/index.vue';
import XFFS from '@/modules/shengTaiLiuLiangXieFangSheShiMod/xieFangFangShi/index.vue'; //
import XFFB from '@/modules/shengTaiLiuLiangXieFangSheShiMod/xieFangFenBu/index.vue'; //
import STLLXZYCBH from "@/modules/shengTaiLiuLiangXieFangSheShiMod/xianZhiYanChenBianHua/index.vue"
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
const JidiSelectEventStore = useJidiSelectEventStore();
let wbsCode = ref('');
watch(
() => JidiSelectEventStore.selectedItem,
newVal => {
console.log('流域切换:', newVal);
if (newVal?.wbsCode) {
wbsCode.value = newVal.wbsCode;
}
},
{ deep: true, immediate: true }
);
</script>
<template>
@ -14,7 +28,8 @@ import XFFB from "@/modules/shengTaiLiuLiangXieFangSheShiMod/xieFangFenBu/index.
<div class="rightContent">
<RightDrawer>
<XFFS></XFFS>
<XFFB></XFFB>
<XFFB v-if="wbsCode == 'all'"> </XFFB>
<STLLXZYCBH v-if="wbsCode != 'all'" ></STLLXZYCBH>
</RightDrawer>
</div>
</div>