From fb4b5b7e26162b5be1b56e27356df7a7c88f2c9d Mon Sep 17 00:00:00 2001 From: dohyeons Date: Wed, 17 Dec 2025 17:10:26 +0900 Subject: [PATCH] =?UTF-8?q?=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A5=BC=20textarea=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/controllers/reportController.ts | 57 +++++++++++++------ .../report/designer/CanvasComponent.tsx | 2 + .../designer/ReportDesignerRightPanel.tsx | 9 +-- .../report/designer/ReportPreviewModal.tsx | 4 +- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/backend-node/src/controllers/reportController.ts b/backend-node/src/controllers/reportController.ts index 7cb33cc6..62c1fd06 100644 --- a/backend-node/src/controllers/reportController.ts +++ b/backend-node/src/controllers/reportController.ts @@ -623,18 +623,29 @@ export class ReportController { ? AlignmentTypeRef.RIGHT : AlignmentTypeRef.LEFT; + // 줄바꿈 처리: \n으로 split하여 각 줄을 TextRun으로 생성 + const lines = displayValue.split("\n"); + const textChildren: TextRun[] = []; + lines.forEach((line: string, index: number) => { + if (index > 0) { + // 줄바꿈 추가 (break: 1은 줄바꿈 1개) + textChildren.push(new TextRunRef({ break: 1 })); + } + textChildren.push( + new TextRunRef({ + text: line, + size: fontSizeHalfPt, + color: (component.fontColor || "#000000").replace("#", ""), + bold: component.fontWeight === "bold" || component.fontWeight === "600", + font: "맑은 고딕", + }) + ); + }); + result.push( new ParagraphRef({ alignment, - children: [ - new TextRunRef({ - text: displayValue, - size: fontSizeHalfPt, - color: (component.fontColor || "#000000").replace("#", ""), - bold: component.fontWeight === "bold" || component.fontWeight === "600", - font: "맑은 고딕", - }), - ], + children: textChildren, }) ); } @@ -908,20 +919,30 @@ export class ReportController { ? AlignmentType.RIGHT : AlignmentType.LEFT; + // 줄바꿈 처리: \n으로 split하여 각 줄을 TextRun으로 생성 + const lines = displayValue.split("\n"); + const textChildren: TextRun[] = []; + lines.forEach((line: string, index: number) => { + if (index > 0) { + textChildren.push(new TextRun({ break: 1 })); + } + textChildren.push( + new TextRun({ + text: line, + size: fontSizeHalfPt, + color: (component.fontColor || "#000000").replace("#", ""), + bold: component.fontWeight === "bold" || component.fontWeight === "600", + font: "맑은 고딕", + }) + ); + }); + // 테이블 셀로 감싸서 width 제한 → 자동 줄바꿈 const textCell = new TableCell({ children: [ new Paragraph({ alignment, - children: [ - new TextRun({ - text: displayValue, - size: fontSizeHalfPt, - color: (component.fontColor || "#000000").replace("#", ""), - bold: component.fontWeight === "bold" || component.fontWeight === "600", - font: "맑은 고딕", - }), - ], + children: textChildren, }), ], width: { size: pxToTwip(component.width), type: WidthType.DXA }, diff --git a/frontend/components/report/designer/CanvasComponent.tsx b/frontend/components/report/designer/CanvasComponent.tsx index 7e8e54d2..cb7b7347 100644 --- a/frontend/components/report/designer/CanvasComponent.tsx +++ b/frontend/components/report/designer/CanvasComponent.tsx @@ -270,6 +270,7 @@ export function CanvasComponent({ component }: CanvasComponentProps) { color: component.fontColor, fontWeight: component.fontWeight, textAlign: component.textAlign as "left" | "center" | "right", + whiteSpace: "pre-wrap", }} className="w-full" > @@ -291,6 +292,7 @@ export function CanvasComponent({ component }: CanvasComponentProps) { color: component.fontColor, fontWeight: component.fontWeight, textAlign: component.textAlign as "left" | "center" | "right", + whiteSpace: "pre-wrap", }} > {displayValue} diff --git a/frontend/components/report/designer/ReportDesignerRightPanel.tsx b/frontend/components/report/designer/ReportDesignerRightPanel.tsx index bc2eea74..f2f0949a 100644 --- a/frontend/components/report/designer/ReportDesignerRightPanel.tsx +++ b/frontend/components/report/designer/ReportDesignerRightPanel.tsx @@ -5,6 +5,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; @@ -1120,16 +1121,16 @@ export function ReportDesignerRightPanel() { {/* 기본값 (텍스트/라벨만) */} {(selectedComponent.type === "text" || selectedComponent.type === "label") && (
- - 텍스트 내용 +