e51cdbc42a
- 감사 사유 입력 기능 추가 및 UI 수정 - 사용/법인 삭제 시 '완전삭제' 여부 확인 및 로직 적용 - 감사로그에 사유(message) 저장 필드 추가
660 lines
27 KiB
Plaintext
660 lines
27 KiB
Plaintext
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
|
|
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
|
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
|
|
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
|
|
<%@ include file="/jsp/common/include/localemessage.jsp" %>
|
|
|
|
<c:set var="locale" value="<%= localeMessage.getLocale() %>"/>
|
|
|
|
<script language="javascript" src="<c:url value="/js/jquery-1.12.1.min.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/jquery-ui.js"/>"></script>
|
|
<%-- <script language="javascript" src="<c:url value="/js/jquery-ui.min.js"/>"></script> --%>
|
|
<script language="javascript" src="<c:url value="/js/grid.locale-${locale}.js"/>" charset="utf-8"></script>
|
|
<script language="javascript" src="<c:url value="/js/prefixfree.min.js"/>"></script>
|
|
|
|
<script type="text/javascript">
|
|
jQuery.browser = {};
|
|
(function () {
|
|
jQuery.browser.msie = false;
|
|
jQuery.browser.version = 0;
|
|
if (navigator.userAgent.match(/MSIE ([0-9]+)\./)) {
|
|
jQuery.browser.msie = true;
|
|
jQuery.browser.version = RegExp.$1;
|
|
}
|
|
})();
|
|
</script>
|
|
|
|
|
|
<script language="javascript" src="<c:url value="/js/jquery.jqGrid.min.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/jquery.form.min.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/jquery.contextMenu.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/custom.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/common-${locale}.js"/>"></script>
|
|
<script type="text/javascript">
|
|
/* 자동 로그아웃: iframe 내 활동을 sessionStorage에 기록 (main.jsp 타이머와 공유) */
|
|
(function() { var m = function() { sessionStorage.setItem('lastActivity', String(Date.now())); }; ['mousemove','keydown','click','touchstart'].forEach(function(e){ document.addEventListener(e, m, true); }); })();
|
|
</script>
|
|
<script language="javascript" src="<c:url value="/js/jquery.inputmask.bundle.min.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/jquery.searchabledropdown-1.0.8.min.js"/>"></script>
|
|
<%-- <script language="javascript" src="<c:url value="/js/jquery.searchable-1.1.0.min.js"/>"></script> --%>
|
|
<script language="javascript" src="<c:url value="/js/jexcel.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/jsuites.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/jsuites.webcomponents.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/custom.component.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/Nwagon.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/vkbeautify.js"/>"></script>
|
|
<script language="javascript" src="<c:url value="/js/select2.min.js"/>"></script>
|
|
|
|
<script src="<c:url value="/addon/codemirror/lib/codemirror.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/mode/javascript/javascript.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/mode/xml/xml.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/addon/edit/matchbrackets.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/addon/edit/closebrackets.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/addon/comment/comment.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/addon/comment/continuecomment.js"/>"></script>
|
|
|
|
<script src="<c:url value="/addon/codemirror/lint/jsonlint.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/addon/lint/lint.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/addon/lint/javascript-lint.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/addon/lint/html-lint.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/addon/lint/json-lint.js"/>"></script>
|
|
<script src="<c:url value="/addon/codemirror/addon/lint/css-lint.js"/>"></script>
|
|
|
|
<!-- Summernote -->
|
|
<script src="<c:url value="/addon/summernote/summernote-lite.min.js"/>"></script>
|
|
<script src="<c:url value="/addon/summernote/summernote-cleaner.js"/>"></script>
|
|
<script src="<c:url value="/addon/summernote/lang/summernote-ko-KR.js"/>"></script>
|
|
<script src="<c:url value="/addon/summernote/summernote-custom.js"/>"></script>
|
|
<link rel="stylesheet" type="text/css" href="<c:url value="/addon/summernote/summernote-custom.css"/>"/>
|
|
|
|
<script language="javascript">
|
|
|
|
function buttonControl() {
|
|
if (arguments.length == 0) {
|
|
$("img[level], button[level]").hide();
|
|
if ("${rmsMenuAuth}" == "W") {
|
|
$("img[level='W']").show();
|
|
$("img[level='R']").show();
|
|
$("button[level='W']").show();
|
|
$("button[level='R']").show();
|
|
} else if ("${rmsMenuAuth}" == "R") {
|
|
$("img[level='R']").show();
|
|
$("button[level='R']").show();
|
|
}
|
|
} else if (arguments.length == 1) {
|
|
var status = arguments[0];
|
|
if (arguments[0]) {
|
|
status = 'DETAIL';
|
|
} else {
|
|
status = 'NEW';
|
|
}
|
|
|
|
if (arguments[0] == 'DETAIL') {
|
|
status = 'DETAIL';
|
|
} else if (arguments[0] == 'NEW') {
|
|
status = 'NEW';
|
|
} else if (arguments[0] == 'TEMP') {
|
|
status = 'TEMP';
|
|
}
|
|
|
|
$("img[level]").hide();
|
|
$("button[level]").hide();
|
|
if ("${rmsMenuAuth}" == "W") {
|
|
$("img[level='W'][status*=" + status + "]").show();
|
|
$("img[level='R'][status*=" + status + "]").show();
|
|
$("button[level='W'][status*=" + status + "]").show();
|
|
$("button[level='R'][status*=" + status + "]").show();
|
|
} else if ("${rmsMenuAuth}" == "R") {
|
|
$("img[level='R'][status*=" + status + "]").show();
|
|
$("button[level='R'][status*=" + status + "]").show();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
function buttonControl(){
|
|
if (arguments.length == 0){
|
|
$("img[level]").hide();
|
|
if ("${rmsMenuAuth}" =="W"){
|
|
$("img[level='W']").show();
|
|
$("img[level='R']").show();
|
|
}else if ("${rmsMenuAuth}" =="R"){
|
|
$("img[level='R']").show();
|
|
$("tr[level='W']").hide();
|
|
}
|
|
} else if (arguments.length == 1){
|
|
var isStatus = false;
|
|
if (isBoolean(arguments[0])){
|
|
isStatus = arguments[0];
|
|
}else{
|
|
if (arguments[0] != "" && arguments[0] !="null"){
|
|
isStatus = true;
|
|
}else{
|
|
isStatus = false;
|
|
}
|
|
}
|
|
var sel = "";
|
|
if (isStatus){
|
|
//detail
|
|
sel = "DETAIL";
|
|
}else{
|
|
//new
|
|
sel = "NEW";
|
|
$("#btn_modify").attr('src',"<c:url value='/img/btn_regist.png'/>");
|
|
}
|
|
$("img[level]").hide();
|
|
if ("${rmsMenuAuth}" =="W"){
|
|
$("img[level='W'][status*="+sel+"]").show();
|
|
$("img[level='R'][status*="+sel+"]").show();
|
|
}else if ("${rmsMenuAuth}" =="R"){
|
|
$("img[level='R'][status*="+sel+"]").show();
|
|
$("tr[level='W']").hide();
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
function getSearchUrlForReturn() {
|
|
var array = [];
|
|
<c:forEach var="pageParameter" items="${param}"><c:if test="${fn:startsWith(pageParameter.key,'search')}">
|
|
array.push('<c:out value="${pageParameter.key}" />' + "=" + '<c:out value="${pageParameter.value}" />'.replace(/%23/g, '#'));
|
|
</c:if>
|
|
</c:forEach>
|
|
<c:forEach var="pageParameter" items="${param}"><c:if test="${fn:startsWith(pageParameter.key,'like')}">
|
|
array.push('<c:out value="${pageParameter.key}" />' + "=" + '<c:out value="${pageParameter.value}" />'.replace(/%23/g, '#'));
|
|
</c:if></c:forEach>
|
|
return array.join("&");
|
|
}
|
|
|
|
function getSearchUrlForReturnArray() {
|
|
var array = [];
|
|
<c:forEach var="pageParameter" items="${param}"><c:if test="${fn:startsWith(pageParameter.key,'search')}">
|
|
array.push('<c:out value="${pageParameter.key}" />' + "=" + '<c:out value="${pageParameter.value}" />'.replace(/%23/g, '#'));
|
|
</c:if>
|
|
</c:forEach>
|
|
<c:forEach var="pageParameter" items="${param}"><c:if test="${fn:startsWith(pageParameter.key,'like')}">
|
|
array.push('<c:out value="${pageParameter.key}" />' + "=" + '<c:out value="${pageParameter.value}" />'.replace(/%23/g, '#'));
|
|
</c:if></c:forEach>
|
|
return array;
|
|
}
|
|
|
|
function getReturnUrlForReturn(search) {
|
|
var returnUrl = '${param.returnUrl}';
|
|
returnUrl = returnUrl + '?cmd=' + 'LIST';
|
|
returnUrl = returnUrl + '&page=' + '${param.page}';
|
|
returnUrl = returnUrl + '&menuId=' + '${param.menuId}';
|
|
returnUrl = returnUrl + '&sortName=' + '${param.sortName}';
|
|
returnUrl = returnUrl + '&sortOrder=' + '${param.sortOrder}';
|
|
//검색조건
|
|
returnUrl = returnUrl + '&' + getSearchUrlForReturn();
|
|
return returnUrl;
|
|
}
|
|
|
|
function getReloadUrl(cmd) {
|
|
var returnUrl = '${param.returnUrl}';
|
|
returnUrl = returnUrl + '?cmd=' + cmd;
|
|
returnUrl = returnUrl + '&page=' + '${param.pages}';
|
|
returnUrl = returnUrl + '&menuId=' + '${param.menuId}';
|
|
//검색조건
|
|
returnUrl = returnUrl + '&' + getSearchUrlForReturn();
|
|
return returnUrl;
|
|
}
|
|
|
|
function putSelectFromParam() {
|
|
var array = [];
|
|
<c:forEach var="pageParameter" items="${param}">
|
|
<c:if test="${fn:startsWith(pageParameter.key,'search')}">
|
|
var name = "${pageParameter.key}";
|
|
var value = "${pageParameter.value}"
|
|
|
|
$("select[name=" + name + "]").val(value);
|
|
$("input[name=" + name + "]").val(value);
|
|
</c:if>
|
|
</c:forEach>
|
|
|
|
}
|
|
|
|
function getMenuId() {
|
|
return '${param.menuId}';
|
|
}
|
|
|
|
var $ = jQuery.noConflict();
|
|
$(document).keydown(function (e) {
|
|
var element = e.target.nodeName.toLowerCase();
|
|
if (element != 'input' && element != 'textarea') {
|
|
if (e.keyCode === 8) {
|
|
return false;
|
|
}
|
|
}
|
|
})
|
|
|
|
function camelToSnake(str) {
|
|
return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
|
}
|
|
|
|
function snakeToCamel(str) {
|
|
return str.replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());
|
|
}
|
|
|
|
|
|
/**
|
|
* JS 메시지 변수 사용시 포멧팅을 위해 추가 다음과 같이 사용 가능
|
|
* 인터페이스 삭제시 배포시스템에서도 삭제가 될 수 있습니다. {0}를 삭제하시겠습니까?".formatLocale($("#infId").val())
|
|
*
|
|
* 사용 예>
|
|
* 기존 JS 메시지
|
|
* 인터페이스 삭제시 배포시스템에서도 삭제가 될 수 있습니다.\n" + $("#infId").val() + "를 삭제하시겠습니까?
|
|
* format 함수 사용한 JS 메시지
|
|
* 인터페이스 삭제시 배포시스템에서도 삭제가 될 수 있습니다.\n {0}를 삭제하시겠습니까?".formatLocale($("#infId").val())
|
|
* Java Locale(ResourceBundle)과 함께 사용한 예시
|
|
* localeMessage.getString("interface.message.confirmDeleteInterfaceWithDeployedSystem" ) %>".formatLocale($("#infId").val());
|
|
*/
|
|
String.prototype.formatLocale = function () {
|
|
var args = arguments;
|
|
return this.replace(/{(\d+)}/g, function (match, number) {
|
|
return typeof args[number] != 'undefined'
|
|
? args[number]
|
|
: match
|
|
;
|
|
});
|
|
};
|
|
|
|
formatLocale = function (format) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
return format.replace(/{(\d+)}/g, function (match, number) {
|
|
return typeof args[number] != 'undefined'
|
|
? args[number]
|
|
: match
|
|
;
|
|
});
|
|
};
|
|
|
|
function prettyJson(jsonText) {
|
|
if (!jsonText) {
|
|
return jsonText;
|
|
}
|
|
|
|
var prettyJson = new Array();
|
|
var depth = 0;
|
|
var currChar;
|
|
var prevChar;
|
|
var doubleQuoteIn = false;
|
|
|
|
for (var i = 0; i < jsonText.length; i++) {
|
|
currChar = jsonText.charAt(i);
|
|
|
|
if (currChar == '\"') {
|
|
if (prevChar != '\\') {
|
|
doubleQuoteIn = !doubleQuoteIn;
|
|
}
|
|
}
|
|
|
|
switch (currChar) {
|
|
case '{':
|
|
prettyJson.push(currChar);
|
|
if (!doubleQuoteIn) {
|
|
prettyJson.push('\n');
|
|
insertTab(prettyJson, ++depth);
|
|
}
|
|
break;
|
|
case '}':
|
|
if (!doubleQuoteIn) {
|
|
prettyJson.push('\n');
|
|
insertTab(prettyJson, --depth);
|
|
}
|
|
prettyJson.push(currChar);
|
|
break;
|
|
case ',':
|
|
prettyJson.push(currChar);
|
|
if (!doubleQuoteIn) {
|
|
prettyJson.push('\n');
|
|
insertTab(prettyJson, depth);
|
|
}
|
|
break;
|
|
default:
|
|
prettyJson.push(currChar);
|
|
break;
|
|
}
|
|
|
|
prevChar = currChar;
|
|
}
|
|
return prettyJson.join('');
|
|
}
|
|
|
|
const TAB = ' ';
|
|
|
|
function insertTab(prettyJson, depth) {
|
|
for (var i = 0; i < depth; i++) {
|
|
prettyJson.push(TAB);
|
|
}
|
|
}
|
|
|
|
async function downloadFiles(url, body) {
|
|
url += "&serviceType=" + sessionStorage["serviceType"]
|
|
let headers;
|
|
if (body instanceof FormData || body instanceof URLSearchParams) {
|
|
headers = {};
|
|
} else {
|
|
headers = {
|
|
'Content-Type': 'application/json',
|
|
};
|
|
}
|
|
try {
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: headers,
|
|
body: body
|
|
});
|
|
if (!response.ok) throw new Error('Server responded with an error!');
|
|
|
|
const blob = await response.blob();
|
|
const contentDisposition = response.headers.get('Content-Disposition');
|
|
let filename = "downloaded_file"; // 기본 파일 이름
|
|
if (contentDisposition) {
|
|
const filenameMatch = contentDisposition.match(/filename="?([^"]+)"?/);
|
|
if (filenameMatch.length > 1) {
|
|
filename = filenameMatch[1];
|
|
filename = decodeURI(filename);
|
|
}
|
|
}
|
|
const downloadUrl = window.URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = downloadUrl;
|
|
a.download = filename; // 압축 파일 이름, 서버에서 설정 가능
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
document.body.removeChild(a);
|
|
window.URL.revokeObjectURL(downloadUrl);
|
|
} catch (error) {
|
|
console.error('Download failed:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 스타일링된 Alert 모달
|
|
* @param {string} message - 표시할 메시지
|
|
* @param {object} options - 옵션 (type: 'info'|'warning'|'error'|'success', title: string, onClose: function)
|
|
*/
|
|
function showAlert(message, options) {
|
|
options = options || {};
|
|
var type = options.type || 'info';
|
|
var title = options.title || getAlertTitle(type);
|
|
var onClose = options.onClose || function(){};
|
|
|
|
// 기존 모달 제거
|
|
$('#commonAlertModal').remove();
|
|
|
|
var iconHtml = getAlertIcon(type);
|
|
var colorClass = 'alert-' + type;
|
|
|
|
var modalHtml =
|
|
'<div id="commonAlertModal" class="common-alert-overlay">' +
|
|
'<div class="common-alert-modal ' + colorClass + '">' +
|
|
'<div class="common-alert-header">' +
|
|
'<span class="common-alert-icon">' + iconHtml + '</span>' +
|
|
'<span class="common-alert-title">' + title + '</span>' +
|
|
'</div>' +
|
|
'<div class="common-alert-body">' +
|
|
'<p class="common-alert-message">' + message + '</p>' +
|
|
'</div>' +
|
|
'<div class="common-alert-footer">' +
|
|
'<button type="button" class="common-alert-btn" id="commonAlertOkBtn">확인</button>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>';
|
|
|
|
$('body').append(modalHtml);
|
|
|
|
// 애니메이션 효과
|
|
setTimeout(function() {
|
|
$('#commonAlertModal').addClass('show');
|
|
}, 10);
|
|
|
|
// 닫기 이벤트
|
|
$('#commonAlertOkBtn').on('click', function() {
|
|
closeCommonAlert(onClose);
|
|
});
|
|
|
|
// ESC 키로 닫기
|
|
$(document).on('keydown.commonAlert', function(e) {
|
|
if (e.keyCode === 27) {
|
|
closeCommonAlert(onClose);
|
|
}
|
|
});
|
|
|
|
// Enter 키로 확인
|
|
$(document).on('keydown.commonAlertEnter', function(e) {
|
|
if (e.keyCode === 13) {
|
|
closeCommonAlert(onClose);
|
|
}
|
|
});
|
|
}
|
|
|
|
function closeCommonAlert(callback) {
|
|
$('#commonAlertModal').removeClass('show');
|
|
setTimeout(function() {
|
|
$('#commonAlertModal').remove();
|
|
$(document).off('keydown.commonAlert');
|
|
$(document).off('keydown.commonAlertEnter');
|
|
if (typeof callback === 'function') {
|
|
callback();
|
|
}
|
|
}, 200);
|
|
}
|
|
|
|
function getAlertTitle(type) {
|
|
switch(type) {
|
|
case 'error': return '오류';
|
|
case 'warning': return '경고';
|
|
case 'success': return '완료';
|
|
default: return '알림';
|
|
}
|
|
}
|
|
|
|
function getAlertIcon(type) {
|
|
switch(type) {
|
|
case 'error': return '<i class="material-icons">error</i>';
|
|
case 'warning': return '<i class="material-icons">warning</i>';
|
|
case 'success': return '<i class="material-icons">check_circle</i>';
|
|
default: return '<i class="material-icons">info</i>';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 스타일링된 Confirm 모달
|
|
* @param {string} message - 표시할 메시지
|
|
* @param {object} options - 옵션 (type, title, confirmText, cancelText, onConfirm, onCancel)
|
|
*/
|
|
function showConfirm(message, options) {
|
|
options = options || {};
|
|
var type = options.type || 'info';
|
|
var title = options.title || '확인';
|
|
var confirmText = options.confirmText || '확인';
|
|
var cancelText = options.cancelText || '취소';
|
|
var onConfirm = options.onConfirm || function(){};
|
|
var onCancel = options.onCancel || function(){};
|
|
|
|
// 기존 모달 제거
|
|
$('#commonConfirmModal').remove();
|
|
|
|
var iconHtml = getAlertIcon(type);
|
|
var colorClass = 'alert-' + type;
|
|
|
|
var modalHtml =
|
|
'<div id="commonConfirmModal" class="common-alert-overlay">' +
|
|
'<div class="common-alert-modal ' + colorClass + '">' +
|
|
'<div class="common-alert-header">' +
|
|
'<span class="common-alert-icon">' + iconHtml + '</span>' +
|
|
'<span class="common-alert-title">' + title + '</span>' +
|
|
'</div>' +
|
|
'<div class="common-alert-body">' +
|
|
'<p class="common-alert-message">' + message + '</p>' +
|
|
'</div>' +
|
|
'<div class="common-alert-footer">' +
|
|
'<button type="button" class="common-confirm-cancel-btn" id="commonConfirmCancelBtn">' + cancelText + '</button>' +
|
|
'<button type="button" class="common-alert-btn" id="commonConfirmOkBtn">' + confirmText + '</button>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>';
|
|
|
|
$('body').append(modalHtml);
|
|
|
|
setTimeout(function() {
|
|
$('#commonConfirmModal').addClass('show');
|
|
}, 10);
|
|
|
|
// 확인 버튼
|
|
$('#commonConfirmOkBtn').on('click', function() {
|
|
closeCommonConfirm(onConfirm);
|
|
});
|
|
|
|
// 취소 버튼
|
|
$('#commonConfirmCancelBtn').on('click', function() {
|
|
closeCommonConfirm(onCancel);
|
|
});
|
|
|
|
// ESC 키로 취소
|
|
$(document).on('keydown.commonConfirm', function(e) {
|
|
if (e.keyCode === 27) {
|
|
closeCommonConfirm(onCancel);
|
|
}
|
|
});
|
|
}
|
|
|
|
function closeCommonConfirm(callback) {
|
|
$('#commonConfirmModal').removeClass('show');
|
|
setTimeout(function() {
|
|
$('#commonConfirmModal').remove();
|
|
$(document).off('keydown.commonConfirm');
|
|
if (typeof callback === 'function') {
|
|
callback();
|
|
}
|
|
}, 200);
|
|
}
|
|
|
|
/**
|
|
* 사유 입력 모달 - 확인 시 입력한 사유 문자열을 onConfirm(reason)으로 전달
|
|
* @param {string} message - 안내 메시지
|
|
* @param {object} options - (title, confirmText, cancelText, placeholder, required, onConfirm, onCancel)
|
|
* required 기본 true (빈 사유 차단)
|
|
*/
|
|
function showReasonPrompt(message, options) {
|
|
options = options || {};
|
|
var title = options.title || '사유 입력';
|
|
var confirmText = options.confirmText || '확인';
|
|
var cancelText = options.cancelText || '취소';
|
|
var placeholder = options.placeholder || '사유를 입력하세요.';
|
|
var required = options.required !== false;
|
|
var onConfirm = options.onConfirm || function(){};
|
|
var onCancel = options.onCancel || function(){};
|
|
|
|
// 기존 모달 제거
|
|
$('#commonReasonModal').remove();
|
|
|
|
var iconHtml = getAlertIcon('warning');
|
|
|
|
var modalHtml =
|
|
'<div id="commonReasonModal" class="common-alert-overlay">' +
|
|
'<div class="common-alert-modal alert-warning">' +
|
|
'<div class="common-alert-header">' +
|
|
'<span class="common-alert-icon">' + iconHtml + '</span>' +
|
|
'<span class="common-alert-title">' + title + '</span>' +
|
|
'</div>' +
|
|
'<div class="common-alert-body">' +
|
|
'<p class="common-alert-message">' + message + '</p>' +
|
|
'<textarea id="commonReasonInput" maxlength="200" placeholder="' + placeholder + '" style="width:100%;height:80px;margin-top:10px;box-sizing:border-box;font-size:13px;padding:8px;border:1px solid #ddd;border-radius:4px;resize:vertical;"></textarea>' +
|
|
'<p id="commonReasonError" style="display:none;color:#f44336;font-size:12px;margin:6px 0 0;">사유를 입력해 주세요.</p>' +
|
|
'</div>' +
|
|
'<div class="common-alert-footer">' +
|
|
'<button type="button" class="common-confirm-cancel-btn" id="commonReasonCancelBtn">' + cancelText + '</button>' +
|
|
'<button type="button" class="common-alert-btn" id="commonReasonOkBtn">' + confirmText + '</button>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>';
|
|
|
|
$('body').append(modalHtml);
|
|
|
|
setTimeout(function() {
|
|
$('#commonReasonModal').addClass('show');
|
|
$('#commonReasonInput').focus();
|
|
}, 10);
|
|
|
|
// 확인 버튼
|
|
$('#commonReasonOkBtn').on('click', function() {
|
|
var reason = $.trim($('#commonReasonInput').val());
|
|
if (required && reason === '') {
|
|
$('#commonReasonError').show();
|
|
$('#commonReasonInput').focus();
|
|
return;
|
|
}
|
|
closeCommonReason(function() { onConfirm(reason); });
|
|
});
|
|
|
|
// 취소 버튼
|
|
$('#commonReasonCancelBtn').on('click', function() {
|
|
closeCommonReason(onCancel);
|
|
});
|
|
|
|
// ESC 키로 취소
|
|
$(document).on('keydown.commonReason', function(e) {
|
|
if (e.keyCode === 27) {
|
|
closeCommonReason(onCancel);
|
|
}
|
|
});
|
|
}
|
|
|
|
function closeCommonReason(callback) {
|
|
$('#commonReasonModal').removeClass('show');
|
|
setTimeout(function() {
|
|
$('#commonReasonModal').remove();
|
|
$(document).off('keydown.commonReason');
|
|
if (typeof callback === 'function') {
|
|
callback();
|
|
}
|
|
}, 200);
|
|
}
|
|
</script>
|
|
|
|
<!-- 공용 Alert 모달 스타일 -->
|
|
<style>
|
|
.common-alert-overlay { display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:99999; justify-content:center; align-items:center; }
|
|
.common-alert-overlay.show { display:flex; animation:alertFadeIn 0.2s ease; }
|
|
@keyframes alertFadeIn { from { opacity:0; } to { opacity:1; } }
|
|
.common-alert-modal { background:#fff; border-radius:8px; box-shadow:0 8px 32px rgba(0,0,0,0.3); width:380px; max-width:90%; overflow:hidden; animation:alertSlideIn 0.2s ease; }
|
|
@keyframes alertSlideIn { from { transform:translateY(-20px); opacity:0; } to { transform:translateY(0); opacity:1; } }
|
|
.common-alert-header { display:flex; align-items:center; gap:10px; padding:16px 20px; border-bottom:1px solid #eee; }
|
|
.common-alert-icon { display:flex; align-items:center; justify-content:center; width:32px; height:32px; border-radius:50%; }
|
|
.common-alert-icon i { font-size:20px; }
|
|
.common-alert-title { font-size:15px; font-weight:600; color:#333; }
|
|
.common-alert-body { padding:20px; }
|
|
.common-alert-message { margin:0; font-size:13px; line-height:1.6; color:#555; word-break:keep-all; }
|
|
.common-alert-footer { display:flex; justify-content:flex-end; padding:12px 20px; background:#fafafa; border-top:1px solid #eee; }
|
|
.common-alert-btn { padding:8px 24px; font-size:13px; font-weight:500; border:none; border-radius:4px; cursor:pointer; transition:all 0.2s; }
|
|
.common-confirm-cancel-btn { padding:8px 24px; font-size:13px; font-weight:500; border:1px solid #ddd; border-radius:4px; cursor:pointer; transition:all 0.2s; background:#fff; color:#666; margin-right:8px; }
|
|
.common-confirm-cancel-btn:hover { background:#f5f5f5; border-color:#ccc; }
|
|
|
|
/* Info 타입 (기본) */
|
|
.alert-info .common-alert-icon { background:rgba(0,128,128,0.1); }
|
|
.alert-info .common-alert-icon i { color:rgba(0,128,128,1); }
|
|
.alert-info .common-alert-btn { background:rgba(0,128,128,0.85); color:#fff; }
|
|
.alert-info .common-alert-btn:hover { background:rgba(0,128,128,1); }
|
|
|
|
/* Warning 타입 */
|
|
.alert-warning .common-alert-icon { background:rgba(255,152,0,0.1); }
|
|
.alert-warning .common-alert-icon i { color:#ff9800; }
|
|
.alert-warning .common-alert-btn { background:#ff9800; color:#fff; }
|
|
.alert-warning .common-alert-btn:hover { background:#f57c00; }
|
|
|
|
/* Error 타입 */
|
|
.alert-error .common-alert-icon { background:rgba(244,67,54,0.1); }
|
|
.alert-error .common-alert-icon i { color:#f44336; }
|
|
.alert-error .common-alert-btn { background:#f44336; color:#fff; }
|
|
.alert-error .common-alert-btn:hover { background:#d32f2f; }
|
|
|
|
/* Success 타입 */
|
|
.alert-success .common-alert-icon { background:rgba(76,175,80,0.1); }
|
|
.alert-success .common-alert-icon i { color:#4caf50; }
|
|
.alert-success .common-alert-btn { background:#4caf50; color:#fff; }
|
|
.alert-success .common-alert-btn:hover { background:#388e3c; }
|
|
</style>
|