WholeProcessPlatform/frontend/src/modules/shuidianhuangjingjieruMod/TwoLayer/ShuiDianKaiFQKTwoLayer.vue

1066 lines
26 KiB
Vue
Raw Normal View History

2026-05-15 08:51:17 +08:00
<script setup lang="ts">
2026-07-06 08:54:58 +08:00
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import type { ColumnsType } from 'ant-design-vue/es/table/interface';
import { DownloadOutlined } from '@ant-design/icons-vue';
import BasicSearch from '@/components/BasicSearch/index.vue';
import BasicTable from '@/components/BasicTable/index.vue';
import { message, Spin, Empty } from 'ant-design-vue';
import { useModelStore } from '@/store/modules/model';
import { handleTabs } from '@/components/MapModal/setting.config';
import {
getVmsstbprptKendoList,
getVmsstbprptKendoListCust,
getBaseWbsb
} from '@/api/home';
2026-06-09 11:17:07 +08:00
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
2026-05-15 08:51:17 +08:00
const props = defineProps<{
2026-07-06 08:54:58 +08:00
defaultJidiInfo?: Record<string, string | number | boolean>;
seriesName?: string;
stateName?: string;
defaultTab?: string;
}>();
2026-05-15 08:51:17 +08:00
interface TabItem {
2026-07-06 08:54:58 +08:00
key: string;
value: string;
col: string;
unit: string;
count: number;
2026-05-15 08:51:17 +08:00
}
interface PieDataItem {
2026-07-06 08:54:58 +08:00
key: string;
name: string;
value: number;
unit: string;
dataDimensionRecursive?: string;
index?: number;
2026-05-15 08:51:17 +08:00
}
interface TableFilterParams {
2026-07-06 08:54:58 +08:00
baseId?:
| string
| Array<{
field: string;
operator: string;
dataType: string;
value: string[];
}>;
hbrvcd?:
| string
| Array<{
field: string;
operator: string;
dataType: string;
value: string[];
}>;
bldsttCcode?: string;
stnmContains?: string | null;
prsc?: Array<{
field: string;
operator: string;
dataType: string;
value: string[];
}>;
ttpwr?: Array<{ field: string; operator: string }>;
sttpCode?: string;
2026-05-15 08:51:17 +08:00
}
2026-07-06 08:54:58 +08:00
const modelStore = useModelStore();
const JidiSelectEventStore = useJidiSelectEventStore();
2026-05-15 08:51:17 +08:00
2026-07-06 08:54:58 +08:00
const qid = ref<string>((props.defaultJidiInfo?.baseid as string) || 'all');
const jiDiList = ref<any[]>([]);
const defJD = ref<string>((props.defaultJidiInfo?.basename as string) || '');
2026-05-15 08:51:17 +08:00
2026-07-06 08:54:58 +08:00
const tabIndex = ref<string>('');
const tabKey = ref<string>('');
const tabCol = ref<string>('');
const tabList = ref<TabItem[]>([]);
const stnm = ref<string | null>(null);
const formRef = ref<any>();
const pieData = ref<PieDataItem[]>([]);
const pieCode = ref<string[]>([]);
const pikData = ref<PieDataItem[]>([]);
const chartInstance = ref<any>(null);
const chartInitialized = ref<boolean>(false);
const dataLoading = ref<boolean>(false);
const chartRefs = ref<Record<string, HTMLElement>>({});
const chartInstances = ref<Record<string, any>>({});
const setChartRef = (el: any, key: string) => {
if (el) {
chartRefs.value[key] = el as HTMLElement;
2026-05-15 18:08:29 +08:00
}
2026-07-06 08:54:58 +08:00
};
const tableRefs = ref<Record<string, any>>({});
const setTableRef = (el: any, key: string) => {
if (el) tableRefs.value[key] = el;
};
const unit = '万kW';
const jdColor = [
'#5B8FF9',
'#5AD8A6',
'#F6BD16',
'#7262FD',
'#FF6B6B',
'#9556a4',
'#30b7b9'
];
const tableRef = ref<any>(null);
function transUnit(value: number): number {
return Math.round(value * 0.1 * 100) / 100;
}
async function fetchTabData(params: any): Promise<TabItem[]> {
2026-05-15 18:08:29 +08:00
try {
2026-07-06 08:54:58 +08:00
const _name = `装机容量(${unit})`;
const useTtpwrFilter = props.seriesName === _name;
const aggregates = [{ field: 'ttpwr', aggregate: 'sum' }];
2026-05-15 18:08:29 +08:00
const sortConfig = useTtpwrFilter
? [{ dir: 'desc', field: 'bldsttCcode', aggregates }]
2026-07-06 08:54:58 +08:00
: [{ dir: 'desc', field: 'bldsttCcode' }];
const filterParams = useTtpwrFilter
? [...params, { field: 'ttpwr', operator: 'isnotnull' }]
: params;
const res = await getVmsstbprptKendoList({
filter: {
logic: 'and',
filters: filterParams
},
group: sortConfig
});
const resData = res?.data?.data || [];
if (!Array.isArray(resData)) return [];
let list: TabItem[] = [];
resData.forEach((cur: any) => {
if (cur.key == '0') {
2026-05-15 18:08:29 +08:00
list.push({
col: useTtpwrFilter ? 'ttpwr' : 'engTotal',
key: 'noBuild',
2026-07-06 08:54:58 +08:00
unit: useTtpwrFilter ? unit : '座',
2026-05-15 18:08:29 +08:00
value: '未建',
2026-07-06 08:54:58 +08:00
count: useTtpwrFilter
? cur?.items[0]?.SUM_TTPWR
? transUnit(cur.items[0].SUM_TTPWR)
: 0
: cur?.items[0]?.COUNT_BLDSTTCCODE || 0
});
} else if (cur.key == '1') {
2026-05-15 18:08:29 +08:00
list.push({
col: useTtpwrFilter ? 'ttpwr' : 'engTotal',
key: 'building',
2026-07-06 08:54:58 +08:00
unit: useTtpwrFilter ? unit : '座',
2026-05-15 18:08:29 +08:00
value: '在建',
2026-07-06 08:54:58 +08:00
count: useTtpwrFilter
? cur?.items[0]?.SUM_TTPWR
? transUnit(cur.items[0].SUM_TTPWR)
: 0
: cur?.items[0]?.COUNT_BLDSTTCCODE || 0
});
} else if (cur.key == '2') {
2026-05-15 18:08:29 +08:00
list.push({
col: useTtpwrFilter ? 'ttpwr' : 'engTotal',
key: 'build',
2026-07-06 08:54:58 +08:00
unit: useTtpwrFilter ? unit : '座',
2026-05-15 18:08:29 +08:00
value: '已建',
2026-07-06 08:54:58 +08:00
count: useTtpwrFilter
? cur?.items[0]?.SUM_TTPWR
? transUnit(cur.items[0].SUM_TTPWR)
: 0
: cur?.items[0]?.COUNT_BLDSTTCCODE || 0
});
2026-05-15 18:08:29 +08:00
}
2026-07-06 08:54:58 +08:00
});
return list;
2026-05-15 18:08:29 +08:00
} catch (error) {
2026-07-06 08:54:58 +08:00
console.error('获取Tab数据失败:', error);
message.error('获取Tab数据失败');
return [];
2026-05-15 18:08:29 +08:00
}
2026-05-15 08:51:17 +08:00
}
async function fetchPieData(params: any): Promise<PieDataItem[]> {
2026-05-15 18:08:29 +08:00
try {
2026-07-06 08:54:58 +08:00
const _name = `装机容量(${unit})`;
const useTtpwrFilter = props.seriesName === _name;
const aggregates = [{ field: 'ttpwr', aggregate: 'sum' }];
2026-05-15 18:08:29 +08:00
const sortConfig = [
2026-07-06 08:54:58 +08:00
qid.value === 'all' || qid.value === 'other'
? null
: { dir: 'asc', field: 'rvcdStepSort' },
2026-05-15 18:08:29 +08:00
qid.value === 'all' ? { dir: 'asc', field: 'baseStepSort' } : null,
2026-07-06 08:54:58 +08:00
{ dir: 'asc', field: qid.value === 'all' ? 'baseId' : 'hbrvcd' },
{ dir: 'desc', field: qid.value === 'all' ? 'baseName' : 'hbrvcdName' },
useTtpwrFilter
? { dir: 'desc', field: 'bldsttCcode', aggregates }
: { dir: 'desc', field: 'bldsttCcode' }
].filter(Boolean);
const filterParams = useTtpwrFilter
? [...params, { field: 'ttpwr', operator: 'isnotnull' }]
: params;
const res = await getVmsstbprptKendoList({
filter: {
logic: 'and',
filters: filterParams
2026-05-15 18:08:29 +08:00
},
2026-07-06 08:54:58 +08:00
group: sortConfig
});
const resData = res?.data?.data || [];
if (!Array.isArray(resData)) return [];
let list = resData.flatMap((item: any) => {
let arr: PieDataItem[] = [];
2026-07-07 18:59:55 +08:00
const itmeData = item?.items;
2026-07-06 08:54:58 +08:00
2026-05-15 18:08:29 +08:00
itmeData?.map((outItem: any) => {
2026-07-07 18:59:55 +08:00
const level5Data = outItem?.items?.[0]?.items?.[0]?.items?.[0];
const name = outItem?.items?.[0]?.key;
2026-07-06 08:54:58 +08:00
2026-05-15 18:08:29 +08:00
if (name) {
arr.push({
2026-07-07 18:59:55 +08:00
key: outItem?.key,
2026-05-15 18:08:29 +08:00
dataDimensionRecursive: 'true',
name: name,
unit: '',
2026-07-06 08:54:58 +08:00
value:
2026-07-07 18:59:55 +08:00
useTtpwrFilter
2026-07-06 08:54:58 +08:00
? level5Data?.SUM_TTPWR && +transUnit(level5Data?.SUM_TTPWR)
2026-07-07 18:59:55 +08:00
: level5Data?.COUNT_BLDSTTCCODE
2026-07-06 08:54:58 +08:00
});
2026-05-15 18:08:29 +08:00
}
2026-07-06 08:54:58 +08:00
});
2026-05-15 08:51:17 +08:00
2026-07-06 08:54:58 +08:00
return arr;
});
2026-05-15 08:51:17 +08:00
2026-07-06 08:54:58 +08:00
if (qid.value === 'other' && list.length > 0) {
const introRes = await getBaseWbsb({
filter: {
logic: 'and',
filters: [
{ field: 'wbsType', operator: 'eq', value: 'PSB_RVCD' },
{ field: 'objId', operator: 'eq', value: 'other' },
{ field: 'orderIndex', operator: 'isnotnull' }
]
},
sort: [{ field: 'orderIndex', dir: 'asc' }],
select: ['wbsCode', 'wbsName', 'orderIndex']
});
const introData = introRes?.data?.data || [];
if (introData?.length && list?.length) {
list = list
.map((el: any) => {
const found = introData.find(
(item: any) => el?.key === item?.wbsCode
);
return {
...el,
index: found?.orderIndex
};
2026-05-15 18:08:29 +08:00
})
2026-07-06 08:54:58 +08:00
.sort((a: any, b: any) => a?.index - b?.index);
2026-05-15 18:08:29 +08:00
}
}
2026-07-06 08:54:58 +08:00
return list;
2026-05-15 18:08:29 +08:00
} catch (error) {
2026-07-06 08:54:58 +08:00
console.error('获取饼图数据失败:', error);
message.error('获取饼图数据失败');
return [];
2026-05-15 18:08:29 +08:00
}
2026-05-15 08:51:17 +08:00
}
2026-07-06 08:54:58 +08:00
const listUrl = computed(() =>
qid.value === 'all' ? getVmsstbprptKendoListCust : getVmsstbprptKendoList
);
2026-05-15 08:51:17 +08:00
2026-07-06 08:54:58 +08:00
const customTransform = (res: any) => ({
records: res?.data?.data || res?.data?.items || [],
total: res?.data?.total || 0
});
2026-05-15 08:51:17 +08:00
function handleExport() {
if (tableRef.value && typeof tableRef.value.export === 'function') {
2026-07-06 08:54:58 +08:00
tableRef.value.export();
2026-05-15 08:51:17 +08:00
} else {
2026-07-06 08:54:58 +08:00
message.info('导出功能待实现');
2026-05-15 08:51:17 +08:00
}
}
const chartSetting = computed<EChartsOption>(() => {
2026-07-06 08:54:58 +08:00
const _name = `装机容量(${unit})`; // unit = '万kW'
const useTtpwrFilter = props.seriesName === _name;
const total = pieData.value
.reduce((acc, item) => acc + item.value, 0)
.toFixed(2);
const flag = props.seriesName === '数量(座)';
const bbbb = flag ? '电站总数量' : '总装机容量';
const dddd = flag ? '电站数量' : '装机容量';
const cccc = flag ? ' (座)' : ` (${unit})`;
2026-05-15 08:51:17 +08:00
const colors = pieData.value.map((item: any, index: any) => {
2026-07-06 08:54:58 +08:00
return jdColor[index % jdColor.length];
});
2026-05-15 08:51:17 +08:00
return {
2026-07-06 08:54:58 +08:00
color: colors,
2026-05-15 08:51:17 +08:00
tooltip: {
trigger: 'item',
2026-07-06 08:54:58 +08:00
formatter: (params: any) =>
2026-05-15 08:51:17 +08:00
`${dddd}<div>${params.marker}${params.name}: &nbsp;&nbsp;&nbsp;&nbsp;<span style="float:right">${params.value}${cccc}</span></div>`
},
title: [
2026-07-06 08:54:58 +08:00
{
text: String(total || 0),
left: useTtpwrFilter?'24%':'28%',
top: '43%',
textStyle: { fontSize: 24, fontWeight: 'bold', color: '#333' }
2026-05-15 08:51:17 +08:00
},
2026-07-06 08:54:58 +08:00
{
text: bbbb,
left: useTtpwrFilter?'27%':'28%',
top: '50%',
textStyle: { fontSize: 14, color: '#666' }
2026-05-15 08:51:17 +08:00
},
2026-07-06 08:54:58 +08:00
{
text: cccc,
left: useTtpwrFilter?'29%':'32%',
top: '55%',
textStyle: { fontSize: 12, color: '#999' }
2026-05-15 08:51:17 +08:00
}
],
legend: {
type: 'scroll',
orient: 'vertical',
right: 10,
top: 20,
bottom: 20,
textStyle: { fontSize: 12 }
},
series: [
{
name: dddd,
type: 'pie',
2026-07-06 08:54:58 +08:00
radius: ['30%', '40%'],
2026-05-15 08:51:17 +08:00
center: ['35%', '50%'],
avoidLabelOverlap: true,
itemStyle: {
borderRadius: 4,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: true,
position: 'outside',
2026-07-06 08:54:58 +08:00
formatter: '{b}',
2026-05-15 08:51:17 +08:00
fontSize: 12
},
emphasis: {
scale: true,
scaleSize: 10
},
2026-07-06 08:54:58 +08:00
data: pieData.value.map(item => ({ ...item }))
2026-05-15 08:51:17 +08:00
}
]
2026-07-06 08:54:58 +08:00
};
});
function initChart(tabKeyStr?: string) {
const currentTabKey = tabKeyStr || tabKey.value || 'build';
const chartContainer = chartRefs.value[currentTabKey];
if (!chartContainer) {
setTimeout(() => initChart(currentTabKey), 200);
return;
2026-05-15 08:51:17 +08:00
}
2026-07-06 08:54:58 +08:00
if (chartInstances.value[currentTabKey]) {
chartInstances.value[currentTabKey].dispose();
chartInstances.value[currentTabKey] = null;
2026-05-15 18:08:29 +08:00
}
2026-07-06 08:54:58 +08:00
try {
chartInstances.value[currentTabKey] = echarts.init(chartContainer, null, {
width: 541,
height: 482
});
chartInstances.value[currentTabKey].on(
'legendselectchanged',
handleLegendSelectChanged
);
if (pieData.value.length > 0) {
updateChart(currentTabKey);
setTimeout(() => {
chartInstances.value[currentTabKey]?.resize();
}, 100);
}
chartInitialized.value = true;
} catch (error) {
console.error('ECharts init failed:', error);
setTimeout(() => initChart(currentTabKey), 300);
2026-05-15 18:08:29 +08:00
}
2026-05-15 08:51:17 +08:00
}
2026-07-06 08:54:58 +08:00
function updateChart(tabKeyStr?: string) {
const currentTabKey = tabKeyStr || tabKey.value || 'build';
const instance = chartInstances.value[currentTabKey];
if (!instance) return;
instance.setOption(chartSetting.value, true);
2026-05-15 08:51:17 +08:00
}
function handleResize() {
2026-07-06 08:54:58 +08:00
Object.values(chartInstances.value).forEach(instance => {
if (instance) instance.resize();
});
2026-05-15 08:51:17 +08:00
}
function handleLegendSelectChanged(e: any) {
2026-07-06 08:54:58 +08:00
const trueRivers = Object.keys(e.selected).filter(key => e.selected[key]);
const allFalse = Object.values(e.selected).every(value => value === false);
2026-05-15 08:51:17 +08:00
const selectedKeys = pikData.value
.filter((item: any) => trueRivers.includes(item.name))
2026-07-06 08:54:58 +08:00
.map((item: any) => item.key);
2026-05-15 08:51:17 +08:00
2026-07-06 08:54:58 +08:00
pieCode.value = allFalse ? [] : selectedKeys;
}
2026-05-15 08:51:17 +08:00
2026-07-06 08:54:58 +08:00
const columns = [
2026-05-15 08:51:17 +08:00
{
title: '电站名称',
dataIndex: 'stnm',
key: 'stnm',
fixed: 'left',
ellipsis: true,
width: 150,
2026-07-06 08:54:58 +08:00
sort: true,
slots: { customRender: 'stnm' },
2026-05-15 08:51:17 +08:00
customRender: ({ record }: any) => ({
children: record.stnm,
attrs: {
onClick: () => handleRowClick(record)
},
style: {
color: '#1890ff',
cursor: 'pointer'
}
})
},
{
title: '开发方式',
dataIndex: 'dvtp',
key: 'dvtp',
ellipsis: true,
2026-07-06 08:54:58 +08:00
width: 150,
sort: true,
2026-05-15 08:51:17 +08:00
customRender: ({ record }: any) => record.dvtpName || '-'
},
{
2026-07-06 08:54:58 +08:00
title: `装机容量(${unit})`,
2026-05-15 08:51:17 +08:00
dataIndex: 'ttpwr',
key: 'ttpwr',
ellipsis: true,
2026-07-06 08:54:58 +08:00
width: 150,
sort: true,
customRender: ({ text }: any) => (text ? Number(text).toFixed(2) : '-')
2026-05-15 08:51:17 +08:00
},
{
title: '设计年发电量(亿kW·h)',
dataIndex: 'yrge',
key: 'yrge',
2026-07-06 08:54:58 +08:00
width: 150,
sort: true,
ellipsis: true
2026-05-15 08:51:17 +08:00
},
{
title: '总库容(亿m³)',
dataIndex: 'ttcp',
key: 'ttcp',
2026-07-06 08:54:58 +08:00
width: 150,
sort: true,
2026-05-15 08:51:17 +08:00
ellipsis: true
},
{
title: '所属基地',
dataIndex: 'baseName',
key: 'baseName',
2026-07-06 08:54:58 +08:00
width: 150,
sort: true,
2026-05-15 08:51:17 +08:00
ellipsis: true
},
{
title: '所属行政区',
dataIndex: 'addvcdName',
key: 'addvcdName',
2026-07-06 08:54:58 +08:00
width: 150,
sort: true,
2026-05-15 08:51:17 +08:00
ellipsis: true
},
{
title: '所在河段',
dataIndex: 'hbrvcdName',
key: 'hbrvcdName',
2026-07-06 08:54:58 +08:00
width: 240,
merge: true,
sort: true,
2026-05-15 08:51:17 +08:00
ellipsis: true
},
{
title: '第一台机组投产时间',
dataIndex: 'piodt',
key: 'piodt',
ellipsis: true,
2026-07-06 08:54:58 +08:00
sort: true,
2026-05-15 08:51:17 +08:00
width: 170
},
{
title: '全部机组投产时间',
dataIndex: 'aiodt',
key: 'aiodt',
2026-07-06 08:54:58 +08:00
width: 150,
sort: true,
2026-05-15 08:51:17 +08:00
ellipsis: true
}
2026-07-06 08:54:58 +08:00
];
2026-05-15 08:51:17 +08:00
function handleRowClick(record: any) {
2026-05-15 18:08:29 +08:00
modelStore.params = {
2026-05-15 08:51:17 +08:00
sttp: 'ENG',
stcd: record.stcd,
titleName: record.stnm
2026-07-06 08:54:58 +08:00
} as any;
modelStore.title = record.stnm ? `${record.stnm} ` : '';
modelStore.tabList = handleTabs(modelStore.params);
modelStore.modalVisible = true;
2026-05-15 08:51:17 +08:00
}
const searchList = computed(() => [
{
type: 'Select',
name: 'Select',
label: '基地选择',
2026-07-06 08:54:58 +08:00
options:
jiDiList.value?.map((item: any) => ({
qid: item.baseid,
value: item.basename,
label: item.basename
})) || []
2026-05-15 08:51:17 +08:00
},
{
type: 'Input',
name: 'stnm',
label: '',
fieldProps: {
allowClear: true,
placeholder: '请输入电站名称'
}
}
2026-07-06 08:54:58 +08:00
]);
2026-05-15 08:51:17 +08:00
const initialValues = computed(() => ({
Select: defJD.value,
stnm: null
2026-07-06 08:54:58 +08:00
}));
2026-05-15 08:51:17 +08:00
function handleSearch(values: any) {
const matchedOption = searchList.value[0]?.options?.find(
(value: any) => value.label === values.Select
2026-07-06 08:54:58 +08:00
);
qid.value = matchedOption?.qid || 'other';
stnm.value = values.stnm;
2026-05-15 08:51:17 +08:00
}
function handleReset() {
2026-07-06 08:54:58 +08:00
const defaultBaseId = props.defaultJidiInfo?.baseid as string;
const defaultBasename = props.defaultJidiInfo?.basename as string;
qid.value = defaultBaseId || 'all';
stnm.value = null;
defJD.value = defaultBasename || '全部基地';
setTimeout(() => {
tabList.value.forEach(item => {
if (tableRefs.value[item.key]) {
tableRefs.value[item.key].getList(buildFilter.value);
}
});
}, 100);
2026-05-15 08:51:17 +08:00
}
2026-07-06 08:54:58 +08:00
const tableSearchParams = computed(() => ({
sort: [
{ field: 'baseStepSort', dir: 'asc' },
{ field: 'rvcdStepSort', dir: 'asc' },
{ field: 'siteStepSort', dir: 'asc' },
{ field: 'ttpwr', dir: 'desc' }
],
group: [],
select: [],
groupResultFlat: false
}));
2026-05-15 08:51:17 +08:00
2026-07-06 08:54:58 +08:00
const buildFilter = computed(() => {
let filters = [
pieCode.value?.length > 0 && qid.value === 'all'
? {
2026-05-15 08:51:17 +08:00
field: 'baseId',
operator: 'in',
dataType: 'string',
value: pieCode.value
2026-07-06 08:54:58 +08:00
}
: qid.value != 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: qid.value
}
: null,
{
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: 'ENG'
},
pieCode.value?.length > 0 && qid.value !== 'all'
? {
2026-05-15 08:51:17 +08:00
field: 'hbrvcd',
operator: 'in',
dataType: 'string',
value: pieCode.value
2026-07-06 08:54:58 +08:00
}
: null,
{
field: 'bldsttCcode',
operator: 'eq',
dataType: 'string',
value:
tabKey.value === 'noBuild'
? '0'
: tabKey.value === 'building'
? '1'
: '2'
},
stnm.value
? {
field: 'stnm',
operator: 'contains',
dataType: 'string',
value: stnm.value
}
: null,
{
field: 'prsc',
operator: 'in',
dataType: 'string',
value: ['1', '2', '3']
2026-05-15 08:51:17 +08:00
}
2026-07-06 08:54:58 +08:00
].filter(Boolean);
return {
logic: 'and',
filters
};
});
watch(
qid,
async newQid => {
if (!newQid) return;
dataLoading.value = true;
try {
// const params = {
// baseId: newQid,
// sttpCode: 'ENG',
// prsc: [{ field: 'prsc', operator: 'in', dataType: 'string', value: ['1', '2', '3'] }]
// }
let params = [
newQid != 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: newQid
}
: null,
{
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: 'ENG'
},
{
field: 'prsc',
operator: 'in',
dataType: 'string',
value: ['1', '2', '3']
}
].filter(Boolean);
const result = await fetchTabData(params);
tabList.value = result;
// debugger
if (result.length > 0) {
if (props.defaultTab) {
const matchedTab = result.find(
item => item.value === props.defaultTab
);
if (matchedTab) {
tabIndex.value = matchedTab.value;
tabKey.value = matchedTab.key;
tabCol.value = matchedTab.col;
} else {
tabIndex.value = result[0].value;
tabKey.value = result[0].key;
tabCol.value = result[0].col;
}
2026-05-15 08:51:17 +08:00
} else {
2026-07-06 08:54:58 +08:00
tabIndex.value = result[0].value;
tabKey.value = result[0].key;
tabCol.value = result[0].col;
2026-05-15 08:51:17 +08:00
}
}
2026-07-06 08:54:58 +08:00
} catch (error) {
console.error('获取Tab数据失败:', error);
message.error('获取Tab数据失败');
} finally {
dataLoading.value = false;
2026-05-15 08:51:17 +08:00
}
2026-07-06 08:54:58 +08:00
},
{ immediate: true }
);
2026-05-15 08:51:17 +08:00
watch(
() => props.defaultTab,
2026-07-06 08:54:58 +08:00
newDefaultTab => {
if (!newDefaultTab || tabList.value.length === 0) return;
const matchedTab = tabList.value.find(item => item.value === newDefaultTab);
2026-05-15 08:51:17 +08:00
if (matchedTab) {
2026-07-06 08:54:58 +08:00
tabIndex.value = matchedTab.value;
tabKey.value = matchedTab.key;
tabCol.value = matchedTab.col;
2026-05-15 08:51:17 +08:00
}
},
{ immediate: true }
2026-07-06 08:54:58 +08:00
);
2026-05-15 08:51:17 +08:00
watch(
[tabKey, tabCol, stnm, qid],
async () => {
2026-07-06 08:54:58 +08:00
if (!tabKey.value || !tabCol.value) return;
dataLoading.value = true;
2026-05-15 08:51:17 +08:00
try {
2026-07-06 08:54:58 +08:00
let params: any = [
qid.value != 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: qid.value
2026-05-15 08:51:17 +08:00
}
2026-07-06 08:54:58 +08:00
: null,
{
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: 'ENG'
},
{
field: 'bldsttCcode',
operator: 'eq',
dataType: 'string',
value:
tabKey.value === 'noBuild'
? '0'
: tabKey.value === 'building'
? '1'
: '2'
},
{
field: 'prsc',
operator: 'in',
dataType: 'string',
value: ['1', '2', '3']
},
stnm.value
? {
field: 'stnm',
operator: 'contains',
dataType: 'string',
value: stnm.value
}
: null
].filter(Boolean);
// const params: any = {
// stnmContains: stnm.value,
// baseId: qid.value,
// sttpCode: 'ENG',
// bldsttCcode:
// tabKey.value === 'noBuild'
// ? '0'
// : tabKey.value === 'building'
// ? '1'
// : '2',
// prsc: [
// {
// field: 'prsc',
// operator: 'in',
// dataType: 'string',
// value: ['1', '2', '3']
// }
// ]
// };
if (props.seriesName === `装机容量(${unit})`) {
params.push({
field: 'ttpwr',
operator: 'isnotnull',
dataType: 'string'
});
2026-05-15 18:08:29 +08:00
}
2026-07-06 08:54:58 +08:00
const result = await fetchPieData(params);
pikData.value = result;
pieData.value = result;
pieCode.value = [];
await nextTick();
setTimeout(() => {
initChart();
}, 200);
2026-05-15 08:51:17 +08:00
} catch (error) {
2026-07-06 08:54:58 +08:00
console.error('获取饼图数据失败:', error);
message.error('获取饼图数据失败');
2026-05-15 08:51:17 +08:00
} finally {
2026-07-06 08:54:58 +08:00
dataLoading.value = false;
2026-05-15 08:51:17 +08:00
}
},
{ deep: true }
2026-07-06 08:54:58 +08:00
);
2026-05-15 08:51:17 +08:00
onMounted(() => {
2026-06-09 11:17:07 +08:00
JidiSelectEventStore.jidiData.forEach(element => {
jiDiList.value.push({
label: element.wbsName,
2026-07-06 08:54:58 +08:00
value: element.wbsCode,
baseid: element.wbsCode,
basename: element.wbsName
});
2026-06-09 11:17:07 +08:00
});
2026-07-06 08:54:58 +08:00
2026-05-15 08:51:17 +08:00
if (!qid.value) {
2026-07-06 08:54:58 +08:00
qid.value = 'all';
2026-05-15 08:51:17 +08:00
}
2026-07-06 08:54:58 +08:00
window.addEventListener('resize', handleResize);
});
2026-05-15 18:08:29 +08:00
watch(tabIndex, async (newTab, oldTab) => {
2026-07-06 08:54:58 +08:00
const matchedTab = tabList.value.find(item => item.value === newTab);
if (matchedTab) {
tabKey.value = matchedTab.key;
tabCol.value = matchedTab.col;
}
await nextTick();
2026-05-15 18:08:29 +08:00
setTimeout(() => {
2026-07-06 08:54:58 +08:00
const matchedTab = tabList.value.find(item => item.value === newTab);
if (matchedTab) {
const currentTabKey = matchedTab.key;
initChart(currentTabKey);
if (tableRefs.value[currentTabKey]) {
tableRefs.value[currentTabKey].getList(buildFilter.value);
}
2026-05-15 18:08:29 +08:00
}
2026-07-06 08:54:58 +08:00
}, 300);
});
const handleViewDetail = (record: any) => {
modelStore.modalVisible = true;
modelStore.params.sttp = record.sttpCode;
modelStore.title = record.stnm ;
modelStore.params.stcd = record.stcd;
}
watch(
buildFilter,
() => {
tabList.value.forEach(item => {
if (tableRefs.value[item.key]) {
tableRefs.value[item.key].getList(buildFilter.value);
}
});
},
{ deep: true }
);
2026-05-15 18:08:29 +08:00
2026-05-15 08:51:17 +08:00
onUnmounted(() => {
2026-07-06 08:54:58 +08:00
Object.values(chartInstances.value).forEach(instance => {
if (instance) instance.dispose();
});
chartInstances.value = {};
window.removeEventListener('resize', handleResize);
});
2026-05-15 08:51:17 +08:00
</script>
<template>
<div class="shuidian-kaifa-container">
<BasicSearch
ref="formRef"
:searchList="searchList"
:initialValues="initialValues"
@finish="handleSearch"
@reset="handleReset"
>
<template #actions>
<a-button @click="handleExport">
<template #icon><DownloadOutlined /></template>
导出
</a-button>
</template>
</BasicSearch>
2026-07-06 08:54:58 +08:00
<a-spin :spinning="dataLoading" tip="加载中...">
<a-tabs v-model:activeKey="tabIndex" class="dwsta-table-tu">
<a-tab-pane
v-for="item in tabList"
:key="item.value"
:tab="`${item.value}(${item.count}${item.unit})`"
>
<div class="chart-table-layout">
<div class="chart-section">
<a-empty
v-if="pieData.length === 0 && !dataLoading"
description="暂无数据"
/>
<div
v-else
:ref="el => setChartRef(el, item.key)"
class="pie-chart"
style="width: 541px; height: 482px"
></div>
</div>
2026-05-15 08:51:17 +08:00
2026-07-06 08:54:58 +08:00
<div class="table-section">
<BasicTable
:ref="el => setTableRef(el, item.key)"
:columns="columns"
:listUrl="listUrl"
:searchParams="tableSearchParams"
:transformData="customTransform"
:defaultPageSize="20"
:scrollY="380"
>
<template #stnm="{ record }">
<a @click="handleViewDetail(record)" class="text-link">
{{record.stnm }}
</a>
</template>
</BasicTable>
</div>
2026-05-15 08:51:17 +08:00
</div>
2026-07-06 08:54:58 +08:00
</a-tab-pane>
</a-tabs>
</a-spin>
2026-05-15 08:51:17 +08:00
</div>
</template>
<style scoped lang="scss">
.shuidian-kaifa-container {
display: flex;
flex-direction: column;
height: 700px;
padding: 16px;
background: #fff;
border-radius: 4px;
}
.dwsta-table-tu {
flex: 1;
display: flex;
flex-direction: column;
2026-07-06 08:54:58 +08:00
2026-05-15 08:51:17 +08:00
:deep(.ant-tabs-content) {
height: 100%;
}
2026-07-06 08:54:58 +08:00
2026-05-15 08:51:17 +08:00
:deep(.ant-tabs-tabpane) {
height: 100%;
}
2026-07-06 08:54:58 +08:00
2026-05-15 08:51:17 +08:00
:deep(.ant-tabs-nav) {
margin-bottom: 16px;
}
}
.chart-table-layout {
display: flex;
gap: 16px;
height: calc(100% - 40px);
min-height: 450px;
2026-07-06 08:54:58 +08:00
2026-05-15 08:51:17 +08:00
.chart-section {
flex: 0 0 541px;
2026-07-06 08:54:58 +08:00
// background: #fafafa;
2026-05-15 08:51:17 +08:00
border-radius: 4px;
padding: 16px;
2026-07-06 08:54:58 +08:00
// box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
2026-05-15 08:51:17 +08:00
display: flex;
align-items: center;
justify-content: center;
2026-07-06 08:54:58 +08:00
2026-05-15 08:51:17 +08:00
.pie-chart {
width: 541px;
2026-07-06 08:54:58 +08:00
height: 482px;
2026-05-15 08:51:17 +08:00
}
}
2026-07-06 08:54:58 +08:00
2026-05-15 08:51:17 +08:00
.table-section {
flex: 1;
overflow: hidden;
background: #fff;
border-radius: 4px;
}
}
2026-07-06 08:54:58 +08:00
.text-link {
color: #2f6b98;
2026-05-15 08:51:17 +08:00
2026-07-06 08:54:58 +08:00
&:hover {
color: #40a9ff;
}
2026-05-15 08:51:17 +08:00
}
2026-07-06 08:54:58 +08:00
</style>