레포트에 페이지번호 컴포넌트 추가

This commit is contained in:
dohyeons
2025-12-18 09:45:07 +09:00
parent 0abe87ae1a
commit 0ed8e686c0
7 changed files with 271 additions and 9 deletions

View File

@@ -618,7 +618,9 @@ export class ReportController {
ImageRunRef: typeof ImageRun,
TableRef: typeof Table,
TableRowRef: typeof TableRow,
TableCellRef: typeof TableCell
TableCellRef: typeof TableCell,
pageIndex: number = 0,
totalPages: number = 1
): (Paragraph | Table)[] => {
const result: (Paragraph | Table)[] = [];
@@ -749,6 +751,46 @@ export class ReportController {
}
}
// PageNumber
else if (component.type === "pageNumber") {
const format = component.pageNumberFormat || "number";
const currentPageNum = pageIndex + 1;
let pageNumberText = "";
switch (format) {
case "number":
pageNumberText = `${currentPageNum}`;
break;
case "numberTotal":
pageNumberText = `${currentPageNum} / ${totalPages}`;
break;
case "koreanNumber":
pageNumberText = `${currentPageNum} 페이지`;
break;
default:
pageNumberText = `${currentPageNum}`;
}
const fontSizeHalfPt = pxToHalfPtFn(component.fontSize || 13);
const alignment =
component.textAlign === "center"
? AlignmentTypeRef.CENTER
: component.textAlign === "right"
? AlignmentTypeRef.RIGHT
: AlignmentTypeRef.LEFT;
result.push(
new ParagraphRef({
alignment,
children: [
new TextRunRef({
text: pageNumberText,
size: fontSizeHalfPt,
color: (component.fontColor || "#000000").replace("#", ""),
font: "맑은 고딕",
}),
],
})
);
}
// Divider - 테이블 셀로 감싸서 정확한 너비 적용
else if (component.type === "divider" && component.orientation === "horizontal") {
result.push(
@@ -775,9 +817,11 @@ export class ReportController {
};
// 섹션 생성 (페이지별)
const sections = layoutConfig.pages
.sort((a: any, b: any) => a.page_order - b.page_order)
.map((page: any) => {
const sortedPages = layoutConfig.pages.sort((a: any, b: any) => a.page_order - b.page_order);
const totalPagesCount = sortedPages.length;
const sections = sortedPages
.map((page: any, pageIndex: number) => {
const pageWidthTwip = mmToTwip(page.width);
const pageHeightTwip = mmToTwip(page.height);
const marginTopMm = page.margins?.top || 10;
@@ -874,7 +918,7 @@ export class ReportController {
}
// 컴포넌트 셀 생성
const cellContent = createCellContent(component, displayValue, pxToHalfPt, pxToTwip, queryResultsMap, AlignmentType, VerticalAlign, BorderStyle, Paragraph, TextRun, ImageRun, Table, TableRow, TableCell);
const cellContent = createCellContent(component, displayValue, pxToHalfPt, pxToTwip, queryResultsMap, AlignmentType, VerticalAlign, BorderStyle, Paragraph, TextRun, ImageRun, Table, TableRow, TableCell, pageIndex, totalPagesCount);
cells.push(
new TableCell({
children: cellContent,
@@ -1162,6 +1206,79 @@ export class ReportController {
lastBottomY = adjustedY + component.height;
}
// PageNumber 컴포넌트 - 테이블 셀로 감싸서 정확한 위치 적용
else if (component.type === "pageNumber") {
const format = component.pageNumberFormat || "number";
const currentPageNum = pageIndex + 1;
let pageNumberText = "";
switch (format) {
case "number":
pageNumberText = `${currentPageNum}`;
break;
case "numberTotal":
pageNumberText = `${currentPageNum} / ${totalPagesCount}`;
break;
case "koreanNumber":
pageNumberText = `${currentPageNum} 페이지`;
break;
default:
pageNumberText = `${currentPageNum}`;
}
const pageNumFontSize = pxToHalfPt(component.fontSize || 13);
const alignment =
component.textAlign === "center"
? AlignmentType.CENTER
: component.textAlign === "right"
? AlignmentType.RIGHT
: AlignmentType.LEFT;
// 테이블 셀로 감싸서 width와 indent 정확히 적용
const pageNumCell = new TableCell({
children: [
new Paragraph({
alignment,
children: [
new TextRun({
text: pageNumberText,
size: pageNumFontSize,
color: (component.fontColor || "#000000").replace("#", ""),
font: "맑은 고딕",
}),
],
}),
],
width: { size: pxToTwip(component.width), type: WidthType.DXA },
borders: {
top: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
bottom: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
left: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
right: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
},
verticalAlign: VerticalAlign.TOP,
});
const pageNumTable = new Table({
rows: [new TableRow({ children: [pageNumCell] })],
width: { size: pxToTwip(component.width), type: WidthType.DXA },
indent: { size: indentLeft, type: WidthType.DXA },
borders: {
top: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
bottom: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
left: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
right: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
insideHorizontal: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
insideVertical: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
},
});
// spacing을 위한 빈 paragraph
if (spacingBefore > 0) {
children.push(new Paragraph({ spacing: { before: spacingBefore, after: 0 }, children: [] }));
}
children.push(pageNumTable);
lastBottomY = adjustedY + component.height;
}
// Table 컴포넌트
else if (component.type === "table" && component.queryId) {
const queryResult = queryResultsMap[component.queryId];