//? Dropzone 진행률 표시 CSS — 페이지당 1회 주입 // 기존 main.css에서 .dz-preview div { width:100% } 이므로 // 파일명 div를 flex:1로 축소시켜 X 버튼과 같은 줄에 두고 // .dz-progress만 flex-basis:100%로 다음 줄에 배치 (function(){ if(document.getElementById('hy-dz-progress-style')) return; var css = '' + '.dz-preview{flex-wrap:wrap !important;align-items:center !important;}' // 파일명 박스: 100% 너비 강제 해제 → flex 분배 (X 버튼 옆에 위치) + '.dz-preview>div:not(.dz-progress){flex:1 1 0 !important;width:auto !important;min-width:0 !important;}' // progress bar: 새 줄, 전체 폭, 배경/패딩 초기화 + '.dz-progress{flex-basis:100% !important;order:99;width:100% !important;height:6px !important;margin:6px 0 0 !important;background:#e9ecef !important;border-radius:3px !important;overflow:hidden;padding:0 !important;}' + '.dz-progress .dz-upload{display:block;height:100%;width:0;background:linear-gradient(90deg,#1187f5,#4dabf7);transition:width 200ms ease;}' + '.dz-progress-text{margin-left:auto;padding:0 8px;font-size:12px;color:#555;font-variant-numeric:tabular-nums;white-space:nowrap;}' + '.dz-preview.dz-success .dz-progress{background:#d3f9d8 !important;}' + '.dz-preview.dz-success .dz-progress .dz-upload{background:#37b24d;}' + '.dz-preview.dz-success .dz-progress-text{color:#37b24d;font-weight:600;}' ; var s = document.createElement('style'); s.id = 'hy-dz-progress-style'; s.textContent = css; (document.head || document.documentElement).appendChild(s); })(); //? Dropzone 인스턴스에 진행률 텍스트 핸들러 부착 // uploadprogress 이벤트로 .dz-progress-text 업데이트, 완료 시 "100%" 표시 function attachDzProgress( dz ){ if(!dz || !dz.on) return; dz.on('uploadprogress', function(file, progress){ if(!file.previewElement) return; var t = file.previewElement.querySelector('.dz-progress-text'); if(t) t.textContent = Math.round(progress) + '%'; }); dz.on('success', function(file){ if(!file.previewElement) return; file.previewElement.classList.add('dz-success'); var t = file.previewElement.querySelector('.dz-progress-text'); if(t) t.textContent = '완료'; }); } //? Dropzone 업로드 진행 중 차단 // .dz-preview 마다 hidden input(*_fs_no[])이 붙어야 업로드 완료 — 안 붙어있으면 진행 중 // 실패한 파일은 complete 콜백에서 removeFile로 사라지므로 preview에 남아있지 않음 function checkAllFilesUploaded( alertMsg ){ const pending = $('.dz-preview').filter(function(){ return $(this).find('input[type="hidden"][name$="_fs_no[]"]').length === 0; }).length; if(pending > 0){ alert( alertMsg || '파일 업로드가 완료된 후 다시 시도해주세요.' ); return false; } return true; } // 전체 체크 클릭 $(document).on('change', '#all_check', function () { const isChecked = $(this).prop('checked'); // 전체 체크 상태에 따라 아래 전부 체크/해제 $('input[type="checkbox"]').not('#all_check') .prop('checked', isChecked); }); // 개별 체크 클릭 $(document).on('change', 'input[type="checkbox"]:not(#all_check)', function () { const total = $('input[type="checkbox"]:not(#all_check)').length; const checked = $('input[type="checkbox"]:not(#all_check):checked').length; // 전부 체크되면 전체체크 ON // 하나라도 해제되면 전체체크 OFF $('#all_check').prop('checked', total === checked); }); //엑셀 다운로드 function downloadExcel(exportForm, fileName) { const query = window.location.search; const currentUrl = encodeURIComponent(window.location.href); // 다운로드 토큰 생성 요청 fetch('/generate_download_token.html', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ export_form: exportForm, file_name: fileName }) }) .then(response => response.json()) .then(data => { if (data.token) { // query가 이미 ?로 시작하므로 ? 제거 후 & 추가 const additionalParams = query ? query.substring(1) : ''; // ?를 제거 let url = `/dwauth.html?export_form=${encodeURIComponent(exportForm)}&file_name=${encodeURIComponent(fileName)}&token=${data.token}&return_url=${currentUrl}`; if (additionalParams) { url += '&' + additionalParams; } window.location.href = url; } else { alert('토큰 생성에 실패했습니다.'); } }) .catch(error => { console.error('Error:', error); alert('다운로드 페이지 접근에 실패했습니다.'); }); } //? itseditor 라이센스 키 (한양 도메인 전용) — Summernote 제거 후 대체 //window.WEBNOTE_LICENSE_KEY = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiLtlZzslpHrjIDtlZnqtZAiLCJkb20iOiIqLmhhbnlhbmcuYWMua3IiLCJpc3MiOiJpdHN0YW5kYXJkIiwiaWF0IjoxNzgyMzQ1NjAwLCJraWQiOiJJVFMtMzU5Qi1ZU0k3LVo4TjIifQ.lZEQ06bDatgWwl0YwD9RcwrpYb6qWVBqewNc0H7YfOij7Cxbm711YWKW_P5J5fQn9l-hAnqVPislNYNG-jBE1Ig0uI50ZJqeN22q61L9ccakT7y_DU99ye6fRCGFN1l23nxHfRF_C9yj7VjvS8yU5HeaWrVvZmctz53D1zzZvB8eVM7mB1rI_3JHctbvBWQDJSg7Tmp5ufOxkSjJM3LzxKbAFiLL3D-GsLnORTBLGjbvb2BS_ghtq6MtzWHTqf6rsu9imz1gWU_KoUNbBH7PPL0gEn1MqPZxOgoRYjnFAOdUsC4FnCJj7WE-uNR2GtrdNsDwhLQxDtm4_aUyeE2ydw"; window.WEBNOTE_LICENSE_KEY = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiLtlZzslpHrjIDtlZnqtZAiLCJkb20iOiIqLmhhbnlhbmcuYWMua3IiLCJpc3MiOiJpdHN0YW5kYXJkIiwiaWF0IjoxNzgyMzQ1NjAwLCJraWQiOiJJVFMtMzU5Qi1ZU0k3LVo4TjIifQ.lZEQ06bDatgWwl0YwD9RcwrpYb6qWVBqewNc0H7YfOij7Cxbm711YWKW_P5J5fQn9l-hAnqVPislNYNG-jBE1Ig0uI50ZJqeN22q61L9ccakT7y_DU99ye6fRCGFN1l23nxHfRF_C9yj7VjvS8yU5HeaWrVvZmctz53D1zzZvB8eVM7mB1rI_3JHctbvBWQDJSg7Tmp5ufOxkSjJM3LzxKbAFiLL3D-GsLnORTBLGjbvb2BS_ghtq6MtzWHTqf6rsu9imz1gWU_KoUNbBH7PPL0gEn1MqPZxOgoRYjnFAOdUsC4FnCJj7WE-uNR2GtrdNsDwhLQxDtm4_aUyeE2ydw"; //? 초기화된 에디터 인스턴스 저장 (element id → editor) window.webNoteEditors = window.webNoteEditors || {}; //? 웹에디터 생성 — 기존 시그니처 유지: webNote(field, width, height, placeholder) // field: 셀렉터 문자열('#id'), jQuery 객체, 또는 DOM 요소 // width: (미사용, 호환성 유지) // height: 픽셀 수 (기본 400) // placeholder: 안내문 (빈값이면 기본값) // 반환: itseditor 인스턴스 (또는 null) function webNote( field, width, height, placeholder ) { // 셀렉터 해석 var el = null; if (typeof field === 'string') { el = document.querySelector(field); } else if (field && field.jquery && field.length) { el = field[0]; } else if (field && field.nodeType === 1) { el = field; } if (!el) return null; var h = parseInt(height, 10); if (isNaN(h) || h <= 0) h = 400; if (typeof window.ITSEditor !== 'function') { console.error('[webNote] itseditor(ITSEditor) not loaded'); return null; } var opts = { licenseKey: window.WEBNOTE_LICENSE_KEY, height: h, placeholder: (placeholder && placeholder !== '') ? placeholder : '내용을 작성해주세요.', imageUpload: '/sources/summernote/summernote-ajax.php?prc_mode=file_upload_ajax', lang: 'ko', stickyToolbar: true, autosave: true }; var editor = new window.ITSEditor(el, opts); if (el.id) window.webNoteEditors[el.id] = editor; return editor; } //? 폼 제출 전 에디터 → textarea 동기화 // itseditor는 자동 동기화하지만, 명시적 호출도 지원 (webNoteSync('#id') 또는 webNoteSync()) function webNoteSync( id ) { function syncOne(key) { var ed = window.webNoteEditors[key]; var el = document.getElementById(key); if (ed && el && typeof ed.getData === 'function') { try { el.value = ed.getData(); } catch(e) { /* ignore */ } } } if (id) { var key = (typeof id === 'string' && id.charAt(0) === '#') ? id.substring(1) : id; syncOne(key); } else { for (var key in window.webNoteEditors) { if (Object.prototype.hasOwnProperty.call(window.webNoteEditors, key)) { syncOne(key); } } } } function dateSelectall( field ) { $( field ).datepicker ({ changeYear: true, changeMonth: true, altFormat: 'yy-mm-dd', dateFormat: 'yy-mm-dd', minDate: "2014-01-01", maxDate: "+5Y", monthNames:[ '1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월' ], monthNamesShort:[ '1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월' ], dayNames:[ '일', '월', '화', '수', '목', '금', '토' ], dayNamesShort:[ '일', '월', '화', '수', '목', '금', '토' ], dayNamesMin:[ '일', '월', '화', '수', '목', '금', '토' ] }); } function datePeriod( slave_field, master_field ) { $( slave_field ).datepicker ({ changeYear: true, changeMonth: true, altFormat: 'yy-mm-dd', dateFormat: 'yy-mm-dd', //showOn: "both", //buttonImage: "/image/icon_calendar.gif", //buttonImageOnly: true, minDate: $( master_field ).val(), monthNames:[ '1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월' ], monthNamesShort:[ '1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월' ], dayNames:[ '일', '월', '화', '수', '목', '금', '토' ], dayNamesShort:[ '일', '월', '화', '수', '목', '금', '토' ], dayNamesMin:[ '일', '월', '화', '수', '목', '금', '토' ] }); } function DateSelect( field ) { $( field ).datepicker ({ // showOn: "button", // 버튼과 텍스트 필드 모두 캘린더를 보여준다. // buttonImage: "/sources/image/calendar.gif", // 버튼 이미지 changeYear: true, changeMonth: true, altFormat: 'yy-mm-dd', dateFormat: 'yy-mm-dd', minDate: "2000-01-01", monthNames:[ '1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월' ], monthNamesShort:[ '1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월' ], dayNames:[ '일', '월', '화', '수', '목', '금', '토' ], dayNamesShort:[ '일', '월', '화', '수', '목', '금', '토' ], dayNamesMin:[ '일', '월', '화', '수', '목', '금', '토' ] }); } //숫자만 입력 function numericType( tag_name ) { $( tag_name ).click( function(){ $(this).select(); }); $( tag_name ).keyup(function(){ var v = $(this).val().replace(/[^0-9]/g,''); $(this).val( v ); if(v == ''){ $(this).val(0); } }); $( tag_name ).focusout(function(){ var v = $(this).val().replace(/[^0-9]/g,''); $(this).val( v ); if(v == ''){ $(this).val(0); } }); }