ui(cupang): 폼 프레임 크기 고정 + 라인 추가/삭제 버튼 하단 우측

- 공통 헤더 450px, 품목 라인 900x900 내부 스크롤
- 저장/취소 위 구분선 제거
- 라인 추가 + 라인 삭제 버튼을 품목 라인 하단 우측에 배치
- 행별 ✕ 삭제 제거 → "라인 삭제"가 마지막 라인 삭제(최소 1줄 유지)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-05-30 05:24:49 +09:00
parent d4e823f1fa
commit 150335cf87
3 changed files with 36 additions and 14 deletions
@@ -76,18 +76,21 @@
</span>
</div>
<div class="erp-table-wrap">
<div class="erp-table-wrap cpg-lines-scroll">
<table class="erp-table cpg-lines">
<thead>
<tr>
<th>#</th><th>제품명</th><th>제품코드</th><th>수량</th>
<th>입수량</th><th>박스 계산</th><th>라인메모</th><th></th>
<th>입수량</th><th>박스 계산</th><th>라인메모</th>
</tr>
</thead>
<tbody id="cpg-lines-body"><!-- JS 렌더 --></tbody>
</table>
</div>
<div class="cpg-lines-foot">
<button type="button" class="erp-btn erp-btn-outline" id="cpg-add-line">+ 라인 추가</button>
<button type="button" class="erp-btn erp-btn-danger" id="cpg-del-line">라인 삭제</button>
</div>
</div>
</div><!-- /cpg-form-2col -->
+19 -8
View File
@@ -75,17 +75,28 @@
.cpg-form-2col {
display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start;
}
.cpg-form-head { flex: 1 1 380px; min-width: 0; margin-bottom: 0; }
.cpg-form-lines { flex: 1 1 520px; min-width: 0; margin-bottom: 0; }
@media (max-width: 900px) {
.cpg-form-head, .cpg-form-lines { flex-basis: 100%; }
/* 공통 헤더: 너비 450 고정 */
.cpg-form-head { flex: 0 0 450px; width: 450px; min-width: 0; margin-bottom: 0; }
/* 품목 라인: 900x900 고정, 내부 스크롤 */
.cpg-form-lines {
flex: 0 0 900px; width: 900px; height: 900px; min-width: 0; margin-bottom: 0;
display: flex; flex-direction: column; overflow: hidden;
}
/* 저장/취소 — 공통 헤더 카드 하단에 위치(우측 라인 수와 무관) */
.cpg-form-actions {
margin-top: 16px;
@media (max-width: 1400px) {
.cpg-form-lines { flex-basis: auto; width: 100%; }
}
@media (max-width: 940px) {
.cpg-form-head { flex-basis: 100%; width: 100%; }
}
/* 라인 테이블 영역만 스크롤 (footer 는 하단 고정) */
.cpg-lines-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; }
.cpg-lines-foot {
display: flex; justify-content: flex-end; gap: 8px;
padding-top: 12px;
border-top: 1px solid var(--color-subtle-ash);
}
/* 저장/취소 — 공통 헤더 카드 하단에 위치(우측 라인 수와 무관) */
.cpg-form-actions { margin-top: 16px; }
.cpg-card-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.cpg-card-head h2 { font-size: 16px; font-weight: 600; margin: 0; }
+11 -3
View File
@@ -75,8 +75,7 @@
'<td><input class="erp-input cpg-qty" type="number" min="1" /></td>' +
'<td><input class="erp-input cpg-upb" type="number" min="1" placeholder="입수량" /></td>' +
'<td><span class="cpg-line-calc">—</span></td>' +
'<td><input class="erp-input cpg-memo" type="text" /></td>' +
'<td><button type="button" class="erp-btn erp-btn-outline cpg-line-del">✕</button></td>';
'<td><input class="erp-input cpg-memo" type="text" /></td>';
var code = data.product_code || "";
var nameSel = buildNameSelect(code);
@@ -104,7 +103,6 @@
}
});
tr.querySelector(".cpg-line-del").addEventListener("click", function () { tr.remove(); renumber(); });
tr.querySelector(".cpg-qty").addEventListener("input", function () { recalc(tr); });
tr.querySelector(".cpg-upb").addEventListener("input", function () { recalc(tr); });
@@ -123,6 +121,16 @@
// 초기 라인
if (initLines.length) { initLines.forEach(makeRow); } else { makeRow(); }
document.getElementById("cpg-add-line").addEventListener("click", function () { makeRow(); });
// 마지막 라인 삭제 (최소 1줄 유지)
var delBtn = document.getElementById("cpg-del-line");
if (delBtn) {
delBtn.addEventListener("click", function () {
var rows = body.querySelectorAll("tr");
if (rows.length <= 1) { alert("최소 1개 라인은 필요합니다."); return; }
rows[rows.length - 1].remove();
renumber();
});
}
// 제출: 라인 직렬화
form.addEventListener("submit", function (e) {