生态流量模块,接口对接
This commit is contained in:
commit
fcab0f077e
@ -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
|
||||
});
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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 类型设置默认格式
|
||||
|
||||
@ -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 || '',
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
@ -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}: <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>
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
812
frontend/src/modules/shengtaidabiaoTwoMod/TwoLayer/STLLXFFS.vue
Normal file
812
frontend/src/modules/shengtaidabiaoTwoMod/TwoLayer/STLLXFFS.vue
Normal 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>
|
||||
@ -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>
|
||||
|
||||
614
frontend/src/modules/stllyanchengChangeMod/index.vue
Normal file
614
frontend/src/modules/stllyanchengChangeMod/index.vue
Normal 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}: <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>
|
||||
@ -33,7 +33,7 @@ service.interceptors.request.use(
|
||||
config.headers._sysid = '10EC2E0B-AEA9-4757-83A2-201BA1BC54E9';
|
||||
|
||||
config.headers.authorization =
|
||||
'bearer aa5be16b-d1a3-4b93-9886-b2490025c7d6';
|
||||
'bearer 0952e56d-8a77-4c43-abe4-a44367a22d73';
|
||||
config.baseURL = '/';
|
||||
} else {
|
||||
const user = useUserStoreHook();
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user