diff --git a/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp b/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp index 930133d..911b472 100644 --- a/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp +++ b/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp @@ -3,7 +3,7 @@ <%@ page import="com.pms.common.utils.*"%> <%@ page import="java.util.*"%> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> -<%@include file="/init.jsp"%> +<%@include file="/init_new.jsp"%> <% PersonBean person = (PersonBean) session.getAttribute(Constants.PERSON_BEAN); String userId = CommonUtils.checkNull(person.getUserId()); @@ -888,7 +888,7 @@
-
+

영업관리_견적관리_견적요청등록

diff --git a/WebContent/WEB-INF/view/contractMgmt/supplyRegistPopUp.jsp b/WebContent/WEB-INF/view/contractMgmt/supplyRegistPopUp.jsp index 2a8b071..fcea563 100644 --- a/WebContent/WEB-INF/view/contractMgmt/supplyRegistPopUp.jsp +++ b/WebContent/WEB-INF/view/contractMgmt/supplyRegistPopUp.jsp @@ -2,7 +2,7 @@ <%@ page import="com.pms.common.utils.*"%> <%@ page import="java.util.*" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> -<%@include file= "/init.jsp" %> +<%@include file= "/init_new.jsp" %> diff --git a/WebContent/WEB-INF/view/main/header.jsp b/WebContent/WEB-INF/view/main/header.jsp index 9bf5e07..2e494b6 100644 --- a/WebContent/WEB-INF/view/main/header.jsp +++ b/WebContent/WEB-INF/view/main/header.jsp @@ -126,12 +126,12 @@ $(function(){ $(".menu").hover( function() { if (!$(this).hasClass('menu_on')) { - $(this).css('background-color', '#E08550'); + $(this).css('background-color', '#003399'); } }, function() { if (!$(this).hasClass('menu_on')) { - $(this).css('background-color', '#F29661'); + $(this).css('background-color', '#0011ff'); } } ); diff --git a/WebContent/WEB-INF/view/main/menu.jsp b/WebContent/WEB-INF/view/main/menu.jsp index f42fe86..731802f 100644 --- a/WebContent/WEB-INF/view/main/menu.jsp +++ b/WebContent/WEB-INF/view/main/menu.jsp @@ -151,6 +151,7 @@ function fn_alert(){ } function fn_initMenuArea(){ $("#menu").empty(); + $('#forced-menu').remove(); // 강제로 추가된 메뉴도 제거 } function fnm_changeContentsLocation(url, menuObjId, obj){ @@ -179,12 +180,10 @@ function fnm_changeContentsLocation(url, menuObjId, obj){ function add_menu(objid, subMenuObjid, onlyViewMenu){ //Swal.fire("add_menu : " + objid + ":" + subMenuObjid + ":" + onlyViewMenu); - console.log("=== add_menu 함수 시작 ==="); - console.log("Parameters:", {objid: objid, subMenuObjid: subMenuObjid, onlyViewMenu: onlyViewMenu}); var menu =""; if(fnc_isNotEmpty(objid)){ - console.log("objid가 비어있지 않음, AJAX 호출 시작"); + //console.log("objid가 비어있지 않음, AJAX 호출 시작"); $.ajax({ url:"/main/getmenu.do", type:"POST", @@ -192,9 +191,9 @@ function add_menu(objid, subMenuObjid, onlyViewMenu){ dataType:"json", async:false, success:function(data){ - console.log("AJAX 응답 성공:", data); + //console.log("AJAX 응답 성공:", data); if(data.RESULT && data.RESULT.length>0){ - console.log("메뉴 아이템 개수:", data.RESULT.length); + //console.log("메뉴 아이템 개수:", data.RESULT.length); for(var i=0;i"+data.RESULT[i].MENU_NAME_KOR+"
"; /* @@ -216,28 +215,36 @@ function add_menu(objid, subMenuObjid, onlyViewMenu){ menu +=""; } - console.log("메뉴 생성:", data.RESULT[i].MENU_NAME_KOR, "Level:", lev); + // console.log("메뉴 생성:", data.RESULT[i].MENU_NAME_KOR, "Level:", lev); //menu +=""; //} } } - console.log("생성된 메뉴 HTML 길이:", menu.length); - console.log("생성된 메뉴 HTML:", menu.substring(0, 200) + "..."); + //console.log("생성된 메뉴 HTML 길이:", menu.length); + //console.log("생성된 메뉴 HTML:", menu.substring(0, 200) + "..."); }, error: function(jqxhr, status, error){ console.log("AJAX 오류:", error); } }); } else { - console.log("objid가 비어있음, sel_menu 호출"); + //console.log("objid가 비어있음, sel_menu 호출"); } console.log("DOM 추가 전 - 메뉴 HTML 길이:", menu.length); + + // 기존 메뉴 완전히 제거 + $("#menu").empty(); + $('#forced-menu').remove(); // 강제로 추가된 메뉴도 제거 + $('#menu').addClass('clickable'); $("#menu").append(menu); // 메뉴를 강제로 표시 (원래 위치에 맞게) if(menu.length > 0) { + // 기존 강제 메뉴가 있다면 제거 + $('#forced-menu').remove(); + // 기존 메뉴 프레임의 위치 정보 가져오기 var menuFrame = window.frameElement; var frameRect = menuFrame ? menuFrame.getBoundingClientRect() : {left: 0, top: 0}; diff --git a/WebContent/WEB-INF/view/releaseMgmt/releaseMgmtFormSimplePopUp.jsp b/WebContent/WEB-INF/view/releaseMgmt/releaseMgmtFormSimplePopUp.jsp index 9782b62..642feac 100644 --- a/WebContent/WEB-INF/view/releaseMgmt/releaseMgmtFormSimplePopUp.jsp +++ b/WebContent/WEB-INF/view/releaseMgmt/releaseMgmtFormSimplePopUp.jsp @@ -2,7 +2,7 @@ <%@ page import="com.pms.common.utils.*"%> <%@ page import="java.util.*" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> -<%@include file= "/init.jsp" %> +<%@include file= "/init_new.jsp" %> <% PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN); String userId = CommonUtils.checkNull(person.getUserId()); diff --git a/WebContent/css/basic_new.css b/WebContent/css/basic_new.css new file mode 100644 index 0000000..55bcd0c --- /dev/null +++ b/WebContent/css/basic_new.css @@ -0,0 +1,1075 @@ +/* Modern PLM System CSS - 2025 Redesign */ +/* 깔끔하고 전문적인 업무용 시스템 디자인 */ + +:root { + --primary-color: #3b82f6; + --primary-hover: #2563eb; + --primary-light: #dbeafe; + --secondary-color: #64748b; + --success-color: #10b981; + --danger-color: #ef4444; + --warning-color: #f59e0b; + --background: #f8fafc; + --surface: #ffffff; + --border-color: #e2e8f0; + --text-primary: #1e293b; + --text-secondary: #64748b; + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --radius-sm: 6px; + --radius-md: 8px; + --radius-lg: 12px; +} + +/* 기본 바디 스타일 - 깔끔한 배경 */ +body { + background: var(--background); + min-height: 100vh; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', Roboto, 'Helvetica Neue', Arial, sans-serif; + color: var(--text-primary); + line-height: 1.6; + margin: 0; + padding: 20px; +} + +/* 부드러운 페이드인 애니메이션 */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* 메인 섹션 스타일 */ +section, aside { + background: var(--surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + margin: 0 auto 20px; + padding: 0; + box-shadow: var(--shadow-sm); + max-width: 1200px; + animation: fadeIn 0.3s ease-out; +} + +/* 팝업 최소 너비 설정 */ +.business_popup_min_width { + min-width: 800px; +} + +/* 날짜 입력 필드 스타일 */ +.date_icon { + background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E") no-repeat right 6px center; + background-size: 12px; + padding-right: 26px !important; + cursor: pointer; +} + +/* 페이지 제목 스타일 - 파란 배경 (모든 방식으로 최우선 적용) */ +html body section .plm_menu_name h2, +html body .plm_menu_name h2, +body section .plm_menu_name h2, +body .plm_menu_name h2, +section .plm_menu_name h2, +div.plm_menu_name h2, +.plm_menu_name > h2, +.plm_menu_name h2 { + background: #3b82f6 !important; + background-color: #3b82f6 !important; + background-image: linear-gradient(135deg, #4285f4 0%, #3b82f6 100%) !important; + color: #ffffff !important; + padding: 16px 24px !important; + margin: 0 !important; + font-size: 16px !important; + font-weight: 600 !important; + border: none !important; + border-bottom: none !important; + border-top: none !important; + border-left: none !important; + border-right: none !important; + border-radius: 12px 12px 0 0 !important; + display: flex !important; + align-items: center !important; + position: relative !important; + box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15) !important; +} + +html body section .plm_menu_name h2 span, +html body .plm_menu_name h2 span, +body section .plm_menu_name h2 span, +body .plm_menu_name h2 span, +section .plm_menu_name h2 span, +div.plm_menu_name h2 span, +.plm_menu_name > h2 > span, +.plm_menu_name h2 > span, +.plm_menu_name h2 span { + display: flex !important; + align-items: center !important; + gap: 0 !important; + flex: 1 !important; + color: #ffffff !important; + background: transparent !important; + background-color: transparent !important; +} + +/* 섹션 제목 스타일 - 중간 영역의 서브 타이틀 */ +#businessPopupFormWrap h4 { + background: white; + color: var(--text-primary); + padding: 8px 16px; + margin: 0 0 8px 0; + font-size: 13px; + font-weight: 600; + border-bottom: 1px solid #e2e8f0; + border-left: none; + display: flex; + align-items: center; + position: relative; +} + +#businessPopupFormWrap h4 span { + display: flex; + align-items: center; + gap: 6px; + flex: 1; +} + +#businessPopupFormWrap h4 span::before { + content: '📎'; + font-size: 14px; + flex-shrink: 0; +} + +/* 중첩된 businessPopupFormWrap 스타일 */ +.input_sub_title #businessPopupFormWrap { + padding: 8px; + background: #fafbfc; + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + margin: 4px 0; + max-width: 100%; + overflow: hidden; +} + +.input_sub_title #businessPopupFormWrap h4 { + background: #f8fafc; + padding: 6px 12px; + margin: 0 0 6px 0; + font-size: 12px; + border-radius: 4px; +} + +.input_sub_title #businessPopupFormWrap h4 span::before { + content: '📎'; + font-size: 13px; +} + +.input_sub_title .pmsPopupForm { + background: white; + max-width: 100%; +} + +.input_sub_title .pmsPopupForm td { + padding: 4px 8px; +} + +/* 헤더에 닫기 버튼이 있는 경우를 위한 스타일 */ +.plm_menu_name h2 .close-btn { + position: absolute; + right: 20px; + top: 50%; + transform: translateY(-50%); + background: rgba(255, 255, 255, 0.2); + border: none; + color: white; + width: 32px; + height: 32px; + border-radius: 6px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 18px; + transition: all 0.2s ease; + backdrop-filter: blur(10px); +} + +.plm_menu_name h2 .close-btn:hover { + background: rgba(255, 255, 255, 0.3); +} + +/* 팝업 폼 래퍼 */ +#businessPopupFormWrap, +#EntirePopupFormWrap { + padding: 0; +} + +/* 폼 팝업 타이틀 스타일 - h4와 동일하게 */ +#EntirePopupFormWrap .form_popup_title { + background: white; + color: var(--text-primary); + padding: 8px 28px; + margin: 0; + font-size: 15px; + font-weight: 600; + border-bottom: 2px solid #e2e8f0; + border-left: none; + display: flex; + align-items: center; + position: relative; +} + +#EntirePopupFormWrap .form_popup_title span { + display: flex; + align-items: center; + gap: 8px; + flex: 1; +} + +#EntirePopupFormWrap .form_popup_title span::before { + content: '📋'; + font-size: 18px; + flex-shrink: 0; +} + +/* 테이블 스타일 - 현대적이고 깔끔하게 */ +.pmsPopupForm, +.pmsPopuptable { + width: 100%; + margin: 0; + table-layout: fixed; + background: var(--surface); + border: none; + border-radius: 0; + box-shadow: none; + border-collapse: separate; + border-spacing: 0; +} + +.pmsPopupForm tr, +.pmsPopuptable tr { + height: auto; +} + +.pmsPopupForm td, +.pmsPopuptable td { + height: auto; + font-size: 11px; + padding: 6px 12px; /* 8px에서 6px로 더욱 압축 */ + border-bottom: 1px solid var(--border-color); + vertical-align: middle; +} + +.pmsPopupForm tr:last-child td, +.pmsPopuptable tr:last-child td { + border-bottom: none; +} + +/* 라벨 셀 스타일 - 심플하고 읽기 쉽게 */ +.input_title { + background: #f8fafc; + color: var(--text-primary); + border-right: 1px solid var(--border-color); + font-weight: 600; + position: relative; + padding: 20px 24px; + vertical-align: middle !important; +} + +.input_title label { + color: var(--text-primary); + font-weight: 600; + font-size: 14px; + display: block; + text-align: center; +} + +/* 테이블 셀 세로 정렬 강제 적용 */ +.pmsPopupForm .input_title, +.pmsPopuptable .input_title { + vertical-align: middle !important; +} + +.pmsPopupForm .input_sub_title, +.pmsPopuptable .input_sub_title { + vertical-align: middle !important; +} + +/* 필수 항목 표시 제거 */ +/* .input_title label::after { + content: '*'; + color: var(--danger-color); + margin-left: 4px; + font-weight: 700; +} */ + +.input_sub_title { + background: var(--surface); + color: var(--text-secondary); + font-weight: 500; + font-size: 13px; +} + +.input_title_b { + background: #eff6ff; + color: var(--primary-color); + border-right: 1px solid var(--border-color); + font-weight: 600; + padding: 20px 24px; +} + +/* 입력 필드 스타일 - 최소 크기로 압축 (16px) */ +.pmsPopupForm input[type="text"], +.pmsPopupForm input[type="number"], +.pmsPopupForm select, +.pmsPopuptable input[type="text"], +.pmsPopuptable input[type="number"], +.pmsPopuptable select { + width: 100%; + height: 16px !important; /* 20px에서 16px로 축소 */ + line-height: 14px !important; /* 텍스트 세로 정렬 */ + border: 1px solid var(--border-color); + border-radius: 4px; + padding: 0 6px !important; + font-size: 11px !important; + color: var(--text-primary); + background: var(--surface); + transition: all 0.2s ease; + font-family: inherit; + vertical-align: middle; +} + +/* 셀렉트 박스 전용 스타일 */ +.pmsPopupForm select, +.pmsPopuptable select { + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cpath fill='%2364748b' d='M4 6L0 2h8z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 6px center; + background-size: 7px; + padding-right: 22px !important; + cursor: pointer; +} + +.pmsPopupForm input[type="text"]:hover, +.pmsPopupForm input[type="number"]:hover, +.pmsPopupForm select:hover, +.pmsPopuptable input[type="text"]:hover, +.pmsPopuptable input[type="number"]:hover, +.pmsPopuptable select:hover { + border-color: var(--secondary-color); + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.05); +} + +.pmsPopupForm input[type="text"]:focus, +.pmsPopupForm input[type="number"]:focus, +.pmsPopupForm select:focus, +.pmsPopuptable input[type="text"]:focus, +.pmsPopuptable input[type="number"]:focus, +.pmsPopuptable select:focus { + border-color: var(--primary-color); + outline: none; + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1); + background: var(--surface); +} + +.pmsPopupForm input[type="text"]:disabled, +.pmsPopupForm input[type="number"]:disabled, +.pmsPopupForm select:disabled, +.pmsPopuptable input[type="text"]:disabled, +.pmsPopuptable input[type="number"]:disabled, +.pmsPopuptable select:disabled { + background: #f1f5f9; + color: var(--text-secondary); + cursor: not-allowed; +} + +/* 텍스트영역 스타일 - 여러 페이지 통합 지원 */ +.pmsPopupForm textarea, +.pmsPopuptable textarea { + width: 100%; + min-height: 60px; + border: 1px solid var(--border-color); + border-radius: 4px; + padding: 8px; + font-size: 11px; + color: var(--text-primary); + background: var(--surface); + resize: vertical; + transition: all 0.2s ease; + font-family: inherit; + line-height: 1.5; +} + +.pmsPopupForm textarea:hover, +.pmsPopuptable textarea:hover { + border-color: var(--secondary-color); + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.05); +} + +.pmsPopupForm textarea:focus, +.pmsPopuptable textarea:focus { + border-color: var(--primary-color); + outline: none; + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1); +} + +/* 체크박스 스타일 */ +.pmsPopupForm input[type="checkbox"], +.pmsPopuptable input[type="checkbox"] { + width: 16px; + height: 16px; + accent-color: var(--primary-color); + cursor: pointer; + margin: 0 4px 0 0; +} + +/* 버튼 래퍼 */ +.btn_wrap { + margin: 0; + padding: 24px 32px; + border-top: 1px solid var(--border-color); + background: #fafbfc; + border-radius: 0 0 var(--radius-lg) var(--radius-lg); +} + +.plm_btn_wrap_center { + display: flex; + justify-content: center; + gap: 12px; +} + +/* 버튼 스타일 - 깔끔하고 명확하게 */ +.plm_btns { + height: 42px; + border-radius: var(--radius-md); + background: var(--primary-color); + color: white; + cursor: pointer; + font-size: 14px; + border: none; + padding: 0 24px; + font-weight: 600; + transition: all 0.2s ease; + box-shadow: var(--shadow-sm); + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + margin: 0; + float: none; +} + +.plm_btns:hover { + background: var(--primary-hover); + box-shadow: var(--shadow-md); + transform: translateY(-1px); +} + +.plm_btns:active { + transform: translateY(0); + box-shadow: var(--shadow-sm); +} + +/* 닫기 버튼은 세컨더리 스타일 */ +#btn_close { + background: white; + color: var(--text-primary); + border: 1.5px solid var(--border-color); +} + +#btn_close:hover { + background: #f8fafc; + border-color: var(--secondary-color); +} + +/* 메인 액션 버튼 */ +.btns { + height: 44px; + border-radius: var(--radius-md); + background: var(--primary-color); + color: white; + cursor: pointer; + font-size: 15px; + border: none; + padding: 0 28px; + font-weight: 600; + transition: all 0.2s ease; + box-shadow: var(--shadow-md); + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + margin: 0 6px; +} + +.btns:hover { + background: var(--primary-hover); + box-shadow: var(--shadow-lg); + transform: translateY(-2px); +} + +.btns:active { + transform: translateY(0); + box-shadow: var(--shadow-md); +} + +/* 테이블 스타일 */ +.plm_table_wrap { + width: 100%; + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + overflow: hidden; + margin-bottom: 20px; + background: var(--surface); + box-shadow: var(--shadow-sm); +} + +.plm_table { + width: 100%; + table-layout: fixed; + border-collapse: collapse; + background: var(--surface); + text-align: center; + font-size: 14px; +} + +.plm_table .plm_thead { + background: #f8fafc; + color: var(--text-primary); + font-weight: 600; + border-bottom: 2px solid var(--border-color); +} + +.plm_table .plm_thead td { + border-right: 1px solid var(--border-color); + padding: 14px 12px; + font-weight: 600; + font-size: 14px; +} + +.plm_table .plm_thead td:last-child { + border-right: none; +} + +.plm_table td { + height: auto; + border-bottom: 1px solid var(--border-color); + border-right: 1px solid var(--border-color); + padding: 12px; + vertical-align: middle; +} + +.plm_table td:last-child { + border-right: none; +} + +.plm_table tr:hover td { + background: #f8fafc; +} + +.plm_table tr:last-child td { + border-bottom: none; +} + +.plm_table td a { + color: var(--primary-color); + text-decoration: none; + font-weight: 500; + transition: color 0.2s ease; +} + +.plm_table td a:hover { + color: var(--primary-hover); + text-decoration: underline; +} + +/* 스크롤 테이블 */ +.plm_scroll_table { + max-height: 400px; + overflow-y: auto; + border-top: 1px solid var(--border-color); +} + +.plm_scroll_table::-webkit-scrollbar { + width: 10px; +} + +.plm_scroll_table::-webkit-scrollbar-track { + background: #f8fafc; +} + +.plm_scroll_table::-webkit-scrollbar-thumb { + background: var(--secondary-color); + border-radius: 5px; +} + +.plm_scroll_table::-webkit-scrollbar-thumb:hover { + background: var(--text-primary); +} + +/* Select2 스타일 조정 - 16px로 통일 */ +.select2-container--default .select2-selection--single { + border: 1px solid var(--border-color) !important; + border-radius: 4px !important; + height: 16px !important; /* 입력 필드와 동일하게 16px */ + display: flex !important; + align-items: center !important; + background: var(--surface); + transition: all 0.2s ease; +} + +.select2-container--default .select2-selection--single:hover { + border-color: var(--secondary-color) !important; + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.05); +} + +.select2-container--default .select2-selection--single:focus, +.select2-container--default.select2-container--open .select2-selection--single { + border-color: var(--primary-color) !important; + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1) !important; + outline: none !important; +} + +.select2-container--default .select2-selection--single .select2-selection__rendered { + line-height: 14px !important; /* 텍스트 세로 정렬 */ + padding-left: 6px !important; + padding-right: 22px !important; + color: var(--text-primary) !important; + font-size: 11px !important; +} + +.select2-container--default .select2-selection--single .select2-selection__placeholder { + color: var(--text-secondary) !important; +} + +.select2-container--default .select2-selection--single .select2-selection__arrow { + height: 14px !important; + right: 4px !important; + top: 1px !important; +} + +.select2-container--default .select2-selection--single .select2-selection__arrow b { + border-color: var(--text-secondary) transparent transparent transparent !important; + border-width: 3px 3px 0 3px !important; + margin-left: -3px !important; + margin-top: -1px !important; +} + +/* Select2 드롭다운 스타일 */ +.select2-container--default .select2-results__option { + padding: 4px 6px !important; + font-size: 11px !important; +} + +.select2-container--default .select2-results__option--highlighted[aria-selected] { + background-color: var(--primary-light) !important; + color: var(--primary-color) !important; +} + +.select2-dropdown { + border: 1px solid var(--border-color) !important; + border-radius: 4px !important; + box-shadow: var(--shadow-lg) !important; +} + +.select2-search--dropdown .select2-search__field { + border: 1px solid var(--border-color) !important; + border-radius: 3px !important; + padding: 3px 5px !important; + font-size: 11px !important; +} + +.select2-search--dropdown .select2-search__field:focus { + border-color: var(--primary-color) !important; + outline: none !important; +} + +/* 알림 메시지 스타일 */ +.success-message { + background: #f0fdf4; + color: #166534; + border: 1px solid #bbf7d0; + border-left: 4px solid var(--success-color); + padding: 14px 18px; + border-radius: var(--radius-md); + margin: 16px 0; + font-weight: 500; + display: flex; + align-items: center; + gap: 10px; +} + +.success-message::before { + content: '✓'; + font-weight: bold; + font-size: 18px; +} + +.error-message { + background: #fef2f2; + color: #991b1b; + border: 1px solid #fecaca; + border-left: 4px solid var(--danger-color); + padding: 14px 18px; + border-radius: var(--radius-md); + margin: 16px 0; + font-weight: 500; + display: flex; + align-items: center; + gap: 10px; +} + +.error-message::before { + content: '⚠'; + font-weight: bold; + font-size: 18px; +} + +.warning-message { + background: #fffbeb; + color: #92400e; + border: 1px solid #fde68a; + border-left: 4px solid var(--warning-color); + padding: 14px 18px; + border-radius: var(--radius-md); + margin: 16px 0; + font-weight: 500; + display: flex; + align-items: center; + gap: 10px; +} + +.warning-message::before { + content: 'ⓘ'; + font-weight: bold; + font-size: 18px; +} + +/* 로딩 상태 */ +.loading-state { + opacity: 0.6; + pointer-events: none; + position: relative; +} + +.loading-state::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 24px; + height: 24px; + margin: -12px 0 0 -12px; + border: 3px solid var(--primary-light); + border-top-color: var(--primary-color); + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + body { + padding: 10px; + } + + .pmsPopupForm td { + display: block; + width: 100%; + padding: 12px 16px; + } + + .input_title { + border-right: none; + border-bottom: none; + padding: 12px 16px 8px; + } + + .input_title label { + justify-content: flex-start; + text-align: left; + } + + .pmsPopupForm tr td:last-child { + border-bottom: 1px solid var(--border-color); + } + + .plm_btn_wrap_center { + flex-direction: column; + } + + .plm_btns, .btns { + width: 100%; + } + + #businessPopupFormWrap h4, + .plm_menu_name h2 { + padding: 16px 20px; + font-size: 18px; + } + + .btn_wrap { + padding: 16px 20px; + } +} + +/* 접근성 향상 */ +*:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +/* 다크모드 지원 (선택사항) */ +@media (prefers-color-scheme: dark) { + :root { + --background: #0f172a; + --surface: #1e293b; + --border-color: #334155; + --text-primary: #f1f5f9; + --text-secondary: #94a3b8; + } + + .input_title { + background: #1e293b; + } + + .btn_wrap { + background: #1e293b; + } +} + +/* 드래그앤드롭 영역 스타일 */ +.dropzone { + background: #f8fafc; + border: 2px dashed var(--border-color); + border-radius: var(--radius-md); + padding: 12px; + text-align: center; + color: var(--text-secondary); + font-size: 12px; + font-weight: 500; + transition: all 0.3s ease; + cursor: pointer; + margin: 4px 0; + min-height: 30px; + display: flex; + align-items: center; + justify-content: center; + max-width: 100%; + box-sizing: border-box; +} + +.dropzone:hover { + background: #eff6ff; + border-color: var(--primary-color); + color: var(--primary-color); +} + +.dropzone.dragover { + background: #dbeafe; + border-color: var(--primary-color); + color: var(--primary-color); + transform: scale(1.01); +} + +/* 파일 업로드 관련 스타일 */ +.project_form_in_table { + padding: 8px; + background: var(--surface); + max-width: 100%; + overflow: hidden; + box-sizing: border-box; +} + +.project_form_in_table input[type="file"] { + padding: 6px; + font-size: 11px; + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + background: var(--surface); + margin-right: 6px; + cursor: pointer; + max-width: calc(100% - 100px); +} + +.project_form_in_table > div { + margin-bottom: 6px; +} + +.project_form_in_table table { + max-width: 100%; + table-layout: fixed; +} + +.upload_btns { + height: 30px; + border-radius: var(--radius-md); + background: var(--primary-color); + color: white; + cursor: pointer; + font-size: 12px; + border: none; + padding: 0 16px; + font-weight: 600; + transition: all 0.2s ease; + box-shadow: var(--shadow-sm); + display: inline-flex; + align-items: center; + justify-content: center; + margin: 0; + vertical-align: middle; +} + +.upload_btns:hover { + background: var(--primary-hover); + box-shadow: var(--shadow-md); + transform: translateY(-1px); +} + +.upload_btns:active { + transform: translateY(0); + box-shadow: var(--shadow-sm); +} + +/* 파일 목록 테이블 스타일 */ +.fileListscrollTbody { + width: 100%; + border-collapse: collapse; + font-size: 11px; +} + +.fileListscrollTbody td { + padding: 6px 8px; + border-bottom: 1px solid var(--border-color); + vertical-align: middle; + text-align: center; + font-size: 11px; +} + +.fileListscrollTbody td.align_l { + text-align: left; +} + +.fileListscrollTbody td a { + color: var(--primary-color); + text-decoration: none; + font-weight: 500; + transition: color 0.2s ease; +} + +.fileListscrollTbody td a:hover { + color: var(--primary-hover); + text-decoration: underline; +} + +.fileListscrollTbody tr:hover td { + background: #f8fafc; +} + +/* 삭제 버튼 스타일 */ +.delete_btn { + display: inline-block; + width: 18px; + height: 18px; + background: var(--danger-color); + border-radius: 3px; + cursor: pointer; + position: relative; + margin-left: 6px; + vertical-align: middle; + transition: all 0.2s ease; +} + +.delete_btn:hover { + background: #dc2626; + transform: scale(1.1); +} + +.delete_btn::before, +.delete_btn::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 10px; + height: 2px; + background: white; +} + +.delete_btn::before { + transform: translate(-50%, -50%) rotate(45deg); +} + +.delete_btn::after { + transform: translate(-50%, -50%) rotate(-45deg); +} + +/* 파일 아이콘 스타일 */ +.file_icon, +.file_empty_icon { + display: inline-block; + padding: 8px 16px; + border-radius: var(--radius-md); + font-size: 13px; + font-weight: 500; + text-decoration: none; + transition: all 0.2s ease; + cursor: pointer; +} + +.file_icon { + background: var(--primary-light); + color: var(--primary-color); + border: 1px solid var(--primary-color); +} + +.file_icon:hover { + background: var(--primary-color); + color: white; +} + +.file_empty_icon { + background: #f1f5f9; + color: var(--text-secondary); + border: 1px solid var(--border-color); +} + +.file_empty_icon:hover { + background: #e2e8f0; + border-color: var(--secondary-color); +} + +/* 프린트 스타일 */ +@media print { + body { + background: white; + } + + section, aside { + box-shadow: none; + border: 1px solid #ddd; + } + + .btn_wrap, + .plm_btns, + .btns, + .upload_btns, + .delete_btn { + display: none; + } + + .dropzone { + display: none; + } +} \ No newline at end of file diff --git a/WebContent/init_new.jsp b/WebContent/init_new.jsp new file mode 100644 index 0000000..6ff5a26 --- /dev/null +++ b/WebContent/init_new.jsp @@ -0,0 +1,165 @@ +<%@page import="com.pms.common.utils.*"%> +<%@page import="com.pms.common.bean.PersonBean" %> + +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + +<% +boolean isLoggedIn = SessionManager.hasSession(session); +boolean isAdmin = false; + +String connectUserId = ""; +String connectUserDeptCode = ""; +String connectUserName = ""; +String connectUserDeptName = ""; +String partnerCd = ""; +if(!isLoggedIn){ + out.write(""); + out.write(""); +}else{ + PersonBean initPerson = null; + initPerson = (PersonBean)session.getAttribute(Constants.PERSON_BEAN); + connectUserId = CommonUtils.checkNull(initPerson.getUserId()); + connectUserDeptCode = CommonUtils.checkNull(initPerson.getDeptCode()); + connectUserName = CommonUtils.checkNull(initPerson.getUserName()); + connectUserDeptName = CommonUtils.checkNull(initPerson.getDeptName()); + partnerCd = CommonUtils.checkNull(initPerson.getPartner_cd()); + + if("plm_admin".equals(connectUserId)){ + isAdmin = true; + } + +} +pageContext.setAttribute("newLineChar", "\n"); +%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
loading
+
+

+
diff --git a/start-prod-full.sh b/start-prod-full.sh index ffea255..2c5a946 100755 --- a/start-prod-full.sh +++ b/start-prod-full.sh @@ -61,6 +61,251 @@ if ! git reset --hard origin/main; then exit 1 fi +# Java 개발 환경 확인 및 설치 +echo "Checking Java development environment..." + +# JDK 7 우선 설치 및 설정 +if ! command -v javac &> /dev/null; then + echo "Java compiler (javac) not found. Installing OpenJDK 7..." + + # 패키지 목록 업데이트 + apt-get update + + # OpenJDK 7 JDK 설치 (JRE가 아닌 JDK) + apt-get install -y openjdk-7-jdk + + # 설치 확인 + if ! command -v javac &> /dev/null; then + echo "Failed to install OpenJDK 7. Trying alternative installation..." + apt-get install -y default-jdk + + if ! command -v javac &> /dev/null; then + echo "Failed to install Java compiler. Exiting..." + exit 1 + fi + fi +fi + +# JAVA_HOME 설정 (JDK 7 우선) +export JAVA_HOME="" +JDK7_PATHS=( + "/usr/lib/jvm/java-7-openjdk-amd64" + "/usr/lib/jvm/java-1.7.0-openjdk-amd64" + "/usr/lib/jvm/openjdk-7-jdk" + "/usr/lib/jvm/default-java" +) + +for path in "${JDK7_PATHS[@]}"; do + if [ -d "$path" ] && [ -f "$path/bin/javac" ]; then + export JAVA_HOME="$path" + export PATH="$JAVA_HOME/bin:$PATH" + echo "Set JAVA_HOME to: $JAVA_HOME" + break + fi +done + +if [ -z "$JAVA_HOME" ]; then + echo "Warning: Could not find JDK 7 installation directory" +fi + +# Java 버전 확인 +echo "Java compiler version:" +javac -version +echo "Java runtime version:" +java -version + +# Java 소스 컴파일 +echo "Compiling Java sources..." + +# Java 컴파일을 위한 디렉토리 생성 및 기존 클래스 파일 정리 +echo "Preparing compilation directory..." +rm -rf WebContent/WEB-INF/classes +mkdir -p WebContent/WEB-INF/classes + +# 클래스패스 설정 (모든 jar 파일 포함) +CLASSPATH="" +for jar in WebContent/WEB-INF/lib/*.jar; do + if [ -z "$CLASSPATH" ]; then + CLASSPATH="$jar" + else + CLASSPATH="$CLASSPATH:$jar" + fi +done + +# JDK 7 기본 라이브러리 추가 +if [ -n "$JAVA_HOME" ]; then + if [ -f "$JAVA_HOME/jre/lib/rt.jar" ]; then + CLASSPATH="$CLASSPATH:$JAVA_HOME/jre/lib/rt.jar" + echo "Added JDK 7 runtime: $JAVA_HOME/jre/lib/rt.jar" + fi + if [ -f "$JAVA_HOME/lib/tools.jar" ]; then + CLASSPATH="$CLASSPATH:$JAVA_HOME/lib/tools.jar" + echo "Added JDK 7 tools: $JAVA_HOME/lib/tools.jar" + fi +fi + +# Servlet API는 WEB-INF/lib에 있는 것을 사용 (이미 클래스패스에 포함됨) +echo "Using Servlet API from WEB-INF/lib (javax.servlet-api-4.0.1.jar)" + +echo "Classpath: $CLASSPATH" + +# Java 소스 파일 찾기 및 컴파일 +if [ -d "src" ]; then + echo "Found Java source directory: src" + + # Java 소스 파일 목록 생성 + find src -name "*.java" > java_sources.txt + + if [ -s java_sources.txt ]; then + echo "Compiling Java files..." + + # Java 컴파일 실행 (Java 7 호환성을 위해 source와 target 버전 명시) + echo "Starting Java compilation with classpath..." + echo "Number of Java files to compile: $(wc -l < java_sources.txt)" + + # 컴파일 실행 및 결과 확인 + COMPILE_EXIT_CODE=0 + javac -cp "$CLASSPATH" -d WebContent/WEB-INF/classes -encoding UTF-8 -source 1.7 -target 1.7 @java_sources.txt 2>&1 | tee compile.log + COMPILE_EXIT_CODE=${PIPESTATUS[0]} + + if [ $COMPILE_EXIT_CODE -eq 0 ]; then + echo "Java compilation successful!" + + # 컴파일된 클래스 파일 수 확인 + CLASS_COUNT=$(find WebContent/WEB-INF/classes -name "*.class" | wc -l) + echo "Successfully compiled $CLASS_COUNT class files" + + # 컴파일된 패키지 구조 표시 + if [ $CLASS_COUNT -gt 0 ]; then + echo "Compiled packages:" + find WebContent/WEB-INF/classes -type d | grep -v "^WebContent/WEB-INF/classes$" | head -10 + fi + + else + echo "Java compilation failed! (Exit code: $COMPILE_EXIT_CODE)" + echo "Compilation errors:" + if [ -f compile.log ]; then + tail -50 compile.log + fi + + echo "Attempting compilation with extended classpath..." + + # 이미 설정된 JAVA_HOME 사용하여 확장된 클래스패스 구성 + EXTENDED_CLASSPATH="$CLASSPATH" + + if [ -n "$JAVA_HOME" ]; then + echo "Using JAVA_HOME: $JAVA_HOME" + # JDK 7 필수 라이브러리들 추가 + for lib in "jre/lib/rt.jar" "lib/tools.jar" "jre/lib/jsse.jar" "jre/lib/jce.jar"; do + if [ -f "$JAVA_HOME/$lib" ]; then + EXTENDED_CLASSPATH="$EXTENDED_CLASSPATH:$JAVA_HOME/$lib" + echo "Added: $JAVA_HOME/$lib" + fi + done + else + echo "Warning: JAVA_HOME not set, using system default" + fi + + # 시스템 클래스패스로 재시도 + echo "Extended classpath: $EXTENDED_CLASSPATH" + RETRY_EXIT_CODE=0 + javac -cp "$EXTENDED_CLASSPATH" -d WebContent/WEB-INF/classes -encoding UTF-8 -source 1.7 -target 1.7 @java_sources.txt 2>&1 | tee compile_retry.log + RETRY_EXIT_CODE=${PIPESTATUS[0]} + + if [ $RETRY_EXIT_CODE -eq 0 ]; then + echo "Java compilation successful with extended classpath!" + CLASS_COUNT=$(find WebContent/WEB-INF/classes -name "*.class" | wc -l) + echo "Successfully compiled $CLASS_COUNT class files" + + # 컴파일된 패키지 구조 표시 + if [ $CLASS_COUNT -gt 0 ]; then + echo "Compiled packages:" + find WebContent/WEB-INF/classes -type d | grep -v "^WebContent/WEB-INF/classes$" | head -10 + fi + else + echo "Java compilation failed even with extended classpath. (Exit code: $RETRY_EXIT_CODE)" + echo "Retry compilation errors:" + if [ -f compile_retry.log ]; then + tail -50 compile_retry.log + fi + echo "WARNING: Continuing with deployment anyway. Some features may not work properly." + fi + fi + + # 임시 파일 정리 + rm -f java_sources.txt compile.log compile_retry.log + + # XML, properties 등 리소스 파일들을 classes 디렉토리에 복사 + echo "Copying resource files (XML, properties, etc.) to classes directory..." + + # src 디렉토리에서 Java 파일이 아닌 모든 파일들을 찾아서 복사 + find src -type f ! -name "*.java" | while read resource_file; do + # src/ 부분을 제거하여 상대 경로 생성 + relative_path=${resource_file#src/} + target_dir="WebContent/WEB-INF/classes/$(dirname "$relative_path")" + + # 대상 디렉토리 생성 + mkdir -p "$target_dir" + + # 파일 복사 + cp "$resource_file" "WebContent/WEB-INF/classes/$relative_path" + echo "Copied: $resource_file -> WebContent/WEB-INF/classes/$relative_path" + done + + # 복사된 리소스 파일 수 확인 + RESOURCE_COUNT=$(find WebContent/WEB-INF/classes -type f ! -name "*.class" | wc -l) + echo "Copied $RESOURCE_COUNT resource files (XML, properties, etc.)" + else + echo "No Java source files found in src directory" + + # Java 파일이 없어도 리소스 파일은 복사 + echo "Copying resource files (XML, properties, etc.) to classes directory..." + find src -type f ! -name "*.java" | while read resource_file; do + relative_path=${resource_file#src/} + target_dir="WebContent/WEB-INF/classes/$(dirname "$relative_path")" + mkdir -p "$target_dir" + cp "$resource_file" "WebContent/WEB-INF/classes/$relative_path" + echo "Copied: $resource_file -> WebContent/WEB-INF/classes/$relative_path" + done + + RESOURCE_COUNT=$(find WebContent/WEB-INF/classes -type f ! -name "*.class" | wc -l) + echo "Copied $RESOURCE_COUNT resource files (XML, properties, etc.)" + fi +else + echo "No src directory found - skipping Java compilation and resource copying" +fi + +# 컴파일된 클래스 파일 권한 설정 및 최종 확인 +if [ -d "WebContent/WEB-INF/classes" ]; then + chmod -R 644 WebContent/WEB-INF/classes + find WebContent/WEB-INF/classes -type d -exec chmod 755 {} \; + + FINAL_CLASS_COUNT=$(find WebContent/WEB-INF/classes -name "*.class" | wc -l) + FINAL_RESOURCE_COUNT=$(find WebContent/WEB-INF/classes -type f ! -name "*.class" | wc -l) + + if [ $FINAL_CLASS_COUNT -gt 0 ] || [ $FINAL_RESOURCE_COUNT -gt 0 ]; then + echo "✓ Build completed successfully!" + echo "✓ Total compiled class files: $FINAL_CLASS_COUNT" + echo "✓ Total resource files (XML, properties, etc.): $FINAL_RESOURCE_COUNT" + echo "✓ Set appropriate permissions for all files" + + # 클래스 파일 크기 확인 + CLASSES_SIZE=$(du -sh WebContent/WEB-INF/classes 2>/dev/null | cut -f1) + echo "✓ Classes directory size: $CLASSES_SIZE" + + # 주요 리소스 파일 타입 확인 + if [ $FINAL_RESOURCE_COUNT -gt 0 ]; then + echo "✓ Resource file types found:" + find WebContent/WEB-INF/classes -type f ! -name "*.class" | sed 's/.*\.//' | sort | uniq -c | head -5 + fi + else + echo "⚠ WARNING: No compiled class files or resource files found in WebContent/WEB-INF/classes" + echo "⚠ The application may not function properly without compiled Java classes and resources" + fi +else + echo "⚠ WARNING: WebContent/WEB-INF/classes directory not found" +fi + # 컨테이너 상태 확인 echo "Checking container status..." docker-compose -f docker-compose.prod.yml up --build --force-recreate -d