refactor(M02): 자재 조합 표를 마스터 템플릿으로 옮김 · M02 좌측 「자재 조합」 컨테이너

- 표 resources/master_data/자재조합.json → resources/master_template/자재조합.json(git mv) · 키 UM 은 표 안 「다음」 번호 · _키대장 · master_keys 의 UM 뺌 · check_master 틀이 새 자리를 같이 봄
- 서버: M01 /api/m01/matset* 뺌 · M02 저장소 M02_MasterTemplete_Matset.py(목록 · 새로 · 고치기 · 지우기 · 쓰는 열 검사) · 길 GET/POST /api/m02/material-combos · PUT/DELETE /api/m02/material-combos/{키} · 갈라 내기(branchMaterialCombo)도 이 저장소로
- 화면: M01 좌측 「자재 조합」 컨테이너 뺌 · M02 좌측 「자재 조합」 컨테이너(찾기 · 키 맨 앞 목록 · 새로 · 본떠 만들기 · 지우기) · 메인 칸 상세(이름 · 비고 · 본뜬키 · 담은 자재 표 · 자재 더하기 · 빼기 · 저장) · 쓰는 열이 있으면 지우기는 확인 창 없이 알림
- 시험: test_m01_matset → test_m02_matset · test_m02_combo_branch 사본 자리 · 실제 자재 코드

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VwJQ5eRrCKf3nH9EFeKvJz
This commit is contained in:
2026-09-28 22:25:30 +09:00
co-authored by Claude Opus 5.5
parent 6606ef167a
commit 4abfc5b265
28 changed files with 753 additions and 882 deletions
@@ -3,7 +3,7 @@
* 마스터 템플릿 좌측 패널 — 시스템 양식 목록(표/도면/구조물 도면/면적산출/재료산출) · 새로 · 본떠 · 지우기.
* 서버 길은 계약 `6_계약.md`. 구조물 도면 · 면적산출 · 재료산출 줄은 집계표 구조물 열(꼴=수)마다 하나씩 —
* 서버가 미리 만들어 둠(도번 SD · 면적번 SA · 재료번 SM + 같은 8자리) ·
* 줄 글은 번호가 맨 앞(「SD01010100 돌기슭막이 …」).
* 줄 글은 번호가 맨 앞(「SD01010100 돌기슭막이 …」). 맨 아래 「자재 조합」 컨테이너는 `M02_MasterTemplete_Matset.ts`.
* ========================================================================== */
import {
@@ -34,6 +34,7 @@ import {
structureLabel,
type StructureColumn,
} from "./M02_MasterTemplete_Structure";
import { buildMatsetSection } from "./M02_MasterTemplete_Matset";
import { canEdit, type Selection } from "./M02_MasterTemplete_UI_Main";
const KINDS: { kind: Kind; label: () => string }[] = [
@@ -75,6 +76,8 @@ export interface SideOptions {
getOpen: () => Selection | null;
/** 저장 안 한 고침을 버릴지 확인 — 취소면 false */
confirmLeave: () => Promise<boolean>;
/** 메인 칸에 양식 밖 화면(자재 조합 상세)을 띄움 */
showView: (label: string, node: HTMLElement) => (dirty: boolean) => void;
}
export interface SideHandle {
@@ -128,12 +131,30 @@ export function buildSide(opt: SideOptions): SideHandle {
del.addEventListener("click", () => void deleteCurrent());
return [el("div", { className: "m02-side__row", children: [btnNew, copy, del] })];
};
const matset = buildMatsetSection({
isAdmin: canEdit(layer, opt.isAdmin),
confirmLeave: opt.confirmLeave,
show: opt.showView,
close: () => opt.onOpen(null),
onOpen: () => {
picked = null;
paintList();
paintColumns();
paintButtons();
},
});
const matsetSection = section(matset.title, matset.body, ...matset.actions);
// 펼칠 때마다 새로 받음 — 재료산출 옆 판이 갈라 낸 조합도 바로 보이게
matsetSection.querySelector(".ui-collapsible__title")?.addEventListener("click", () => {
if (matsetSection.classList.contains("is-collapsed")) void matset.refresh();
});
const listHost = el("div", {
className: "m02-side__lists ui-sidebar-panel",
children: [
section(L("M02_KindTable"), bodies.get("table")!, ...actionRow("table")),
section(L("M02_KindDrawing"), bodies.get("drawing")!, ...actionRow("drawing")),
...COLUMN_KINDS.map((k, i) => section(k.label(), columnBodies[i])),
matsetSection,
],
});
attachCollapsible(listHost);
@@ -202,6 +223,7 @@ export function buildSide(opt: SideOptions): SideHandle {
async function select(info: TemplateInfo): Promise<void> {
if (!isOpen(info) && !(await opt.confirmLeave())) return;
picked = null;
matset.clear();
opt.onOpen({ layer, projectId: null, kind: info.종류, name: info.이름 });
paintList();
paintButtons();
@@ -210,6 +232,7 @@ export function buildSide(opt: SideOptions): SideHandle {
async function selectColumn(col: StructureColumn, kind: ColumnKind): Promise<void> {
if (!isPicked(kind, col.id) && !(await opt.confirmLeave())) return;
picked = null;
matset.clear();
// 제목은 편집 화면이 문서 번호를 앞에 붙임(「SD010101 돌기슭막이 …」)
opt.onOpen({ layer, projectId: null, kind, name: col.id, label: columnHead(col) });
paintColumns();
@@ -245,7 +268,7 @@ export function buildSide(opt: SideOptions): SideHandle {
if (mine !== seq) return;
paintList();
paintButtons();
await refreshStructure();
await Promise.all([refreshStructure(), matset.refresh()]);
}
/* --- 시스템 층 새로 · 본떠 · 지우기(표 · 도면만 — 구조물 도면은 집계표 열이 정함) --- */