- DataFlow: 표 넷 = 데이터표 · 함수 판 알림 · 선/알약 경고 · 끊긴 곳 = 띠 알림 · 알약 · 칸 종류 = 배지 · 고르는 줄 = 목록 줄 · 입력 넷 = 입력 · 도구줄 여섯 · 날 색 → 공통 값 - 구조물 옵션 · 구조물 · 도면 · 면적 · 품목 고르기: 판 띠 = 띠 알림 · 한눈/종류별/부품 = 탭 · 표 둘 = 데이터표 · 체크 둘 = 체크 · 카드 · 번호 = 카드 · 배지 · 도면 도구줄 - 일위대가 · 호표 · 실무자료 · 본 화면 · 서고: 알림 = 띠 알림 · 빈 상태 · 보조 글 · 도구줄 여섯 · 옛 보라 별칭 0 - M01 로직 입력칸 = 입력 부품(작은 칸) · 일위대가 상세 줄 수 고정 시험 693 · 지킴 시험 M02 몫 더함 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
106 lines
4.1 KiB
TypeScript
106 lines
4.1 KiB
TypeScript
/* =============================================================================
|
|
* M02_SO_Def_Parts.ts
|
|
* 구조물 정의 「부품」 탭(PLAN 322-2) — 코드가 그리는 방법(부품 상자 `common_util_structure_parts.json`).
|
|
* 갈래마다 부품 · 이름 · 읽는 칸 · 맞는 자리꼴 · 정본 · 쓰는 종류 · 켬/끔(정의 `부품` = 끈 것만).
|
|
* 끈 부품을 쓰는 종류는 그 갈래가 없음(카드 이름은 종류 이름)으로 — 표 줄(`resolveCatalog`)이 따름.
|
|
* ========================================================================== */
|
|
|
|
import { el } from "@ui/ui_template_elements";
|
|
import type { StructDef } from "./M02_SO_Def_Model";
|
|
import {
|
|
OWNER_KO,
|
|
PART_BOX,
|
|
partsOff,
|
|
PLACE_KO,
|
|
setPartOn,
|
|
shortName,
|
|
usersOf,
|
|
} from "./M02_SO_Def_Reflect";
|
|
import { checkBox, head } from "./M02_SO_Def_Ui";
|
|
import { to } from "./M02_SO_Text";
|
|
import { createText } from "@ui/ui_template_text";
|
|
|
|
type Branch = keyof typeof PART_BOX;
|
|
|
|
export function buildParts(opt: {
|
|
def: StructDef;
|
|
edit: boolean;
|
|
changed: () => void;
|
|
}): HTMLElement {
|
|
const { def, edit, changed } = opt;
|
|
const off = partsOff(def);
|
|
/** 옵션 키 → 정의 이름(단위) — 그 부품을 쓰는 종류의 칸 이름 먼저 · 없으면 아무 종류 · 그래도 없으면 키. */
|
|
const labelOf = (key: string, users: readonly string[]): string => {
|
|
const types = [
|
|
...def.types.filter((t) => users.includes(t.type_id)),
|
|
...def.types.filter((t) => !users.includes(t.type_id)),
|
|
];
|
|
const o = types.flatMap((t) => t.options).find((x) => x.key === key);
|
|
return o ? (o.unit ? `${o.label} (${o.unit})` : o.label) : key;
|
|
};
|
|
const blocks = (Object.keys(PART_BOX) as Branch[]).flatMap((branch) => [
|
|
...head(branch),
|
|
el("table", {
|
|
className: "ui-table ui-table--data m02-sod__table m02-sod__table--wrap",
|
|
attrs: { "data-sod-parts": branch },
|
|
children: [
|
|
el("thead", {
|
|
children: [
|
|
el("tr", {
|
|
children: (["ColName", "PartRead", "PartFits", "PartUsers", "PartOn"] as const).map(
|
|
(key) => el("th", { text: to(key) }),
|
|
),
|
|
}),
|
|
],
|
|
}),
|
|
el("tbody", {
|
|
children: Object.entries(PART_BOX[branch]).map(([id, part]) => {
|
|
const key = `${branch}.${id}`;
|
|
// 끈 부품을 쓰던 종류도 보이게 — 끈 동안은 표가 none 으로 풀므로 켠 꼴로 셈
|
|
const users = usersOf({ ...def, 부품: {} } as StructDef, branch, id);
|
|
return el("tr", {
|
|
attrs: { "data-sod-part": key },
|
|
className: off[key] === false ? "is-off" : "",
|
|
children: [
|
|
// 영어 키는 툴팁만(322-2 다듬기) — 이름 = 짧은 이름 · 읽는 칸 = 정의 칸 이름
|
|
el("td", { text: shortName(part.이름), attrs: { title: `${id} · ${part.이름}` } }),
|
|
el("td", {
|
|
text:
|
|
part["읽는 칸"]
|
|
.map((k) =>
|
|
labelOf(
|
|
k,
|
|
users.map((row) => row.typeId),
|
|
),
|
|
)
|
|
.join(" · ") || "—",
|
|
}),
|
|
el("td", {
|
|
text: `${part.자리꼴.map((p) => PLACE_KO[p] ?? p).join(" · ")} / ${part.정본
|
|
.map((o) => OWNER_KO[o] ?? o)
|
|
.join(" · ")}`,
|
|
}),
|
|
el("td", { text: users.map((row) => row.name).join(" · ") || "—" }),
|
|
el("td", {
|
|
children: [
|
|
checkBox(
|
|
to("PartOn"),
|
|
off[key] !== false,
|
|
(on) => (setPartOn(def, key, on), changed()),
|
|
{ edit, attr: "data-sod-part-on" },
|
|
),
|
|
],
|
|
}),
|
|
],
|
|
});
|
|
}),
|
|
}),
|
|
],
|
|
}),
|
|
]);
|
|
return el("div", {
|
|
className: "m02-sod__tablewrap",
|
|
children: [createText(to("PartsNote")), ...blocks],
|
|
});
|
|
}
|