[as] 웹기안기의 화면 조정

This commit is contained in:
2026-10-19 16:43:51 +09:00
parent 42dc2dc027
commit 9a77e9c52a
2 changed files with 74 additions and 28 deletions
@@ -34,6 +34,7 @@ import {
DialogHeader,
DialogTitle,
Skeleton,
cn,
} from "@common/components";
import { PwrkCnsltnDocEvlDialog } from "./pwrk-cnsltn-doc-evl-dialog";
@@ -97,12 +98,23 @@ function resolveDefaultBranchSeCd({
supplementBranches?: Set<string>;
isFinalApproverAfterMerger?: boolean;
}): string {
// 0. 병합자 후의 최종 승인자는 무조건 MAIN 탭으로 고정
if (isForkJoin && isFinalApproverAfterMerger) {
// 0. 순차 결재(!isForkJoin)인 경우: 무조건 "MAIN" 고정 (SP, SF 부서 분기가 없으므로 단일 종합본 처리)
if (!isForkJoin) {
return "MAIN";
}
// 1. 공단 사용자 등 본인 부서(branchSeCd)가 있는 경우 본인 부서 탭을 1순위로 지정
// 1. TE, SL, RK 상태가 아닌 경우 (예: RB 등): SP, SF 부서 탭이 노출되지 않고 MAIN 탭만 노출되므로 무조건 "MAIN" 고정
// RK 상태는 1차 결재진행상태인 TE 상태와 논리적으로 동일하게 취급되어 부서별(SP, SF) 탭 선택이 유지됨
if (prgrsSttsComCd !== "TE" && prgrsSttsComCd !== "SL" && prgrsSttsComCd !== "RK") {
return "MAIN";
}
// 2. 병합자 후의 최종 승인자는 무조건 MAIN 탭으로 고정
if (isFinalApproverAfterMerger) {
return "MAIN";
}
// 3. 공단 사용자 등 본인 부서(branchSeCd)가 있는 경우 본인 부서 탭을 1순위로 지정
if (branchSeCd === "TOTAL_AGG") {
return "MAIN";
}
@@ -110,22 +122,22 @@ function resolveDefaultBranchSeCd({
return branchSeCd;
}
// 2. 지자체 사용자(ROLE_USER05) 또는 본인 부서가 없는 경우: 보완요청 부서 우선 선택
if (isForkJoin && supplementBranches && supplementBranches.size > 0) {
// 4. 지자체 사용자(ROLE_USER05) 또는 본인 부서가 없는 경우: 보완요청 부서 우선 선택 (TE, SL 상태일 때)
if (supplementBranches && supplementBranches.size > 0) {
if (supplementBranches.size > 1) {
return "SP";
}
if (supplementBranches.has("SP")) return "SP";
if (supplementBranches.has("SF")) return "SF";
}
if (isForkJoin && supplementDmndBranch && ["SP", "SF"].includes(supplementDmndBranch)) {
if (supplementDmndBranch && ["SP", "SF"].includes(supplementDmndBranch)) {
return supplementDmndBranch;
}
if (userRole === "ROLE_USER05" && (prgrsSttsComCd === "SL" || prgrsSttsComCd === "RB")) {
if (userRole === "ROLE_USER05" && prgrsSttsComCd === "SL") {
return supplementDmndBranch || "SP";
}
return isForkJoin ? "SP" : "MAIN";
return "SP";
}
function PwrkCnsltnDocMngDialog({
@@ -314,13 +326,15 @@ function PwrkCnsltnDocMngDialog({
const completedDraft = findCompletedPwrkDraft(pwrkCnsltnData);
const crtDmndUuid = completedDraft?.crtDmndUuid;
const targetBranchForApi = isForkJoin ? currentBranchSeCd : undefined;
const {
data: documentBlob,
isLoading: isDocumentLoading,
isError: isDocumentError,
} = useQuery({
queryKey: ["pwrk-cnsltn-doc-crt-rslt", "open-latest", crtDmndUuid, currentBranchSeCd],
queryFn: () => pwrkCnsltnDocCrtRsltService.openWebHwpLatest(crtDmndUuid!, currentBranchSeCd),
queryKey: ["pwrk-cnsltn-doc-crt-rslt", "open-latest", crtDmndUuid, targetBranchForApi],
queryFn: () => pwrkCnsltnDocCrtRsltService.openWebHwpLatest(crtDmndUuid!, targetBranchForApi),
select: (response) => response.data,
enabled: open && Boolean(crtDmndUuid),
});
@@ -443,7 +457,7 @@ function PwrkCnsltnDocMngDialog({
const response = await pwrkCnsltnDocCrtRsltService.downloadLatest(
completedDraft.crtDmndUuid,
currentBranchSeCd,
targetBranchForApi,
);
const objectUrl = window.URL.createObjectURL(response.data);
const anchor = document.createElement("a");
@@ -514,9 +528,15 @@ function PwrkCnsltnDocMngDialog({
const baseCanSave = !viewOnly && (canSaveProp ?? canSaveByAtrz);
const canSaveCurrentBranch = useMemo(() => {
// 1. 지자체 사용자 (ROLE_USER05): 보완요청(SL) 및 지자체회신/조치결과작성(RB) 상태에서 보완 부서만 저장 허용
// 1. 지자체 사용자 (ROLE_USER05)
if (userRole === "ROLE_USER05") {
if (prgrsSttsComCd === "SL" || prgrsSttsComCd === "RB") {
// 1-1. RB(조치결과작성) 상태: 병렬결재에서도 프로세스상 한 개의 MAIN만 남아 처리되므로 MAIN 탭 저장 허용!
if (prgrsSttsComCd === "RB") {
return currentBranchSeCd === "MAIN";
}
// 1-2. SL(보완요청/조치결과요청) 상태: 보완요청 부서(SP, SF) 초안만 저장 허용
if (prgrsSttsComCd === "SL") {
if (isForkJoin) {
// 보완요청 부서(supplementBranches)가 존재하는 경우 해당 부서만 저장 허용
if (supplementBranches.size > 0) {
@@ -572,11 +592,19 @@ function PwrkCnsltnDocMngDialog({
supplementBranches,
]);
const editorIframeHeight = isForkJoin
? "h-[50vh] min-h-[26rem]"
: "h-[58vh] min-h-[32rem]";
const editorContainerMinHeight = isForkJoin ? "min-h-[26rem]" : "min-h-[32rem]";
const pjtcoTableHeight = isForkJoin
? "h-[calc(50vh+4rem)]"
: "h-[calc(58vh+4rem)]";
return (
<>
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent
className="max-h-[96vh] max-w-[80vw] overflow-y-auto"
className="flex max-h-[96vh] max-w-[80vw] flex-col gap-4 overflow-y-auto"
aria-describedby={undefined}
>
<DialogHeader>
@@ -587,7 +615,8 @@ function PwrkCnsltnDocMngDialog({
<div className="flex flex-wrap items-center justify-between gap-2 rounded-md border border-border bg-muted/40 px-3 py-2">
<div className="flex items-center gap-2">
<span className="text-sm font-semibold text-muted-foreground">부서별 문서 탭:</span>
{!isFinalApproverAfterMerger && (
{!isFinalApproverAfterMerger &&
(prgrsSttsComCd === "TE" || prgrsSttsComCd === "SL" || prgrsSttsComCd === "RK") && (
<>
<Button
type="button"
@@ -618,15 +647,17 @@ function PwrkCnsltnDocMngDialog({
</div>
<span className="text-xs text-muted-foreground">
{userRole === "ROLE_USER05"
? isForkJoin && supplementBranches.size > 0
? supplementBranches.has(currentBranchSeCd)
? supplementBranches.size > 1
? `[보완 수정 모드] 관로·시설 부서 모두 보완요청 상태이며, ${currentBranchSeCd === "SP" ? "관로" : "시설"} 초안을 수정 및 저장할 수 있습니다.`
: `[보완 수정 모드] ${supplementBranches.has("SP") ? "관로" : "시설"} 초안만 수정 및 저장 가능합니다.`
: `[읽기 전용 모드] ${currentBranchSeCd === "MAIN" ? "종합본" : currentBranchSeCd === "SP" ? "관로 초안" : "시설 초안"}은 보완 비대상으로 저장 불가합니다.`
: prgrsSttsComCd === "SL" || prgrsSttsComCd === "RB"
? `지자체 담당자: ${currentBranchSeCd === "MAIN" ? "종합본 열람 전용" : `${currentBranchSeCd === "SP" ? "관로" : "시설"} 초안 보완 수정 모드 (저장 가능)`}`
: "지자체 사용자: 문서 열람 모드"
? prgrsSttsComCd === "RB"
? "지자체 담당자: 종합 실무협의서(MAIN) 조치결과 작성 모드 (저장 가능)"
: isForkJoin && supplementBranches.size > 0
? supplementBranches.has(currentBranchSeCd)
? supplementBranches.size > 1
? `[보완 수정 모드] 관로·시설 부서 모두 보완요청 상태이며, ${currentBranchSeCd === "SP" ? "관로" : "시설"} 초안을 수정 및 저장할 수 있습니다.`
: `[보완 수정 모드] ${supplementBranches.has("SP") ? "관로" : "시설"} 초안만 수정 및 저장 가능합니다.`
: `[읽기 전용 모드] ${currentBranchSeCd === "MAIN" ? "종합본" : currentBranchSeCd === "SP" ? "관로 초안" : "시설 초안"}은 보완 비대상으로 저장 불가합니다.`
: prgrsSttsComCd === "SL"
? `지자체 담당자: ${currentBranchSeCd === "MAIN" ? "종합본 열람 전용" : `${currentBranchSeCd === "SP" ? "관로" : "시설"} 초안 보완 수정 모드 (저장 가능)`}`
: "지자체 사용자: 문서 열람 모드"
: isFinalApproverAfterMerger
? "최종 승인자: MAIN 종합 실무협의서 열람 모드"
: isMerger || effectiveBranchSeCd === "TOTAL_AGG"
@@ -650,7 +681,11 @@ function PwrkCnsltnDocMngDialog({
</div>
) : null}
{isLoading ? <Skeleton className="h-[70vh] min-h-[40rem] w-full" /> : null}
{isLoading ? (
<Skeleton
className={cn("w-full", isForkJoin ? "h-[56vh] min-h-[26rem]" : "h-[64vh] min-h-[32rem]")}
/>
) : null}
{isError ? (
<p className="py-16 text-center text-lg text-muted-foreground">
실무협의서 정보를 불러오지 못했습니다.
@@ -662,13 +697,14 @@ function PwrkCnsltnDocMngDialog({
</p>
) : null}
{completedDraft && documentBlob ? (
<div className="flex min-h-[40rem] items-stretch gap-2">
<div className={cn("flex items-stretch gap-2", editorContainerMinHeight)}>
<div className="min-w-0 flex-1">
<HangulGiangi
documentBlob={documentBlob}
documentKey={`${completedDraft.crtDmndUuid}_${currentBranchSeCd}`}
documentFileName={documentFileName}
canSave={canSaveCurrentBranch}
iframeClassName={editorIframeHeight}
onSaveDocument={handleSaveDocument}
onDownload={handleDownload}
onDmndSplmnt={onDmndSplmnt}
@@ -676,7 +712,12 @@ function PwrkCnsltnDocMngDialog({
</div>
{pjtcoAjmtPage?.content?.length ? (
isPjtcoAjmtTableOpen ? (
<section className="flex h-[calc(64vh+4rem)] w-0 flex-[0.4] flex-col overflow-hidden rounded-md border border-border">
<section
className={cn(
"flex w-0 flex-[0.4] flex-col overflow-hidden rounded-md border border-border",
pjtcoTableHeight,
)}
>
<header className="flex items-center justify-between gap-2 border-b border-border px-3 py-2">
<h3 className="text-xl font-semibold">금액검증결과</h3>
<button
@@ -26,6 +26,7 @@ function HangulGiangi({
bridgeUrl = DEFAULT_BRIDGE_URL,
ctrlBaseUrl = WEBHYP_CTRL_URL,
className,
iframeClassName,
onReady,
}: HangulGiangiProps) {
const iframeRef = useRef<HTMLIFrameElement>(null);
@@ -216,7 +217,10 @@ function HangulGiangi({
name={HWP_CTRL_IFRAME_NAME}
title="웹한글 기안기"
src={iframeSrc}
className="fullscreen:h-screen fullscreen:min-h-0 fullscreen:w-screen h-[64vh] min-h-[40rem] w-full border-0 bg-background"
className={cn(
"fullscreen:h-screen fullscreen:min-h-0 fullscreen:w-screen w-full border-0 bg-background",
iframeClassName ?? "h-[64vh] min-h-[40rem]",
)}
/>
</div>
);
@@ -323,6 +327,7 @@ interface HangulGiangiProps {
bridgeUrl?: string;
ctrlBaseUrl?: string;
className?: string;
iframeClassName?: string;
onReady?: () => void;
}