From fbbf36020b238a6c4d81b7cac2282bdf7f947e90 Mon Sep 17 00:00:00 2001 From: "jeonghyo.k" Date: Thu, 26 Mar 2026 13:43:56 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat(reports):=20=EB=B3=B4=EA=B3=A0?= =?UTF-8?q?=EC=84=9C=20=EC=A1=B0=EC=9C=84/=EA=B8=B0=EC=83=81=20=EC=84=B9?= =?UTF-8?q?=EC=85=98=20=EC=8B=A4=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=82=BD?= =?UTF-8?q?=EC=9E=85=20=EB=B0=8F=20HWPX=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EB=82=B4=EB=B3=B4=EB=82=B4=EA=B8=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 보고서 oil-tide 섹션에 기상/조위 실데이터 렌더링 추가 - HWPX 이미지 내보내기 구조를 HWPX 스펙(hc:img + manifest 방식)으로 수정 - 확산 분석 목록 정렬 기준 변경: RUN_DTM DESC 우선 --- .claude/workflow-version.json | 2 +- backend/src/prediction/predictionService.ts | 2 +- .../reports/components/ReportGenerator.tsx | 26 +++++++++ .../src/tabs/reports/components/hwpxExport.ts | 56 +++++++++++-------- 4 files changed, 61 insertions(+), 25 deletions(-) diff --git a/.claude/workflow-version.json b/.claude/workflow-version.json index 863bec2..003eaf0 100644 --- a/.claude/workflow-version.json +++ b/.claude/workflow-version.json @@ -1,6 +1,6 @@ { "applied_global_version": "1.6.1", - "applied_date": "2026-03-25", + "applied_date": "2026-03-26", "project_type": "react-ts", "gitea_url": "https://gitea.gc-si.dev", "custom_pre_commit": true diff --git a/backend/src/prediction/predictionService.ts b/backend/src/prediction/predictionService.ts index 63a6845..2c3dde0 100644 --- a/backend/src/prediction/predictionService.ts +++ b/backend/src/prediction/predictionService.ts @@ -183,7 +183,7 @@ export async function listAnalyses(input: ListAnalysesInput): Promise${trs}`; } } + if (activeCat === 0 && sec.id === 'oil-tide') { + const wx = oilPayload?.weather; + if (wx) { + const stationLabel = weatherSnapshot + ? `${weatherSnapshot.stationName} 조위관측소` + : '조위관측소'; + const capturedAt = weatherSnapshot + ? new Date(weatherSnapshot.capturedAt).toLocaleString('ko-KR', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) + : ''; + const rows = [ + ['풍향/풍속', `${wx.windDir} / ${wx.windSpeed}`], + ['파고', wx.waveHeight + (wx.waveMaxHeight ? ` (최대 ${wx.waveMaxHeight})` : '')], + ['파주기', wx.wavePeriod ?? '—'], + ['수온', wx.temp], + ['기압', wx.pressure ?? '—'], + ['시정', wx.visibility ?? '—'], + ['염분', wx.salinity ?? '—'], + ...(wx.currentDir ? [['유향/유속', `${wx.currentDir} / ${wx.currentSpeed ?? '—'}`]] : []), + ]; + const headerHtml = `

${stationLabel}${capturedAt ? ` 수집: ${capturedAt}` : ''}

`; + const trs = rows.map(r => + `${r[0]}${r[1]}` + ).join(''); + content = `${headerHtml}${trs}
`; + } + } // HNS 섹션에 실 데이터 삽입 if (activeCat === 1 && hnsPayload) { diff --git a/frontend/src/tabs/reports/components/hwpxExport.ts b/frontend/src/tabs/reports/components/hwpxExport.ts index e708afd..7ef5814 100644 --- a/frontend/src/tabs/reports/components/hwpxExport.ts +++ b/frontend/src/tabs/reports/components/hwpxExport.ts @@ -498,17 +498,40 @@ function buildEmptyPara(): string { function buildPicParagraph(binDataId: number, widthHwp: number, heightHwp: number): string { const pId = nextId(); const picId = nextId(); + const fileId = `image${binDataId}`; + const halfW = Math.round(widthHwp / 2); + const halfH = Math.round(heightHwp / 2); return ( `` + '' + - `` + - `` + + `` + + '' + + `` + + `` + + '' + + `` + + '' + + '' + + '' + + '' + + '' + + '' + + `` + + `` + + `` + + `` + + '' + + `` + + '' + + `` + + `` + + '' + + `` + '' + '' + - `` + '' + '' + '' @@ -879,8 +902,6 @@ export async function exportAsHWPX( // 이미지 처리 let imageBinIds: { step3?: number; step6?: number; sensitiveMap?: number; sensitivityMap?: number } | undefined; let extraManifestItems = ''; - let binDataListXml = ''; - let binCount = 0; const processImage = (src: string, binId: number, fileId: string) => { // 실제 이미지 포맷 감지 (JPEG vs PNG) @@ -890,13 +911,10 @@ export async function exportAsHWPX( const filePath = `BinData/image${binId}.${ext}`; const base64 = src.replace(/^data:image\/\w+;base64,/, ''); + // HWPX 스펙: 이미지는 ZIP 루트의 BinData/에 저장 (Contents/ 아래 아님) zip.file(filePath, base64, { base64: true }); - extraManifestItems += ``; - // inMemory="NO": 데이터는 ZIP 내 파일로 저장, 요소 내용은 파일 경로 - binDataListXml += - `${filePath}`; - binCount++; + // isEmbeded="1": 한글 HWPX 표준 속성, hc:img binaryItemIDRef가 이 id로 참조 + extraManifestItems += ``; }; if (images?.step3 || images?.step6) { @@ -921,16 +939,8 @@ export async function exportAsHWPX( processImage(images.sensitivityMap, 4, 'image4'); } - // header.xml: binDataList를 hh:refList 뒤에 삽입 (HWPML 스펙 준수) - let headerXml = HEADER_XML; - if (binCount > 0) { - const binDataList = - `` + - binDataListXml + - ''; - // refList 닫힘 태그 직후에 삽입 (binDataList는 head의 직접 자식) - headerXml = HEADER_XML.replace('', '' + binDataList); - } + // header.xml: hh:binDataList 불필요 — hc:img binaryItemIDRef → content.hpf manifest 방식 사용 + const headerXml = HEADER_XML; // Contents zip.file('Contents/content.hpf', buildContentHpf(extraManifestItems)); From c01db13b22dd197a7c78bac85846943786413c53 Mon Sep 17 00:00:00 2001 From: "jeonghyo.k" Date: Thu, 26 Mar 2026 13:50:25 +0900 Subject: [PATCH 2/3] =?UTF-8?q?docs:=20=EB=A6=B4=EB=A6=AC=EC=A6=88=20?= =?UTF-8?q?=EB=85=B8=ED=8A=B8=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/RELEASE-NOTES.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/RELEASE-NOTES.md b/docs/RELEASE-NOTES.md index df94b69..4451b38 100644 --- a/docs/RELEASE-NOTES.md +++ b/docs/RELEASE-NOTES.md @@ -4,6 +4,13 @@ ## [Unreleased] +### 추가 +- 보고서: 조위/기상(oil-tide) 섹션에 실데이터 렌더링 추가 (풍향/풍속·파고·수온·유향 등) + +### 수정 +- 보고서: HWPX 이미지 내보내기 구조를 HWPX 스펙(hc:img + manifest 방식)으로 수정 +- 확산예측: 분석 목록 정렬 기준 변경 (RUN_DTM DESC 우선) + ## [2026-03-25.2] ### 추가 From 3d4801c7ea8d7dc74ea9de12170af8bdfca414b2 Mon Sep 17 00:00:00 2001 From: "jeonghyo.k" Date: Thu, 26 Mar 2026 14:08:33 +0900 Subject: [PATCH 3/3] =?UTF-8?q?docs:=20=EB=A6=B4=EB=A6=AC=EC=A6=88=20?= =?UTF-8?q?=EB=85=B8=ED=8A=B8=20=EC=A0=95=EB=A6=AC=20(2026-03-26)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/RELEASE-NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/RELEASE-NOTES.md b/docs/RELEASE-NOTES.md index 4451b38..5d3d2a1 100644 --- a/docs/RELEASE-NOTES.md +++ b/docs/RELEASE-NOTES.md @@ -4,6 +4,8 @@ ## [Unreleased] +## [2026-03-26] + ### 추가 - 보고서: 조위/기상(oil-tide) 섹션에 실데이터 렌더링 추가 (풍향/풍속·파고·수온·유향 등)