비즈니스 로그조회 추가
This commit is contained in:
@@ -7,7 +7,7 @@ import {
|
||||
import { ViewTitleCountType } from '../../../assets/data';
|
||||
import { TitleItem, TitleItemLabel, TitleItemValue } from '../../../styles/ModuleComponents';
|
||||
|
||||
const ViewTableInfo = ({children, total, total_all, handleOrderBy, handlePageSize, countType = ViewTitleCountType.total}) => {
|
||||
const ViewTableInfo = ({children, total, total_all, orderType, handleOrderBy, pageType, handlePageSize, countType = ViewTitleCountType.total}) => {
|
||||
return (
|
||||
<TableInfo>
|
||||
{total !== undefined && total_all !== undefined &&
|
||||
@@ -27,18 +27,44 @@ const ViewTableInfo = ({children, total, total_all, handleOrderBy, handlePageSiz
|
||||
}
|
||||
</ListCount>}
|
||||
<ListOption>
|
||||
<SelectInput className="input-select" onChange={e => handleOrderBy(e.target.value)}>
|
||||
<option value="DESC">내림차순</option>
|
||||
<option value="ASC">오름차순</option>
|
||||
</SelectInput>
|
||||
<SelectInput name="" id="" className="input-select" onChange={e => handlePageSize(e.target.value)}>
|
||||
<option value="50">50개</option>
|
||||
<option value="100">100개</option>
|
||||
</SelectInput>
|
||||
<OrderBySelect orderType={orderType} handleOrderBy={handleOrderBy} />
|
||||
<PageSelect pageType={pageType} handlePageSize={handlePageSize} />
|
||||
{children}
|
||||
</ListOption>
|
||||
</TableInfo>
|
||||
);
|
||||
};
|
||||
|
||||
const OrderBySelect = ({orderType, handleOrderBy}) => {
|
||||
return(
|
||||
orderType === "asc" ?
|
||||
<SelectInput className="input-select" onChange={e => handleOrderBy(e.target.value)}>
|
||||
<option value="ASC">오름차순</option>
|
||||
<option value="DESC">내림차순</option>
|
||||
</SelectInput>
|
||||
:
|
||||
<SelectInput className="input-select" onChange={e => handleOrderBy(e.target.value)}>
|
||||
<option value="DESC">내림차순</option>
|
||||
<option value="ASC">오름차순</option>
|
||||
</SelectInput>
|
||||
);
|
||||
}
|
||||
|
||||
const PageSelect = ({pageType, handlePageSize}) => {
|
||||
return(
|
||||
pageType === "B" ?
|
||||
<SelectInput name="" id="" className="input-select" onChange={e => handlePageSize(e.target.value)}>
|
||||
<option value="500">500개</option>
|
||||
<option value="1000">1000개</option>
|
||||
<option value="5000">5000개</option>
|
||||
<option value="10000">10000개</option>
|
||||
</SelectInput>
|
||||
:
|
||||
<SelectInput name="" id="" className="input-select" onChange={e => handlePageSize(e.target.value)}>
|
||||
<option value="50">50개</option>
|
||||
<option value="100">100개</option>
|
||||
</SelectInput>
|
||||
);
|
||||
}
|
||||
|
||||
export default ViewTableInfo;
|
||||
@@ -1,25 +1,99 @@
|
||||
import * as XLSX from 'xlsx-js-style';
|
||||
import { ExcelDownButton } from '../../../styles/ModuleComponents';
|
||||
|
||||
const ExcelDownloadButton = ({ tableRef, fileName = 'download.xlsx', sheetName = 'Sheet1' }) => {
|
||||
const ExcelDownloadButton = ({ tableRef, data, fileName = 'download.xlsx', sheetName = 'Sheet1' }) => {
|
||||
const isNumeric = (value) => {
|
||||
// 숫자 또는 숫자 문자열인지 확인
|
||||
return !isNaN(value) && !isNaN(parseFloat(value));
|
||||
};
|
||||
|
||||
const downloadExcel = () => {
|
||||
// 테두리 스타일 정의
|
||||
const borderStyle = {
|
||||
style: "thin",
|
||||
color: { rgb: "000000" }
|
||||
};
|
||||
|
||||
// 기본 셀 스타일
|
||||
const baseCellStyle = {
|
||||
font: {
|
||||
name: "맑은 고딕",
|
||||
sz: 11
|
||||
},
|
||||
border: {
|
||||
top: borderStyle,
|
||||
bottom: borderStyle,
|
||||
left: borderStyle,
|
||||
right: borderStyle
|
||||
}
|
||||
};
|
||||
|
||||
// 헤더 스타일
|
||||
const headerStyle = {
|
||||
...baseCellStyle,
|
||||
font: {
|
||||
...baseCellStyle.font,
|
||||
bold: true
|
||||
},
|
||||
alignment: {
|
||||
horizontal: 'center',
|
||||
vertical: 'center'
|
||||
},
|
||||
fill: {
|
||||
fgColor: { rgb: "d9e1f2" },
|
||||
patternType: "solid"
|
||||
}
|
||||
};
|
||||
|
||||
// 기본 데이터 셀 스타일
|
||||
const dataStyle = {
|
||||
...baseCellStyle,
|
||||
alignment: {
|
||||
horizontal: 'left',
|
||||
vertical: 'center',
|
||||
wrapText: true
|
||||
}
|
||||
};
|
||||
|
||||
const flattenObject = (obj, prefix = '') => {
|
||||
return Object.keys(obj).reduce((acc, key) => {
|
||||
const prefixedKey = prefix ? `${prefix}.${key}` : key;
|
||||
|
||||
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
|
||||
Object.assign(acc, flattenObject(obj[key], prefixedKey));
|
||||
} else if (Array.isArray(obj[key])) {
|
||||
// 배열은 JSON 문자열로 변환
|
||||
acc[prefixedKey] = JSON.stringify(obj[key]);
|
||||
} else {
|
||||
acc[prefixedKey] = obj[key];
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
||||
const downloadTableExcel = () => {
|
||||
try {
|
||||
if (!tableRef.current) return;
|
||||
if (!tableRef || !tableRef.current) {
|
||||
alert('테이블 참조가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const tableElement = tableRef.current;
|
||||
const headerRows = tableElement.getElementsByTagName('thead')[0].getElementsByTagName('tr');
|
||||
const bodyRows = tableElement.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
|
||||
|
||||
// 일반 행만 포함 (상세 행 제외)
|
||||
const normalBodyRows = Array.from(bodyRows).filter(row => {
|
||||
// 상세 행은 colspan 속성이 있는 td를 포함
|
||||
const hasTdWithColspan = Array.from(row.cells).some(cell => cell.hasAttribute('colspan'));
|
||||
return !hasTdWithColspan;
|
||||
});
|
||||
|
||||
// 헤더 데이터 추출
|
||||
const headers = Array.from(headerRows[0].cells).map(cell => cell.textContent);
|
||||
|
||||
// 바디 데이터 추출 및 숫자 타입 처리
|
||||
const bodyData = Array.from(bodyRows).map(row =>
|
||||
const bodyData = normalBodyRows.map(row =>
|
||||
Array.from(row.cells).map(cell => {
|
||||
const value = cell.textContent;
|
||||
return isNumeric(value) ? parseFloat(value) : value;
|
||||
@@ -29,41 +103,6 @@ const ExcelDownloadButton = ({ tableRef, fileName = 'download.xlsx', sheetName =
|
||||
// 워크북 생성
|
||||
const wb = XLSX.utils.book_new();
|
||||
|
||||
// 테두리 스타일 정의
|
||||
const borderStyle = {
|
||||
style: "thin",
|
||||
color: { rgb: "000000" }
|
||||
};
|
||||
|
||||
// 스타일 정의
|
||||
const centerStyle = {
|
||||
font: {
|
||||
name: "맑은 고딕",
|
||||
sz: 11
|
||||
},
|
||||
alignment: {
|
||||
horizontal: 'right',
|
||||
vertical: 'right'
|
||||
},
|
||||
border: {
|
||||
top: borderStyle,
|
||||
bottom: borderStyle,
|
||||
left: borderStyle,
|
||||
right: borderStyle
|
||||
}
|
||||
};
|
||||
|
||||
const headerStyle = {
|
||||
alignment: {
|
||||
horizontal: 'center',
|
||||
vertical: 'center'
|
||||
},
|
||||
fill: {
|
||||
fgColor: { rgb: "d9e1f2" },
|
||||
patternType: "solid"
|
||||
}
|
||||
};
|
||||
|
||||
// 데이터에 스타일 적용
|
||||
const wsData = [
|
||||
// 헤더 행
|
||||
@@ -75,7 +114,7 @@ const ExcelDownloadButton = ({ tableRef, fileName = 'download.xlsx', sheetName =
|
||||
...bodyData.map(row =>
|
||||
row.map(cell => ({
|
||||
v: cell,
|
||||
s: centerStyle
|
||||
s: dataStyle
|
||||
}))
|
||||
)
|
||||
];
|
||||
@@ -103,8 +142,120 @@ const ExcelDownloadButton = ({ tableRef, fileName = 'download.xlsx', sheetName =
|
||||
}
|
||||
};
|
||||
|
||||
const downloadDataExcel = () => {
|
||||
try {
|
||||
if (!data || !data || data.length === 0) {
|
||||
alert('다운로드할 데이터가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 모든 로그 항목을 플랫한 구조로 변환
|
||||
const flattenedData = data.map(item => {
|
||||
// 기본 필드
|
||||
const baseData = {
|
||||
'logTime': item.logTime,
|
||||
'GUID': item.userGuid === 'None' ? '' : item.userGuid,
|
||||
'Nickname': item.userNickname === 'None' ? '' : item.userNickname,
|
||||
'Account ID': item.accountId === 'None' ? '' : item.accountId,
|
||||
'Action': item.action,
|
||||
'Domain' : item.domain === 'None' ? '' : item.domain,
|
||||
'Tran ID': item.tranId
|
||||
};
|
||||
|
||||
// Actor 데이터 플랫하게 추가
|
||||
const actorData = item.header && item.header.Actor ?
|
||||
flattenObject(item.header.Actor, 'Actor') : {};
|
||||
|
||||
// Infos 데이터 플랫하게 추가
|
||||
let infosData = {};
|
||||
if (item.body && item.body.Infos && Array.isArray(item.body.Infos)) {
|
||||
item.body.Infos.forEach((info, index) => {
|
||||
infosData = {
|
||||
...infosData,
|
||||
...flattenObject(info, `Info`)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...baseData,
|
||||
...actorData,
|
||||
...infosData
|
||||
};
|
||||
});
|
||||
|
||||
// 모든 항목의 모든 키 수집하여 헤더 생성
|
||||
const allKeys = new Set();
|
||||
flattenedData.forEach(item => {
|
||||
Object.keys(item).forEach(key => allKeys.add(key));
|
||||
});
|
||||
const headers = Array.from(allKeys);
|
||||
|
||||
// 워크북 생성
|
||||
const wb = XLSX.utils.book_new();
|
||||
|
||||
// 데이터 행들 생성
|
||||
const dataRows = flattenedData.map(item => {
|
||||
return headers.map(header => {
|
||||
const value = item[header] !== undefined ? item[header] : '';
|
||||
return {
|
||||
v: value,
|
||||
s: dataStyle
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
// 워크시트 데이터 구성
|
||||
const wsData = [
|
||||
// 헤더 행
|
||||
headers.map(h => ({
|
||||
v: h,
|
||||
s: headerStyle
|
||||
})),
|
||||
// 데이터 행들
|
||||
...dataRows
|
||||
];
|
||||
|
||||
// 워크시트 생성
|
||||
const ws = XLSX.utils.aoa_to_sheet(wsData);
|
||||
|
||||
// 열 너비 설정 (최소 10, 최대 50)
|
||||
ws['!cols'] = headers.map((header) => {
|
||||
// 헤더 길이와 데이터 길이 중 최대값으로 열 너비 결정
|
||||
const maxLength = Math.max(
|
||||
header.length * 1.5,
|
||||
...flattenedData.map(item => {
|
||||
const value = item[header];
|
||||
return value !== undefined ? String(value).length * 1.2 : 0;
|
||||
})
|
||||
);
|
||||
return { wch: Math.max(10, Math.min(50, maxLength)) };
|
||||
});
|
||||
|
||||
// 워크시트를 워크북에 추가
|
||||
XLSX.utils.book_append_sheet(wb, ws, sheetName);
|
||||
|
||||
// 엑셀 파일 다운로드
|
||||
XLSX.writeFile(wb, fileName);
|
||||
} catch (error) {
|
||||
console.error('Excel download failed:', error);
|
||||
alert('엑셀 다운로드 중 오류가 발생했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownload = () => {
|
||||
if (tableRef) {
|
||||
downloadTableExcel();
|
||||
} else if (data) {
|
||||
downloadDataExcel();
|
||||
} else {
|
||||
alert('유효한 데이터 소스가 없습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<ExcelDownButton onClick={downloadExcel}>
|
||||
<ExcelDownButton onClick={handleDownload}>
|
||||
엑셀 다운로드
|
||||
</ExcelDownButton>
|
||||
);
|
||||
|
||||
113
src/components/common/button/ExcelDownButton_bak.js
Normal file
113
src/components/common/button/ExcelDownButton_bak.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import * as XLSX from 'xlsx-js-style';
|
||||
import { ExcelDownButton } from '../../../styles/ModuleComponents';
|
||||
|
||||
const ExcelDownloadButton = ({ tableRef, fileName = 'download.xlsx', sheetName = 'Sheet1' }) => {
|
||||
const isNumeric = (value) => {
|
||||
// 숫자 또는 숫자 문자열인지 확인
|
||||
return !isNaN(value) && !isNaN(parseFloat(value));
|
||||
};
|
||||
|
||||
const downloadExcel = () => {
|
||||
try {
|
||||
if (!tableRef.current) return;
|
||||
|
||||
const tableElement = tableRef.current;
|
||||
const headerRows = tableElement.getElementsByTagName('thead')[0].getElementsByTagName('tr');
|
||||
const bodyRows = tableElement.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
|
||||
|
||||
// 헤더 데이터 추출
|
||||
const headers = Array.from(headerRows[0].cells).map(cell => cell.textContent);
|
||||
|
||||
// 바디 데이터 추출 및 숫자 타입 처리
|
||||
const bodyData = Array.from(bodyRows).map(row =>
|
||||
Array.from(row.cells).map(cell => {
|
||||
const value = cell.textContent;
|
||||
return isNumeric(value) ? parseFloat(value) : value;
|
||||
})
|
||||
);
|
||||
|
||||
// 워크북 생성
|
||||
const wb = XLSX.utils.book_new();
|
||||
|
||||
// 테두리 스타일 정의
|
||||
const borderStyle = {
|
||||
style: "thin",
|
||||
color: { rgb: "000000" }
|
||||
};
|
||||
|
||||
// 스타일 정의
|
||||
const centerStyle = {
|
||||
font: {
|
||||
name: "맑은 고딕",
|
||||
sz: 11
|
||||
},
|
||||
alignment: {
|
||||
horizontal: 'right',
|
||||
vertical: 'right'
|
||||
},
|
||||
border: {
|
||||
top: borderStyle,
|
||||
bottom: borderStyle,
|
||||
left: borderStyle,
|
||||
right: borderStyle
|
||||
}
|
||||
};
|
||||
|
||||
const headerStyle = {
|
||||
alignment: {
|
||||
horizontal: 'center',
|
||||
vertical: 'center'
|
||||
},
|
||||
fill: {
|
||||
fgColor: { rgb: "d9e1f2" },
|
||||
patternType: "solid"
|
||||
}
|
||||
};
|
||||
|
||||
// 데이터에 스타일 적용
|
||||
const wsData = [
|
||||
// 헤더 행
|
||||
headers.map(h => ({
|
||||
v: h,
|
||||
s: headerStyle
|
||||
})),
|
||||
// 데이터 행들
|
||||
...bodyData.map(row =>
|
||||
row.map(cell => ({
|
||||
v: cell,
|
||||
s: centerStyle
|
||||
}))
|
||||
)
|
||||
];
|
||||
|
||||
// 워크시트 생성
|
||||
const ws = XLSX.utils.aoa_to_sheet(wsData);
|
||||
|
||||
// 열 너비 설정 (최소 8, 최대 50)
|
||||
ws['!cols'] = headers.map((_, index) => {
|
||||
const maxLength = Math.max(
|
||||
headers[index].length * 2,
|
||||
...bodyData.map(row => String(row[index] || '').length * 1.2)
|
||||
);
|
||||
return { wch: Math.max(8, Math.min(50, maxLength)) };
|
||||
});
|
||||
|
||||
// 워크시트를 워크북에 추가
|
||||
XLSX.utils.book_append_sheet(wb, ws, sheetName);
|
||||
|
||||
// 엑셀 파일 다운로드
|
||||
XLSX.writeFile(wb, fileName);
|
||||
} catch (error) {
|
||||
console.error('Excel download failed:', error);
|
||||
alert('엑셀 다운로드 중 오류가 발생했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ExcelDownButton onClick={downloadExcel}>
|
||||
엑셀 다운로드
|
||||
</ExcelDownButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExcelDownloadButton;
|
||||
Reference in New Issue
Block a user