feat: [문서] 검사성적서/작업일지 저장 시 HTML 스냅샷 캡처 전송

- InspectionReportModal: contentWrapperRef로 DOM 캡처, handleSave에서 rendered_html 포함
- WorkLogModal: contentWrapperRef로 DOM 캡처, handleSave에서 rendered_html 포함
- saveInspectionDocument/saveWorkLog 타입에 rendered_html 추가
- MNG에서 스냅샷 기반 문서 출력을 위한 프론트 파이프라인 완성
This commit is contained in:
2026-03-06 17:46:06 +09:00
parent fe930b5831
commit a1fb0d4f9b
4 changed files with 18 additions and 3 deletions

View File

@@ -857,6 +857,7 @@ export async function saveInspectionDocument(
title?: string; title?: string;
data: Record<string, unknown>[]; data: Record<string, unknown>[];
approvers?: { role_name: string; user_id?: number }[]; approvers?: { role_name: string; user_id?: number }[];
rendered_html?: string;
} }
): Promise<{ ): Promise<{
success: boolean; success: boolean;

View File

@@ -164,6 +164,7 @@ export function InspectionReportModal({
const [isSaving, setIsSaving] = useState(false); const [isSaving, setIsSaving] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const contentRef = useRef<InspectionContentRef>(null); const contentRef = useRef<InspectionContentRef>(null);
const contentWrapperRef = useRef<HTMLDivElement>(null);
// API에서 로딩된 검사 데이터 (props 없을 때 fallback) // API에서 로딩된 검사 데이터 (props 없을 때 fallback)
const [apiWorkItems, setApiWorkItems] = useState<WorkItemData[] | null>(null); const [apiWorkItems, setApiWorkItems] = useState<WorkItemData[] | null>(null);
@@ -341,6 +342,8 @@ export function InspectionReportModal({
if (!workOrderId || !contentRef.current) return; if (!workOrderId || !contentRef.current) return;
const data = contentRef.current.getInspectionData(); const data = contentRef.current.getInspectionData();
// HTML 스냅샷 캡처 (MNG 출력용)
const renderedHtml = contentWrapperRef.current?.innerHTML || undefined;
setIsSaving(true); setIsSaving(true);
try { try {
// 템플릿 모드: Document 기반 저장 (정규화 형식) // 템플릿 모드: Document 기반 저장 (정규화 형식)
@@ -359,6 +362,7 @@ export function InspectionReportModal({
step_id: activeStepId ?? undefined, step_id: activeStepId ?? undefined,
title: activeTemplate.title || activeTemplate.name, title: activeTemplate.title || activeTemplate.name,
data: inspData.records, data: inspData.records,
rendered_html: renderedHtml,
}); });
if (result.success) { if (result.success) {
toast.success('검사 문서가 저장되었습니다.'); toast.success('검사 문서가 저장되었습니다.');
@@ -530,7 +534,9 @@ export function InspectionReportModal({
)} )}
</div> </div>
)} )}
{renderContent()} <div ref={contentWrapperRef}>
{renderContent()}
</div>
</> </>
)} )}
</DocumentViewer> </DocumentViewer>

View File

@@ -11,7 +11,7 @@
* - 양식 미매핑 시 processType 폴백 * - 양식 미매핑 시 processType 폴백
*/ */
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect, useCallback, useRef } from 'react';
import { Loader2, Save } from 'lucide-react'; import { Loader2, Save } from 'lucide-react';
import { DocumentViewer } from '@/components/document-system'; import { DocumentViewer } from '@/components/document-system';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@@ -63,6 +63,7 @@ export function WorkLogModal({
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isSaving, setIsSaving] = useState(false); const [isSaving, setIsSaving] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const contentWrapperRef = useRef<HTMLDivElement>(null);
// 목업 WorkOrder 생성 // 목업 WorkOrder 생성
const createMockOrder = (id: string, pType?: ProcessType): WorkOrder => ({ const createMockOrder = (id: string, pType?: ProcessType): WorkOrder => ({
@@ -155,9 +156,13 @@ export function WorkLogModal({
unit: item.unit || 'EA', unit: item.unit || 'EA',
})); }));
// HTML 스냅샷 캡처 (MNG 출력용)
const renderedHtml = contentWrapperRef.current?.innerHTML || undefined;
const result = await saveWorkLog(workOrderId, { const result = await saveWorkLog(workOrderId, {
table_data: tableData, table_data: tableData,
title: workLogTemplateName || '작업일지', title: workLogTemplateName || '작업일지',
rendered_html: renderedHtml,
}); });
if (result.success) { if (result.success) {
@@ -255,7 +260,9 @@ export function WorkLogModal({
<p className="text-muted-foreground">{error || '데이터를 불러올 수 없습니다.'}</p> <p className="text-muted-foreground">{error || '데이터를 불러올 수 없습니다.'}</p>
</div> </div>
) : ( ) : (
renderContent() <div ref={contentWrapperRef}>
{renderContent()}
</div>
)} )}
</DocumentViewer> </DocumentViewer>
); );

View File

@@ -744,6 +744,7 @@ export async function saveWorkLog(
table_data?: Array<Record<string, unknown>>; table_data?: Array<Record<string, unknown>>;
remarks?: string; remarks?: string;
title?: string; title?: string;
rendered_html?: string;
} }
): Promise<{ ): Promise<{
success: boolean; success: boolean;