348 lines
9.2 KiB
Plaintext
348 lines
9.2 KiB
Plaintext
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||
<%@ page import="com.pms.common.utils.*"%>
|
||
<%@ page import="java.util.*" %>
|
||
<%@include file= "/init.jsp" %>
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<title><%=Constants.SYSTEM_NAME%></title>
|
||
<style>
|
||
/* 이미지 미리보기 영역 */
|
||
.image-preview-container {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 10px;
|
||
padding: 10px;
|
||
max-height: 300px;
|
||
overflow-y: auto;
|
||
border: 1px solid #ddd;
|
||
border-radius: 4px;
|
||
background: #f9f9f9;
|
||
}
|
||
.image-preview-item {
|
||
position: relative;
|
||
width: 120px;
|
||
height: 120px;
|
||
border: 1px solid #ccc;
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
background: #fff;
|
||
}
|
||
.image-preview-item img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
cursor: pointer;
|
||
}
|
||
.image-preview-item .delete-btn {
|
||
position: absolute;
|
||
top: 2px;
|
||
right: 2px;
|
||
width: 20px;
|
||
height: 20px;
|
||
background: rgba(255, 0, 0, 0.8);
|
||
color: white;
|
||
border: none;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
font-size: 12px;
|
||
line-height: 18px;
|
||
text-align: center;
|
||
}
|
||
.image-preview-item .delete-btn:hover {
|
||
background: rgba(255, 0, 0, 1);
|
||
}
|
||
.image-preview-item .file-name {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
background: rgba(0,0,0,0.6);
|
||
color: white;
|
||
font-size: 10px;
|
||
padding: 2px 4px;
|
||
text-overflow: ellipsis;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
}
|
||
.no-image-msg {
|
||
width: 100%;
|
||
text-align: center;
|
||
color: #999;
|
||
padding: 30px;
|
||
}
|
||
/* 드래그앤드롭 영역 */
|
||
.drop-zone {
|
||
border: 2px dashed #ccc;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
text-align: center;
|
||
color: #666;
|
||
margin-bottom: 10px;
|
||
transition: all 0.3s;
|
||
}
|
||
.drop-zone.dragover {
|
||
border-color: #007bff;
|
||
background: #e8f4ff;
|
||
}
|
||
.drop-zone p {
|
||
margin: 0;
|
||
font-size: 14px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<script>
|
||
var callbackFnc = "${param.callbackFnc}";
|
||
var _isChanged = false;
|
||
var _fileCnt = 0;
|
||
|
||
// 이미지 확장자 목록
|
||
var allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
|
||
|
||
$(document).ready(function(){
|
||
|
||
$("#btn_close").click(function(){
|
||
openerCallback();
|
||
self.close(0);
|
||
});
|
||
|
||
// 드래그앤드롭 이벤트 설정
|
||
setupDropZone();
|
||
|
||
// 이미지 목록 조회
|
||
loadImageList();
|
||
|
||
// 파일 선택 시 확장자 검사
|
||
$("#imageFile").change(function(){
|
||
validateImageFiles(this.files);
|
||
});
|
||
|
||
// 업로드 버튼
|
||
$("#btnUpload").click(function(){
|
||
var files = $("#imageFile")[0].files;
|
||
if(files.length > 0){
|
||
if(validateImageFiles(files)){
|
||
uploadImages(files);
|
||
}
|
||
}else{
|
||
Swal.fire("선택된 이미지가 없습니다.");
|
||
}
|
||
});
|
||
});
|
||
|
||
// 드래그앤드롭 영역 설정
|
||
function setupDropZone(){
|
||
var dropZone = document.getElementById("imageDropZone");
|
||
|
||
dropZone.addEventListener("dragover", function(e){
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
$(this).addClass("dragover");
|
||
});
|
||
|
||
dropZone.addEventListener("dragleave", function(e){
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
$(this).removeClass("dragover");
|
||
});
|
||
|
||
dropZone.addEventListener("drop", function(e){
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
$(this).removeClass("dragover");
|
||
|
||
var files = e.dataTransfer.files;
|
||
if(files.length > 0){
|
||
if(validateImageFiles(files)){
|
||
uploadImages(files);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 이미지 파일 검증
|
||
function validateImageFiles(files){
|
||
for(var i = 0; i < files.length; i++){
|
||
var fileName = files[i].name;
|
||
var ext = fileName.split('.').pop().toLowerCase();
|
||
|
||
if(allowedExtensions.indexOf(ext) === -1){
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: '허용되지 않는 파일 형식',
|
||
text: '이미지 파일만 업로드 가능합니다.\n허용 확장자: ' + allowedExtensions.join(', ')
|
||
});
|
||
$("#imageFile").val("");
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 이미지 업로드 - 기존 fnc_fileMultiUpload 함수 사용
|
||
function uploadImages(files){
|
||
fnc_fileMultiUpload(files, null, "${param.targetObjId}", "${param.docType}", "${param.docTypeName}", null, "loadImageList", null, "");
|
||
}
|
||
|
||
// 이미지 목록 조회
|
||
function loadImageList(){
|
||
$.ajax({
|
||
url: "/common/getFileList.do",
|
||
type: "POST",
|
||
data: {
|
||
"targetObjId": "${param.targetObjId}",
|
||
"docType": "${param.docType}"
|
||
},
|
||
dataType: "json",
|
||
async: false,
|
||
success: function(data){
|
||
// 부모 창 새로고침
|
||
if(opener && typeof opener.fn_search == "function"){
|
||
opener.fn_search();
|
||
}
|
||
_fileCnt = data.length;
|
||
renderImageList(data);
|
||
openerCallback();
|
||
},
|
||
error: function(){
|
||
console.error("이미지 목록 조회 실패");
|
||
}
|
||
});
|
||
}
|
||
|
||
// 이미지 목록 렌더링
|
||
function renderImageList(data){
|
||
var container = $("#imagePreviewArea");
|
||
container.empty();
|
||
|
||
if(data.length == 0){
|
||
container.append('<div class="no-image-msg">등록된 이미지가 없습니다.</div>');
|
||
return;
|
||
}
|
||
|
||
$.each(data, function(i, file){
|
||
var ext = file.UPPER_FILE_EXT;
|
||
// 이미지 파일인 경우만 표시
|
||
if(allowedExtensions.indexOf(ext.toLowerCase()) > -1){
|
||
// objId 기반으로 이미지 표시 (viewImageByObjId.do 사용)
|
||
var imgSrc = "/common/viewImageByObjId.do?objId=" + file.OBJID;
|
||
|
||
var html = '<div class="image-preview-item">';
|
||
html += '<img src="' + imgSrc + '" onclick="viewImage(\'' + imgSrc + '\')" title="클릭하여 원본보기">';
|
||
// 삭제 권한 체크
|
||
if(file.WRITER == "${connectUserId}" || "${connectUserId}" == "plm_admin"){
|
||
html += '<button type="button" class="delete-btn" onclick="deleteImage(\'' + file.OBJID + '\', event)" title="삭제">×</button>';
|
||
}
|
||
html += '<div class="file-name" title="' + file.REAL_FILE_NAME + '">' + file.REAL_FILE_NAME + '</div>';
|
||
html += '</div>';
|
||
container.append(html);
|
||
}
|
||
});
|
||
|
||
// 이미지가 하나도 없는 경우
|
||
if(container.children().length == 0){
|
||
container.append('<div class="no-image-msg">등록된 이미지가 없습니다.</div>');
|
||
}
|
||
}
|
||
|
||
// 이미지 원본 보기 - 새 창에서 이미지 표시
|
||
function viewImage(imgUrl){
|
||
var img = new Image();
|
||
img.src = imgUrl;
|
||
// 이미지 크기에 맞게 팝업 열기
|
||
img.onload = function(){
|
||
var width = Math.min(img.width + 30, 1200);
|
||
var height = Math.min(img.height + 30, 800);
|
||
window.open(imgUrl, "ImageViewPopUp", "width=" + width + ",height=" + height + ",scrollbars=yes,resizable=yes");
|
||
};
|
||
// 이미지 로딩 실패시 기본 크기로 열기
|
||
img.onerror = function(){
|
||
window.open(imgUrl, "ImageViewPopUp", "width=800,height=600,scrollbars=yes,resizable=yes");
|
||
};
|
||
}
|
||
|
||
// 이미지 삭제
|
||
function deleteImage(fileObjId, event){
|
||
// 이벤트 전파 방지
|
||
if(event){
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
}
|
||
|
||
if(confirm("이미지를 삭제하시겠습니까?")){
|
||
$.ajax({
|
||
url: "/common/deleteFileInfo.do",
|
||
type: "POST",
|
||
data: {"objId": fileObjId},
|
||
dataType: "json",
|
||
success: function(){
|
||
loadImageList();
|
||
// 부모 창 새로고침
|
||
if(opener && typeof opener.fn_search == "function"){
|
||
opener.fn_search();
|
||
}
|
||
},
|
||
error: function(){
|
||
alert("삭제 실패: 서버 통신 오류가 발생했습니다.");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
// 부모 창 콜백
|
||
function openerCallback(){
|
||
if((fnc_isEmpty(callbackFnc) || callbackFnc == "fnc_tabulCallbackFnc") && opener && opener.fnc_tabulCallbackFnc){
|
||
opener.fnc_tabulCallbackFnc("${param.targetObjId}", "${param.docType}", "${param.columnField}", _fileCnt);
|
||
}else if(fnc_checkNull(callbackFnc) != "" && opener){
|
||
opener.eval(callbackFnc+"();");
|
||
}
|
||
}
|
||
</script>
|
||
<body>
|
||
<form name="form1" action="" method="post">
|
||
<input type="hidden" name="fileList" id="fileList" />
|
||
<section class="business_staff_popup_min_width">
|
||
<div class="plm_menu_name">
|
||
<h2>
|
||
<span>이미지 등록</span>
|
||
</h2>
|
||
</div>
|
||
<div id="businessPopupFormWrap">
|
||
<table class="pmsPopupForm">
|
||
<tr>
|
||
<td class="input_title align_c" style="width:80px;">이미지<br>업로드</td>
|
||
<td>
|
||
<!-- 드래그앤드롭 영역 -->
|
||
<div id="imageDropZone" class="drop-zone">
|
||
<p>📷 이미지 파일을 여기에 드래그하거나 아래에서 선택하세요</p>
|
||
<p style="font-size:11px; color:#999; margin-top:5px;">허용 확장자: jpg, jpeg, png, gif, bmp, webp</p>
|
||
</div>
|
||
<!-- 파일 선택 -->
|
||
<div style="margin-bottom: 10px;">
|
||
<input type="file" name="imageFile" id="imageFile" multiple accept="image/*">
|
||
<input type="button" id="btnUpload" value="업로드" class="plm_btns">
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="input_title align_c">이미지<br>목록</td>
|
||
<td>
|
||
<!-- 이미지 미리보기 영역 -->
|
||
<div id="imagePreviewArea" class="image-preview-container">
|
||
<div class="no-image-msg">등록된 이미지가 없습니다.</div>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<div class="btn_wrap">
|
||
<div class="plm_btn_wrap_center">
|
||
<input type="button" value="닫기" id="btn_close" class="plm_btns">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</form>
|
||
</body>
|
||
</html>
|