fix(B05): 저장 전 구조물 [삭제] 무동작 — 조각이 옛 배열을 고치던 문제
증상: 방금 [추가]한(아직 저장 전) 항목을 목록에서 고른 뒤 [삭제]를 눌러도 목록에 그대로 남음. 저장 뒤에는 정상. 원인: 700줄 분리(2026-09-04)로 `_Commit`·`_Events` 조각이 `structures` 배열을 **참조로** 받아 두는데, `setStructures()` 가 `structures = next.map(...)` 로 배열을 갈아끼움. 화면 목록은 새 배열로 그려지고 조각은 옛 배열을 splice 해 사라지지 않았음. 같은 이유로 `renderOptionFields()` 의 `optionInputs = []` 도 조각이 옛 칸 목록을 읽을 수 있어 저장값이 어긋날 자리였음. 조치: 두 배열 모두 **자체를 바꾸지 않고 내용만 갈아끼움**(`splice` · `length = 0`)하고 `const` 로 못박아 다시 갈아끼우지 못하게 함. 데이터 흐름은 그대로 — 삭제는 캐시만 바꾸고, 영구저장은 [저장]에서만 나감(5장 데이터 3층). 검증(시험 프로젝트 8cd2e635, 공용 브라우저 실조작): - 저장 전: [추가] → 목록 12건 → 고르고 [삭제] → **11건으로 사라짐**, 서버는 revision 4·0건 그대로(쓰기 없음), 세션 캐시도 빈 목록 - 저장 경로: [추가] → [저장] revision 5·1건 → [삭제](서버 5·1건 유지) → [저장] revision 6·0건 - 저장값: 옹벽 옵션 `height_m 2.5 · length_m 10 · before_m 5 · after_m 5`, 기준 5+0(100m) → 구간 95~105m 정상 - 시험 프로젝트는 구조물 0건으로 되돌려 둠. `tsc --noEmit` 통과, tmp/tests 378 passed Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -158,7 +158,8 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
|
||||
}
|
||||
|
||||
let types: StructureType[] = [];
|
||||
let structures: StructureInstance[] = [];
|
||||
// 배열 자체를 바꾸지 않는다(조각들이 참조로 들고 있음) — 내용만 갈아끼운다.
|
||||
const structures: StructureInstance[] = [];
|
||||
let pipeFacilities: PipeFacilityItem[] = [];
|
||||
let editingId: string | null = null;
|
||||
/** 목록에서 고른 계곡 통과 시설(누가거리 키). 삭제 버튼이 이쪽으로 동작한다. */
|
||||
@@ -171,7 +172,7 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
|
||||
* 순간(또는 폼에 위치를 실어 연 순간)에만 true. 옵션 활성화 시점도 임시 배치와
|
||||
* 같은 이 순간이다(2026-08-18 사용자 지시). */
|
||||
let positionConfirmed = false;
|
||||
let optionInputs: Array<{
|
||||
const optionInputs: Array<{
|
||||
key: string;
|
||||
required: boolean;
|
||||
input: HTMLInputElement | HTMLSelectElement;
|
||||
@@ -290,7 +291,9 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
|
||||
* 몫이라 그리지 않는다(B05 = 유무·종류·위치 단계, 2026-08-17 사용자 확정). */
|
||||
function renderOptionFields(values: Record<string, string | number> = {}): void {
|
||||
const type = currentType();
|
||||
optionInputs = [];
|
||||
// 여기도 배열을 갈아끼우지 않는다 — 조각들이 참조로 받아 두므로 새 배열로
|
||||
// 바꾸면 옛 칸 목록을 읽어 저장값이 어긋난다(2026-09-04).
|
||||
optionInputs.length = 0;
|
||||
optionRow.replaceChildren();
|
||||
// 서브폼이 담당하는 타입(계곡 통과 시설·독립 기슭막이)은 여기서 그리지 않는다.
|
||||
const visible = type && !facilityFormKind(type) ? type.options.filter(isB05Option) : [];
|
||||
@@ -537,7 +540,10 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
|
||||
setStructures(next) {
|
||||
// 서버 정본 주입 — onChange를 울리지 않는다. 울리면 Page가 다시 저장을 걸어
|
||||
// 저장→재조회→주입→저장의 무한 고리가 된다(변경 알림은 사용자 조작에서만).
|
||||
structures = next.map((entry) => ({ ...entry }));
|
||||
// 배열을 **갈아끼우지 않고 안을 채운다** — 저장·배선 조각(`_Commit`·`_Events`)이
|
||||
// 이 배열을 참조로 받아 두므로, 새 배열로 바꾸면 그쪽이 옛 배열을 고쳐
|
||||
// 목록에 반영되지 않는다(2026-09-04 실측: 저장 전 항목 [삭제]가 안 먹던 원인).
|
||||
structures.splice(0, structures.length, ...next.map((entry) => ({ ...entry })));
|
||||
// 실시간 반영으로 되돌아온 목록이면 폼을 닫지 않는다 — 고치던 칸이 사라진다.
|
||||
if (applyingLive) renderList();
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user