미필 일단 업로드까진 완료
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"%>
|
<%@ 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="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>
|
<style>
|
||||||
.upload-area {
|
@keyframes spin {
|
||||||
padding: 20px;
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
.upload-form {
|
.loading.active {
|
||||||
margin-bottom: 20px;
|
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;
|
.file-input-row:hover {
|
||||||
padding: 10px;
|
background-color: #e9ecef;
|
||||||
background: #f5f5f5;
|
border-color: #4CAF50;
|
||||||
border-radius: 4px;
|
}
|
||||||
|
|
||||||
|
.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;
|
.file-input-text i.material-icons {
|
||||||
margin-top: 20px;
|
font-size: 18px;
|
||||||
|
margin-right: 8px;
|
||||||
|
color: #4CAF50;
|
||||||
}
|
}
|
||||||
.upload-result {
|
|
||||||
margin-top: 15px;
|
.btn_delete_file {
|
||||||
padding: 10px;
|
padding: 4px;
|
||||||
|
background-color: #dc3545;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
border-radius: 4px;
|
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;
|
.btn_delete_file:hover {
|
||||||
color: #3c763d;
|
background-color: #c82333;
|
||||||
}
|
}
|
||||||
.upload-result.error {
|
|
||||||
background: #f2dede;
|
.btn_delete_file i.material-icons {
|
||||||
color: #a94442;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="upload-area">
|
<script type="text/javascript">
|
||||||
<h4><i class="fa fa-upload"></i> 미필 과태료 대상 PRN 파일 업로드</h4>
|
/**
|
||||||
<hr>
|
* TXT 파일 업로드 팝업 JavaScript
|
||||||
|
* 중요로직: 과태료 대상(미필) TXT 파일을 업로드하고 검증한다.
|
||||||
<form id="uploadForm" enctype="multipart/form-data">
|
*/
|
||||||
<div class="file-input-wrapper">
|
$(document).ready(function() {
|
||||||
<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>
|
/**
|
||||||
var contextPath = '${pageContext.request.contextPath}';
|
* 파일 업로드 버튼 클릭 이벤트
|
||||||
|
* 중요로직: 파일 선택 후 검증을 거쳐 서버로 업로드한다.
|
||||||
$(document).ready(function() {
|
*/
|
||||||
// 파일 선택 이벤트
|
$("#btnUpload").on('click', function() {
|
||||||
$('#file').change(function() {
|
uploadFile();
|
||||||
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();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function uploadFile() {
|
/**
|
||||||
var file = $('#file')[0].files[0];
|
* 닫기 버튼 클릭 이벤트
|
||||||
if (!file) {
|
*/
|
||||||
alert('파일을 선택해주세요.');
|
$("#btnClose, #btnCloseTop").on('click', function() {
|
||||||
return;
|
closePopup();
|
||||||
}
|
});
|
||||||
|
|
||||||
// 파일 확장자 검사
|
/**
|
||||||
var ext = file.name.split('.').pop().toLowerCase();
|
* 파일 선택 시 파일 정보 표시
|
||||||
if (ext !== 'prn' && ext !== 'txt') {
|
*/
|
||||||
alert('PRN 또는 TXT 파일만 업로드 가능합니다.');
|
$("#txtFile").on('change', function() {
|
||||||
return;
|
handleFileSelect(this);
|
||||||
}
|
});
|
||||||
|
|
||||||
var formData = new FormData();
|
/**
|
||||||
formData.append('file', file);
|
* 파일 삭제 버튼 클릭 이벤트
|
||||||
|
*/
|
||||||
$('#btnUpload').prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> 업로드 중...');
|
$("#btnClearFile").on('click', function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
$.ajax({
|
e.preventDefault();
|
||||||
url: contextPath + '/carInspectionPenalty/registration-om/upload.ajax',
|
clearFileInput();
|
||||||
type: 'POST',
|
});
|
||||||
data: formData,
|
});
|
||||||
processData: false,
|
|
||||||
contentType: false,
|
/**
|
||||||
success: function(response) {
|
* 파일 업로드 함수
|
||||||
if (response.success) {
|
* 중요로직: 파일 검증 후 FormData를 사용하여 파일을 서버로 전송한다.
|
||||||
$('#uploadResult')
|
*/
|
||||||
.removeClass('error')
|
function uploadFile() {
|
||||||
.addClass('success')
|
var fileInput = document.getElementById('txtFile');
|
||||||
.html('<i class="fa fa-check"></i> ' + response.message.replace(/\n/g, '<br>'))
|
var file = fileInput.files[0];
|
||||||
.show();
|
|
||||||
|
// 중요로직: 파일 선택 여부 검증
|
||||||
// 성공 시 파일 입력 초기화
|
if (!file) {
|
||||||
$('#file').val('');
|
alert("파일을 선택해주세요.");
|
||||||
$('#fileInfo').hide();
|
return;
|
||||||
} else {
|
}
|
||||||
$('#uploadResult')
|
|
||||||
.removeClass('success')
|
// 중요로직: 파일 확장자 검증
|
||||||
.addClass('error')
|
var fileName = file.name;
|
||||||
.html('<i class="fa fa-times"></i> ' + response.message.replace(/\n/g, '<br>'))
|
var fileExt = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
|
||||||
.show();
|
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) {
|
closePopup();
|
||||||
$('#uploadResult')
|
} else {
|
||||||
.removeClass('success')
|
alert(response.message || '파일 업로드에 실패했습니다.');
|
||||||
.addClass('error')
|
|
||||||
.html('<i class="fa fa-times"></i> 업로드 중 오류가 발생했습니다.')
|
|
||||||
.show();
|
|
||||||
},
|
|
||||||
complete: function() {
|
|
||||||
$('#btnUpload').prop('disabled', false).html('<i class="fa fa-upload"></i> 업로드');
|
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
}
|
error: function(xhr, status, error) {
|
||||||
|
// 로딩 숨김
|
||||||
function formatFileSize(bytes) {
|
$("#loading").removeClass('active');
|
||||||
if (bytes === 0) return '0 Bytes';
|
$("#btnUpload").prop('disabled', false);
|
||||||
var k = 1024;
|
|
||||||
var sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
console.error("업로드 오류:", error);
|
||||||
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
}
|
||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 파일 선택 처리 함수
|
||||||
|
* 선택된 파일명을 화면에 표시합니다.
|
||||||
|
*/
|
||||||
|
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>
|
</script>
|
||||||
|
|||||||
Loading…
Reference in New Issue