fix(cupang): 혼합 상자 이동은 용량 제한 없이, ③ 목록 max-height 로 스크롤 보장
- mixPut/moveUnits 에서 용량 제한 제거. 이동 목록도 "가득"이어도 선택 가능 (채움률이 100% 를 넘으면 빨간색으로 표시만) - 부모 flex 높이 계산에 기대던 스크롤을 max-height 로 직접 지정 (③ 72vh, ① 표 64vh, ② 목록 64vh) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901q" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901r" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
@@ -766,10 +766,9 @@
|
|||||||
return (contents[key] || []).filter(function (it) { return it.product_code === code; })[0];
|
return (contents[key] || []).filter(function (it) { return it.product_code === code; })[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 상자에 담기 — 용량만큼만 들어간다. 담은 수량을 돌려준다.
|
// 상자에 담기 — 용량은 표시용일 뿐, 이동은 막지 않는다(넘치면 100% 초과 표시).
|
||||||
function mixPut(key, code, name, qty) {
|
function mixPut(key, code, name, qty) {
|
||||||
var room = mixRoomFor(key, code);
|
var put = qty;
|
||||||
var put = Math.min(room, qty);
|
|
||||||
if (put <= 0) return 0;
|
if (put <= 0) return 0;
|
||||||
var hit = mixItem(key, code);
|
var hit = mixItem(key, code);
|
||||||
if (hit) { hit.quantity += put; }
|
if (hit) { hit.quantity += put; }
|
||||||
@@ -809,12 +808,9 @@
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 상자 → 상자 이동. 실제로 옮긴 수량을 돌려준다(자리만큼만).
|
// 상자 → 상자 이동. 용량과 무관하게 요청한 수량을 옮긴다.
|
||||||
function moveUnits(fromKey, toKey, code, name, qty) {
|
function moveUnits(fromKey, toKey, code, name, qty) {
|
||||||
var room = mixRoomFor(toKey, code);
|
var pulled = mixPull(fromKey, code, qty);
|
||||||
var move = Math.min(qty, room);
|
|
||||||
if (move <= 0) return 0;
|
|
||||||
var pulled = mixPull(fromKey, code, move);
|
|
||||||
if (!pulled) return 0;
|
if (!pulled) return 0;
|
||||||
mixPut(toKey, code, name, pulled);
|
mixPut(toKey, code, name, pulled);
|
||||||
return pulled;
|
return pulled;
|
||||||
@@ -974,7 +970,7 @@
|
|||||||
mixKeysOf(cid).forEach(function (k) {
|
mixKeysOf(cid).forEach(function (k) {
|
||||||
if (k === fromKey) return;
|
if (k === fromKey) return;
|
||||||
var room = mixRoomFor(k, code);
|
var room = mixRoomFor(k, code);
|
||||||
opts += '<option value="' + esc(k) + '"' + (room ? "" : " disabled") + ">" +
|
opts += '<option value="' + esc(k) + '">' +
|
||||||
esc(labels[k] || k) + (room ? " (여유 " + room + "개)" : " (가득)") + "</option>";
|
esc(labels[k] || k) + (room ? " (여유 " + room + "개)" : " (가득)") + "</option>";
|
||||||
});
|
});
|
||||||
opts += '<option value="__new__">+ 새 상자로</option>';
|
opts += '<option value="__new__">+ 새 상자로</option>';
|
||||||
@@ -994,8 +990,7 @@
|
|||||||
(entry.count > 1 ? '<span class="cpg-tree-per">(' + it.quantity + "개 × " + entry.count + "상자)</span>" : "") +
|
(entry.count > 1 ? '<span class="cpg-tree-per">(' + it.quantity + "개 × " + entry.count + "상자)</span>" : "") +
|
||||||
"</li>";
|
"</li>";
|
||||||
}
|
}
|
||||||
var canAdd = mixRoomFor(entry.key, it.product_code) > 0 &&
|
var canAdd = !!boxHaving(cid, it.product_code, entry.key);
|
||||||
!!boxHaving(cid, it.product_code, entry.key);
|
|
||||||
return '<li><span class="cpg-tree-name">' + esc(it.product_name) + "</span>" +
|
return '<li><span class="cpg-tree-name">' + esc(it.product_name) + "</span>" +
|
||||||
'<span class="cpg-mix-ctl">' +
|
'<span class="cpg-mix-ctl">' +
|
||||||
'<button type="button" class="cpg-mix-step" data-mix-dec data-key="' + esc(entry.key) +
|
'<button type="button" class="cpg-mix-step" data-mix-dec data-key="' + esc(entry.key) +
|
||||||
@@ -1026,11 +1021,13 @@
|
|||||||
boxes += a.count;
|
boxes += a.count;
|
||||||
pieces += a.count * per;
|
pieces += a.count * per;
|
||||||
var isMix = a.key.indexOf("m:") === 0;
|
var isMix = a.key.indexOf("m:") === 0;
|
||||||
var fillTxt = isMix ? Math.round(mixFill(a.key) * 100) + "% 채움" : "";
|
var fillPct = isMix ? Math.round(mixFill(a.key) * 100) : 0;
|
||||||
|
var fillTxt = isMix ? fillPct + "% 채움" : "";
|
||||||
|
var fillCls = fillPct > 100 ? " is-over" : "";
|
||||||
items += '<li class="cpg-dist-item' + (isMix ? " is-mix" : "") + '" data-entry="' + a.id + '">' +
|
items += '<li class="cpg-dist-item' + (isMix ? " is-mix" : "") + '" data-entry="' + a.id + '">' +
|
||||||
'<div class="cpg-dist-line">' +
|
'<div class="cpg-dist-line">' +
|
||||||
'<span class="cpg-dist-name">' + esc(labels[a.key] || a.key) +
|
'<span class="cpg-dist-name">' + esc(labels[a.key] || a.key) +
|
||||||
(fillTxt ? ' <em class="cpg-mix-fill">' + fillTxt + "</em>" : "") + "</span>" +
|
(fillTxt ? ' <em class="cpg-mix-fill' + fillCls + '">' + fillTxt + "</em>" : "") + "</span>" +
|
||||||
'<input class="erp-input cpg-dist-qty" type="number" min="1" max="999" step="1" inputmode="numeric" value="' + a.count + '" />' +
|
'<input class="erp-input cpg-dist-qty" type="number" min="1" max="999" step="1" inputmode="numeric" value="' + a.count + '" />' +
|
||||||
'<span class="cpg-dist-unit">상자 · ' + (a.count * per) + "개</span>" +
|
'<span class="cpg-dist-unit">상자 · ' + (a.count * per) + "개</span>" +
|
||||||
'<button type="button" class="erp-btn erp-btn-danger cpg-dist-del" title="빼기" aria-label="빼기">✕</button>' +
|
'<button type="button" class="erp-btn erp-btn-danger cpg-dist-del" title="빼기" aria-label="빼기">✕</button>' +
|
||||||
@@ -1273,13 +1270,9 @@
|
|||||||
if (entry && entry.key.indexOf("m:") === 0) {
|
if (entry && entry.key.indexOf("m:") === 0) {
|
||||||
e.stopImmediatePropagation(); // 뒤 핸들러가 또 지우지 않게
|
e.stopImmediatePropagation(); // 뒤 핸들러가 또 지우지 않게
|
||||||
(contents[entry.key] || []).slice().forEach(function (it) {
|
(contents[entry.key] || []).slice().forEach(function (it) {
|
||||||
var left = it.quantity;
|
var rest = mixKeysOf(dcid).filter(function (k) { return k !== entry.key; });
|
||||||
while (left > 0) {
|
var dest = boxWithRoom(dcid, it.product_code, entry.key) || rest[0] || newMixBox(dcid);
|
||||||
var dest = boxWithRoom(dcid, it.product_code, entry.key) || newMixBox(dcid);
|
moveUnits(entry.key, dest, it.product_code, it.product_name, it.quantity);
|
||||||
var moved = moveUnits(entry.key, dest, it.product_code, it.product_name, left);
|
|
||||||
if (!moved) break;
|
|
||||||
left -= moved;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
syncMix(entry.key);
|
syncMix(entry.key);
|
||||||
render();
|
render();
|
||||||
@@ -1295,7 +1288,8 @@
|
|||||||
var cid = centerOfKey(key);
|
var cid = centerOfKey(key);
|
||||||
var item = mixItem(key, code);
|
var item = mixItem(key, code);
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
var to = boxWithRoom(cid, code, key) || newMixBox(cid);
|
var others = mixKeysOf(cid).filter(function (k) { return k !== key; });
|
||||||
|
var to = boxWithRoom(cid, code, key) || others[0] || newMixBox(cid);
|
||||||
var n = moveUnits(key, to, code, item.product_name, 1);
|
var n = moveUnits(key, to, code, item.product_name, 1);
|
||||||
if (!n) { msg.textContent = "옮길 자리가 없습니다."; return; }
|
if (!n) { msg.textContent = "옮길 자리가 없습니다."; return; }
|
||||||
render();
|
render();
|
||||||
@@ -1308,9 +1302,6 @@
|
|||||||
var ikey = inc.getAttribute("data-key");
|
var ikey = inc.getAttribute("data-key");
|
||||||
var icode = inc.getAttribute("data-code");
|
var icode = inc.getAttribute("data-code");
|
||||||
var icid = centerOfKey(ikey);
|
var icid = centerOfKey(ikey);
|
||||||
if (mixRoomFor(ikey, icode) <= 0) {
|
|
||||||
msg.textContent = "이 상자에 더 들어갈 자리가 없습니다."; return;
|
|
||||||
}
|
|
||||||
var from = boxHaving(icid, icode, ikey);
|
var from = boxHaving(icid, icode, ikey);
|
||||||
if (!from) { msg.textContent = "다른 상자에 이 제품이 없습니다."; return; }
|
if (!from) { msg.textContent = "다른 상자에 이 제품이 없습니다."; return; }
|
||||||
var src = mixItem(from, icode);
|
var src = mixItem(from, icode);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901q" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901r" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901q" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901r" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901q" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901r" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901q" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901r" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901q" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901r" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{# 출고 묶음 보기 — 상자 계산 화면과 같은 3열 구성. 읽기 전용(수정 없음). #}
|
{# 출고 묶음 보기 — 상자 계산 화면과 같은 3열 구성. 읽기 전용(수정 없음). #}
|
||||||
|
|||||||
@@ -1453,3 +1453,15 @@ body.cpg-dragging { cursor: grabbing; user-select: none; }
|
|||||||
flex: 1 1 auto; min-height: 0;
|
flex: 1 1 auto; min-height: 0;
|
||||||
overflow-y: auto; overflow-x: hidden;
|
overflow-y: auto; overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ③ 목록 스크롤 — 부모 높이 계산에 기대지 않도록 최대 높이를 직접 준다 */
|
||||||
|
.cpg-dist-card .cpg-dist-list {
|
||||||
|
max-height: min(72vh, 820px);
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
/* ①② 도 같은 방식으로 안전장치 */
|
||||||
|
.cpg-calc-card .erp-table-wrap { max-height: min(64vh, 720px); }
|
||||||
|
.cpg-calc-sum .cpg-sum-scroll { max-height: min(64vh, 720px); }
|
||||||
|
/* 용량 초과 표시 */
|
||||||
|
.cpg-mix-fill.is-over { color: var(--color-callout-red); font-weight: 600; }
|
||||||
|
|||||||
Reference in New Issue
Block a user