/** * STMATE w 8.0 — 조달청포맷(TEXT,JDL) 생성·검사 끼워 넣기 (scr_jdl.js) · 1번(파일) 메뉴 * 원본: ST_U_Convert Conv_ST8_Jodal(「조달청포맷(TEXT,JDL) 생성」) · JDLCHK.Tab_33.dll JDLCheck * 서버: api_jdl.py — 묶음 요약 · zip 받기 · 받은 묶음 검사(열 개수 · 코드 글자) */ (function (global) { "use strict"; const PLUG = (global.STMATE_PLUGINS = global.STMATE_PLUGINS || { screens: {}, actions: {}, menus: [], }); const app = () => global.STMATE_APP; async function req(url, body, raw) { const res = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); if (!res.ok) throw new Error(await res.text()); return raw ? res.blob() : res.json(); } function curPath(ctx) { if (!ctx.currentSourcePath) throw new Error("먼저 프로젝트를 불러오세요."); return ctx.currentSourcePath; } function download(blob, name) { const a = document.createElement("a"); a.href = URL.createObjectURL(blob); a.download = name; document.body.appendChild(a); a.click(); setTimeout(() => (URL.revokeObjectURL(a.href), a.remove()), 1000); } function pickFiles() { return new Promise((resolve, reject) => { const inp = document.createElement("input"); inp.type = "file"; inp.multiple = true; inp.accept = ".txt,.TXT"; inp.onchange = async () => { const list = Array.from(inp.files || []); if (!list.length) return reject(new Error("파일을 고르지 않음")); const out = {}; for (const f of list) out[f.name] = await new Promise((ok, no) => { const rd = new FileReader(); rd.onload = () => ok(String(rd.result)); rd.onerror = () => no(rd.error); rd.readAsDataURL(f); }); resolve(out); }; inp.click(); }); } function summary(r) { const lines = Object.entries(r.counts).map(([k, v]) => { const e = (r.checks[k] || []).length; return `${k}: ${v}줄${e ? ` · 오류 ${e}` : ""}`; }); const warn = r.warnings.length ? `\n\n[알림]\n${r.warnings.slice(0, 8).join("\n")}` : ""; return ( `계열 ${r.series} (PCLASS ${r.pclass})\n${lines.join("\n")}` + `${warn}\n\n[아직 못 만드는 것 — 원본 규칙 미확인]\n${r.missing.join("\n")}` ); } const ACTS = { async jdlExport(ctx) { const body = { source_path: curPath(ctx) }; const r = await req("/api/jdl/export", body); if (!confirm(`[조달청포맷(TEXT,JDL) 생성]\n${summary(r)}\n\n묶음 파일을 zip 으로 받을까요?`)) return; const name = (ctx.state.projectMeta.pname || "공사").slice(0, 28); download(await req("/api/jdl/export.zip", body, true), `${name}_JDL_TEXT.zip`); }, async jdlCheck() { const files = await pickFiles(); const r = await req("/api/jdl/check", { files }); const text = Object.entries(r.checks) .map(([k, v]) => `${k}: ${v.length ? v.slice(0, 20).join("\n ") : "통과"}`) .join("\n"); alert(`[JDL 파일 오류검사]\n${text}`); }, }; async function run(act) { try { await ACTS[act](app().ctx); } catch (err) { alert("JDL 처리 실패: " + err.message); } } [ ["Act_JdlExport", "조달청포맷(TEXT,JDL) 생성", "jdlExport"], ["Act_JdlCheck", "JDL 파일 오류검사 (JDLCheck)", "jdlCheck"], ].forEach(([act, label, key]) => { PLUG.actions[act] = () => run(key); PLUG.menus.push({ menu: "m1", label, act }); }); })(window);