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}: <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>
|