Files
Aislo/resources/tester/helper_778_5_sk_pick.cjs
eomsangdonandClaude Opus 5.5 c5067aa2b6 feat(809-1a): 일위대가 불러오기 = 경쟁사 로직 인정 · 요소만 연결 · [수정] 모달 = 일위대가 컨테이너 부품 · 기초 판정 걷음
- [수정] 모달 = Labor_Table(읽기 · 덧칸 표지 · 엑셀 금액) · 줄 = 로직(단가산출 · 일위대가) / 요소(연결됨 · 후보 · 못 이음) · 단가산출 줄 = 가져온 식 SK 수식 탭 모달(Labor_SkEdit) · 서버 hopyo-view(M02_Hopyo_View)
- 엑셀 보기 목록 · 칠 = 줄 표지(View.listing) · 단가산출 탭 = 블록 목록 + [가져온 식으로 열기] · [내 단가산출로]
- 걷음(요구 703): 판정 체계 785(Judge · Solve · Bind · San_Basis 다섯 · Make.Move · Row 1차 판정 · 화면 Check · CheckRows · Rows · Block · JudgeApi · Picks · Judge.css) · [우리 기초로 바꾸기](to-base) · 근거 기초 제안 · Clause 기초 판정
- 시험 지움: 642_2(Bind · Solve) · 642_3(Row 1차 판정) · 642_5(옮기기 Move) · 642_6(판정 화면) · 786_2(옛 [수정] 모달) · 793_3a(근거 → 기초 제안) — 모두 걷은 기초 판정 길 몫
- 시험 고침: 642_1 · 794_2a2 · 794_2b(근거 제안 부분만 뺌) · 793_2 · 793_3b(기초 바꾸기 기대 → 없음) · 627 · 779_2 · 785_4 · 807_1 · m02_hopyo_excel · grid · stmate(judge 길 → view 길)
- 새 시험 test_809_1_import_labor(기초 길 0 · 표지 1,350 줄 · 가져온 식 SK · 모달 = Labor_Table · 금액 = 엑셀)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:17:58 +09:00

129 lines
4.9 KiB
JavaScript

