From 16d89b7976330a0017632c109c0a95d53dff77d8 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 29 Aug 2026 16:42:57 +0900 Subject: [PATCH] =?UTF-8?q?fix(B06):=20=EC=98=AE=EA=B8=B4=20=EC=A1=B0?= =?UTF-8?q?=EC=A0=95=20=ED=96=89=EC=9D=B4=20=EC=82=AC=EB=9D=BC=EC=A7=80?= =?UTF-8?q?=EB=8D=98=20=EB=AC=B8=EC=A0=9C=EC=99=80=20=EB=8B=A8=20=EC=88=98?= =?UTF-8?q?=20=ED=91=9C=EC=8B=9C=20=EB=B2=94=EC=9C=84=EB=A5=BC=20=EA=B3=A0?= =?UTF-8?q?=EC=B9=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 원인: 단 수·옵션 행 DOM을 유입구·유출구로 옮긴 뒤, 다음 선택에서 clearSideSlots가 replaceChildren으로 그 행을 없앴다. 창은 카드당 하나라 같은 카드에서 다른 벽을 고르면 행이 영영 돌아오지 않았다. - 옮길 때 제자리에 주석 표식을 남기고, 선택이 바뀌면 그 자리로 되돌린다. - 단 수 행은 **기준(소유) 측점**에서만 다룬다 — 연동으로 넘어온 링크 카드에서는 숨긴다(2026-08-29 사용자). 검증: 유출→유입→유출로 옮겨 다녀도 단 수·옵션이 매번 제자리에 복귀. 링크 카드(4+0.0)에서는 옵션만 뜨고 단 수는 숨김. --- B06_Section/B06_Section_UI_Adjust_Dock.ts | 15 ++++++++++++++- .../B06_Section_UI_Cross_Structure_Panel.ts | 13 +++++++++---- .../B06_Section_UI_Cross_View_Structure.ts | 1 + 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/B06_Section/B06_Section_UI_Adjust_Dock.ts b/B06_Section/B06_Section_UI_Adjust_Dock.ts index ea4d76e7..33a54f20 100644 --- a/B06_Section/B06_Section_UI_Adjust_Dock.ts +++ b/B06_Section/B06_Section_UI_Adjust_Dock.ts @@ -28,8 +28,17 @@ function slotUsable(target: HTMLElement | undefined): target is HTMLElement { return !!group && !group.hidden; } -/** 옮겨 놨던 행을 비운다 — 사본이 갈릴 때마다 옛 행을 남기지 않는다. 그룹 강조도 끈다. */ +/** 옮겨 온 행과 그 **제자리 표식** — 되돌릴 때 원래 순서로 꽂기 위해 짝으로 둔다. + * 표식 없이 지우면 행 DOM이 사라져, 같은 창에서 다른 벽을 고를 때 그 행이 다시는 + * 나오지 않는다(2026-08-29 사용자 보고: 단 수·옵션이 사라짐). */ +const movedRows: Array<{ row: HTMLElement; anchor: Comment }> = []; + +/** 옮겨 온 행을 **원래 자리로 되돌리고** 슬롯을 비운다. 그룹 강조도 끈다. */ function clearSideSlots(): void { + while (movedRows.length) { + const { row, anchor } = movedRows.pop()!; + anchor.parentNode?.replaceChild(row, anchor); + } for (const target of [sideSlots?.inlet, sideSlots?.outlet]) { target?.replaceChildren(); target?.closest("fieldset")?.classList.remove("is-active"); @@ -51,6 +60,10 @@ function relocateSideRows(panelRoot: HTMLElement): void { ); rows.forEach((row) => { if (row.classList.contains("is-hidden")) return; + // 제자리에 표식을 남기고 옮긴다 — 선택이 바뀌면 이 자리로 되돌린다. + const anchor = document.createComment("adjust-row"); + row.parentNode?.insertBefore(anchor, row); + movedRows.push({ row, anchor }); target.append(row); }); // 고른 구조물이 어느 쪽인지 그룹 테두리로 알린다(2026-08-29 사용자 지시 3). diff --git a/B06_Section/B06_Section_UI_Cross_Structure_Panel.ts b/B06_Section/B06_Section_UI_Cross_Structure_Panel.ts index 597d6a43..4d93473d 100644 --- a/B06_Section/B06_Section_UI_Cross_Structure_Panel.ts +++ b/B06_Section/B06_Section_UI_Cross_Structure_Panel.ts @@ -62,6 +62,9 @@ export interface StructurePanelDeps { optionsFor: () => { revetAllowed: boolean; basinLUAllowed: boolean }; /** 다단 기슭막이 상태 — 유출 벽 선택 시 단 수 행 표시 판단에 쓴다. */ extraState: () => { canAdd: boolean; count: number }; + /** 이 카드가 연동으로 넘어온 링크 카드인가 — 단 수는 **기준(소유) 측점**에서만 + * 다룬다(2026-08-29 사용자). 링크 카드에서는 단 수 행을 숨긴다. */ + isLinkedCard: () => boolean; /** 다단 기슭막이 단 수 지정 — 지형 허용보다 크면 기하가 자르고 토스트로 알린다. */ setExtraCount: (count: number) => void; /** 다단 등간격 배치(2026-08-22 ①) — 사면 구간이 같아지게 단들을 재배치. */ @@ -580,10 +583,12 @@ export function buildStructurePanel( : { canAdd: false, count: 0 }; extraRow.classList.toggle( "is-hidden", - !( - tierChannel === "outlet" || - (tierChannel === "basin" && (ownTiers || (isBasin && (tiers.canAdd || tiers.count > 0)))) - ), + deps.isLinkedCard() || + !( + tierChannel === "outlet" || + (tierChannel === "basin" && + (ownTiers || (isBasin && (tiers.canAdd || tiers.count > 0)))) + ), ); currentCount = tiers.count; countValue.textContent = `${tiers.count}단`; diff --git a/B06_Section/B06_Section_UI_Cross_View_Structure.ts b/B06_Section/B06_Section_UI_Cross_View_Structure.ts index 041ccfd5..3aff0cb9 100644 --- a/B06_Section/B06_Section_UI_Cross_View_Structure.ts +++ b/B06_Section/B06_Section_UI_Cross_View_Structure.ts @@ -143,6 +143,7 @@ export function structurePanelDeps(ctx: StructurePanelContext): StructurePanelDe fineMove: (key) => (key !== "inlet" && key !== "outlet") || ctx.hiddenPipe(), optionsFor: () => ctx.inletOptions(), extraState: () => ctx.extraState(), + isLinkedCard: () => ctx.isLinked, basinExtraState: () => ctx.basinExtraState(), hiddenPipe: () => ctx.hiddenPipe(), setExtraCount: (count) => {