feat(b09): 설계내역서 「연결 ▾」 칸 단추 · 우클릭과 같은 연결 메뉴 (182-2)
- 비고 앞 「연결」 칸 — 손 항목 줄만 「연결 ▾」 · 연결됨 = 호표 번호 ▾ · 누름 = 그 칸 아래 연결 메뉴 - 메뉴 = 일위대가 호표 · 단가산출 호표 · 단가산출 로직 + 로직 입력값 · 연결 풀기(166-2 고르기 창 재사용) - 단추 칸 = 이동 안 함 · 묶음 줄 · 자동 줄 = 안 엶 - 시험 test_182 연결 단추(칸 · 메뉴 · 고르기 창 → ref) · node 입력 = 표준입력(명령 줄 길이) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015KYZ2HWWdUwZWYnn3tQz7X
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
* 줄 누름 = 단가를 낸 탭 줄(자재 → 재료비목록표 · 구조물 → 일위대가목록표)
|
||||
* 우클릭 = 줄 추가 · 지우기 · 연결 · 레벨(`…_UI_Tabs_Bill_Edit`)
|
||||
* 레벨(182) = 줄 `level`(셈이 냄) → class is-lvN · 글자 크기 · 첫 칸 들여쓰기(CSS) · 묶음 줄 = 이름만 고침
|
||||
* 「연결 ▾」 칸(182) = 손 항목 줄만 · 누름 = 우클릭 [연결] 과 같은 메뉴(연결됨 = 호표 번호)
|
||||
* ========================================================================== */
|
||||
|
||||
import type { DataRow } from "@ui/ui_template_data_table";
|
||||
@@ -18,13 +19,17 @@ import {
|
||||
editQty,
|
||||
editText,
|
||||
handEditable,
|
||||
openLinkMenu,
|
||||
type BillTable,
|
||||
} from "./B09_Estimation_UI_Tabs_Bill_Edit";
|
||||
|
||||
export const buildBill: TabBuild = (ctx): BillTable => {
|
||||
const { sheets, user, setUser } = ctx;
|
||||
const bill: Row = sheets.bill || { rows: [], totals: null };
|
||||
const rows: DataRow[] = bill.rows;
|
||||
const rows: DataRow[] = bill.rows.map((r: Row) => ({
|
||||
...r,
|
||||
connect: r.hand && r.kind === "item" ? `${r.note || "연결"} ▾` : "",
|
||||
}));
|
||||
const direct: Row = bill.totals?.direct || {};
|
||||
const pair = (key: string, label: string) => [
|
||||
money(`price_${key}`, "단가", [label]),
|
||||
@@ -40,6 +45,7 @@ export const buildBill: TabBuild = (ctx): BillTable => {
|
||||
...pair("labor", "노무비"),
|
||||
...pair("material", "재료비"),
|
||||
...pair("expense", "경비"),
|
||||
text("connect", "연결", 96),
|
||||
text("note", "비고", 200),
|
||||
],
|
||||
rows,
|
||||
@@ -47,7 +53,7 @@ export const buildBill: TabBuild = (ctx): BillTable => {
|
||||
frozen: 1,
|
||||
hint:
|
||||
"공종 나무 = 엑셀 꼴 고정 · 금액 = ROUNDDOWN(단가 × 수량, 0) 비목마다 · 4 자재대 = 대비표 「별도」 · 관급자재대 = 「관급」 표시 자재 · 조달수수료 율(%)은 수량 칸에 넣음 · " +
|
||||
"수량 칸 = 덮어쓰기(빈칸 = 자동) · 우클릭 = 줄 추가 · 지우기 · 일위대가 · 단가산출 연결(새 산근 단가 = [저장] 뒤) · " +
|
||||
"수량 칸 = 덮어쓰기(빈칸 = 자동) · 우클릭 · 「연결 ▾」 = 줄 추가 · 지우기 · 일위대가 · 단가산출 연결(새 산근 단가 = [저장] 뒤) · " +
|
||||
"레벨 = 우클릭 묶음 줄로 · 하위 줄 추가 · 들여쓰기 · 내어쓰기(묶음 금액 = 아래 항목 합 · 공종 합은 항목만) · " +
|
||||
`빈 줄 ${direct.blank ?? 0} — 계는 아는 금액만 · 원가계산서는 빈 줄이 없을 때만 받음`,
|
||||
editable: (i, key) => {
|
||||
@@ -79,7 +85,11 @@ export const buildBill: TabBuild = (ctx): BillTable => {
|
||||
return [`is-lv${r.level ?? 1}`, title, r.hand ? "is-hand" : ""].filter((c) => c).join(" ");
|
||||
},
|
||||
menu: (i) => billMenu(ctx, rows, i),
|
||||
link: (i) => {
|
||||
onCell: (i, key) => {
|
||||
if (key === "connect") openLinkMenu(ctx, rows, i);
|
||||
},
|
||||
link: (i, key) => {
|
||||
if (key === "connect") return null; // 「연결 ▾」 = 메뉴(이동 안 함)
|
||||
const ref = rows[i]?.ref as Row | null | undefined;
|
||||
return ref?.key ? { tab: ref.tab as TabId, key: String(ref.key) } : null;
|
||||
},
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* 연결 = 있는 호표(일위대가목록표 dg · 단가산출근거목록표 sg) · M01 로직(새 산근 = 서버 셈 · [저장] 뒤 단가)
|
||||
* 우클릭 = 공용 메뉴(`ui_template_context_menu` · 화면 고정 자리) · 로직 고르기 · 입력값 = M02 창 재사용
|
||||
* 레벨(182) = 손 줄 kind(group = 묶음 줄 · 이름만) · parent(묶음 손 줄 키) — 하위 줄 추가 · 묶음 줄로 ·
|
||||
* 항목으로 · 들여쓰기 · 내어쓰기 · 손 묶음 깊이 2
|
||||
* 항목으로 · 들여쓰기 · 내어쓰기 · 손 묶음 깊이 2 · 「연결 ▾」 칸 = 우클릭 [연결] 과 같은 메뉴
|
||||
* ========================================================================== */
|
||||
|
||||
import type { DataRow } from "@ui/ui_template_data_table";
|
||||
@@ -336,6 +336,17 @@ export function billMenu(ctx: TabContext, rows: DataRow[], i: number): MapContex
|
||||
}
|
||||
|
||||
let shared: MapContextMenu | null = null;
|
||||
/** 마지막으로 누른 칸 — 「연결 ▾」 단추 메뉴 자리 */
|
||||
let lastCell: Element | null = null;
|
||||
|
||||
/** 「연결 ▾」 칸 누름(182) — 우클릭 [연결] 과 같은 메뉴를 그 칸 아래에 엶 */
|
||||
export function openLinkMenu(ctx: TabContext, rows: DataRow[], i: number): void {
|
||||
const row = rows[i];
|
||||
const box = lastCell?.getBoundingClientRect();
|
||||
if (!shared || !box || !row?.hand || row.kind !== "item") return;
|
||||
const [picks, more] = linkItems(ctx, String(row.key));
|
||||
shared.open(box.left, box.bottom, more.length ? [...picks, "-", ...more] : picks);
|
||||
}
|
||||
|
||||
/** 표에 줄 우클릭 메뉴를 붙임(공용 표는 안 고침) — 글 칸 위는 브라우저 메뉴(붙여넣기) 그대로 */
|
||||
export function attachRowMenu(
|
||||
@@ -348,6 +359,12 @@ export function attachRowMenu(
|
||||
ctxMenu.element.style.position = "fixed"; // 화면 기준 자리(clientX · Y)
|
||||
document.body.append(ctxMenu.element);
|
||||
}
|
||||
// 칸 누름보다 먼저(잡기 단계) — 「연결 ▾」 메뉴를 그 칸 자리에 엶
|
||||
root.addEventListener(
|
||||
"click",
|
||||
(event) => (lastCell = (event.target as Element).closest("td")),
|
||||
true,
|
||||
);
|
||||
root.addEventListener("contextmenu", (event) => {
|
||||
const target = event.target as Element;
|
||||
if (target.closest("input")) return;
|
||||
|
||||
Reference in New Issue
Block a user