/* 780-2 · 809-1 엑셀 보기 오른쪽 판 바꾸기 헬퍼 — stdin `{sheetSk: {...}}` = `Hopyo_SheetSk` 를 트랜스파일해 Node 로 돌림 ·
* 단가산출 칸 · 시트 막대 · 판은 가짜 · stdout = JSON. 옛 마법사 줄 고름(`SkPick` · `SkApi`)은 785-7 에서 지움. */
const fs = require("fs");
const path = require("path");
const { makeLoader } = require("./helper_ts_stub_loader.cjs");
const ROOT = path.join(__dirname, "..", "..");
const fakeEl = () => ({
hidden: false,
attrs: {},
kids: [],
setAttribute(k, v) {
this.attrs[k] = v;
},
append(x) {
this.kids.push(x);
},
});
const list = []; // 그린 목록 줄 벌
const reads = []; // 목록 읽음
const opened = []; // [가져온 식으로 열기]
const BRIEFS = [
{ 번: 8, 이름: "거푸집", 단위: "㎡", 부름: [1], SK: null, 판정: "가져온 식" },
{ 번: 9, 이름: "잡석", 단위: "㎥", 부름: [], SK: null, 판정: null },
{ 번: 10, 이름: "운반", 단위: "㎡", 부름: [2], SK: "SK-000001", 판정: "가져온 식" },
];
const STUBS = {
"@ui/ui_template_locale": { t: (k) => (k === "M02_JudgeBlock" ? "단산{n}" : k) },
"@ui/ui_template_badge": { createBadge: (text, tone) => `${tone}:${text}` },
"@ui/ui_template_text": { createText: (text) => text },
"@ui/ui_template_list_row": { createListRow: (opts) => ({ opts, dataset: {} }) },
"./M02_MasterTemplete_Hopyo_SheetNav": {
readHopyoMarks: async (scope, key, to) => {
reads.push({ key, to });
return BRIEFS;
},
},
"./M02_MasterTemplete_Hopyo_Imported": { openImported: (o) => opened.push(o) },
"@config/config_frontend": { API_BASE_URL: "/api", ROUTES: {} },
"@ui/ui_template_elements": {
createButton: (o) => ({ label: o.label, dataset: {}, hidden: false, click: () => o.onClick({ stopPropagation() {} }) }),
el: (tag, o = {}) => ({
...fakeEl(),
tag,
kids: o.children ?? [],
className: o.className,
replaceChildren(...kids) {
this.kids = kids;
if (kids.length && kids[0]?.opts) list.push(kids);
},
}),
},
};
const stub = new Proxy({}, { get: () => () => {} });
const { loadTs } = makeLoader({
root: ROOT,
requireFor: (full) => (request) => {
if (STUBS[request]) return STUBS[request];
if (request.startsWith(".") && !request.endsWith(".css"))
return loadTs(`${path.resolve(path.dirname(full), request)}.ts`);
return stub;
},
});
global.sessionStorage = { getItem: () => null, setItem: () => {}, removeItem: () => {} };
(async () => {
const input = JSON.parse(fs.readFileSync(0, "utf8"));
process.stdout.write(JSON.stringify(await sheetSk(input.sheetSk)));
})().catch((error) => {
process.stderr.write(String(error?.stack ?? error));
process.exit(1);
});
/** 780-2 · 809-1 판 바꾸기 — 탭(역할) 차례로 고름 · 판 숨김 · 목록 읽음 한 번 · 강조 · 줄 누름 = 뛰기 · 줄 끝 = 가져온 식 모달 */
async function sheetSk({ same, canWrite, picks }) {
const M02 = path.join(ROOT, "M02_MasterTemplete");
const { createSheetSk } = loadTs(path.join(M02, "M02_MasterTemplete_Hopyo_SheetSk.ts"));
const roles = { s1: "일위대가표", s2: "단가산출표", s3: "단가산출상세" };
const jumps = [];
const nav = {
role: (sheet) => roles[sheet],
blockAt: (sheet, row) =>
sheet === "s2" ? row - 4 : sheet === "s3" ? Math.floor(row / 10) : null,
spotOf: (no, role) => ({ 시트: role === "단가산출표" ? "s2" : "s3", 행: [no, no + 1] }),
jumpTo: (sheet, rows) => jumps.push([sheet, rows]),
};
const toggled = [];
const side = {
hidden: false,
after: () => {},
parentElement: { classList: { toggle: (c, on) => toggled.push([c, on]) } },
};
const scope = { layer: "personal", owner: null };
const target = same ? scope : { layer: "company", owner: null };
const p = createSheetSk({ scope, key: "HP-000001", target, canWrite, nav, side });
const seen = [];
const rows = () => list.at(-1) ?? [];
for (const [sheet, cell] of picks) {
p.at({ 시트: sheet, 칸: cell });
await new Promise((r) => setTimeout(r, 0));
const active = rows().find((r) => r.opts.active)?.opts.label ?? null;
seen.push({
호표판숨김: side.hidden,
단가판숨김: p.root.hidden,
읽음: reads.length,
강조: active,
});
if (sheet !== "s1") {
const row = rows().find((r) => r.opts.label.startsWith("단산8 "));
row?.opts.onClick();
row?.opts.trailing.kids.at(-2).click(); // [가져온 식으로 열기](만들 층)
}
}
return {
seen,
toggled,
jumps,
reads,
opened: opened.map((o) => ({ no: o.no, canWrite: o.canWrite, to: o.target.layer })),
rows: rows().map((r) => ({
label: r.opts.label,
sub: r.opts.sub,
stripe: r.opts.stripe,
tail: r.opts.trailing.kids.filter((k) => !k.hidden).map((k) => (typeof k === "string" ? k : k.label)),
})),
count: p.count(),
};
}