Merge branch 'main' of http://121.37.111.42:3000/zhengsl/WholeProcessPlatform
This commit is contained in:
commit
826261a7a2
@ -2,7 +2,7 @@ import request from '@/utils/request';
|
|||||||
//生态流量达标情况
|
//生态流量达标情况
|
||||||
export function qgcetQgcStaticData(data: any) {
|
export function qgcetQgcStaticData(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-eng-server/eng/eq/interval/qgc/getQgcStaticData',
|
url: '/eq/interval/qgc/getQgcStaticData',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -10,7 +10,7 @@ export function qgcetQgcStaticData(data: any) {
|
|||||||
//tabs 日
|
//tabs 日
|
||||||
export function dayGetKendoListCust(data: any) {
|
export function dayGetKendoListCust(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-eng-server/eng/eq/interval/qgc/day/GetKendoListCust',
|
url: '/eq/interval/qgc/day/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -18,7 +18,7 @@ export function dayGetKendoListCust(data: any) {
|
|||||||
//tabs 小时
|
//tabs 小时
|
||||||
export function hourGetKendoListCust(queryParams: any) {
|
export function hourGetKendoListCust(queryParams: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-eng-server/eng/eq/interval/qgc/hour/GetKendoListCust',
|
url: '/eq/interval/qgc/hour/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: queryParams
|
data: queryParams
|
||||||
});
|
});
|
||||||
@ -26,7 +26,7 @@ export function hourGetKendoListCust(queryParams: any) {
|
|||||||
//接入过生态流量数据的电站
|
//接入过生态流量数据的电站
|
||||||
export function evnmAutoMonitorGetKendoListCust(queryParams: any) {
|
export function evnmAutoMonitorGetKendoListCust(queryParams: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/evnmAutoMonitor/GetKendoListCust',
|
url: '/eq/evnmAutoMonitor/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: queryParams
|
data: queryParams
|
||||||
});
|
});
|
||||||
@ -34,15 +34,63 @@ export function evnmAutoMonitorGetKendoListCust(queryParams: any) {
|
|||||||
//获取电站
|
//获取电站
|
||||||
export function vmsstbprptGetKendoList(queryParams: any) {
|
export function vmsstbprptGetKendoList(queryParams: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/vmsstbprpt/GetKendoList',
|
url: '/eq/vmsstbprpt/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: queryParams
|
data: queryParams
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//生态流量达标情况 /api/wmp-eng-server/eng/eq/qecRateCount
|
//生态流量达标情况
|
||||||
export function eqqecRateCount(queryParams: any) {
|
export function eqqecRateCount(queryParams: any) {
|
||||||
return request({
|
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',
|
method: 'post',
|
||||||
data: queryParams
|
data: queryParams
|
||||||
});
|
});
|
||||||
|
|||||||
@ -994,22 +994,22 @@ const wtPointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '建成日期',
|
name: '建成日期',
|
||||||
filed: 'jcdt',
|
filed: 'jcdt',
|
||||||
@ -1070,22 +1070,22 @@ const FhWpPointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '建成日期',
|
name: '建成日期',
|
||||||
filed: 'jcdt',
|
filed: 'jcdt',
|
||||||
@ -1259,22 +1259,22 @@ const FhZQPointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '建成日期',
|
name: '建成日期',
|
||||||
filed: 'jcdt',
|
filed: 'jcdt',
|
||||||
@ -1328,22 +1328,22 @@ const FPPointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
name: '开工日期',
|
name: '开工日期',
|
||||||
@ -1507,22 +1507,22 @@ const FPPointColumns1: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
name: '开工日期',
|
name: '开工日期',
|
||||||
@ -1766,22 +1766,22 @@ const FPPointColumns2: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
name: '开工日期',
|
name: '开工日期',
|
||||||
@ -1971,22 +1971,22 @@ const FPPointColumns4: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
name: '开工日期',
|
name: '开工日期',
|
||||||
@ -2190,22 +2190,22 @@ const FPPointColumns5: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
name: '开工日期',
|
name: '开工日期',
|
||||||
@ -2254,22 +2254,22 @@ const FBPointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
name: '开工日期',
|
name: '开工日期',
|
||||||
@ -2420,22 +2420,22 @@ const VaPointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
name: '开工日期',
|
name: '开工日期',
|
||||||
@ -2551,22 +2551,22 @@ const VPPointColumns: Array<any> = [
|
|||||||
format: 'YYYY-MM-DD',
|
format: 'YYYY-MM-DD',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '建成日期',
|
name: '建成日期',
|
||||||
filed: 'jcdt',
|
filed: 'jcdt',
|
||||||
@ -2644,22 +2644,22 @@ const wePointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '',
|
name: '',
|
||||||
filed: '',
|
filed: '',
|
||||||
@ -2684,22 +2684,22 @@ const waPointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '监测方式',
|
name: '监测方式',
|
||||||
filed: 'mwayName',
|
filed: 'mwayName',
|
||||||
@ -2759,22 +2759,22 @@ const StinfoAiVidoPointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '监控点地址',
|
name: '监控点地址',
|
||||||
filed: 'stlc',
|
filed: 'stlc',
|
||||||
@ -2822,22 +2822,22 @@ const DwPointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '所属电站',
|
name: '所属电站',
|
||||||
filed: 'ennm',
|
filed: 'ennm',
|
||||||
@ -3006,22 +3006,22 @@ const DwFivePointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '所属电站',
|
name: '所属电站',
|
||||||
filed: 'ennm',
|
filed: 'ennm',
|
||||||
@ -3176,22 +3176,22 @@ const DwSixPointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '所属电站',
|
name: '所属电站',
|
||||||
filed: 'ennm',
|
filed: 'ennm',
|
||||||
@ -3325,22 +3325,22 @@ const DwOnePointColumns: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '所属电站',
|
name: '所属电站',
|
||||||
filed: 'ennm',
|
filed: 'ennm',
|
||||||
@ -3486,22 +3486,22 @@ const EQPointColumns2: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '所属电站',
|
name: '所属电站',
|
||||||
filed: 'ennm',
|
filed: 'ennm',
|
||||||
@ -3619,22 +3619,22 @@ const EQPointColumns5: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '所属电站',
|
name: '所属电站',
|
||||||
filed: 'ennm',
|
filed: 'ennm',
|
||||||
@ -3723,22 +3723,22 @@ const EQPointColumns3: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '所属电站',
|
name: '所属电站',
|
||||||
filed: 'ennm',
|
filed: 'ennm',
|
||||||
@ -3857,22 +3857,22 @@ const EQPointColumns4: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '所属电站',
|
name: '所属电站',
|
||||||
filed: 'ennm',
|
filed: 'ennm',
|
||||||
@ -3990,22 +3990,22 @@ const EQPointColumns1: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '所属电站',
|
name: '所属电站',
|
||||||
filed: 'ennm',
|
filed: 'ennm',
|
||||||
@ -4123,22 +4123,22 @@ const EQPointColumns7: Array<any> = [
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
url: ''
|
url: ''
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: '经度(°)',
|
// name: '经度(°)',
|
||||||
filed: 'lgtd',
|
// filed: 'lgtd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '纬度(°)',
|
// name: '纬度(°)',
|
||||||
filed: 'lttd',
|
// filed: 'lttd',
|
||||||
visible: true,
|
// visible: true,
|
||||||
type: 'number',
|
// type: 'number',
|
||||||
toFixed: 6,
|
// toFixed: 6,
|
||||||
url: ''
|
// url: ''
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: '所属电站',
|
name: '所属电站',
|
||||||
filed: 'ennm',
|
filed: 'ennm',
|
||||||
|
|||||||
@ -683,9 +683,11 @@ const handleFocus = () => {
|
|||||||
// Handle focus
|
// Handle focus
|
||||||
};
|
};
|
||||||
|
|
||||||
const filterOption = (input: string, option?: { value: string }) => {
|
const filterOption = (input: string, option?: { label: string; value: string }) => {
|
||||||
if (!option) return false;
|
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
|
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) {
|
if (datetimeValue.value) {
|
||||||
// 使用传入的 format,如果没有则根据 picker 类型设置默认格式
|
// 使用传入的 format,如果没有则根据 picker 类型设置默认格式
|
||||||
|
|||||||
@ -88,7 +88,7 @@
|
|||||||
</div>
|
</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">
|
@cancel="handleDetailModalClose">
|
||||||
<HJMZDTwoLays :tc="{
|
<HJMZDTwoLays :tc="{
|
||||||
stcd: detailData.stcd || '',
|
stcd: detailData.stcd || '',
|
||||||
|
|||||||
@ -63,7 +63,7 @@ const customTransform = (res: any) => {
|
|||||||
// 查看详情
|
// 查看详情
|
||||||
const handleViewDetail = (record: any) => {
|
const handleViewDetail = (record: any) => {
|
||||||
modelStore.modalVisible = true;
|
modelStore.modalVisible = true;
|
||||||
modelStore.params.sttp = "VD_FBFM";
|
modelStore.params.sttp = record.sttpCode;
|
||||||
modelStore.title = record.stnm ;
|
modelStore.title = record.stnm ;
|
||||||
modelStore.params.stcd = record.stcd;
|
modelStore.params.stcd = record.stcd;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,21 @@
|
|||||||
<!-- SidePanelItem.vue -->
|
<!-- SidePanelItem.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<SidePanelItem title="生态流量限值沿程变化" :select="select" :datetimePicker="datetimePicker" >
|
<SidePanelItem
|
||||||
<!-- 图表容器 -->
|
title="生态流量限值沿程变化"
|
||||||
<div ref="chartRef" style="width: 100%; height: 400px;"></div>
|
:select="select"
|
||||||
</SidePanelItem>
|
:datetimePicker="datetimePicker"
|
||||||
</div>
|
@update-values="handlePanelChange1"
|
||||||
|
>
|
||||||
|
<!-- 图表容器 -->
|
||||||
|
<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>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -13,191 +23,327 @@ import { ref, onMounted, computed, watch, onBeforeUnmount } from 'vue';
|
|||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import type { EChartsOption } 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({
|
defineOptions({
|
||||||
name: 'xieFangFenBu'
|
name: 'xieFangFenBu'
|
||||||
});
|
});
|
||||||
const select = ref({
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
show: true,
|
let wbsCode = ref('');
|
||||||
value: undefined,
|
|
||||||
options: [
|
|
||||||
|
|
||||||
]
|
const select = ref({
|
||||||
|
show: true,
|
||||||
|
value: undefined,
|
||||||
|
options: [],
|
||||||
|
picker: undefined,
|
||||||
|
format: undefined
|
||||||
});
|
});
|
||||||
const datetimePicker = ref({
|
const datetimePicker = ref({
|
||||||
show: true,
|
show: true,
|
||||||
value: undefined,
|
value: dayjs().format('YYYY-MM'), // 默认值为当前月份
|
||||||
format: 'YYYY-MM', //YYYY-MM-DD HH
|
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([
|
const chartData = ref([]);
|
||||||
{ stnm: '站点A001', qecLimit: 120.5 },
|
|
||||||
{ stnm: '站点B002', qecLimit: 135.8 },
|
// 加载状态
|
||||||
{ stnm: '站点C003', qecLimit: 98.3 },
|
const loading = ref(false);
|
||||||
{ 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 flowUnit = ref('m³/s');
|
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 chartOption = computed<EChartsOption>(() => {
|
||||||
const dataLength = chartData.value.length;
|
const dataLength = chartData.value.length;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
legend: {
|
legend: {
|
||||||
data: ['生态流量限值'],
|
data: ['生态流量限值'],
|
||||||
center: true,
|
center: true,
|
||||||
icon: 'rect',
|
icon: 'rect',
|
||||||
itemHeight: 3
|
itemHeight: 3
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: 40,
|
top: 40,
|
||||||
left: 40,
|
left: 40,
|
||||||
right: 20,
|
right: 20,
|
||||||
bottom: 60
|
bottom: 60
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
confine: true,
|
confine: true,
|
||||||
formatter: function (params: any) {
|
formatter: function (params: any) {
|
||||||
if (!params || params.length === 0) return '';
|
if (!params || params.length === 0) return '';
|
||||||
const value = params[0].value ?? '-';
|
const value = params[0].value ?? '-';
|
||||||
return `<h3 style="color:#FFF">${params[0].name}</h3>
|
return `<h3 style="color:#FFF">${params[0].name}</h3>
|
||||||
<div>${params[0].marker}生态流量限值: <span style="float:right">${value} ${flowUnit.value}</span></div>`;
|
<div>${params[0].marker}生态流量限值: <span style="float:right">${value} ${flowUnit.value}</span></div>`;
|
||||||
},
|
},
|
||||||
axisPointer: {
|
axisPointer: {
|
||||||
type: 'line'
|
type: 'line'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
data: chartData.value.map((item: any) => item.stnm),
|
data: chartData.value.map((item: any) => item.stnm),
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
interval: dataLength > 12 ? 2 : 0,
|
interval: dataLength > 12 ? 2 : 0,
|
||||||
rotate: 0,
|
rotate: 0,
|
||||||
formatter: (value: string, index: number) => {
|
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) {
|
if (dataLength === 2) {
|
||||||
return `{a|${displayText}}`;
|
return `{a|${displayText}}`;
|
||||||
} else if (index % 2 !== 0) {
|
} else if (index % 2 !== 0) {
|
||||||
// 奇数索引:上方显示
|
// 奇数索引:上方显示
|
||||||
return `{a|${displayText}}`;
|
return `{a|${displayText}}`;
|
||||||
} else {
|
} else {
|
||||||
// 偶数索引:下方显示(通过换行实现错位)
|
// 偶数索引:下方显示(通过换行实现错位)
|
||||||
return '\n{b|}' + `{b|${displayText}}`;
|
return '\n{b|}' + `{b|${displayText}}`;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
rich: {
|
|
||||||
a: {
|
|
||||||
height: 20,
|
|
||||||
align: 'center'
|
|
||||||
},
|
|
||||||
b: {
|
|
||||||
height: 30,
|
|
||||||
align: 'center'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
yAxis: [{
|
rich: {
|
||||||
type: 'value',
|
a: {
|
||||||
name: `流量(${flowUnit.value})`
|
height: 20,
|
||||||
}],
|
align: 'center'
|
||||||
dataZoom: [
|
},
|
||||||
{
|
b: {
|
||||||
type: 'inside',
|
height: 30,
|
||||||
show: false
|
align: 'center'
|
||||||
},
|
}
|
||||||
{
|
}
|
||||||
type: 'slider',
|
},
|
||||||
show: false
|
axisTick: {
|
||||||
}
|
show: false
|
||||||
],
|
}
|
||||||
series: [
|
},
|
||||||
{
|
yAxis: [
|
||||||
name: '生态流量限值',
|
{
|
||||||
type: 'line',
|
type: 'value',
|
||||||
data: chartData.value.map((item: any) => item.qecLimit),
|
name: `流量(${flowUnit.value})`
|
||||||
smooth: false,
|
}
|
||||||
showSymbol: true,
|
],
|
||||||
symbolSize: 6
|
dataZoom: [
|
||||||
}
|
{
|
||||||
],
|
type: 'inside',
|
||||||
color: [generateModerateColor()]
|
show: false
|
||||||
};
|
},
|
||||||
|
{
|
||||||
|
type: 'slider',
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '生态流量限值',
|
||||||
|
type: 'line',
|
||||||
|
data: chartData.value.map((item: any) => ({
|
||||||
|
value: item.qecLimit,
|
||||||
|
stcd: item.stcd,
|
||||||
|
stnm: item.stnm
|
||||||
|
})),
|
||||||
|
smooth: false,
|
||||||
|
showSymbol: true,
|
||||||
|
symbolSize: 6,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#f7a737'
|
||||||
|
},
|
||||||
|
lineStyle: {
|
||||||
|
color: '#f7a737'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
color: ['#f7a737']
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// 图表实例引用
|
// 图表实例引用
|
||||||
let chartInstance: echarts.ECharts | null = null;
|
let chartInstance: echarts.ECharts | null = null;
|
||||||
const chartRef = ref<HTMLDivElement>();
|
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 = () => {
|
const initChart = () => {
|
||||||
if (!chartRef.value) {
|
if (!chartRef.value) {
|
||||||
console.warn('图表容器未找到');
|
console.warn('图表容器未找到');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('开始初始化图表...');
|
console.log('开始初始化图表...');
|
||||||
chartInstance = echarts.init(chartRef.value);
|
chartInstance = echarts.init(chartRef.value);
|
||||||
chartInstance.setOption(chartOption.value);
|
chartInstance.setOption(chartOption.value);
|
||||||
console.log('图表初始化完成');
|
|
||||||
|
|
||||||
// 监听窗口大小变化
|
// 添加点击事件监听
|
||||||
window.addEventListener('resize', handleResize);
|
chartInstance.on('click', handleChartClick);
|
||||||
|
|
||||||
|
console.log('图表初始化完成');
|
||||||
|
|
||||||
|
// 监听窗口大小变化
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理窗口大小变化
|
// 处理窗口大小变化
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
chartInstance?.resize();
|
chartInstance?.resize();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新图表配置
|
// 更新图表配置
|
||||||
watch(chartOption, (newOption) => {
|
watch(chartOption, newOption => {
|
||||||
if (chartInstance) {
|
if (chartInstance) {
|
||||||
chartInstance.setOption(newOption, true);
|
chartInstance.setOption(newOption, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
// 监听数据变化,处理空数据情况
|
||||||
initChart();
|
watch(chartData, (newData) => {
|
||||||
|
if (chartInstance && newData.length === 0) {
|
||||||
|
chartInstance.clear();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await selectdata();
|
||||||
|
await getEchartsData();
|
||||||
|
initChart();
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
window.removeEventListener('resize', handleResize);
|
window.removeEventListener('resize', handleResize);
|
||||||
chartInstance?.dispose();
|
chartInstance?.dispose();
|
||||||
chartInstance = null;
|
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>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<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>
|
</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>
|
||||||
@ -1,194 +1,365 @@
|
|||||||
<!-- SidePanelItem.vue -->
|
<!-- SidePanelItem.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div class="xie-fang-fang-shi-container">
|
<div class="xie-fang-fang-shi-container">
|
||||||
<SidePanelItem title="生态流量泄放方式">
|
<SidePanelItem title="生态流量泄放方式">
|
||||||
<div ref="chartRef" class="pie-chart"></div>
|
<!-- Loading 状态 -->
|
||||||
</SidePanelItem>
|
<a-spin v-if="loading" :spinning="true" style="width: 100%; height: 350px; display: flex; justify-content: center; align-items: center;" />
|
||||||
</div>
|
|
||||||
|
<!-- 空状态提示 -->
|
||||||
|
<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>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<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 SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import type { 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({
|
defineOptions({
|
||||||
name: 'xieFangFangShi'
|
name: 'xieFangFangShi'
|
||||||
});
|
});
|
||||||
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
const chartRef = ref<HTMLElement | null>(null);
|
const chartRef = ref<HTMLElement | null>(null);
|
||||||
let chartInstance: ECharts | null = null;
|
let chartInstance: ECharts | null = null;
|
||||||
|
let wbsCode = ref('');
|
||||||
|
|
||||||
// 静态数据
|
// Loading 状态
|
||||||
const pieData = [
|
const loading = ref(false);
|
||||||
{ value: 44.83, name: '基荷发电' },
|
|
||||||
{ value: 19.31, name: '泄洪设施' },
|
// 动态数据
|
||||||
{ value: 8.28, name: '生态机组' },
|
const pieData = ref<any[]>([]);
|
||||||
{ value: 8.96, name: '生态放流管' },
|
const totalCount = ref(0);
|
||||||
{ value: 9.65, name: '生态放流闸' },
|
const apiRawData = ref<any[]>([]); // 保存原始 API 数据
|
||||||
{ value: 5.52, name: '生态放流孔' },
|
|
||||||
{ value: 3.45, name: '生态放流洞' }
|
// 弹框状态
|
||||||
];
|
const modalVisible = ref(false);
|
||||||
|
const modalTitle = ref('');
|
||||||
|
const selectedData = ref<any>(null);
|
||||||
|
|
||||||
// 颜色配置(根据图片配色)
|
// 颜色配置(根据图片配色)
|
||||||
const colors = [
|
const colors = [
|
||||||
'#9556a4', // 基荷发电 - 紫色
|
'#9556a4', // 基荷发电 - 紫色
|
||||||
'#30b7b9', // 泄洪设施 - 青绿色
|
'#30b7b9', // 泄洪设施 - 青绿色
|
||||||
'#4b79ab', // 生态机组 - 蓝色
|
'#4b79ab', // 生态机组 - 蓝色
|
||||||
'#dbb629', // 生态放流管 - 黄色
|
'#dbb629', // 生态放流管 - 黄色
|
||||||
'#df91ab', // 生态放流闸 - 粉色
|
'#df91ab', // 生态放流闸 - 粉色
|
||||||
'#78c300', // 生态放流孔 - 浅绿色
|
'#78c300', // 生态放流孔 - 浅绿色
|
||||||
'#7399c6' // 生态放流洞 - 浅蓝色
|
'#7399c6' // 生态放流洞 - 浅蓝色
|
||||||
];
|
];
|
||||||
|
|
||||||
// 初始化图表
|
// 初始化图表
|
||||||
const initChart = () => {
|
const initChart = () => {
|
||||||
if (!chartRef.value) return;
|
if (!chartRef.value) return;
|
||||||
|
|
||||||
// 确保容器有正确的高度
|
// 确保容器有正确的高度
|
||||||
if (chartRef.value.clientHeight === 0) {
|
if (chartRef.value.clientHeight === 0) {
|
||||||
// 如果容器高度为 0,延迟初始化
|
// 如果容器高度为 0,延迟初始化
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
initChart();
|
initChart();
|
||||||
}, 100);
|
}, 100);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
chartInstance = echarts.init(chartRef.value);
|
chartInstance = echarts.init(chartRef.value);
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
trigger: 'item',
|
||||||
formatter: '{b}: {c}%'
|
formatter: '{b}: {c}%'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '泄放设施',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['42%', '62%'], // 环形:内径 42%,外径 62%(进一步缩小)
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
avoidLabelOverlap: true,
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 0,
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderWidth: 2
|
||||||
},
|
},
|
||||||
series: [
|
label: {
|
||||||
{
|
show: true,
|
||||||
name: '泄放设施',
|
position: 'outside',
|
||||||
type: 'pie',
|
alignTo: 'edge', // 标签对齐到边缘
|
||||||
radius: ['42%', '62%'], // 环形:内径 42%,外径 62%(进一步缩小)
|
margin: 8, // 标签与圆环的距离
|
||||||
center: ['50%', '50%'],
|
formatter: (params: any) => {
|
||||||
avoidLabelOverlap: true,
|
return `{name|${params.name}}\n{value|${params.value}%}`;
|
||||||
itemStyle: {
|
},
|
||||||
borderRadius: 0,
|
rich: {
|
||||||
borderColor: '#fff',
|
name: {
|
||||||
borderWidth: 2
|
fontSize: 12,
|
||||||
},
|
color: '#666666', // 灰蓝色标签
|
||||||
label: {
|
lineHeight: 18,
|
||||||
show: true,
|
fontFamily: 'Microsoft YaHei, sans-serif',
|
||||||
position: 'outside',
|
align: 'left' // 左对齐
|
||||||
alignTo: 'edge', // 标签对齐到边缘
|
|
||||||
margin: 8, // 标签与圆环的距离
|
|
||||||
formatter: (params: any) => {
|
|
||||||
return `{name|${params.name}}\n{value|${params.value}%}`;
|
|
||||||
},
|
|
||||||
rich: {
|
|
||||||
name: {
|
|
||||||
fontSize: 12,
|
|
||||||
color: '#666666', // 灰蓝色标签
|
|
||||||
lineHeight: 18,
|
|
||||||
fontFamily: 'Microsoft YaHei, sans-serif',
|
|
||||||
align: 'left' // 左对齐
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
fontSize: 12,
|
|
||||||
color: '#2f6b98', // 灰蓝色百分比
|
|
||||||
lineHeight: 18,
|
|
||||||
fontFamily: 'Microsoft YaHei, sans-serif',
|
|
||||||
align: 'center', // 左对齐
|
|
||||||
fontWeight: 'bold' // 百分比加粗
|
|
||||||
}
|
|
||||||
},
|
|
||||||
overflow: 'none', // 不省略,完整显示
|
|
||||||
padding: [0, 0]
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: true,
|
|
||||||
length: 12,
|
|
||||||
length2: 12,
|
|
||||||
lineStyle: {
|
|
||||||
width: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
scale: false, // 禁用悬停放大
|
|
||||||
itemStyle: {
|
|
||||||
brightness: 1.2, // 鼠标悬停时颜色变亮 20%
|
|
||||||
shadowBlur: 0 // 禁用阴影
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: true // 悬停时不显示引导线变化
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: pieData.map((item, index) => ({
|
|
||||||
...item,
|
|
||||||
itemStyle: { color: colors[index % colors.length] },
|
|
||||||
labelLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: colors[index % colors.length]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
],
|
|
||||||
// 中心文字
|
|
||||||
title: {
|
|
||||||
text: '145',
|
|
||||||
subtext: '泄放设施总数量\n(个)',
|
|
||||||
left: 'center',
|
|
||||||
top: 'center',
|
|
||||||
textStyle: {
|
|
||||||
color: '#2e86de',
|
|
||||||
fontSize: 30,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
fontFamily: 'Arial'
|
|
||||||
},
|
},
|
||||||
subtextStyle: {
|
value: {
|
||||||
color: '#666',
|
fontSize: 12,
|
||||||
fontSize: 12,
|
color: '#2f6b98', // 灰蓝色百分比
|
||||||
lineHeight: 16,
|
lineHeight: 18,
|
||||||
fontFamily: 'Microsoft YaHei, sans-serif'
|
fontFamily: 'Microsoft YaHei, sans-serif',
|
||||||
|
align: 'center', // 左对齐
|
||||||
|
fontWeight: 'bold' // 百分比加粗
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
overflow: 'none', // 不省略,完整显示
|
||||||
|
padding: [0, 0]
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: true,
|
||||||
|
length: 12,
|
||||||
|
length2: 12,
|
||||||
|
lineStyle: {
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
scale: false, // 禁用悬停放大
|
||||||
|
itemStyle: {
|
||||||
|
brightness: 1.2, // 鼠标悬停时颜色变亮 20%
|
||||||
|
shadowBlur: 0 // 禁用阴影
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: true // 悬停时不显示引导线变化
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: pieData.value.map((item, index) => ({
|
||||||
|
...item,
|
||||||
|
itemStyle: { color: colors[index % colors.length] },
|
||||||
|
labelLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: colors[index % colors.length]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 中心文字
|
||||||
|
title: {
|
||||||
|
text: totalCount.value.toString(),
|
||||||
|
subtext: '泄放设施总数量\n(个)',
|
||||||
|
left: 'center',
|
||||||
|
top: 'center',
|
||||||
|
textStyle: {
|
||||||
|
color: '#2e86de',
|
||||||
|
fontSize: 30,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontFamily: 'Arial'
|
||||||
|
},
|
||||||
|
subtextStyle: {
|
||||||
|
color: '#666',
|
||||||
|
fontSize: 12,
|
||||||
|
lineHeight: 16,
|
||||||
|
fontFamily: 'Microsoft YaHei, sans-serif'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
) // 保留所有原始数据字段
|
||||||
};
|
};
|
||||||
|
|
||||||
chartInstance.setOption(option);
|
modalTitle.value = `${clickedData.name} - 详细信息`;
|
||||||
|
modalVisible.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹框取消事件
|
||||||
|
*/
|
||||||
|
const handleModalCancel = () => {
|
||||||
|
modalVisible.value = false;
|
||||||
|
selectedData.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理响应式
|
// 处理响应式
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
chartInstance?.resize();
|
chartInstance?.resize();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 页面加载时执行的逻辑
|
// 页面加载时执行的逻辑
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 使用 nextTick 确保 DOM 已经完全渲染
|
// 使用 nextTick 确保 DOM 已经完全渲染
|
||||||
|
setTimeout(() => {
|
||||||
|
initChart();
|
||||||
|
// 初始化后再 resize 一次,确保尺寸正确
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
initChart();
|
chartInstance?.resize();
|
||||||
// 初始化后再 resize 一次,确保尺寸正确
|
}, 200);
|
||||||
setTimeout(() => {
|
}, 50);
|
||||||
chartInstance?.resize();
|
window.addEventListener('resize', handleResize);
|
||||||
}, 200);
|
|
||||||
}, 50);
|
// 组件挂载时获取数据
|
||||||
window.addEventListener('resize', handleResize);
|
if (wbsCode.value) {
|
||||||
|
getecharts();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 组件卸载时清理
|
// 组件卸载时清理
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
window.removeEventListener('resize', handleResize);
|
window.removeEventListener('resize', handleResize);
|
||||||
chartInstance?.dispose();
|
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>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.xie-fang-fang-shi-container {
|
.xie-fang-fang-shi-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pie-chart {
|
.pie-chart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 350px;
|
height: 350px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -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>
|
<template>
|
||||||
<div>
|
<SidePanelItem title="泄放方式分布情况">
|
||||||
<SidePanelItem title="泄放方式分布情况">
|
<div ref="chartRef" class="bar-chart-container"></div>
|
||||||
<div class="chart-container">
|
|
||||||
<!-- 自定义图例区域 -->
|
<!-- 空状态提示 -->
|
||||||
<div class="legend-container">
|
<a-empty v-if="showEmpty" description="暂无数据" />
|
||||||
<div class="legend-items">
|
</SidePanelItem>
|
||||||
<div
|
|
||||||
v-for="(item) in currentLegendItems"
|
<!-- 详情弹框 -->
|
||||||
:key="item.name"
|
<a-modal
|
||||||
class="legend-item"
|
v-model:open="modalVisible"
|
||||||
:class="{ 'inactive': legendInactiveSet.has(item.name) }"
|
title="泄放方式分布情况"
|
||||||
@click="toggleLegend(item.name)"
|
width="1536px"
|
||||||
>
|
:footer="null"
|
||||||
<span class="legend-color" :style="{ backgroundColor: item.color }"></span>
|
@cancel="handleModalCancel"
|
||||||
<span class="legend-text">{{ item.name }}</span>
|
>
|
||||||
</div>
|
<FBQKTwolayer
|
||||||
</div>
|
v-if="modalVisible"
|
||||||
<!-- 分页控制 -->
|
:selectData="selectData"
|
||||||
<div class="legend-pagination" v-if="totalPages > 1">
|
:jidiName="jidiName"
|
||||||
<span
|
:jiDiList="JidiSelectEventStore.jidiData"
|
||||||
class="pagination-btn"
|
></FBQKTwolayer>
|
||||||
:class="{ disabled: currentPage === 1 }"
|
</a-modal>
|
||||||
@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>
|
|
||||||
</SidePanelItem>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<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 SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import * as echarts from 'echarts';
|
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({
|
defineOptions({
|
||||||
name: 'xieFangFenBu'
|
name: 'XieFangFenBu'
|
||||||
});
|
});
|
||||||
|
|
||||||
// 图表实例引用
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
|
|
||||||
|
// DOM 引用
|
||||||
const chartRef = ref<HTMLElement | null>(null);
|
const chartRef = ref<HTMLElement | null>(null);
|
||||||
let chartInstance: echarts.ECharts | null = null;
|
let chartInstance: ECharts | null = null;
|
||||||
|
|
||||||
// 图例配置
|
// 响应式数据
|
||||||
const ITEMS_PER_PAGE = 4; // 每页显示 4 个图例
|
const loading = ref(false);
|
||||||
const currentPage = ref(1); // 当前页码
|
const data = ref<any[]>([]);
|
||||||
|
const echartsXData = ref<string[]>([]);
|
||||||
|
const wbsCode = ref('');
|
||||||
|
|
||||||
// 完整的图例数据(8 个图例)
|
// 弹框状态
|
||||||
const allLegendItems = ref([
|
const modalVisible = ref(false);
|
||||||
{ name: '生态放流孔', color: '#7cb342' },
|
const selectData = ref(''); // 选中的设施类型名称
|
||||||
{ name: '生态放流闸', color: '#ce93d8' },
|
const jidiName = ref(''); // 选中的基地名称
|
||||||
{ name: '生态放流洞', color: '#64b5f6' },
|
|
||||||
{ name: '生态放流管', color: '#ffd54f' },
|
|
||||||
{ name: '生态放流口', color: '#ff8a65' },
|
|
||||||
{ name: '生态放流道', color: '#4db6ac' },
|
|
||||||
{ name: '生态放流渠', color: '#ba68c8' },
|
|
||||||
{ name: '生态放流站', color: '#a1887f' }
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 计算总页数
|
// 设施类型配置
|
||||||
const totalPages = computed(() => {
|
const typeName = [
|
||||||
return Math.ceil(allLegendItems.value.length / ITEMS_PER_PAGE);
|
{ 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(() => {
|
* 手写 omit 函数(替代 lodash.omit)
|
||||||
const start = (currentPage.value - 1) * ITEMS_PER_PAGE;
|
*/
|
||||||
const end = start + ITEMS_PER_PAGE;
|
const omit = (obj: any, keys: string[]) => {
|
||||||
return allLegendItems.value.slice(start, end);
|
const result = { ...obj };
|
||||||
});
|
keys.forEach(key => {
|
||||||
|
delete result[key];
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
// 图例 inactive 状态集合
|
/**
|
||||||
const legendInactiveSet = ref<Set<string>>(new Set());
|
* 获取颜色配置(模拟 getUnitConfigByCode)
|
||||||
|
* TODO: 如果项目中有等效实现,请替换此处逻辑
|
||||||
|
*/
|
||||||
|
const getColorByType = (type: string): string => {
|
||||||
|
// 这里可以替换为实际的 getUnitConfigByCode 调用
|
||||||
|
// const config = getUnitConfigByCode('Other', type);
|
||||||
|
// return config?.lineColor || config?.pieColor;
|
||||||
|
|
||||||
// 切换图例显示/隐藏
|
// 暂时使用默认配色
|
||||||
const toggleLegend = (name: string) => {
|
const index = typeName.findIndex(item => item.eqtp === type);
|
||||||
if (legendInactiveSet.value.has(name)) {
|
return defaultColors[index] || '#999999';
|
||||||
legendInactiveSet.value.delete(name);
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化图表
|
||||||
|
*/
|
||||||
|
const initChart = () => {
|
||||||
|
if (!chartRef.value) return;
|
||||||
|
|
||||||
|
// 确保容器有正确的高度
|
||||||
|
if (chartRef.value.clientHeight === 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
initChart();
|
||||||
|
}, 100);
|
||||||
|
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 {
|
} else {
|
||||||
legendInactiveSet.value.add(name);
|
countSums[baseid] = count;
|
||||||
}
|
}
|
||||||
updateChart();
|
});
|
||||||
};
|
|
||||||
|
|
||||||
// 上一页
|
const values = Object.values(countSums);
|
||||||
const prevPage = () => {
|
const maxValue = values.length > 0 ? Math.max(...values) : 0;
|
||||||
if (currentPage.value > 1) {
|
|
||||||
currentPage.value--;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 下一页
|
// 计算总计数据
|
||||||
const nextPage = () => {
|
const totalData: number[] = [];
|
||||||
if (currentPage.value < totalPages.value) {
|
const uniqueBaseNames = [...new Set(echartsXData.value)];
|
||||||
currentPage.value++;
|
uniqueBaseNames.forEach((basename, index) => {
|
||||||
}
|
let total = 0;
|
||||||
};
|
data.value.forEach(item => {
|
||||||
|
if (item.basename === basename) {
|
||||||
|
total += Number(item.count) || 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
totalData[index] = total;
|
||||||
|
});
|
||||||
|
|
||||||
// 示例数据 - 可以替换为实际 API 数据
|
// 构建 series 数据
|
||||||
const xData = ref([
|
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;
|
||||||
'黄河上游干流',
|
});
|
||||||
'东北',
|
});
|
||||||
'闽浙赣',
|
|
||||||
'其他'
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 系列数据(与图例顺序对应,8 个系列)
|
// 获取颜色数组
|
||||||
const seriesData = ref([
|
const colors = typeName.map(type => getColorByType(type.eqtp));
|
||||||
{ 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 option: any = {
|
||||||
const calculateTotal = (index: number) => {
|
tooltip: {
|
||||||
return seriesData.value
|
trigger: 'axis',
|
||||||
.filter(series => !legendInactiveSet.value.has(series.name)) // 只计算未隐藏的系列
|
confine: true,
|
||||||
.reduce((sum, series) => {
|
formatter: (params: any) => {
|
||||||
return sum + (series.data[index] || 0);
|
const content = params
|
||||||
}, 0);
|
.map((item: any) => {
|
||||||
};
|
let value = item.value || 0;
|
||||||
|
if (item.seriesName === '总计') {
|
||||||
// 更新图表
|
value = totalData[item.dataIndex];
|
||||||
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/>`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
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]);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
grid: {
|
itemStyle: {
|
||||||
left: '3%',
|
color: 'transparent'
|
||||||
right: '4%',
|
|
||||||
bottom: '15%',
|
|
||||||
top: '10%',
|
|
||||||
containLabel: true
|
|
||||||
},
|
},
|
||||||
xAxis: {
|
data: Array(totalData.length).fill(0)
|
||||||
type: 'category',
|
}
|
||||||
data: xData.value,
|
],
|
||||||
axisLabel: {
|
color: colors
|
||||||
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;
|
|
||||||
|
|
||||||
// 判断当前系列是否被隐藏
|
return option;
|
||||||
const isHidden = legendInactiveSet.value.has(series.name);
|
};
|
||||||
|
|
||||||
return {
|
/**
|
||||||
name: series.name,
|
* 图表点击事件
|
||||||
type: 'bar',
|
*/
|
||||||
stack: 'total',
|
const handleChartClick = (params: any) => {
|
||||||
barWidth: '60%',
|
// 根据系列名称找到对应的 sttpCode (eqtp)
|
||||||
// 如果系列被隐藏,将数据设置为 null,否则使用原始数据
|
const typeConfig = typeName.find(item => item.label === params.seriesName);
|
||||||
data: isHidden ? series.data.map(() => null) : series.data,
|
selectData.value = typeConfig ? typeConfig.eqtp : '';
|
||||||
// 设置系列颜色
|
|
||||||
itemStyle: {
|
// 将基地名称转换为 wbsCode
|
||||||
color: color
|
const jidiInfo = JidiSelectEventStore.jidiData.find(
|
||||||
},
|
(item: any) => item.wbsName === params.name
|
||||||
// 柱顶数值标签 - 只在最后一个系列显示总和
|
);
|
||||||
label: {
|
jidiName.value = jidiInfo ? jidiInfo.wbsCode : params.name;
|
||||||
show: index === seriesData.value.length - 1, // 只在最后一个系列显示
|
|
||||||
position: 'top',
|
modalVisible.value = true;
|
||||||
fontSize: 12,
|
};
|
||||||
color: '#333',
|
|
||||||
formatter: (params: any) => {
|
/**
|
||||||
// 计算总和
|
* 弹框取消事件
|
||||||
const total = calculateTotal(params.dataIndex);
|
*/
|
||||||
return total > 0 ? total.toString() : '';
|
const handleModalCancel = () => {
|
||||||
}
|
modalVisible.value = false;
|
||||||
},
|
selectData.value = '';
|
||||||
// 鼠标悬停效果
|
jidiName.value = '';
|
||||||
emphasis: {
|
};
|
||||||
itemStyle: {
|
|
||||||
shadowBlur: 0,
|
/**
|
||||||
shadowColor: 'rgba(0, 0, 0, 0)'
|
* 获取数据
|
||||||
}
|
*/
|
||||||
}
|
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'
|
||||||
};
|
};
|
||||||
|
|
||||||
chartInstance.setOption(option, 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 initChart = () => {
|
* 处理窗口大小变化
|
||||||
if (!chartRef.value) return;
|
*/
|
||||||
|
|
||||||
// 延迟初始化确保容器已渲染
|
|
||||||
setTimeout(() => {
|
|
||||||
chartInstance = echarts.init(chartRef.value);
|
|
||||||
updateChart();
|
|
||||||
|
|
||||||
// 强制重绘确保尺寸正确
|
|
||||||
setTimeout(() => {
|
|
||||||
chartInstance?.resize();
|
|
||||||
}, 100);
|
|
||||||
}, 50);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听窗口大小变化
|
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
chartInstance?.resize();
|
chartInstance?.resize();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 监听图例分页变化
|
// 生命周期钩子
|
||||||
watch([currentPage, legendInactiveSet], () => {
|
|
||||||
updateChart();
|
|
||||||
}, { deep: true });
|
|
||||||
|
|
||||||
// 页面加载时执行
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
// 延迟初始化图表,确保 DOM 已渲染
|
||||||
|
setTimeout(() => {
|
||||||
initChart();
|
initChart();
|
||||||
window.addEventListener('resize', handleResize);
|
setTimeout(() => {
|
||||||
|
chartInstance?.resize();
|
||||||
|
}, 200);
|
||||||
|
}, 50);
|
||||||
|
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
|
||||||
|
// 组件挂载时获取数据
|
||||||
|
if (wbsCode.value) {
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 页面卸载时清理
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
window.removeEventListener('resize', handleResize);
|
window.removeEventListener('resize', handleResize);
|
||||||
chartInstance?.dispose();
|
chartInstance?.dispose();
|
||||||
chartInstance = null;
|
chartInstance = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 暴露刷新数据的方法
|
// 监听基地选择变化
|
||||||
const refreshData = (newXData: string[], newSeriesData: any[]) => {
|
watch(
|
||||||
xData.value = newXData;
|
() => JidiSelectEventStore.selectedItem,
|
||||||
seriesData.value = newSeriesData;
|
newVal => {
|
||||||
updateChart();
|
console.log('流域切换:', newVal);
|
||||||
};
|
if (newVal?.wbsCode) {
|
||||||
|
wbsCode.value = newVal.wbsCode;
|
||||||
// 暴露设置图例数据的方法
|
fetchData();
|
||||||
const setLegendData = (legendData: Array<{ name: string; color: string }>) => {
|
}
|
||||||
allLegendItems.value = legendData;
|
},
|
||||||
currentPage.value = 1; // 重置为第一页
|
{ deep: true, immediate: true }
|
||||||
legendInactiveSet.value.clear();
|
);
|
||||||
};
|
|
||||||
|
|
||||||
// 暴露给父组件使用
|
|
||||||
defineExpose({
|
|
||||||
refreshData,
|
|
||||||
setLegendData
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.chart-container {
|
.bar-chart-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 350px;
|
||||||
.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 {
|
|
||||||
width: 100%;
|
|
||||||
height: 350px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -295,7 +295,7 @@ const handleChange = async () => {
|
|||||||
select: ['stcd', 'stnm']
|
select: ['stcd', 'stnm']
|
||||||
};
|
};
|
||||||
let res = await vmsstbprptGetKendoList(params);
|
let res = await vmsstbprptGetKendoList(params);
|
||||||
if (res?.data?.success && res?.data?.data) {
|
if ( res?.data?.data) {
|
||||||
let data = res.data.data;
|
let data = res.data.data;
|
||||||
stcdOptions.value = data.map((item: any) => ({
|
stcdOptions.value = data.map((item: any) => ({
|
||||||
value: item.stcd,
|
value: item.stcd,
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
v-model:value="dateRange"
|
v-model:value="dateRange"
|
||||||
:allow-clear="false"
|
:allow-clear="false"
|
||||||
format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
||||||
style="width: 360px"
|
style="width: 260px"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
@ -70,11 +70,11 @@
|
|||||||
/>
|
/>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</div>
|
</div>
|
||||||
<div class="table">
|
<div class="table1">
|
||||||
<BasicTable
|
<BasicTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:scrollY="380"
|
:scrollY="400"
|
||||||
:list-url="
|
:list-url="
|
||||||
activeTimeType == 'day' ? dayGetKendoListCust : hourGetKendoListCust
|
activeTimeType == 'day' ? dayGetKendoListCust : hourGetKendoListCust
|
||||||
"
|
"
|
||||||
@ -952,7 +952,7 @@ const handleResize = () => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.table {
|
.table1 {
|
||||||
width: 65%;
|
width: 65%;
|
||||||
height: 482px;
|
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>
|
<template #click-action-content>
|
||||||
<div v-if="titleData.cnt" style="max-width: 300px; line-height: 1.6">
|
<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>
|
<p>
|
||||||
2、范围:接入过生态流量数据的电站<span
|
2、范围:接入过生态流量数据的电站<span
|
||||||
style="color: #5989ad; cursor: pointer"
|
style="color: #5989ad; cursor: pointer"
|
||||||
@ -39,6 +41,21 @@
|
|||||||
>
|
>
|
||||||
<ModalYkzhbzdjcgz v-if="huanbaoModalVisible" :titleData="titleData" />
|
<ModalYkzhbzdjcgz v-if="huanbaoModalVisible" :titleData="titleData" />
|
||||||
</a-modal>
|
</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>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -47,15 +64,11 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import { eqqecRateCount, evnmAutoMonitorGetKendoListCust } from '@/api/stll';
|
import { eqqecRateCount, evnmAutoMonitorGetKendoListCust } from '@/api/stll';
|
||||||
import ModalYkzhbzdjcgz from '../shengtaidabiaoMod/TwoLayer/ModalYkzhbzdjcgz.vue';
|
import ModalYkzhbzdjcgz from '../shengtaidabiaoMod/TwoLayer/ModalYkzhbzdjcgz.vue';
|
||||||
|
import STLLXFFS from './TwoLayer/STLLXFFS.vue'
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'shengtaidabiaoMod'
|
name: 'shengtaidabiaoMod'
|
||||||
});
|
});
|
||||||
const obj = {
|
|
||||||
show: true,
|
|
||||||
value:
|
|
||||||
'1、统计电站范围:接入过生态流量数据的电站,2、当来水不足时,生态流量不小于入库流量判定为达标,3、"≥95% 座数"表示统计电站范围内时段达标率大于等于 95% 的电站数量'
|
|
||||||
};
|
|
||||||
const mode = ref('top');
|
const mode = ref('top');
|
||||||
const spinning = ref(false);
|
const spinning = ref(false);
|
||||||
const chartRef = ref<HTMLElement | null>(null);
|
const chartRef = ref<HTMLElement | null>(null);
|
||||||
@ -66,45 +79,20 @@ const chartData = ref<{
|
|||||||
categories: string[];
|
categories: string[];
|
||||||
currentData: number[];
|
currentData: number[];
|
||||||
lastYearData: number[];
|
lastYearData: number[];
|
||||||
|
baseIds: (string | number)[];
|
||||||
|
qecPerformances: (string | number)[];
|
||||||
}>({
|
}>({
|
||||||
categories: [],
|
categories: [],
|
||||||
currentData: [],
|
currentData: [],
|
||||||
lastYearData: []
|
lastYearData: [],
|
||||||
|
baseIds: [],
|
||||||
|
qecPerformances: []
|
||||||
});
|
});
|
||||||
const huanbaoModalVisible = ref(false);
|
const huanbaoModalVisible = ref(false);
|
||||||
// 处理电站数量点击事件
|
// 处理电站数量点击事件
|
||||||
const handleStationClick = () => {
|
const handleStationClick = () => {
|
||||||
huanbaoModalVisible.value = true;
|
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 () => {
|
const loadData = async () => {
|
||||||
spinning.value = true;
|
spinning.value = true;
|
||||||
@ -303,11 +291,48 @@ const initChart = () => {
|
|||||||
|
|
||||||
chartInstance.setOption(option);
|
chartInstance.setOption(option);
|
||||||
|
|
||||||
|
// 添加点击事件
|
||||||
|
chartInstance.off('click');
|
||||||
|
chartInstance.on('click', (params: any) => {
|
||||||
|
handleChartClick(params);
|
||||||
|
});
|
||||||
|
|
||||||
// 强制重绘,确保尺寸正确
|
// 强制重绘,确保尺寸正确
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
chartInstance?.resize();
|
chartInstance?.resize();
|
||||||
}, 0);
|
}, 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 getdate = () => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const oneMonthAgo = new Date(now);
|
const oneMonthAgo = new Date(now);
|
||||||
@ -409,7 +434,9 @@ const getEcharts = async () => {
|
|||||||
),
|
),
|
||||||
lastYearData: uniqueData.map((item: any) =>
|
lastYearData: uniqueData.map((item: any) =>
|
||||||
item.beforeQecRate != null ? Number(item.beforeQecRate) : 0
|
item.beforeQecRate != null ? Number(item.beforeQecRate) : 0
|
||||||
)
|
),
|
||||||
|
baseIds: uniqueData.map((item: any) => item.baseId),
|
||||||
|
qecPerformances: []
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// 按调节性能模式
|
// 按调节性能模式
|
||||||
@ -420,7 +447,9 @@ const getEcharts = async () => {
|
|||||||
),
|
),
|
||||||
lastYearData: apiData.map((item: any) =>
|
lastYearData: apiData.map((item: any) =>
|
||||||
item.beforeQecRate != null ? Number(item.beforeQecRate) : 0
|
item.beforeQecRate != null ? Number(item.beforeQecRate) : 0
|
||||||
)
|
),
|
||||||
|
baseIds: [],
|
||||||
|
qecPerformances: apiData.map((item: any) => item.qecPerformance || '')
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -429,7 +458,9 @@ const getEcharts = async () => {
|
|||||||
chartData.value = {
|
chartData.value = {
|
||||||
categories: [],
|
categories: [],
|
||||||
currentData: [],
|
currentData: [],
|
||||||
lastYearData: []
|
lastYearData: [],
|
||||||
|
baseIds: [],
|
||||||
|
qecPerformances: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -438,7 +469,9 @@ const getEcharts = async () => {
|
|||||||
chartData.value = {
|
chartData.value = {
|
||||||
categories: [],
|
categories: [],
|
||||||
currentData: [],
|
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 变化
|
// 监听 mode 变化
|
||||||
watch(mode, () => {
|
watch(mode, () => {
|
||||||
loadData();
|
loadData();
|
||||||
@ -523,4 +584,8 @@ watch(mode, () => {
|
|||||||
height: 449px;
|
height: 449px;
|
||||||
// padding: 10px;
|
// padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detail-content {
|
||||||
|
padding: 16px 0;
|
||||||
|
}
|
||||||
</style>
|
</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>
|
||||||
@ -34,7 +34,7 @@ service.interceptors.request.use(
|
|||||||
config.headers._sysid = '10EC2E0B-AEA9-4757-83A2-201BA1BC54E9';
|
config.headers._sysid = '10EC2E0B-AEA9-4757-83A2-201BA1BC54E9';
|
||||||
|
|
||||||
config.headers.authorization =
|
config.headers.authorization =
|
||||||
'bearer 3c424544-50d5-4787-9453-97bc18e44427';
|
'bearer 0952e56d-8a77-4c43-abe4-a44367a22d73';
|
||||||
config.baseURL = '/';
|
config.baseURL = '/';
|
||||||
} else {
|
} else {
|
||||||
const user = useUserStoreHook();
|
const user = useUserStoreHook();
|
||||||
|
|||||||
@ -1,21 +1,36 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
import JidiSelectorMod from '@/modules/jidiSelectorMod.vue';
|
||||||
import RightDrawer from "@/components/RightDrawer/index.vue";
|
import RightDrawer from '@/components/RightDrawer/index.vue';
|
||||||
import ShengtaidabiaoMod from '@/modules/shengtaidabiaoMod/index.vue' // 模块-生态流量达标情况 生态流量达标情况
|
import ShengtaidabiaoMod from '@/modules/shengtaidabiaoMod/index.vue'; // 模块-生态流量达标情况 生态流量达标情况
|
||||||
import ShengtaidabiaoTwoMod from '@/modules/shengtaidabiaoTwoMod/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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="moduleContent">
|
<div class="moduleContent">
|
||||||
<div class="leftContent">
|
<div class="leftContent">
|
||||||
<JidiSelectorMod />
|
<JidiSelectorMod />
|
||||||
</div>
|
|
||||||
<div class="rightContent">
|
|
||||||
<RightDrawer>
|
|
||||||
<ShengtaidabiaoMod />
|
|
||||||
<ShengtaidabiaoTwoMod />
|
|
||||||
</RightDrawer>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="rightContent">
|
||||||
|
<RightDrawer>
|
||||||
|
<ShengtaidabiaoMod />
|
||||||
|
<ShengtaidabiaoTwoMod v-if="baseid == 'all'" />
|
||||||
|
<StllyanchengChangeMod v-if="baseid != 'all'" />
|
||||||
|
</RightDrawer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
@ -1,22 +1,37 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
import { ref, watch } from 'vue';
|
||||||
import RightDrawer from "@/components/RightDrawer/index.vue";
|
import JidiSelectorMod from '@/modules/jidiSelectorMod.vue';
|
||||||
import XFFS from "@/modules/shengTaiLiuLiangXieFangSheShiMod/xieFangFangShi/index.vue" //
|
import RightDrawer from '@/components/RightDrawer/index.vue';
|
||||||
import XFFB from "@/modules/shengTaiLiuLiangXieFangSheShiMod/xieFangFenBu/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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="moduleContent">
|
<div class="moduleContent">
|
||||||
<div class="leftContent">
|
<div class="leftContent">
|
||||||
<JidiSelectorMod />
|
<JidiSelectorMod />
|
||||||
</div>
|
|
||||||
<div class="rightContent">
|
|
||||||
<RightDrawer>
|
|
||||||
<XFFS></XFFS>
|
|
||||||
<XFFB></XFFB>
|
|
||||||
</RightDrawer>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="rightContent">
|
||||||
|
<RightDrawer>
|
||||||
|
<XFFS></XFFS>
|
||||||
|
<XFFB v-if="wbsCode == 'all'"> </XFFB>
|
||||||
|
<STLLXZYCBH v-if="wbsCode != 'all'" ></STLLXZYCBH>
|
||||||
|
</RightDrawer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user