feat: 02.하수관로 tab3관종별 현황

This commit is contained in:
2026-02-16 15:03:38 +09:00
parent 93d4cb57e6
commit ca83ac22aa
4 changed files with 199 additions and 44 deletions
@@ -94,9 +94,12 @@ const SewagePipeRvw = () => {
if (tabKey === 'b') {
response = await statisticsManagementApi.getSewagePipeFacilityList(searchParamRef.current);
}else if(tabKey === 'c'){
response = await statisticsManagementApi.getSewagePipeTypeList(searchParamRef.current);
}
if (response?.status === 'success' && response.data) {
setRowDataMap(prev => {
const next = new Map(prev);
next.set(tabKey, toGridRows(response.data as object[]));
@@ -56,7 +56,7 @@ const rawList = [
]
},
{ name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true },
{ name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, editable: false },
{ name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, mergeCells: true,editable: false },
{
name: 'displayYear',
fieldName: 'displayYear',
@@ -235,7 +235,7 @@ const rawList = [
]
},
{ name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true },
{ name: 'bscFctNm', fieldName: 'bscFctNm', header: { text: '하수처리장명' }, editable: false },
{ name: 'bscFctNm', fieldName: 'bscFctNm', header: { text: '하수처리장명' },mergeCells: true, editable: false },
{
name: 'displayYear',
fieldName: 'displayYear',
@@ -351,47 +351,133 @@ const rawList = [
'rmk'
]
},
{
tabKey: 'c',
tabLabel: '관종별 현황',
rowStartNum: 2,
fixedColumns: 3,
columns: [
{ name: 'SIDO', fieldName: '시도', header: { text: '시도' } },
{ name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } },
{ name: 'SWRG_PIPE_NM', fieldName: '관종', header: { text: '관종' } },
{ name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } },
{
tabKey: 'c',
tabLabel: '관종별 현황',
rowStartNum: 2,
fixedColumns: 3,
columns: [
{
name: 'sido',
fieldName: 'sido',
header: { text: '시도' },
mergeCells: true,
editable: false,
sortdisable: true,
footer: [
{
valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => {
const divisionIndex = 0;
const dataSource = grid.getDataSource();
const uniqueValues = new Set<string>();
for (let i = 0; i < dataSource.getRowCount(); i++) {
const divisionValue = dataSource.getValue(i, 'displayYear');
if (divisionValue) uniqueValues.add(String(divisionValue));
}
const divisionValues = Array.from(uniqueValues);
return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계';
}
},
{
valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => {
const divisionIndex = 1;
const dataSource = grid.getDataSource();
const uniqueValues = new Set<string>();
for (let i = 0; i < dataSource.getRowCount(); i++) {
const divisionValue = dataSource.getValue(i, 'displayYear');
if (divisionValue) uniqueValues.add(String(divisionValue));
}
const divisionValues = Array.from(uniqueValues);
return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계';
}
}
]
},
{ name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true },
{ name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true, editable: false },
{
name: 'displayYear',
fieldName: 'displayYear',
header: { text: '구분' },
editable: false,
sortdisable: true,
footer: [
{
valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => {
const divisionIndex = 0;
const dataSource = grid.getDataSource();
const uniqueValues = new Set<string>();
for (let i = 0; i < dataSource.getRowCount(); i++) {
const divisionValue = dataSource.getValue(i, 'displayYear');
if (divisionValue) uniqueValues.add(String(divisionValue));
}
const divisionValues = Array.from(uniqueValues);
return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '';
}
},
{
valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => {
const divisionIndex = 1;
const dataSource = grid.getDataSource();
const uniqueValues = new Set<string>();
for (let i = 0; i < dataSource.getRowCount(); i++) {
const divisionValue = dataSource.getValue(i, 'displayYear');
if (divisionValue) uniqueValues.add(String(divisionValue));
}
const divisionValues = Array.from(uniqueValues);
return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '';
}
}
]
},
{ name: 'TOTAL_EXTN_SUM', fieldName: '계(총계)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
{ name: 'LAYING_EXTN_SUM', fieldName: '매설연장(m)_총계', header: { text: '매설연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
{ name: 'REMVL_EXTN_SUM', fieldName: '철거연장(m)_총계', header: { text: '철거연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
/* 총계 필드 */
{ name: 'totalExtnSum', fieldName: 'totalExtnSum', header: { text: '계' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
{ name: 'layingExtnSum', fieldName: 'layingExtnSum', header: { text: '매설연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
{ name: 'remvlExtnSum', fieldName: 'remvlExtnSum', header: { text: '철거연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
...Array.from({ length: 30 }, (_, i) => {
const yNum = (30 - i).toString().padStart(2, '0');
const yrOffset = 29 - i;
return [
{ name: `TOTAL_EXTN_${yNum}Y`, fieldName: `계(-${yrOffset}년)`, header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
{ name: `LAYING_EXTN_${yNum}Y`, fieldName: `매설연장(m)_(-${yrOffset}년)`, header: { text: '매설연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
{ name: `REMVL_EXTN_${yNum}Y`, fieldName: `철거연장(m)_(-${yrOffset}년)`, header: { text: '철거연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }
];
}).flat(),
/* 30개년 동적 컬럼 생성 (SewerPipeTypeItem 필드 매핑) */
...Array.from({ length: 30 }, (_, i) => {
const yNum = (30 - i).toString().padStart(2, '0');
const yrOffset = 29 - i;
return [
{ name: `totalExtn${yNum}y`, fieldName: `totalExtn${yNum}y`, header: { text: '계' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
{ name: `layingExtn${yNum}y`, fieldName: `layingExtn${yNum}y`, header: { text: '매설연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
{ name: `remvlExtn${yNum}y`, fieldName: `remvlExtn${yNum}y`, header: { text: '철거연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }
];
}).flat(),
{ name: 'LAYING_EXTN', fieldName: `매설연장(m)_당해년도`, header: { text: '매설연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
{ name: 'RMK', fieldName: '비고', header: { text: '비고' } },
],
columnLayout: [
{ name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] },
'SWRG_PIPE_NM', 'YR_GBN',
{ name: 'summaryGroup', header: { text: '총계' }, items: ['TOTAL_EXTN_SUM', 'LAYING_EXTN_SUM', 'REMVL_EXTN_SUM'] },
...Array.from({ length: 30 }, (_, i) => {
const yNum = (30 - i).toString().padStart(2, '0');
const yrOffset = 29 - i;
return { name: `yr${yNum}Group`, header: { text: `-${yrOffset}년` }, items: [`TOTAL_EXTN_${yNum}Y`, `LAYING_EXTN_${yNum}Y`, `REMVL_EXTN_${yNum}Y`] };
}),
{ name: 'currentYrGroup', header: { text: `${baseYear}년` }, items: ['LAYING_EXTN'] },
'RMK'
]
},
{ name: 'layingExtn', fieldName: 'layingExtn', header: { text: '매설연장(m)\n(당해년도)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' },
{ name: 'rmk', fieldName: 'rmk', header: { text: '비고' } },
],
columnLayout: [
{
name: 'areaGroup',
header: { text: '행정구역' },
items: [
// sido부터 swrgPipeNm(관종)까지 푸터 병합
{ column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] },
'gugun',
'swrgPipeNm',
]
},
'displayYear',
{ name: 'summaryGroup', header: { text: '총계' }, items: ['totalExtnSum', 'layingExtnSum', 'remvlExtnSum'] },
...Array.from({ length: 30 }, (_, i) => {
const yNum = (30 - i).toString().padStart(2, '0');
const yrOffset = 29 - i;
return {
name: `yr${yNum}Group`,
header: { text: `-${yrOffset}년` },
items: [`totalExtn${yNum}y`, `layingExtn${yNum}y`, `remvlExtn${yNum}y`]
};
}),
{ name: 'currentYrGroup', header: { text: `${baseYear}년` }, items: ['layingExtn'] },
'rmk'
]
},
{
tabKey: 'd',
tabLabel: '관경별 현황',