fix(B06): 측점만 골랐을 때 기슭막이 조정창이 뜨지 않게 한다
원인: 앞선 커밋에서 넣은 '대표 벽 자동 선택'(selectDefaultWall)이 카드를 고를 때마다 벽을 골라 조정창까지 띄웠다(2026-08-29 사용자 보고: 기슭막이(유출) 창이 계속 떠 있음). - selectDefaultWall과 그에 딸린 자동 선택 표시(withAutoAdopt 등)를 걷어냈다. - 카드·목록 선택 리스너에서 남아 있는 벽 선택을 비운다. 벽을 찍어 카드가 딸려 선택된 경우는 건드리지 않는다(isWallSelecting 가드). 부작용: 단 수·옵션 행은 도면에서 벽을 고른 뒤에만 유입구·유출구에 붙는다 (사용자 확인: 측점 선택 시 자동 구조물 선택은 필요 없음). 검증: 목록 선택·카드 선택 시 조정창 0개·강조 없음, 벽 클릭 시 기슭막이(유출) 창 + 유출구 강조 + 단 수·옵션 행 표시.
This commit is contained in:
@@ -21,20 +21,6 @@ export function setAdjustSideSlots(next: { inlet: HTMLElement; outlet: HTMLEleme
|
||||
sideSlots = next;
|
||||
}
|
||||
|
||||
/** 지금 붙는 사본이 **자동 선택**(카드를 골라 대표 벽이 딸려 온 경우)인가.
|
||||
* 자동이면 그룹 강조를 켜지 않는다 — 강조는 도면에서 구조물을 직접 고를 때만
|
||||
* 쓴다(2026-08-29 사용자 지시). */
|
||||
let autoAdopt = false;
|
||||
|
||||
export function withAutoAdopt(run: () => void): void {
|
||||
autoAdopt = true;
|
||||
try {
|
||||
run();
|
||||
} finally {
|
||||
autoAdopt = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 이식 자리가 지금 화면에 서 있는지 — 숨겨진 그룹(다른 시설)이면 옮기지 않는다. */
|
||||
function slotUsable(target: HTMLElement | undefined): target is HTMLElement {
|
||||
if (!target) return false;
|
||||
@@ -67,8 +53,8 @@ function relocateSideRows(panelRoot: HTMLElement): void {
|
||||
if (row.classList.contains("is-hidden")) return;
|
||||
target.append(row);
|
||||
});
|
||||
// 도면에서 직접 고른 구조물만 그룹 테두리로 알린다(2026-08-29 사용자 지시 3).
|
||||
if (!autoAdopt) target.closest("fieldset")?.classList.add("is-active");
|
||||
// 고른 구조물이 어느 쪽인지 그룹 테두리로 알린다(2026-08-29 사용자 지시 3).
|
||||
target.closest("fieldset")?.classList.add("is-active");
|
||||
}
|
||||
|
||||
function ensureDock(): void {
|
||||
|
||||
@@ -46,9 +46,9 @@ import { staleDesignChainages } from "./B06_Section_UI_Section_Common";
|
||||
import { createStandardPanel, type StandardPanelController } from "./B06_Section_UI_Standard_Panel";
|
||||
import {
|
||||
createB06StructuresPanel,
|
||||
isWallSelecting,
|
||||
wireStructureSelection,
|
||||
} from "./B06_Section_UI_Page_Structures_Panel";
|
||||
import { withAutoAdopt } from "./B06_Section_UI_Adjust_Dock";
|
||||
import "./B06_Section_UI_Style.css";
|
||||
import "./B06_Section_UI_Style_Cross.css";
|
||||
import "./B06_Section_UI_Style_Cross_Controls.css";
|
||||
@@ -471,7 +471,6 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise<void> {
|
||||
stationControls,
|
||||
() => sectionDetail,
|
||||
structuresPanel,
|
||||
(chainageM) => sectionView.refreshCard(chainageM),
|
||||
);
|
||||
// 횡단도(카드) 자체를 골라도 그 측점 구조물 정보를 폼에 올린다(2026-08-29 사용자).
|
||||
// 연동으로 옆에서 넘어온 카드는 **소유 측점** 시설을 보여 준다.
|
||||
@@ -486,27 +485,14 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise<void> {
|
||||
const owner = stationControls.structureSpan.ownerOf(target);
|
||||
structuresPanel.showAtChainage(owner?.chainage_m ?? target.chainage_m);
|
||||
structureSelection.syncInletStructure();
|
||||
selectDefaultWall(owner ?? target);
|
||||
// 카드만 고른 경우엔 구조물(벽·구체) 선택을 비운다 — 조정창이 저절로 뜨면 안 된다
|
||||
// (2026-08-29 사용자). 벽을 찍어 카드가 딸려 선택된 경우는 건드리지 않는다.
|
||||
if (!isWallSelecting() && stationControls.revetOffset.selectedFor(target)) {
|
||||
stationControls.revetOffset.select(target.chainage_m, null);
|
||||
sectionView.refreshCard(target.chainage_m);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 시설을 폼에 올릴 때 **대표 벽**(유출 기준벽, 없으면 유입)을 함께 고른다 —
|
||||
* 단 수·옵션 행은 고른 벽에 딸린 것이라 벽이 없으면 유입구·유출구 그룹이 빈다
|
||||
* (2026-08-29 사용자 보고). 이미 고른 벽이 있으면 건드리지 않는다.
|
||||
*/
|
||||
function selectDefaultWall(section: NonNullable<typeof sectionDetail>["cross_sections"][number]) {
|
||||
const culvert = section.culvert;
|
||||
if (!culvert) return;
|
||||
if (stationControls.revetOffset.selectedFor(section)) return;
|
||||
const key = culvert.outlet ? "outlet" : culvert.inlet ? "inlet" : null;
|
||||
if (!key) return;
|
||||
// 자동으로 딸려 온 선택이라 그룹 강조는 켜지 않는다(2026-08-29 사용자 지시).
|
||||
withAutoAdopt(() => {
|
||||
stationControls.revetOffset.select(section.chainage_m, key);
|
||||
sectionView.refreshCard(section.chainage_m);
|
||||
});
|
||||
}
|
||||
|
||||
// 메인 영역: 종·횡단 도면(sectionView) 또는 안내 메시지를 표시한다.
|
||||
const mainArea = document.createElement("div");
|
||||
mainArea.className = "b06-profile__main";
|
||||
|
||||
@@ -24,12 +24,7 @@ import {
|
||||
} from "../B05_Profile/B05_Profile_Api_Structures";
|
||||
import { fetchDetailPipePoints } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
|
||||
import { showToast } from "@ui/ui_template_elements";
|
||||
import {
|
||||
adjustDockRoot,
|
||||
resetAdjustDock,
|
||||
setAdjustSideSlots,
|
||||
withAutoAdopt,
|
||||
} from "./B06_Section_UI_Adjust_Dock";
|
||||
import { adjustDockRoot, resetAdjustDock, setAdjustSideSlots } from "./B06_Section_UI_Adjust_Dock";
|
||||
import type { SectionDetailResponse } from "./B06_Section_Api_Fetch";
|
||||
import type { StationControls } from "./B06_Section_UI_Page_Station_Controls";
|
||||
|
||||
@@ -208,12 +203,26 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
|
||||
* 구조물의 **소유 측점** 시설을 좌측 폼에 올린다(2026-08-29 일원화 3단계).
|
||||
* 제어 객체의 select를 감싸기만 한다 — 조작·저장 경로는 그대로다.
|
||||
*/
|
||||
/** 지금 처리 중인 선택이 **도면에서 벽·구체를 찍은 것**인가 — 카드 선택 리스너가
|
||||
* 이 값으로 "카드만 고른 경우"를 가려낸다(2026-08-29 사용자: 측점 선택 때 구조물이
|
||||
* 자동으로 골라지면 안 된다). 같은 턴에서만 참이다. */
|
||||
let wallSelecting = false;
|
||||
|
||||
export function isWallSelecting(): boolean {
|
||||
return wallSelecting;
|
||||
}
|
||||
|
||||
function markWallSelecting(): void {
|
||||
wallSelecting = true;
|
||||
queueMicrotask(() => {
|
||||
wallSelecting = false;
|
||||
});
|
||||
}
|
||||
|
||||
export function wireStructureSelection(
|
||||
stationControls: StationControls,
|
||||
detail: () => SectionDetailResponse | null,
|
||||
panel: B06StructuresPanel,
|
||||
/** 대표 벽으로 되돌릴 때 카드를 다시 그린다 — 없으면 되돌리지 않는다. */
|
||||
refreshCard?: (chainageM: number) => void,
|
||||
): { syncInletStructure: () => void } {
|
||||
const ownerChainageOf = (chainageM: number): number => {
|
||||
const sectionAt = detail()?.cross_sections.find(
|
||||
@@ -240,36 +249,21 @@ export function wireStructureSelection(
|
||||
|
||||
const origRevet = stationControls.revetOffset.select;
|
||||
stationControls.revetOffset.select = (chainageM, key) => {
|
||||
markWallSelecting();
|
||||
origRevet(chainageM, key);
|
||||
if (key) {
|
||||
panel.showPipeAt(ownerChainageOf(chainageM));
|
||||
syncInletStructure();
|
||||
return;
|
||||
}
|
||||
// 선택을 풀어도 폼의 단 수·옵션 행은 남아야 한다 — 그 행들은 벽에 딸려 있으므로
|
||||
// 대표 벽으로 조용히 되돌린다(강조만 꺼진다, 2026-08-29 사용자 지시).
|
||||
const target = detail()?.cross_sections.find(
|
||||
(entry) => Math.abs(entry.chainage_m - chainageM) < 0.01,
|
||||
);
|
||||
const fallback = target?.culvert ? (target.culvert.outlet ? "outlet" : "inlet") : null;
|
||||
if (!fallback || !refreshCard) {
|
||||
panel.showPipeAt(null);
|
||||
return;
|
||||
}
|
||||
withAutoAdopt(() => {
|
||||
origRevet(chainageM, fallback);
|
||||
refreshCard(chainageM);
|
||||
});
|
||||
panel.showPipeAt(ownerChainageOf(chainageM));
|
||||
syncInletStructure();
|
||||
panel.showPipeAt(key ? ownerChainageOf(chainageM) : null);
|
||||
if (key) syncInletStructure();
|
||||
};
|
||||
|
||||
const origFord = stationControls.ford.select;
|
||||
stationControls.ford.select = (chainageM, role) => {
|
||||
markWallSelecting();
|
||||
origFord(chainageM, role);
|
||||
panel.showPipeAt(role ? chainageM : null);
|
||||
};
|
||||
const origBox = stationControls.box.select;
|
||||
stationControls.box.select = (chainageM, role) => {
|
||||
markWallSelecting();
|
||||
origBox(chainageM, role);
|
||||
panel.showPipeAt(role ? chainageM : null);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user