diff --git a/WebContent/WEB-INF/view/contractMgmt/estimateTemplate1.jsp b/WebContent/WEB-INF/view/contractMgmt/estimateTemplate1.jsp
index 166724f..31a6d85 100644
--- a/WebContent/WEB-INF/view/contractMgmt/estimateTemplate1.jsp
+++ b/WebContent/WEB-INF/view/contractMgmt/estimateTemplate1.jsp
@@ -64,6 +64,9 @@ String templateObjId = CommonUtils.checkNull(request.getParameter("templateObjId
.no-print {
display: none !important;
}
+ .delete-btn-cell button {
+ display: none !important;
+ }
}
body {
@@ -160,13 +163,15 @@ body {
width: 100%;
border-collapse: collapse;
margin-bottom: 30px;
+ table-layout: fixed;
}
.items-table th,
.items-table td {
border: 1px solid #000;
- padding: 3px 5px;
+ padding: 8px 2px;
text-align: center;
+ vertical-align: middle;
font-size: 9pt;
line-height: 1.3;
}
@@ -176,14 +181,15 @@ body {
font-weight: bold;
}
-.items-table .col-no { width: 6%; }
-.items-table .col-desc { width: 20%; }
+.items-table .col-no { width: 4%; }
+.items-table .col-desc { width: 12%; }
.items-table .col-spec { width: 22%; }
-.items-table .col-qty { width: 7%; }
-.items-table .col-unit { width: 8%; }
-.items-table .col-price { width: 11%; }
-.items-table .col-amount { width: 11%; }
-.items-table .col-note { width: 15%; }
+.items-table .col-qty { width: 4%; }
+.items-table .col-unit { width: 5%; }
+.items-table .col-price { width: 14%; }
+.items-table .col-amount { width: 15%; }
+.items-table .col-note { width: 9%; white-space: normal; word-break: break-all; }
+.items-table td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.items-table .text-left {
text-align: left;
@@ -191,6 +197,8 @@ body {
.items-table .text-right {
text-align: right;
+ overflow: hidden;
+ word-break: break-all;
}
.notes-section {
@@ -262,6 +270,12 @@ textarea {
width: 100%;
font-family: inherit;
font-size: inherit;
+ box-sizing: border-box;
+}
+
+.item-price,
+.item-amount {
+ text-align: right;
}
.item-amount {
@@ -269,9 +283,12 @@ textarea {
}
textarea {
- resize: vertical;
- min-height: 25px;
- padding: 2px;
+ resize: none;
+ height: 1.3em;
+ min-height: auto;
+ padding: 0 2px;
+ white-space: nowrap;
+ overflow: hidden;
}
.editable {
@@ -373,7 +390,7 @@ $(function(){
$(document).on("blur", ".item-price", function(){
var val = $(this).val().replace(/,/g, "");
if(!isNaN(val) && val !== "") {
- $(this).val(Number(val).toLocaleString(undefined, {minimumFractionDigits: 0, maximumFractionDigits: 2}));
+ $(this).val(Number(val).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}));
}
fn_calculateTotal();
});
@@ -502,10 +519,16 @@ function fn_calculateTotalKRW(total) {
$("#totalAmountKRW").text("₩" + addComma(totalKRW));
}
-// 금액 포맷 (소수점 2자리 + 천단위 콤마)
+// 금액 포맷 (항상 소수점 2자리, 천단위 콤마)
function addComma(num) {
if(num === '' || num === null || num === undefined) return '';
- return Number(num).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
+ // DB에 콤마가 포함된 값이 저장된 경우를 위해 콤마 제거 후 파싱
+ var n = Number(String(num).replace(/,/g, ''));
+ if(isNaN(n)) return '';
+ return n.toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2
+ });
}
// 통화 기호 반환
@@ -702,7 +725,7 @@ function fn_loadContractItems(contractObjId) {
itemsHtml += '
';
itemsHtml += '| 계 | ';
itemsHtml += '0 | ';
- itemsHtml += ' | ';
+ itemsHtml += ' | ';
itemsHtml += '
';
// 원화환산 공급가액 행 추가 (숨김)
@@ -864,7 +887,7 @@ function fn_loadData() {
itemsHtml += '';
itemsHtml += '| 계 | ';
itemsHtml += '0 | ';
- itemsHtml += ' | ';
+ itemsHtml += ' | ';
itemsHtml += '
';
// 원화환산 공급가액 행 추가 (숨김)
@@ -1082,7 +1105,7 @@ function fn_loadTemplateData(templateObjId){
itemsHtml += '';
itemsHtml += '| 계 | ';
itemsHtml += '0 | ';
- itemsHtml += ' | ';
+ itemsHtml += ' | ';
itemsHtml += '
';
// 원화환산 공급가액 행 추가 (숨김)
@@ -1422,7 +1445,7 @@ function fn_save() {
규 격 SPECIFICATION |
수량 Q'TY |
단위 UNIT |
- 단 가 UNIT PRICE |
+ 단 가 UNIT PRICE |
금 액 AMOUNT |
비고 |
@@ -1458,7 +1481,7 @@ function fn_save() {
| 계 |
0 |
- |
+ |
@@ -1521,15 +1544,17 @@ function fn_replaceFormElementsWithText() {
$('.estimate-container').find('input[type="text"], textarea, select').each(function(idx) {
var $el = $(this);
var displayText = '';
-
+
if ($el.is('select')) {
displayText = $el.find('option:selected').text() || '';
} else {
displayText = $el.val() || '';
}
-
+
var computedStyle = window.getComputedStyle(this);
- var elWidth = $el.outerWidth();
+ // 단가/금액 컬럼이 좁아 잘릴 수 있으므로 부모 td의 내부 너비 사용
+ var parentTd = $el.closest('td');
+ var elWidth = parentTd.length > 0 ? parentTd.innerWidth() : $el.outerWidth();
var span = $('');
span.text(displayText);
span.css({
@@ -1604,29 +1629,31 @@ function fn_generatePdf() {
}
});
- // 버튼 영역 임시 숨김
+ // 버튼 영역 임시 숨김 (삭제 버튼 셀 전체 숨김으로 PDF에 노출 방지)
$('.btn-area').hide();
-
+ $('.btn-delete-row').hide();
+ $('.btn-delete-total-row').hide();
+
// 폼 요소를 텍스트로 변환 (html2canvas 글자 잘림 방지)
var formBackup = fn_replaceFormElementsWithText();
-
+
// PDF 생성을 위해 스타일 조정
var container = $('.estimate-container');
var originalBg = container.css('background');
var originalShadow = container.css('box-shadow');
var originalPadding = container.css('padding');
-
+
// 깔끔한 PDF를 위해 배경, 그림자, 패딩 제거
container.css({
'background': 'white',
'box-shadow': 'none',
'padding': '10mm'
});
-
+
// body 배경색도 흰색으로
var originalBodyBg = $('body').css('background-color');
$('body').css('background-color', 'white');
-
+
// 견적서 컨테이너 캡처
html2canvas(document.querySelector('.estimate-container'), {
scale: 2, // 적절한 해상도 (파일 크기 최적화)
@@ -1645,6 +1672,8 @@ function fn_generatePdf() {
fn_restoreFormElements(formBackup);
// 버튼 영역 다시 표시
$('.btn-area').show();
+ $('.btn-delete-row').show();
+ $('.btn-delete-total-row').show();
try {
// Canvas를 JPEG 이미지로 변환 (PNG보다 파일 크기 작음)
@@ -1696,6 +1725,8 @@ function fn_generatePdf() {
}).catch(function(error) {
fn_restoreFormElements(formBackup);
$('.btn-area').show();
+ $('.btn-delete-row').show();
+ $('.btn-delete-total-row').show();
Swal.close();
console.error('Canvas 캡처 오류:', error);
Swal.fire({
@@ -1709,7 +1740,7 @@ function fn_generatePdf() {
// PDF를 Base64로 생성하여 서버로 전송하는 함수
function fn_generateAndUploadPdf(callback) {
console.log('fn_generateAndUploadPdf 호출됨');
-
+
// 라이브러리 로드 확인
if(typeof html2canvas === 'undefined' || typeof jsPDF === 'undefined') {
console.error('필요한 라이브러리가 로드되지 않았습니다.');
@@ -1718,30 +1749,32 @@ function fn_generateAndUploadPdf(callback) {
}
return;
}
-
- // 버튼 영역 임시 숨김
+
+ // 버튼 영역 임시 숨김 (삭제 버튼 셀 전체 숨김으로 PDF에 노출 방지)
$('.btn-area').hide();
-
+ $('.btn-delete-row').hide();
+ $('.btn-delete-total-row').hide();
+
// 폼 요소를 텍스트로 변환 (html2canvas 글자 잘림 방지)
var formBackup = fn_replaceFormElementsWithText();
-
+
// PDF 생성을 위해 스타일 조정
var container = $('.estimate-container');
var originalBg = container.css('background');
var originalShadow = container.css('box-shadow');
var originalPadding = container.css('padding');
-
+
// 깔끔한 PDF를 위해 배경, 그림자, 패딩 제거
container.css({
'background': 'white',
'box-shadow': 'none',
'padding': '10mm'
});
-
+
// body 배경색도 흰색으로
var originalBodyBg = $('body').css('background-color');
$('body').css('background-color', 'white');
-
+
// 견적서 컨테이너 캡처
html2canvas(document.querySelector('.estimate-container'), {
scale: 2, // 적절한 해상도 (파일 크기 최적화)
@@ -1750,7 +1783,7 @@ function fn_generateAndUploadPdf(callback) {
backgroundColor: '#ffffff'
}).then(function(canvas) {
console.log('Canvas 캡처 완료');
-
+
// 스타일 복원
container.css({
'background': originalBg,
@@ -1758,12 +1791,14 @@ function fn_generateAndUploadPdf(callback) {
'padding': originalPadding
});
$('body').css('background-color', originalBodyBg);
-
+
// 폼 요소 복원
fn_restoreFormElements(formBackup);
-
+
// 버튼 영역 다시 표시
$('.btn-area').show();
+ $('.btn-delete-row').show();
+ $('.btn-delete-total-row').show();
try {
// Canvas를 JPEG 이미지로 변환 (PNG보다 파일 크기 작음)
@@ -1809,6 +1844,8 @@ function fn_generateAndUploadPdf(callback) {
}).catch(function(error) {
fn_restoreFormElements(formBackup);
$('.btn-area').show();
+ $('.btn-delete-row').show();
+ $('.btn-delete-total-row').show();
console.error('Canvas 캡처 오류:', error);
if(callback && typeof callback === 'function') {
callback(null);
diff --git a/WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp b/WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp
index 2573c81..7dc1cdb 100644
--- a/WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp
+++ b/WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp
@@ -29,6 +29,9 @@ boolean isApproved = "결재완료".equals(apprStatus) || "결재중".equals(app
.no-print {
display: none !important;
}
+ .delete-btn-cell button {
+ display: none !important;
+ }
}
body {
@@ -530,10 +533,16 @@ function fn_calculateSubtotal(tbody) {
tbody.find(".subtotal-amount").val(addComma(total));
}
-// 금액 포맷 (소수점 2자리 + 천단위 콤마)
+// 금액 포맷 (항상 소수점 2자리, 천단위 콤마)
function addComma(num) {
if(num === '' || num === null || num === undefined) return '';
- return Number(num).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
+ // DB에 콤마가 포함된 값이 저장된 경우를 위해 콤마 제거 후 파싱
+ var n = Number(String(num).replace(/,/g, ''));
+ if(isNaN(n)) return '';
+ return n.toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2
+ });
}
// 카테고리 추가
@@ -558,7 +567,7 @@ function fn_addCategory() {
'
' +
'| ' + newCategoryNo + ' | ' +
'' + newCategoryName + ' | ' +
- '' +
+ ' | ' +
'' +
' | ' +
'
' +
@@ -622,7 +631,7 @@ function fn_createCategoryFromData(category) {
'' +
'| ' + categoryNo + ' | ' +
'' + categoryName + ' | ' +
- '' +
+ ' | ' +
'' +
' | ' +
'
' +
@@ -1069,9 +1078,10 @@ function fn_generateAndUploadPdf(callback) {
return;
}
- // 버튼 영역 임시 숨김
+ // 버튼 영역 임시 숨김 (삭제 버튼 셀 전체 숨김으로 PDF에 노출 방지)
$('.estimate-btn-area').hide();
-
+ $('.btn-delete-category').hide();
+
// textarea를 div로 변환 (줄바꿈 보존)
var textareaBackup = [];
$('textarea').each(function(index) {
@@ -1140,7 +1150,8 @@ function fn_generateAndUploadPdf(callback) {
// 버튼 영역 다시 표시
$('.estimate-btn-area').show();
-
+ $('.btn-delete-category').show();
+
try {
// Canvas를 JPEG 이미지로 변환 (PNG보다 파일 크기 작음)
var imgData = canvas.toDataURL('image/jpeg', 0.85); // 85% 품질
@@ -1189,6 +1200,7 @@ function fn_generateAndUploadPdf(callback) {
});
$('.estimate-btn-area').show();
+ $('.btn-delete-category').show();
console.error('Canvas 캡처 오류:', error);
if(callback && typeof callback === 'function') {
callback(null);
@@ -1302,7 +1314,7 @@ function fn_generateAndUploadPdf(callback) {
| 1 |
기구 |
-
+ |
|
@@ -1366,7 +1378,7 @@ Z: SRG25 P급, C0
| 2 |
초음파 스핀들 모듈 |
-
+ |
|
@@ -1407,7 +1419,7 @@ Z: SRG25 P급, C0
| 3 |
전장 |
-
+ |
|
@@ -1451,7 +1463,7 @@ SIEMENS CONTROL PANEL 828D
| 4 |
UTILITY |
-
+ |
|
@@ -1521,7 +1533,7 @@ LUBRICATION
| 5 |
Option |
-
+ |
|
@@ -1570,7 +1582,7 @@ NV4Blue(Renishaw)
| 6 |
Set up |
-
+ |
|
@@ -1615,7 +1627,7 @@ NV4Blue(Renishaw)
| 7 |
포장/물류 |
-
+ |
|