From e944ad43693e6d237449037a0d770df0d95280b9 Mon Sep 17 00:00:00 2001 From: bicochan Date: Wed, 9 Sep 2026 17:38:40 +0900 Subject: [PATCH] =?UTF-8?q?[as]=20feat:=20=EC=8B=A4=EB=AC=B4=ED=98=91?= =?UTF-8?q?=EC=9D=98=EC=84=9C=20=EC=9B=B9=EA=B8=B0=EC=95=88=EA=B8=B0?= =?UTF-8?q?=EC=97=90=20=EB=A0=8C=EB=8D=94=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(with-base-layout)/hangulgiangi/page.tsx | 3 - apps/as/docs/pwrk-cnsltn/development-guide.md | 4 +- apps/as/docs/pwrk-cnsltn/ref-endpoint.md | 4 +- .../docs/pwrk-cnsltn/ref-frontend-entities.md | 12 +- .../as/docs/pwrk-cnsltn/ref-process-status.md | 2 +- apps/as/public/webhwpctrl/index.html | 15 +- apps/as/src/entities/attach/index.ts | 1 + .../api/pwrk-cnsltn-doc-crt-rslt-service.ts | 51 ++ .../pwrk-cnsltn-doc-crt-rslt/index.ts | 9 + .../pwrk-cnsltn-doc-crt-rslt-interface.ts | 18 + ...pwrk-cnsltn-doc-crt-rslt-payload-schema.ts | 9 + .../api/pwrk-cnsltn-mng-service.ts | 18 + .../entities/pwrk-cnsltn-mng/api/queries.ts | 16 + apps/as/src/entities/pwrk-cnsltn-mng/index.ts | 9 + .../lib/find-completed-draft.ts | 12 + .../model/pwrk-cnsltn-mng-interface.ts | 33 ++ .../pages/fnrs-cnsltn/lib/button-config.ts | 36 +- .../ui/components/floating-action-buttons.tsx | 34 +- .../components/pwrk-cnsltn-doc-mng-dialog.tsx | 145 ++++++ apps/as/src/pages/hangulgiangi/index.ts | 1 - .../ui/hangul-giangi-preview-page.tsx | 32 -- apps/as/src/shared/config/api.ts | 2 + apps/as/src/widgets/hangulgiangi/index.ts | 22 - .../hangulgiangi/lib/fetch-demo-blob.ts | 21 - .../widgets/hangulgiangi/lib/get-hwp-ctrl.ts | 13 +- .../lib/hangul-giangi-constants.ts | 18 - .../widgets/hangulgiangi/model/hwp-ctrl.ts | 47 +- .../hangulgiangi/ui/hangul-giangi-toolbar.tsx | 103 +--- .../widgets/hangulgiangi/ui/hangul-giangi.tsx | 471 ++++++++++-------- 29 files changed, 690 insertions(+), 471 deletions(-) delete mode 100644 apps/as/app/(main)/(with-base-layout)/hangulgiangi/page.tsx create mode 100644 apps/as/src/entities/pwrk-cnsltn-doc-crt-rslt/api/pwrk-cnsltn-doc-crt-rslt-service.ts create mode 100644 apps/as/src/entities/pwrk-cnsltn-doc-crt-rslt/index.ts create mode 100644 apps/as/src/entities/pwrk-cnsltn-doc-crt-rslt/model/pwrk-cnsltn-doc-crt-rslt-interface.ts create mode 100644 apps/as/src/entities/pwrk-cnsltn-doc-crt-rslt/model/pwrk-cnsltn-doc-crt-rslt-payload-schema.ts create mode 100644 apps/as/src/entities/pwrk-cnsltn-mng/api/pwrk-cnsltn-mng-service.ts create mode 100644 apps/as/src/entities/pwrk-cnsltn-mng/api/queries.ts create mode 100644 apps/as/src/entities/pwrk-cnsltn-mng/index.ts create mode 100644 apps/as/src/entities/pwrk-cnsltn-mng/lib/find-completed-draft.ts create mode 100644 apps/as/src/entities/pwrk-cnsltn-mng/model/pwrk-cnsltn-mng-interface.ts create mode 100644 apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-mng-dialog.tsx delete mode 100644 apps/as/src/pages/hangulgiangi/index.ts delete mode 100644 apps/as/src/pages/hangulgiangi/ui/hangul-giangi-preview-page.tsx delete mode 100644 apps/as/src/widgets/hangulgiangi/lib/fetch-demo-blob.ts diff --git a/apps/as/app/(main)/(with-base-layout)/hangulgiangi/page.tsx b/apps/as/app/(main)/(with-base-layout)/hangulgiangi/page.tsx deleted file mode 100644 index 95c057a58..000000000 --- a/apps/as/app/(main)/(with-base-layout)/hangulgiangi/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { HangulGiangiPreviewPage } from "@/pages/hangulgiangi"; - -export default HangulGiangiPreviewPage; diff --git a/apps/as/docs/pwrk-cnsltn/development-guide.md b/apps/as/docs/pwrk-cnsltn/development-guide.md index 04c860dd7..a715c4030 100644 --- a/apps/as/docs/pwrk-cnsltn/development-guide.md +++ b/apps/as/docs/pwrk-cnsltn/development-guide.md @@ -144,7 +144,7 @@ SV → ST → LE → FV → ER → AC → TE → TP → RM → RB → RC → RA 7. **보완요청/보완완료는 공통 API** `reqsupplement` / `submitsupplement`. 복귀 상태(`ER`/`TE`/`RK`)는 서버가 이력에서 결정한다. 프론트는 직전 상태를 추측해 보내지 않는다. 8. **결재 승인/회신은** `PUT /elapr-prgrs-stts/{id}/process` **하나**. 1차 최종승인자 → `TP`, 2차 → `RR`은 서버가 Feign으로 처리한다. 9. **2차 결재선 복사는 백엔드**. `POST /elapr-apln/copy-line`은 `AV→RK` 콜백에서 호출한다. 프론트는 `RK`에서 2차 결재선을 **조회·표시**만 한다. -10. **웹기안기는 URL을 직접 Open**. blob Object URL을 `HwpCtrl.Open`에 넘기지 않는다. `orgnlOtptDocCn`은 쓰지 않는다. +10. **웹기안기는 `webhwp/open` 응답을 axios `blob`으로 조회한 뒤 `File`로 감싸 `HwpCtrl.Open`에 전달한다.** `blob:` Object URL과 `orgnlOtptDocCn`은 쓰지 않는다. --- @@ -187,7 +187,7 @@ BEGIN ON [파일보완] (ER, ATRZ01) → GET file-vrfc-results → 팝업 → reqsupplement ON [파일검증] (ER, ATRZ01) → dcrag-to transfer (상태 유지) ON [검토자지정] (ER, ATRZ01) → POST elapr-dmnd (docPrgrsSttsComCd: AC) → START POLL AC - ON [실무협의서관리] (TE|RK) → HwpCtrl.Open(webhwp/open) + ON [실무협의서관리] (TE|RK) → GET webhwp/open (blob) → HwpCtrl.Open(File) ON [실무협의서생성] (TE, 실패/타임아웃) → dcrag-to draft/generate ON [검토결과조회] (TE) → pwrk-cnsltn-mng findById | findByUpDocNo ON [저장] (TE|RK) → pwrk-cnsltn-mng save-apply diff --git a/apps/as/docs/pwrk-cnsltn/ref-endpoint.md b/apps/as/docs/pwrk-cnsltn/ref-endpoint.md index 2ff1e0ecb..b14a429ce 100644 --- a/apps/as/docs/pwrk-cnsltn/ref-endpoint.md +++ b/apps/as/docs/pwrk-cnsltn/ref-endpoint.md @@ -257,7 +257,7 @@ v1.0 가이드의 “이 API를 프론트가 치면 안 된다”는 **폐기**. | ID | 용도 | URI | 응답 | | --- | --- | --- | --- | -| W1 | `HwpCtrl.Open` | `GET .../pwrk-cnsltn-doc-crt-rslt/{crtDmndUuid}/webhwp/open` | `inline` HWPX | +| W1 | 웹기안기 Open | `GET .../pwrk-cnsltn-doc-crt-rslt/{crtDmndUuid}/webhwp/open` | `inline` HWPX blob → `HwpCtrl.Open(File)` | | W2 | 편집 저장 | `POST .../pwrk-cnsltn-doc-crt-rslt` multipart `file` + `crtDmndUuid` | 201, `verSn+1` | | W3 | PC 저장 | `GET .../{crtDmndUuid}/download` | `attachment` blob | @@ -271,7 +271,7 @@ v1.0 가이드의 “이 API를 프론트가 치면 안 된다”는 **폐기**. - 서버 파일명: `재원협의 실무협의서({bizNm})_v{verSn}.hwp` - Content-Type은 `application/x-hwp` 또는 `application/haansofthwpx`일 수 있음. 타입에 의존하지 말 것 -Open은 **절대 URL**을 기안기에 전달. blob Object URL 금지. 쿠키/게이트웨이 인증 가능 여부는 백엔드 확인. +Open은 axios `responseType: "blob"`으로 인증된 API를 호출하고, 응답 Blob을 HWPX `File`로 감싸 `HwpCtrl.Open`에 전달한다. `blob:` Object URL은 사용하지 않는다. multipart `Content-Type` 헤더를 수동 지정하지 않는다 (boundary). JSON `saveJson`은 UI에서 쓰지 않는다. diff --git a/apps/as/docs/pwrk-cnsltn/ref-frontend-entities.md b/apps/as/docs/pwrk-cnsltn/ref-frontend-entities.md index 1d24181f0..f74b63571 100644 --- a/apps/as/docs/pwrk-cnsltn/ref-frontend-entities.md +++ b/apps/as/docs/pwrk-cnsltn/ref-frontend-entities.md @@ -105,6 +105,7 @@ export interface PwrkCnsltnDocCrtRsltService { ): Promise>; findById(crtDmndUuid: string, verSn: number): Promise; findLatestByCrtDmndUuid(crtDmndUuid: string): Promise; + openWebHwpLatest(crtDmndUuid: string): Promise>; download(crtDmndUuid: string, verSn: number): Promise>; downloadLatest(crtDmndUuid: string): Promise>; saveMultipart(formData: FormData): Promise; @@ -117,15 +118,18 @@ export interface PwrkCnsltnDocCrtRsltService { } ``` -`webhwp/open`은 fetch하지 않고 URL 빌더만: +`webhwp/open`은 인증된 axios 요청으로 Blob을 조회한다: ```ts -function webhwpOpenUrl(crtDmndUuid: string, verSn?: number): string { - const base = `${ENDPOINT.AS_SERVICE.PWRK_CNSLTN_DOC_CRT_RSLT}/${crtDmndUuid}`; - return verSn == null ? `${base}/webhwp/open` : `${base}/${verSn}/webhwp/open`; +async function openWebHwpLatest(crtDmndUuid: string) { + return client.get(`${BASE}/${crtDmndUuid}/webhwp/open`, { + responseType: "blob", + }); } ``` +응답 Blob은 HWPX `File`로 감싸 `HwpCtrl.Open(file, "HWPX", ...)`에 전달한다. `blob:` Object URL은 사용하지 않는다. + DC RAG TO (구현됨, 시그니처 유지): ```ts diff --git a/apps/as/docs/pwrk-cnsltn/ref-process-status.md b/apps/as/docs/pwrk-cnsltn/ref-process-status.md index 48cb8b6ab..9b8af0cdd 100644 --- a/apps/as/docs/pwrk-cnsltn/ref-process-status.md +++ b/apps/as/docs/pwrk-cnsltn/ref-process-status.md @@ -241,6 +241,6 @@ stateDiagram-v2 ## 8. 웹기안기 -- `TE`/`RK` [실무협의서관리] → 팝업에서 `HwpCtrl.Open(webhwp/open URL)`. +- `TE`/`RK` [실무협의서관리] → `webhwp/open` Blob 조회 후 팝업에서 `HwpCtrl.Open(File)`. - [검토완료] 시 HWP 파싱·DB 등재는 **서버**. FE는 결재 `process`만. - 편집본 저장: `POST /pwrk-cnsltn-doc-crt-rslt` multipart. `verSn`은 클라이언트가 보내지 않음. diff --git a/apps/as/public/webhwpctrl/index.html b/apps/as/public/webhwpctrl/index.html index 8dc0fc313..dcb8c3e45 100644 --- a/apps/as/public/webhwpctrl/index.html +++ b/apps/as/public/webhwpctrl/index.html @@ -1,4 +1,4 @@ - + @@ -28,6 +28,11 @@ overflow: hidden; border: 0; } + + #hwpctrl_frame { + width: 100% !important; + height: 100% !important; + } @@ -35,8 +40,7 @@