/** * STMATE w 8.0 — 메인 메뉴·툴바·단축키·자동백업·최근 작업폴더·화면 크기 동작 (ui_app_menu.js) * 메뉴 자료 = ui_menu.js(원본 M_Menu1 체계) · 동작 우선순위 = 끼워 넣기(STMATE_PLUGINS.actions) → 여기 H 표 * 설정 저장 = 브라우저 localStorage("stmate_ui_prefs") — 원본 Start8x.Ini 의 창 위치·보기 설정 자리 */ (function (global) { "use strict"; const M = global.STMATE_UI_MENU; const PREF_KEY = "stmate_ui_prefs"; const DEF = { autoBackDaily: false, autoBack30: false, prnPdf: false, useName2: false }; Object.assign(DEF, { dflIndex: "C", dflWidth: 40, screenMode: 0, scale: 100, recent: [] }); Object.assign(DEF, { lastBackDay: "", lastBack30: 0 }); function loadPrefs() { try { return Object.assign({}, DEF, JSON.parse(global.localStorage.getItem(PREF_KEY) || "{}")); } catch (_e) { return Object.assign({}, DEF); } } const prefs = loadPrefs(); const savePrefs = () => { try { global.localStorage.setItem(PREF_KEY, JSON.stringify(prefs)); } catch (_e) { // 저장 공간 없음 — 이번 실행 동안만 유지 } }; const pad = (n) => String(n).padStart(2, "0"); const today = () => { const d = new Date(); return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}`; }; const nowTag = () => { const d = new Date(); return `${today()}_${pad(d.getHours())}${pad(d.getMinutes())}`; }; let API = null; const PLUG = () => global.STMATE_PLUGINS || { screens: {}, actions: {}, menus: [] }; function go(screen) { API.ctx.uiState.activeScreen = screen; API.renderWorkspace(); } // 백업 — 계산 결과 저장 묶음을 「프로젝트_백업_날짜」 폴더·STC 로(서버 work_dbf) async function backup(kind) { const { ctx } = API; if (!ctx.dbfData || !ctx.currentSourcePath) return alert("열린 프로젝트가 없음"); API.recompute(); const payload = global.STMATE_VIEW_PRJ_BOQ.buildSavePayload(ctx); API.decorateSavePayload(payload); const base = String(payload.target_folder_name || "stmate").slice(0, 20); payload.target_folder_name = `${base}_백업_${kind === "day" ? today() : nowTag()}`; try { const res = await API.postJson("/api/save", payload); if (kind === "day") prefs.lastBackDay = today(); if (kind === "30") prefs.lastBack30 = Date.now(); savePrefs(); return res; } catch (err) { alert("자동백업 실패: " + err.message); return null; } } // 재계산 뒤 30분 백업 async function afterCalc() { if (prefs.autoBack30 && Date.now() - (prefs.lastBack30 || 0) >= 30 * 60 * 1000) await backup("30"); } function applyView() { const shell = document.getElementById("stmate-shell"); if (shell) shell.setAttribute("data-screen-mode", String(prefs.screenMode)); const ws = document.getElementById("mdi-workspace"); if (ws) ws.style.zoom = prefs.scale === 100 ? "" : `${prefs.scale}%`; document.documentElement.style.setProperty("--stm-name-w", `${prefs.dflWidth * 7}px`); } function quit(withBackup) { const finish = () => { API.ctx.uiState.activeScreen = "wQuit"; API.renderWorkspace(); }; if (withBackup && prefs.autoBackDaily && prefs.lastBackDay !== today()) return backup("day").then(finish); finish(); } const toggle = (k) => () => ((prefs[k] = !prefs[k]), savePrefs(), render()); const radio = (k, v) => () => ( (prefs[k] = v), savePrefs(), applyView(), render(), API.renderWorkspace() ); const H = { Act_Maneger: () => go("wPrjMgr"), Act_Sys: () => go("wM_Set_Sys"), Act_Dan: () => go("wM_JabPum"), Act_iLWi_San: () => go("wM_Edit_iLWi"), Act_PrjLst: () => go("wPrjList"), Act_Prt: () => go("PM_Prt"), Act_Calc_Grass: async () => (await API.saveAll(), afterCalc()), Act_Calc_All: () => (API.cascadeAndRender(), afterCalc()), Act_Refresh: () => API.ctx.currentSourcePath && API.loadProjectFromServer(API.ctx.currentSourcePath), Act_Arc_Project: () => API.saveAll(), Act_Close_Table: () => { Object.assign(API.ctx, { state: API.Calc.createDefaultState(), dbfData: null, currentSourcePath: "", }); go("wPrjMgr"); }, mi_AutoBack: toggle("autoBackDaily"), mi_Auto_Time_Back: toggle("autoBack30"), Act_Arc_Now: async () => { const r = await backup("now"); if (r) alert(`현재상태 백업 완료\n• 폴더: ${r.saved_dir}\n• 압축: ${r.saved_stc}`); }, mi_Del_Recent: () => ((prefs.recent = []), savePrefs(), render()), Act_Open_Recent: (btn) => API.loadProjectFromServer(btn.getAttribute("data-path"), "wPrjList"), Act_Quit: () => quit(true), Act_Halt: () => quit(false), Act_UseName2: toggle("useName2"), N44: () => ((prefs.scale = 100), (prefs.screenMode = 0), savePrefs(), applyView(), render()), N55: () => { Object.assign(API.ctx.uiState, { boqLevelFilter: "ALL", boqSearch: "", boqLevelMin: 0, boqSel: [], }); API.renderWorkspace(); }, Act_information: () => { const c = API.ctx; const files = (c.dbfData && c.dbfData.file_list) || []; API.openModal( "제품 및 기타정보", `
STMATE w 8.0 재현판 — 원본 메뉴·화면 체계를 웹으로 다시 만든 시험판
열린 프로젝트: ${M.esc(c.currentSourcePath || "(없음)")}
자료 파일 ${files.length}개: ${M.esc(files.join(" · "))}
설정 저장: 브라우저(localStorage) · 자동백업 폴더: 서버 work_dbf