미필 일단 업로드까진 완료
parent
40d8518a50
commit
20312693c6
File diff suppressed because it is too large
Load Diff
@ -1,163 +1,352 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
|
||||
<!-- 팝업 전용 CSS -->
|
||||
<link rel="stylesheet" type="text/css" href="<c:url value='/resources/xit/xit-popup.css'/>" />
|
||||
|
||||
<!-- TXT 파일 업로드 팝업 -->
|
||||
<div class="popup_wrap">
|
||||
<div class="popup_inner">
|
||||
<div class="popup_tit">
|
||||
<h2 class="tit">과태료 대상(미필) PRN 파일 업로드</h2>
|
||||
<a href="#" class="pop-x-btn modalclose" id="btnCloseTop"></a>
|
||||
</div>
|
||||
|
||||
<div class="popup_con">
|
||||
<form id="uploadForm" name="uploadForm">
|
||||
<div class="forms_table_non">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style="width: 20%;" />
|
||||
<col style="width: 80%;" />
|
||||
</colgroup>
|
||||
<tr>
|
||||
<th class="th"><span class="required">*</span> PRN 파일</th>
|
||||
<td>
|
||||
<div class="file-input-row">
|
||||
<input type="file" id="txtFile" name="txtFile" accept=".txt,.prn" class="file_input" />
|
||||
<span class="file-input-text">파일을 선택하세요</span>
|
||||
<button type="button" id="btnClearFile" class="btn_delete_file" style="display: none;" title="파일 삭제">
|
||||
<i class="material-icons">close</i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="file-info" style="margin-top: 10px; color: #666; font-size: 13px;">
|
||||
※ TXT, PRN 파일만 업로드 가능합니다. (최대 50MB)
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div class="file-format-info" style="padding: 15px; background-color: #fff3cd; border: 1px solid #ffc107; border-radius: 4px;">
|
||||
<ul style="margin: 0; padding-left: 15px; color: #856404; font-size: 13px;">
|
||||
<li>● 7~10 번째 줄은 헤더 및 라인구분 기호로 간주되어 스킵됩니다.</li>
|
||||
<li>● UTF-8 -> EUC-KR 변환 후 진행.</li>
|
||||
<li>● 데이터는 EUC-KR 한글 2Byte으로 구분됩니다.</li>
|
||||
<li>● 컬럼 순서: 접수일자, 프로그램ID, 차량번호, 소유자명, 주민등록번호, 자동차명, 사용본거지주소, 검사유효기간</li>
|
||||
<li>● 필수 항목: 접수일자, 차량번호, 소유자명, 검사유효기간</li>
|
||||
<li>● 날짜 형식: YYYY-MM-DD (예: 2023-11-13)</li>
|
||||
<li>● 차량번호 형식: 12가3456 또는 123가4567</li>
|
||||
<li>● 검사유효기간: YYYY-MM-DD ~ YYYY-MM-DD</li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- 중요로직: 로딩 표시 영역 -->
|
||||
<div class="loading" id="loading" style="display: none; text-align: center; padding: 20px;">
|
||||
<div class="spinner" style="border: 4px solid #f3f3f3; border-top: 4px solid #4CAF50; border-radius: 50%; width: 40px; height: 40px; animation: spin 1s linear infinite; margin: 0 auto 10px;"></div>
|
||||
<div>파일 업로드 중입니다. 잠시만 기다려주세요...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="popup_foot">
|
||||
<button type="button" id="btnUpload" class="newbtns bg1">파일 업로드</button>
|
||||
<button type="button" id="btnClose" class="newbtns bg2 modalclose">닫기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.upload-area {
|
||||
padding: 20px;
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
.upload-form {
|
||||
margin-bottom: 20px;
|
||||
.loading.active {
|
||||
display: block !important;
|
||||
}
|
||||
.file-input-wrapper {
|
||||
margin-bottom: 15px;
|
||||
|
||||
/* 파일 입력 스타일 */
|
||||
.file-input-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 15px;
|
||||
background-color: #f8f9fa;
|
||||
border: 2px dashed #dee2e6;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.file-info {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
background: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
|
||||
.file-input-row:hover {
|
||||
background-color: #e9ecef;
|
||||
border-color: #4CAF50;
|
||||
}
|
||||
|
||||
.file-input-row.has-file {
|
||||
background-color: #e7f3ff;
|
||||
border-color: #4CAF50;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.file_input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file-input-text {
|
||||
flex: 1;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
pointer-events: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.btn-area {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
|
||||
.file-input-text i.material-icons {
|
||||
font-size: 18px;
|
||||
margin-right: 8px;
|
||||
color: #4CAF50;
|
||||
}
|
||||
.upload-result {
|
||||
margin-top: 15px;
|
||||
padding: 10px;
|
||||
|
||||
.btn_delete_file {
|
||||
padding: 4px;
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background-color 0.3s ease;
|
||||
z-index: 10;
|
||||
position: relative;
|
||||
}
|
||||
.upload-result.success {
|
||||
background: #dff0d8;
|
||||
color: #3c763d;
|
||||
|
||||
.btn_delete_file:hover {
|
||||
background-color: #c82333;
|
||||
}
|
||||
.upload-result.error {
|
||||
background: #f2dede;
|
||||
color: #a94442;
|
||||
|
||||
.btn_delete_file i.material-icons {
|
||||
font-size: 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="upload-area">
|
||||
<h4><i class="fa fa-upload"></i> 미필 과태료 대상 PRN 파일 업로드</h4>
|
||||
<hr>
|
||||
|
||||
<form id="uploadForm" enctype="multipart/form-data">
|
||||
<div class="file-input-wrapper">
|
||||
<label for="file">PRN 파일 선택</label>
|
||||
<input type="file" class="form-control" id="file" name="file" accept=".prn,.txt">
|
||||
<p class="help-block">* PRN 또는 TXT 파일만 업로드 가능합니다.</p>
|
||||
<p class="help-block">* 업로드 시 UTF-8 → EUC-KR 변환됩니다.</p>
|
||||
</div>
|
||||
|
||||
<div id="fileInfo" class="file-info" style="display: none;">
|
||||
<strong>선택된 파일:</strong> <span id="fileName"></span><br>
|
||||
<strong>파일 크기:</strong> <span id="fileSize"></span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="uploadResult" class="upload-result" style="display: none;"></div>
|
||||
|
||||
<div class="btn-area">
|
||||
<button type="button" class="btn btn-primary" id="btnUpload" disabled>
|
||||
<i class="fa fa-upload"></i> 업로드
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" id="btnClose">
|
||||
<i class="fa fa-times"></i> 닫기
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
/**
|
||||
* TXT 파일 업로드 팝업 JavaScript
|
||||
* 중요로직: 과태료 대상(미필) TXT 파일을 업로드하고 검증한다.
|
||||
*/
|
||||
$(document).ready(function() {
|
||||
|
||||
<script>
|
||||
var contextPath = '${pageContext.request.contextPath}';
|
||||
|
||||
$(document).ready(function() {
|
||||
// 파일 선택 이벤트
|
||||
$('#file').change(function() {
|
||||
var file = this.files[0];
|
||||
if (file) {
|
||||
$('#fileName').text(file.name);
|
||||
$('#fileSize').text(formatFileSize(file.size));
|
||||
$('#fileInfo').show();
|
||||
$('#btnUpload').prop('disabled', false);
|
||||
$('#uploadResult').hide();
|
||||
} else {
|
||||
$('#fileInfo').hide();
|
||||
$('#btnUpload').prop('disabled', true);
|
||||
}
|
||||
});
|
||||
|
||||
// 업로드 버튼 클릭
|
||||
$('#btnUpload').click(function() {
|
||||
uploadFile();
|
||||
});
|
||||
|
||||
// 닫기 버튼 클릭
|
||||
$('#btnClose').click(function() {
|
||||
window.close();
|
||||
});
|
||||
/**
|
||||
* 파일 업로드 버튼 클릭 이벤트
|
||||
* 중요로직: 파일 선택 후 검증을 거쳐 서버로 업로드한다.
|
||||
*/
|
||||
$("#btnUpload").on('click', function() {
|
||||
uploadFile();
|
||||
});
|
||||
|
||||
function uploadFile() {
|
||||
var file = $('#file')[0].files[0];
|
||||
if (!file) {
|
||||
alert('파일을 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 파일 확장자 검사
|
||||
var ext = file.name.split('.').pop().toLowerCase();
|
||||
if (ext !== 'prn' && ext !== 'txt') {
|
||||
alert('PRN 또는 TXT 파일만 업로드 가능합니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
$('#btnUpload').prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> 업로드 중...');
|
||||
|
||||
$.ajax({
|
||||
url: contextPath + '/carInspectionPenalty/registration-om/upload.ajax',
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
$('#uploadResult')
|
||||
.removeClass('error')
|
||||
.addClass('success')
|
||||
.html('<i class="fa fa-check"></i> ' + response.message.replace(/\n/g, '<br>'))
|
||||
.show();
|
||||
|
||||
// 성공 시 파일 입력 초기화
|
||||
$('#file').val('');
|
||||
$('#fileInfo').hide();
|
||||
} else {
|
||||
$('#uploadResult')
|
||||
.removeClass('success')
|
||||
.addClass('error')
|
||||
.html('<i class="fa fa-times"></i> ' + response.message.replace(/\n/g, '<br>'))
|
||||
.show();
|
||||
|
||||
/**
|
||||
* 닫기 버튼 클릭 이벤트
|
||||
*/
|
||||
$("#btnClose, #btnCloseTop").on('click', function() {
|
||||
closePopup();
|
||||
});
|
||||
|
||||
/**
|
||||
* 파일 선택 시 파일 정보 표시
|
||||
*/
|
||||
$("#txtFile").on('change', function() {
|
||||
handleFileSelect(this);
|
||||
});
|
||||
|
||||
/**
|
||||
* 파일 삭제 버튼 클릭 이벤트
|
||||
*/
|
||||
$("#btnClearFile").on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
clearFileInput();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 파일 업로드 함수
|
||||
* 중요로직: 파일 검증 후 FormData를 사용하여 파일을 서버로 전송한다.
|
||||
*/
|
||||
function uploadFile() {
|
||||
var fileInput = document.getElementById('txtFile');
|
||||
var file = fileInput.files[0];
|
||||
|
||||
// 중요로직: 파일 선택 여부 검증
|
||||
if (!file) {
|
||||
alert("파일을 선택해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 중요로직: 파일 확장자 검증
|
||||
var fileName = file.name;
|
||||
var fileExt = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
|
||||
if (fileExt !== 'txt' && fileExt !== 'prn') {
|
||||
alert("TXT, PRN 파일만 업로드 가능합니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 중요로직: 파일 크기 검증 (50MB)
|
||||
if (file.size > 50 * 1024 * 1024) {
|
||||
alert("파일 크기는 50MB를 초과할 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 확인 메시지
|
||||
if (!confirm("선택한 파일을 업로드하시겠습니까?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 중요로직: FormData를 사용하여 파일 데이터 구성
|
||||
var formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
// 로딩 표시
|
||||
$("#loading").addClass('active');
|
||||
$("#btnUpload").prop('disabled', true);
|
||||
|
||||
// 중요로직: AJAX로 파일 업로드
|
||||
$.ajax({
|
||||
url: '<c:url value="/carInspectionPenalty/registration-om/upload.ajax"/>',
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function(response) {
|
||||
// 로딩 숨김
|
||||
$("#loading").removeClass('active');
|
||||
$("#btnUpload").prop('disabled', false);
|
||||
|
||||
if (response.success) {
|
||||
alert(response.message);
|
||||
|
||||
// 중요로직: 부모 창의 목록 새로고침
|
||||
if (window.opener && window.opener.CarFfnlgTrgtIncmpList) {
|
||||
window.opener.CarFfnlgTrgtIncmpList.grid.reload();
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$('#uploadResult')
|
||||
.removeClass('success')
|
||||
.addClass('error')
|
||||
.html('<i class="fa fa-times"></i> 업로드 중 오류가 발생했습니다.')
|
||||
.show();
|
||||
},
|
||||
complete: function() {
|
||||
$('#btnUpload').prop('disabled', false).html('<i class="fa fa-upload"></i> 업로드');
|
||||
|
||||
closePopup();
|
||||
} else {
|
||||
alert(response.message || '파일 업로드에 실패했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
var k = 1024;
|
||||
var sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
// 로딩 숨김
|
||||
$("#loading").removeClass('active');
|
||||
$("#btnUpload").prop('disabled', false);
|
||||
|
||||
console.error("업로드 오류:", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일 선택 처리 함수
|
||||
* 선택된 파일명을 화면에 표시합니다.
|
||||
*/
|
||||
function handleFileSelect(fileInput) {
|
||||
var $fileRow = $('.file-input-row');
|
||||
var $fileText = $('.file-input-text');
|
||||
var $btnClear = $('#btnClearFile');
|
||||
|
||||
if (fileInput.files && fileInput.files.length > 0) {
|
||||
var file = fileInput.files[0];
|
||||
var fileName = file.name;
|
||||
var fileSize = file.size;
|
||||
|
||||
// 파일 크기를 읽기 쉬운 형태로 변환
|
||||
var fileSizeText = formatFileSize(fileSize);
|
||||
|
||||
// 파일명과 크기를 표시
|
||||
$fileText.html(
|
||||
'<i class="material-icons" style="font-size: 18px; margin-right: 8px;">insert_drive_file</i>' +
|
||||
'<span style="color: #333; font-weight: 500;">' + fileName + '</span>' +
|
||||
'<span style="color: #666; font-size: 12px; margin-left: 8px;">(' + fileSizeText + ')</span>'
|
||||
);
|
||||
$fileText.attr('title', fileName);
|
||||
|
||||
// 파일이 선택된 상태 표시
|
||||
$fileRow.addClass('has-file');
|
||||
$btnClear.show();
|
||||
|
||||
// 파일 정보도 업데이트
|
||||
$('.file-info').html(
|
||||
/*'선택된 파일: <strong>' + fileName + '</strong> ' +*/
|
||||
'파일 크기: ' + fileSizeText
|
||||
);
|
||||
} else {
|
||||
clearFileInput();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일 크기를 읽기 쉬운 형태로 변환
|
||||
*/
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
|
||||
var k = 1024;
|
||||
var sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일 입력 초기화
|
||||
*/
|
||||
function clearFileInput() {
|
||||
var $fileInput = $('#txtFile');
|
||||
var $fileRow = $('.file-input-row');
|
||||
var $fileText = $('.file-input-text');
|
||||
var $btnClear = $('#btnClearFile');
|
||||
|
||||
// 파일 입력 초기화
|
||||
$fileInput.val('');
|
||||
|
||||
// 기본 텍스트 표시
|
||||
$fileText.html('파일을 선택하세요');
|
||||
$fileText.removeAttr('title');
|
||||
|
||||
// 파일 선택 상태 제거
|
||||
$fileRow.removeClass('has-file');
|
||||
$btnClear.hide();
|
||||
|
||||
// 파일 정보 초기화
|
||||
$('.file-info').html('※ TXT, PRN 파일만 업로드 가능합니다. (최대 50MB)');
|
||||
}
|
||||
|
||||
/**
|
||||
* 팝업 닫기 함수
|
||||
*/
|
||||
function closePopup() {
|
||||
window.close();
|
||||
}
|
||||
</script>
|
||||
|
||||
Loading…
Reference in New Issue