/** * STMATE w 8.0 — 파일 작업 끼워 넣기 (scr_file.js) · 공사목록표 단추와 1번 메뉴 * 복사등록(차수/단계 변환) · 해당분만 압축(.STC) · 새 공사 · STC 구조·버전 검사(Chk_STC_Ver) · 백업·복원(wM_D_Restore) * 서버: api_file.py — 쓰기는 work_dbf/ 아래만 · 단추는 data-file-act 로 문서 전체에서 받음 */ (function (global) { "use strict"; const PLUG = (global.STMATE_PLUGINS = global.STMATE_PLUGINS || { screens: {}, actions: {}, menus: [], }); const app = () => global.STMATE_APP; async function post(url, body) { const res = await fetch(url, { method: body === undefined ? "GET" : "POST", headers: { "Content-Type": "application/json" }, body: body === undefined ? undefined : JSON.stringify(body), }); if (!res.ok) throw new Error(await res.text()); return res.json(); } const curPath = (ctx) => { if (!ctx.currentSourcePath) throw new Error("먼저 프로젝트를 불러오세요."); return ctx.currentSourcePath; }; const pickedPcode = (ctx) => { const el = document.querySelector('input[name="prj-pcode"]:checked'); const pc = el ? el.value : ctx.uiState.filePcode || "11"; ctx.uiState.filePcode = pc; return pc; }; async function openSaved(path) { const a = app(); const src = await post("/api/sources"); if (src && src.projects) a.ctx.sourcesData = src; const sel = document.getElementById("top-project-select"); if (sel && src && src.projects) sel.innerHTML = src.projects .map((p) => ``) .join(""); await a.loadProjectFromServer(path, "wPrjList"); } const ACTS = { async check(ctx) { const r = await post("/api/file/check", { source_path: curPath(ctx) }); const t = Object.entries(r.tables || {}) .map(([n, h]) => `${n} v${h.ver.toString(16)} ${h.nfield}칸 ${h.nrec}행`) .join("\n"); alert( `[STC 검사] ${r.ok ? "이상 없음" : "문제 있음"} · ${r.edition}\n${(r.problems || []).join("\n")}\n\n${t}`, ); }, async pack(ctx) { const pc = pickedPcode(ctx); const name = prompt( `BOQ${pc} 공사만 담은 STC 이름:`, `${ctx.state.projectMeta.pname || "공사"}_${pc}`, ); if (!name) return; const r = await post("/api/file/pack", { source_path: curPath(ctx), pcode: pc, target_name: name, }); alert(`[해당분만 압축] ${r.saved_stc} (${r.stc_size}B)`); }, async copy(ctx) { const pc = pickedPcode(ctx); const mode = prompt( `BOQ${pc} 복사등록 방식 — copy(그대로) · change(변경 차수 변환) · contract(계약 변환):`, "change", ); if (!mode) return; const body = { source_path: curPath(ctx), src_pcode: pc, mode: mode.trim() }; if (body.mode === "contract") { const r = prompt("단가 적용율 % — 재료,노무,경비:", "87.745,87.745,87.745"); if (!r) return; const [M, L, S] = r.split(",").map((x) => parseFloat(x) || 0); body.rates = { M, L, S }; } const res = await post("/api/file/copy-register", body); alert(`[복사등록] 새 공사 BOQ${res.new_pcode} · ${res.saved_dir}`); await openSaved(res.saved_dir); }, async new(ctx) { const pname = prompt("새 공사명:", ""); if (!pname) return; const res = await post("/api/file/new", { template_path: curPath(ctx), pname }); alert(`[새 공사] 틀(요율·서식·설정)은 지금 공사에서, 내역·단가는 빈 채로 · ${res.saved_dir}`); await openSaved(res.saved_dir); }, async backups(ctx) { const nm = (ctx.state.projectMeta.pname || "").slice(0, 28); const r = await post(`/api/file/backups?name=${encodeURIComponent(nm)}`); const list = r.backups || []; if (!list.length) return alert("[백업] 이 공사 이름의 작업본 백업이 없습니다."); const pick = prompt( `[백업 ${list.length}벌] 되돌릴 번호(취소 = 닫기):\n` + list.map((b, i) => `${i + 1}. ${b.stamp} (${b.size}B)`).join("\n"), "1", ); const b = list[parseInt(pick, 10) - 1]; if (!b) return; const res = await post("/api/file/restore", { backup_path: b.path, target_folder_name: b.name, }); await openSaved(res.saved_dir); }, }; async function run(act) { try { await ACTS[act](app().ctx); } catch (err) { alert("파일 작업 실패: " + err.message); } } document.addEventListener("click", (e) => { const el = e.target && e.target.closest && e.target.closest("[data-file-act]"); if (!el || !ACTS[el.getAttribute("data-file-act")]) return; e.preventDefault(); run(el.getAttribute("data-file-act")); }); document.addEventListener("change", (e) => { if (e.target && e.target.name === "prj-pcode") app().ctx.uiState.filePcode = e.target.value; }); [ ["Act_FileCopyReg", "복사등록 — 차수/단계 변환", "copy"], ["Act_FilePack", "해당분만 압축하기 (.STC)", "pack"], ["Act_FileNew", "새 공사 만들기", "new"], ["Act_FileCheck", "STC 구조·버전 검사 (Chk_STC_Ver)", "check"], ["Act_FileRestore", "작업본 백업·복원 (wM_D_Restore)", "backups"], ].forEach(([act, label, key]) => { PLUG.actions[act] = () => run(key); PLUG.menus.push({ menu: "m1", label, act }); }); })(window);