/** * STMATE w 8.0 — 메인 메뉴(M_Menu1)·툴바(Tool_Bar) 원본 체계 (ui_menu.js) · 순수 자료·HTML 생성 * 근거: REA 분석/09_보조분석_화면저장구조/artifacts/resource-TWM_STMATE_START_8X.dfm.json * 메뉴 항목 캡션 = TMenuItem.Caption 또는 연결 TAction.Caption · 단축키 = TAction.ShortCut * Visible=False 항목(급수설계·전산내역 입찰·K 분류·도움말·팁·MS-DOS 실행 등)은 원본도 숨김 → 넣지 않음 * 범위 밖(유지보수 신청·업그레이드·원격지원·홈페이지·모니터 이동 등)은 꺼진 항목으로 둠 */ (function (global) { "use strict"; const SEP = { sep: true }; const OUT = "범위 밖(인증·업데이트·외부 연결)"; const it = (act, cap, extra) => Object.assign({ act, cap }, extra || {}); const MENU_TREE = [ { id: "m1", cap: "1. 프로젝트/초기값", key: "1", kids: [ it("Act_Maneger", "프로젝트 관리", { hint: "프로젝트 관리 [ 열기, 등록, 백업, 삭제 ]" }), it("Act_Sys", "초기값 입력및수정 (환율/소수점)", { hint: "초기값 입력 및 수정[ 환율 및 기초자료 ]", }), SEP, it("Act_Calc_Grass", "계 산 완 료", { sc: 120, hint: "수정분 계산" }), it("Act_Calc_All", "전체 재계산", { hint: "전체 재계산" }), it("Act_Refresh", "작업파일 다시 읽기", { sc: 16500, hint: "모든 테이블 다시 읽기" }), SEP, it("Act_Arc_Project", "현재프로젝트 압축하기"), it("Act_Close_Table", "프로젝트(작업파일) 닫기"), SEP, it("mi_AutoBack", "종료시 프로젝트 자동백업(1일단위)", { check: "autoBackDaily" }), it("mi_Auto_Time_Back", "30분마다 자동백업(재계산시)", { check: "autoBack30" }), it("Act_Arc_Now", "현재상태 자동백업"), SEP, { id: "mi_Recent", cap: "최근 작업폴더", recent: true, kids: [it("mi_Del_Recent", "최근목록 지우기"), SEP], }, SEP, it("Act_Quit", "시스템종료", { sc: 32849, hint: "시스템 종료[ STmate 종료 ]" }), it("Act_Halt", "프로그램 강제종료"), ], }, { id: "m2", cap: "2. 단가표/대가표", key: "2", kids: [ it("Act_Dan", "단가목록표(전체분)", { sc: 16449, hint: "단가목록표[기초단가 등록 및 수정]", }), it("Act_iLWi_San", "일위대가표,중기사용료,단가산출근거", { sc: 16450, hint: "대가,산근[ 일위대가, 단가산출근거, 중기사용료]", }), ], }, { id: "m3", cap: "3. 내역서/인쇄", key: "3", kids: [ it("Act_PrjLst", "공사목록표", { sc: 16462, hint: "공사목록표[내역서 입력 및 수정)" }), it("Act_Prt", "보고서 인쇄", { sc: 24656, hint: "모든 보고서 인쇄" }), SEP, it( "Act_P_2PDF", "보고서 저장파일 ∥ SRP( 체크해제 ) ⇔ PDF【 Microsoft Print to PDF 】( √ 체크 )", { check: "prnPdf", }, ), it("Act_Un_Dir", "보고서 저장폴더 미지정(마지막 저장폴더로 설정)"), ], }, { id: "m4", cap: "4. 도구", key: "4", kids: [ { id: "mi_Merge", cap: "데이타병합 【 현재폴더(복사처) ← 다른폴더(복사원) 】", kids: [ it("Act_Merge", "동일항목 : 호환규정코드 or 시설코드 or 명칭..단위로 인식"), it("Act_Merge_C", "동일항목 : 코드번호로 인식(두 프로젝트의 코드번호가 같을때)"), ], }, it("Act_Conv_Equip8", "하위버젼 중기비내역 형식 → 2Y.m형식으로.."), SEP, { id: "mi_ManageFile", cap: "파 일 관 리", kids: [ { id: "N14", cap: "코드변경", kids: [ it("Act_Chg_Code_Sel", "1. 선택 변경"), it("Act_Chg_Code_All", "2. 일괄 변경"), it("Act_Chg_Plus", "3. 코드번호 변경 ( 현재코드 + α )"), ], }, { id: "N15", cap: "코드삭제", kids: [ it("Act_Del_Code_Sel", "1. 선택 삭제"), SEP, it("Act_Del_Code_All_Minus", "2. 일괄 삭제 (중기비제외)"), it("Act_Del_Code_All_Plus", "3. 일괄 삭제 (중기비포함)"), ], }, it("Act_Chg_Item", "항목교체(내역포함)"), SEP, it("Act_Del_Prj", "내역서 삭제"), it("Act_Mer_Prj", "내역서 병합"), SEP, it("Act_1st_2nd", "당초단가 ⇒ 변경단가(당초단가 적용)"), it("Act_2nd_1st", "변경단가 ⇒ 당초단가(변경단가 적용)"), ], }, { id: "mi_UseName2", cap: "보조 명칭/규격 관리", kids: [ it("Act_UseName2", "보조 명칭/규격 사용", { check: "useName2" }), SEP, it("Act_Ch_1ST_2ND", "메인명칭/규격 ⇔ 보조명칭/규격(서로바꾸기)"), SEP, it("Act_Ch_Blank_2ND", "보조명칭/규격 초기화"), ], }, { id: "mi_Index", cap: "자료파일 인덱스", kids: [ it("Act_Indx", "인덱스파일 복구"), SEP, it("Act_Indx_N", "명칭 인덱스( 명칭 )"), it("Act_Indx_NS", "명칭 인덱스( 명칭 + 규격 )"), ], }, { id: "N74", cap: "목록표 기본정렬 기준 / 명칭,규격 넓이", kids: [ it("Act_DFL_INDX_C", "코드번호순 기본정렬", { radio: ["dflIndex", "C"] }), it("Act_DFL_INDX_N", "명 칭 순 기본정렬", { radio: ["dflIndex", "N"] }), it("Act_DFL_INDX_I", "분류번호순 기본정렬", { radio: ["dflIndex", "I"] }), it("Act_DFL_INDX_E", "시설코드순 기본정렬", { radio: ["dflIndex", "E"] }), SEP, ...[20, 30, 40, 50, 60].map((w) => it(`Act_DFL_WIDTH_${w}`, `명칭,규격 ${w}Byte 넓이정렬`, { radio: ["dflWidth", w] }), ), ], }, { id: "N30Byte2", cap: "명칭, 규격 30Byte 이상 인쇄설정 (엑셀제외)", kids: [ it("Act_PRN_1LN", "글자수에 관계없이 한줄로 인쇄"), SEP, it("Act_PRN_2LN_30", "30Byte 이상 두줄인쇄"), it("Act_PRN_2LN_40", "40Byte 이상 두줄인쇄"), it("Act_PRN_2LN_50", "50Byte 이상 두줄인쇄"), ], }, it("Act_Restore", "자료파일 복원"), it("Act_Del_TrashFile", "불필요한 하위버전 흔적파일 정리"), SEP, it("Act_Auto_Jod", "조달청제출용 일위대가 자동수정(손료부분,산근제외)"), it("Act_Find_Jod", "조달청제출용 일위대가 내용검증(손료부분,산근포함)"), it("Act_Find_XML", "조달청제출용 대가/산근 내용검증(XML, 손료부분 or 대가수량소수점)"), SEP, { id: "N54", cap: "정보/설정 초기화", kids: [ it("N44", '모든 "위치정보" 초기화'), it("N55", '내역서 "보기설정" 초기화'), it("N56", '산근/대가 "문법및정렬기준" 초기화'), SEP, it("mi_MemSize", "메모리사용량 초기화"), ], }, ], }, { id: "m5", cap: "5. 기타", key: "5", kids: [ it("Act_information", "제품 및 기타정보"), it("Act_Req_AS", "유지보수(A/S)연장 신청", { out: true }), SEP, it("Act_Down_Center", "다운로드 센터(기초자료)", { out: true }), SEP, { id: "N32", cap: "홈페이지 접속", kids: [it("Act_Home", "경영정보(주) - http://www.stma.co.kr", { out: true })], }, it("Act_ReqQS", "원격지원 요청", { out: true }), it("Window1", "윈도우 탐색기", { sc: 16471, out: true }), SEP, it("mi_Auto_Up_Chk", "프로그램 시작시 제품UpGrade 자동확인", { out: true }), it("Act_UpGrade", "UpGrade 정보확인", { out: true }), it("Act_Gongji", "STmate 공지사항 확인", { out: true }), it("Act_Dn_Fld", "다운로드폴더 탐색기로열기", { out: true }), SEP, { id: "mi_SetScreen", cap: "메인윈도우 화면선택", kids: [ it("Act_SetScreen", "메인윈도우 화면변경", { sc: 24653 }), SEP, it("Act_SetScreen_0", "메인윈도우 전체화면 보기", { radio: ["screenMode", 0] }), it("Act_SetScreen_1", "메인윈도우 중간화면 보기", { radio: ["screenMode", 1] }), it("Act_SetScreen_2", "메인윈도우 작은화면 보기", { radio: ["screenMode", 2] }), it("Act_SetScreen_3", "메인윈도우 크기조절화면 보기", { radio: ["screenMode", 3] }), ], }, { id: "miMonitor", cap: "모니터 이동", kids: [ it("miMonitor_0", "주 모니터", { out: true }), it("miMonitor_1", "보조모니터 1", { out: true }), it("miMonitor_2", "보조모니터 2", { out: true }), ], }, { id: "mi_Scale_UD", cap: "주요화면 크기 변경", kids: [ it("Act_Scale_Dfl", "주요화면 크기 100% 설정", { sc: 57392 }), SEP, it("Act_Scale_Up", "주요화면 크기(25% 증가)", { sc: 57382 }), it("Act_Scale_Dn", "주요화면 크기(25% 감소) ", { sc: 57384 }), ], }, ], }, ]; // 툴바 — Act_Maneger · Act_Sys | Act_Dan · Act_iLWi_San | Act_PrjLst · Act_Prt | 계 산 완 료 | 시스템종료 const TOOLBAR = [ { act: "Act_Maneger", screen: "wPrjMgr", cap: "프로젝트관리", ico: "🗂️" }, { act: "Act_Sys", screen: "wM_Set_Sys", cap: "초 기 값", ico: "⚙️" }, SEP, { act: "Act_Dan", screen: "wM_JabPum", cap: "단가목록표", ico: "📋" }, { act: "Act_iLWi_San", screen: "wM_Edit_iLWi", cap: "대 가 표", ico: "🧮" }, SEP, { act: "Act_PrjLst", screen: "wPrjList", cap: "공사목록표", ico: "📁" }, { act: "Act_Prt", screen: "PM_Prt", cap: "보고서인쇄", ico: "🖨️" }, SEP, { act: "Act_Calc_Grass", id: "btn-calc-all", cap: "계 산 완 료", ico: "⚡", hint: "수정분 계산", }, SEP, { act: "Act_Quit", cap: "시스템종료", ico: "⏻" }, ]; // 단축키 — Delphi ShortCut(하위 바이트 = 가상키 · 0x2000 Shift · 0x4000 Ctrl · 0x8000 Alt) const VK = { 13: "Enter", 38: "Up", 40: "Down", 45: "Ins", 46: "Del" }; function decodeShortcut(sc) { if (!sc) return ""; const vk = sc & 0xff, parts = []; if (sc & 0x4000) parts.push("Ctrl"); if (sc & 0x2000) parts.push("Shift"); if (sc & 0x8000) parts.push("Alt"); let k = VK[vk]; if (!k && vk >= 112 && vk <= 123) k = "F" + (vk - 111); if (!k && ((vk >= 48 && vk <= 57) || (vk >= 65 && vk <= 90))) k = String.fromCharCode(vk); parts.push(k || `#${vk}`); return parts.join("+"); } // 키 누름 → 단축키 문자열(decodeShortcut 과 같은 꼴) function eventShortcut(e) { const parts = []; if (e.ctrlKey) parts.push("Ctrl"); if (e.shiftKey) parts.push("Shift"); if (e.altKey) parts.push("Alt"); const k = e.key === "ArrowUp" ? "Up" : e.key === "ArrowDown" ? "Down" : e.key; parts.push(/^[a-z]$/.test(k) ? k.toUpperCase() : k === ")" ? "0" : k); return parts.join("+"); } // 단축키 → 동작 표 function shortcutMap(tree) { const map = {}; const walk = (list) => list.forEach((n) => { if (n.sc && n.act) map[decodeShortcut(n.sc)] = n.act; if (n.kids) walk(n.kids); }); walk(tree || MENU_TREE); return map; } const esc = (s) => String(s == null ? "" : s).replace( /[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c], ); /** * 메뉴 HTML — st = { enabled(act) · checked(node) · recent: [{path,name}] } * 이어진 구분선·앞뒤 구분선은 한 줄로 · 꺼진 항목은 disabled + 까닭(title) */ function renderItems(kids, st) { const out = []; let lastSep = true; kids.forEach((n) => { if (n.sep) { if (!lastSep) out.push("
"); lastSep = true; return; } lastSep = false; if (n.kids) { const extra = n.recent ? (st.recent || []) .map( (r) => ``, ) .join("") || '' : ""; out.push( ``, ); return; } const on = !n.out && st.enabled(n.act); const mark = n.check || n.radio ? (st.checked(n) ? "✔" : "") : ""; const why = n.out ? OUT : on ? n.hint || "" : "아직 만들지 않은 기능"; out.push( ``, ); }); while (out.length && out[out.length - 1] === "
") out.pop(); return out.join(""); } function renderMenuBar(st, tree) { return (tree || MENU_TREE) .map( (m) => ``, ) .join(""); } function renderToolbar(active) { return TOOLBAR.map((b) => b.sep ? '
' : ``, ).join(""); } // 모든 동작 이름(꺼짐 판정·시험용) function allActs(tree) { const acts = []; const walk = (list) => list.forEach((n) => (n.act && acts.push(n.act), n.kids && walk(n.kids))); walk(tree || MENU_TREE); return acts; } global.STMATE_UI_MENU = { MENU_TREE, TOOLBAR, decodeShortcut, eventShortcut, shortcutMap, renderMenuBar, renderToolbar, allActs, esc, }; if (typeof module !== "undefined" && module.exports) module.exports = global.STMATE_UI_MENU; })(typeof window !== "undefined" ? window : globalThis);