Files
wace_plm/WebContent/WEB-INF/view/partMng/structurePopupLeft.jsp

624 lines
17 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>
<link href="/css/tabulator/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="/js/tabulator/tabulator.min.js"></script>
<style>
::-webkit-scrollbar {
width: 10px;
height: 15px;
}
#structureTableWrap1 {
top: 56px;
width: 99%;
}
#structureName {
margin-bottom: 10px;
font-weight: bold;
}
#structureName2 {
margin-bottom: 10px;
font-size: 12px;
color: #666;
}
/* Tabulator 커스텀 스타일 */
.tabulator-row.level-1 { background-color: #fde9d9 !important; }
.tabulator-row.level-2 { background-color: #daeef3 !important; }
.tabulator-row.level-3 { background-color: #e4dfec !important; }
.tabulator-row.level-4 { background-color: #ebf1de !important; }
.tabulator-row.level-5 { background-color: #f2f2f2 !important; }
.tabulator-row.level-6 { background-color: #f2dcdb !important; }
.tabulator-row.level-7 { background-color: #eeece1 !important; }
.tabulator-row.level-8 { background-color: #dce6f1 !important; }
.tabulator-row.level-9 { background-color: #FFFFEB !important; }
.tabulator-row.level-10 { background-color: #ffffff !important; }
/* 파일 아이콘 스타일은 basic.css에서 관리 */
</style>
<script>
var _tabulGrid;
var selectedRowData = null;
$(function(){
if('${param.readonly}' == 'readonly'){
$("#structureName2").hide();
}
$("#btnExcel").click(function() {
fn_excel();
});
// 도면 업로드 버튼 클릭
$("#btnDrawingUpload").click(function() {
$("#drawingFiles").click();
});
// 파일 선택 이벤트
$("#drawingFiles").change(function() {
fn_uploadDrawingFiles(this.files);
});
// Tabulator 초기화
fn_initGrid();
});
// Tabulator 그리드 초기화
function fn_initGrid() {
var maxLevel = ${empty MAXLEV ? 1 : MAXLEV};
// 컬럼 정의
var columns = [
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '선택',
field: 'RADIO',
headerSort: false,
formatter: function(cell) {
var rowData = cell.getData();
return '<input type="radio" name="checkedPartNo" value="' + rowData.CHILD_OBJID + '" ' +
'data-OBJID="' + rowData.OBJID + '" ' +
'data-PART_NO="' + rowData.PART_NO + '" ' +
'data-PARENT_PART_NO="' + rowData.PARENT_PART_NO + '" ' +
'data-PART_NO_QTY="' + rowData.LAST_PART_OBJID + '" ' +
'data-PARENT_PARTS="' + rowData.PARENT_PARTS + '" ' +
'data-LAST_PART_OBJID="' + rowData.LAST_PART_OBJID + '" ' +
'data-PARENT_OBJID="' + rowData.PARENT_OBJID + '" ' +
'data-PART_OBJID="' + rowData.PART_OBJID + '" ' +
'data-BOM_LAST_PART_OBJID="' + rowData.BOM_LAST_PART_OBJID + '">';
},
cellClick: function(e, cell) {
var radio = $(e.target);
if(radio.is(':radio')) {
selectedRowData = cell.getData();
// 다른 라디오 버튼 해제
$('input[name=checkedPartNo]').not(radio).prop('checked', false);
}
}
}
];
// 수준 컬럼 그룹 (헤더는 하나, 서브 컬럼은 여러개)
var levelColumns = [];
for(var i = 1; i <= maxLevel; i++) {
levelColumns.push({
headerHozAlign: 'center',
hozAlign: 'center',
width: 30,
title: i,
field: 'LEVEL_' + i,
headerSort: false,
formatter: function(cell) {
return cell.getValue() === '*' ? '*' : '';
}
});
}
columns.push({
title: '수준',
headerHozAlign: 'center',
headerSort: false,
columns: levelColumns
});
// 나머지 컬럼 추가
columns.push(
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 150,
title: '품번',
field: 'PART_NO',
headerSort: false,
formatter: function(cell) {
var rowData = cell.getData();
return '<a href="#" onclick="openPartMngPopup(\'' +
rowData.PART_OBJID + '\',\'' +
rowData.LAST_PART_OBJID + '\',\'' +
rowData.CHILD_OBJID + '\',\'' +
rowData.BOM_LAST_PART_OBJID + '\');">' +
rowData.PART_NO + '</a>';
}
},
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 200,
title: '품명',
field: 'PART_NAME',
headerSort: false
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '수량',
field: 'QTY_TEMP',
headerSort: false,
editor: function(cell, onRendered, success, cancel) {
var rowData = cell.getData();
if(rowData.STATUS === 'adding') {
var input = $('<input type="text" style="width:100%; text-align:center;" maxlength="3"/>');
input.val(cell.getValue() || '0');
input.on('keydown', function(e) {
if(e.keyCode === 13) {
success(input.val());
} else if(e.keyCode === 27) {
cancel();
}
});
input.on('blur', function() {
success(input.val());
});
return input[0];
}
return false;
},
cellEdited: function(cell) {
var rowData = cell.getData();
fn_saveQty(rowData.CHILD_OBJID, cell.getValue(), rowData.PART_OBJID);
}
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 100,
title: '항목 수량',
field: 'ITEM_QTY',
headerSort: false
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '3D',
field: 'CU01_CNT',
headerSort: false,
formatter: function(cell) {
var rowData = cell.getData();
var isEmpty = cell.getValue() == 0;
return '<a href="#" class="File file_' + (isEmpty ? 'empty_' : '') + 'icon" ' +
'data-OBJID="' + rowData.LAST_PART_OBJID + '" ' +
'data-docType="3D_CAD" ' +
'data-docTypeName="3D CAD 첨부파일"></a>';
}
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '2D',
field: 'CU02_CNT',
headerSort: false,
formatter: function(cell) {
var rowData = cell.getData();
var isEmpty = cell.getValue() == 0;
return '<a href="#" class="File file_' + (isEmpty ? 'empty_' : '') + 'icon" ' +
'data-OBJID="' + rowData.LAST_PART_OBJID + '" ' +
'data-docType="2D_DRAWING_CAD" ' +
'data-docTypeName="2D(Drawing) CAD 첨부파일"></a>';
}
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: 'PDF',
field: 'CU03_CNT',
headerSort: false,
formatter: function(cell) {
var rowData = cell.getData();
var isEmpty = cell.getValue() == 0;
return '<a href="#" class="File file_' + (isEmpty ? 'empty_' : '') + 'icon" ' +
'data-OBJID="' + rowData.LAST_PART_OBJID + '" ' +
'data-docType="2D_PDF_CAD" ' +
'data-docTypeName="2D(PDF) CAD 첨부파일"></a>';
}
},
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 100,
title: '재료',
field: 'MATERIAL',
headerSort: false
},
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 120,
title: '열처리경도',
field: 'HEAT_TREATMENT_HARDNESS',
headerSort: false
},
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 120,
title: '열처리방법',
field: 'HEAT_TREATMENT_METHOD',
headerSort: false
},
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 120,
title: '표면처리',
field: 'SURFACE_TREATMENT',
headerSort: false
},
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 120,
title: '공급업체',
field: 'MAKER',
headerSort: false
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 120,
title: '범주 이름',
field: 'PART_TYPE_TITLE',
headerSort: false
}
);
_tabulGrid = new Tabulator("#structureGrid", {
layout: "fitColumns",
height: "650px",
pagination: false,
headerSort: false, // 정렬 비활성화
columns: columns,
rowFormatter: function(row) {
var data = row.getData();
$(row.getElement()).addClass('level-' + data.LEVEL);
},
ajaxURL: "/partMng/getStructureTreeJson.do",
ajaxParams: {
objId: "${info.OBJID}",
bomReportObjId: "${info.OBJID}",
search_type: "working" // adding 상태 포함해서 조회
},
ajaxResponse: function(url, params, response) {
// 서버 응답 데이터 가공
var processedData = [];
if(response && response.length > 0) {
var maxLevel = response[0].MAX_LEVEL || 1;
response.forEach(function(item) {
// Level 표시를 위한 동적 필드 생성
for(var i = 1; i <= maxLevel; i++) {
item['LEVEL_' + i] = (item.LEVEL == i) ? '*' : '';
}
processedData.push(item);
});
}
return processedData;
}
});
// 파일 아이콘 클릭 이벤트 (동적으로 생성된 요소)
$(document).on('click', '.File', function(e) {
e.preventDefault();
var popup_width = 800;
var popup_height = 335;
var objId = $(this).attr("data-OBJID");
var docType = $(this).attr("data-docType");
var docTypeName = $(this).attr("data-docTypeName");
var params = "?targetObjId=" + objId + "&docType=" + docType + "&docTypeName=" + docTypeName;
var url = "/projectConcept/FileRegistPopup.do" + params;
fn_centerPopup(popup_width, popup_height, url);
});
}
// 수량 저장
function fn_saveQty(leftObjId, qty, leftQtyParObjId){
$.ajax({
url: "/partMng/structureQtySave.do",
method: 'post',
data: {
"BOM_REPORT_OBJID": "${info.OBJID}",
"CHILD_OBJID": leftObjId,
"QTY_TEMP": qty,
"OBJID": leftQtyParObjId
},
dataType: 'json',
success: function(data) {
if(data.result){
Swal.fire('저장하였습니다.');
_tabulGrid.replaceData(); // 그리드 새로고침
// 부모 창(E-BOM 목록) 새로고침
if(window.opener && window.opener.fn_search) {
window.opener.fn_search();
}
}
},
error: function(jqxhr, status, error){
Swal.fire('저장 중 오류가 발생했습니다.');
}
});
}
// Part 상세 팝업
function openPartMngPopup(objId, lastPartObjid, childObjid, BOM_LAST_PART_OBJID){
var popup_width = 800;
var popup_height = 500;
var hiddenForm = document.hiddenForm;
var url = "/partMng/partMngFormPopUp.do";
if("" != objId){
url = "/partMng/partMngDetailPopUp.do?ACTION_TYPE=work";
}
var target = "partMngPopUp";
fn_centerPopup(popup_width, popup_height, url, target);
hiddenForm.action = url;
hiddenForm.OBJID.value = fnc_checkNull(BOM_LAST_PART_OBJID, objId);
if('working' == '${param.actionType}')
hiddenForm.OBJID.value = lastPartObjid;
hiddenForm.LAST_PART_OBJID.value = lastPartObjid;
hiddenForm.CHILD_OBJID.value = childObjid;
hiddenForm.target = target;
hiddenForm.submit();
}
// Excel 다운로드
function fn_excel() {
document.form1.actionType.value = "excel";
var form = document.form1;
form.action = "/partMng/structurePopupLeft.do";
form.submit();
}
// 선택된 행 데이터 가져오기 (Center 프레임에서 사용)
function getSelectedRowData() {
return selectedRowData;
}
// 필터 적용 함수
function fn_applyFilter() {
var partNo = $("#filterPartNo").val().trim();
var partName = $("#filterPartName").val().trim();
// 빈 값이 아닌 필터만 추가
var filters = [];
if(partNo) {
filters.push({field: "PART_NO", type: "like", value: partNo});
}
if(partName) {
filters.push({field: "PART_NAME", type: "like", value: partName});
}
// 필터가 있으면 적용, 없으면 전체 표시
if(filters.length > 0) {
_tabulGrid.setFilter(filters);
} else {
_tabulGrid.clearFilter();
}
}
// 필터 초기화 함수
function fn_resetFilter() {
$("#filterPartNo").val("");
$("#filterPartName").val("");
_tabulGrid.clearFilter();
}
// 도면 업로드 처리 함수
function fn_uploadDrawingFiles(files) {
if(!files || files.length === 0) {
Swal.fire('파일을 선택해주세요.');
return;
}
// 품번 목록 조회 (현재 BOM의 모든 품번)
var bomObjId = "${info.OBJID}";
if(!bomObjId) {
Swal.fire('BOM 정보를 찾을 수 없습니다.');
return;
}
// 파일 분류 및 처리
var filesByType = {
'3D': [], // stp 파일
'2D': [], // dwg, dxf 파일
'PDF': [] // pdf 파일
};
// 파일 확장자 확인 및 분류
for(var i = 0; i < files.length; i++) {
var file = files[i];
var fileName = file.name;
var lastDotIndex = fileName.lastIndexOf('.');
if(lastDotIndex === -1) {
continue; // 확장자가 없는 파일은 스킵
}
var ext = fileName.substring(lastDotIndex + 1).toLowerCase();
console.log('파일명: ' + fileName + ', 확장자: ' + ext); // 디버깅용
if(ext === 'stp' || ext === 'step') {
filesByType['3D'].push(file);
} else if(ext === 'dwg' || ext === 'dxf') {
filesByType['2D'].push(file);
} else if(ext === 'pdf') {
filesByType['PDF'].push(file);
}
}
// 업로드할 파일이 있는지 확인
var totalFiles = filesByType['3D'].length + filesByType['2D'].length + filesByType['PDF'].length;
if(totalFiles === 0) {
Swal.fire('업로드 가능한 파일 형식이 없습니다. (stp, dwg, dxf, pdf만 가능)');
return;
}
// 확인 메시지
var msg = '총 ' + totalFiles + '개의 파일을 업로드하시겠습니까?\n';
msg += '- 3D (STP): ' + filesByType['3D'].length + '개\n';
msg += '- 2D (DWG/DXF): ' + filesByType['2D'].length + '개\n';
msg += '- PDF: ' + filesByType['PDF'].length + '개';
Swal.fire({
title: '도면 다증 업로드',
text: msg,
icon: 'question',
showCancelButton: true,
confirmButtonText: '업로드',
cancelButtonText: '취소'
}).then(function(result) {
if(result.isConfirmed) {
fn_processDrawingUpload(bomObjId, filesByType);
}
});
}
// 실제 업로드 처리
function fn_processDrawingUpload(bomObjId, filesByType) {
// FormData 생성
var formData = new FormData();
formData.append('bomObjId', bomObjId);
// 모든 파일을 files 이름으로 추가 (MultipartRequest가 처리)
var allFiles = filesByType['3D'].concat(filesByType['2D']).concat(filesByType['PDF']);
for(var i = 0; i < allFiles.length; i++) {
formData.append('files', allFiles[i]);
}
// 로딩 표시 (구버전 SweetAlert2)
Swal.fire({
title: '업로드 중...',
text: '파일을 업로드하는 중입니다. 잠시만 기다려주세요.',
allowOutsideClick: false,
allowEscapeKey: false,
allowEnterKey: false,
showConfirmButton: false,
onOpen: function() {
Swal.showLoading();
}
});
// AJAX 업로드
$.ajax({
url: '/partMng/uploadDrawingFiles.do',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
Swal.close();
if(response.result === 'success') {
var successMsg = '도면 업로드가 완료되었습니다.\n\n';
successMsg += '- 성공: ' + response.successCount + '개\n';
if(response.failCount > 0) {
successMsg += '- 실패: ' + response.failCount + '개\n';
}
if(response.notFoundCount > 0) {
successMsg += '- 품번 미존재: ' + response.notFoundCount + '개\n';
}
Swal.fire({
title: '업로드 완료',
text: successMsg,
icon: response.failCount > 0 ? 'warning' : 'success'
}).then(function() {
// 그리드 새로고침
_tabulGrid.replaceData();
// 파일 input 초기화
$("#drawingFiles").val('');
});
} else {
Swal.fire({
title: '업로드 실패',
text: response.message || '도면 업로드 중 오류가 발생했습니다.',
icon: 'error'
});
}
},
error: function(xhr, status, error) {
Swal.close();
console.error('Upload error:', error);
console.error('Response:', xhr.responseText);
Swal.fire({
title: '업로드 실패',
text: '서버 오류가 발생했습니다: ' + error,
icon: 'error'
});
}
});
}
</script>
</head>
<body class="backcolor">
<form name="hiddenForm" id="hiddenForm" method="post">
<input type="hidden" name="OBJID" id="OBJID">
<input type="hidden" name="LAST_PART_OBJID" id="LAST_PART_OBJID">
<input type="hidden" name="CHILD_OBJID" id="CHILD_OBJID">
</form>
<form name="form1" action="" method="post" onsubmit="return false;">
<input type="hidden" name="objid" id="objid" value="${info.OBJID}" />
<input type="hidden" name="objId" id="objId" value="${info.OBJID}" />
<input type="hidden" name="actionType" value="" />
<!-- 필터 값을 저장하기 위한 hidden 필드 (top frame에서 값 전달) -->
<input type="hidden" id="filterPartNo" />
<input type="hidden" id="filterPartName" />
<div id="structureTableWrap1">
<div id="structureName">
<span style="font-weight: bold; color: #333;">
<c:choose>
<c:when test="${not empty info.PART_NO}">
${info.PART_NO}
</c:when>
<c:otherwise>
(${info.CUSTOMER_NAME}_${info.CUSTOMER_PROJECT_NAME}_${info.UNIT_NAME})_${info.REVISION}
</c:otherwise>
</c:choose>
</span>
<input type="button" value="Excel Download" class="plm_btns structure_btn" id="btnExcel" style="float:right;">
<input type="button" value="도면 다중 업로드" class="plm_btns structure_btn" id="btnDrawingUpload" style="float:right; margin-right:5px;">
<input type="file" id="drawingFiles" multiple style="display:none;" accept=".stp,.step,.dwg,.dxf,.pdf">
</div>
<div id="structureGrid"></div>
</div>
</form>
</body>
</html>