fix(cafe24): 옵션 모달 — 옵션 열 축소·품목 표 확대, 창 바닥까지 사용, 품목코드 복사

- 옵션 정의 열 400 → 340px, 모달 폭 1180 → 1280px. 품목 표 열 폭을 줄여
  옵션값 이름이 한 줄(넘치면 말줄임 + title)에 들어가게.
- 모달 높이를 90vh 고정으로 바꾸고 두 열이 바닥까지 늘어나 각자 스크롤
  (품목은 표만 스크롤, 저장 버튼 고정). 첫 구현 때 남은 옛 규칙
  `.cf24-variants-wrap { max-height: 320px }` 가 표 높이를 막고 있었다
  (헤드리스 크롬 실측으로 발견) — 제거.
- 품목코드 클릭 = 클립보드 복사("복사됨" 표시, 비보안 컨텍스트는 execCommand).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-18 18:50:28 +09:00
parent e838e8ee15
commit be0d44ded6
3 changed files with 96 additions and 28 deletions
@@ -1,7 +1,7 @@
{% extends "erp_base.html" %}
{% block head_extra %}
<link rel="stylesheet" href="/static/cafe24.css?v=20260918c" />
<link rel="stylesheet" href="/static/cafe24.css?v=20260918d" />
{% endblock %}
{% block content %}
@@ -1007,7 +1007,7 @@
}
// 옵션 정의 편집 (모달 왼쪽 열)
var html = '<div class="cf24-modal-grid"><section class="cf24-modal-col">' +
var html = '<div class="cf24-modal-grid"><section class="cf24-modal-col cf24-modal-col-options">' +
'<h4 class="cf24-side-title">옵션 정의</h4>' +
'<form class="cf24-side-form" id="cf24-opt-form">';
opt.options.forEach(function (o, gi) {
@@ -1041,7 +1041,7 @@
"</section>";
// 품목 표 (모달 오른쪽 열) — 넓은 창이라 한 줄에 다 들어간다.
html += '<section class="cf24-modal-col"><h4 class="cf24-side-title">품목 (' + variants.length + ')</h4>';
html += '<section class="cf24-modal-col cf24-modal-col-variants"><h4 class="cf24-side-title">품목 (' + variants.length + ')</h4>';
if (!variants.length) {
html += '<p class="cf24-muted">품목이 아직 조회되지 않았습니다. 잠시 뒤 창을 닫았다 다시 여세요.</p>';
} else {
@@ -1054,8 +1054,8 @@
var amount = String(parseInt(v.additional_amount || "0", 10) || 0);
html += '<tr class="cf24-v-item" data-code="' + escHtml(v.variant_code) + '">' +
'<td class="cf24-v-imgcol">' + (v.image ? '<img class="cf24-v-img" src="' + escHtml(v.image) + '" alt="" />' : '<span class="cf24-v-img cf24-v-img-empty"></span>') + "</td>" +
'<td class="cf24-v-name">' + escHtml(label) + "</td>" +
'<td class="cf24-v-syscode"><code>' + escHtml(v.variant_code) + "</code></td>" +
'<td class="cf24-v-name" title="' + escHtml(label) + '">' + escHtml(label) + "</td>" +
'<td class="cf24-v-syscode"><button type="button" class="cf24-v-copy" data-copy-text="' + escHtml(v.variant_code) + '" title="클릭하면 품목코드를 복사합니다">' + escHtml(v.variant_code) + "</button></td>" +
'<td class="cf24-v-code"><input type="text" name="custom_variant_code" maxlength="40" value="' + escHtml(v.custom_variant_code) + '" /></td>' +
'<td class="cf24-v-amount"><input type="text" name="additional_amount" inputmode="numeric" value="' + escHtml(amount) + '" /></td>' +
'<td class="cf24-v-flag"><button type="button" class="cf24-v-toggle' + (v.display ? " is-on" : "") + '" data-flag="display" data-on="' + (v.display ? 1 : 0) + '" data-initial="' + (v.display ? 1 : 0) + '">' + (v.display ? "진열" : "미진열") + "</button></td>" +
@@ -1147,6 +1147,34 @@
if (!saveBtn) return;
var wrap = body.querySelector(".cf24-variants-wrap");
trackDirty(wrap);
// 품목코드 클릭 = 클립보드 복사 (HTTPS 가 아니면 execCommand 로 대체)
wrap.querySelectorAll(".cf24-v-copy").forEach(function (btn) {
btn.addEventListener("click", function () {
var text = btn.dataset.copyText || btn.textContent;
var done = function () {
var old = btn.textContent;
btn.textContent = "복사됨";
btn.classList.add("is-copied");
setTimeout(function () { btn.textContent = old; btn.classList.remove("is-copied"); }, 1200);
};
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(done, function () { fallbackCopy(text, done); });
} else {
fallbackCopy(text, done);
}
});
});
function fallbackCopy(text, done) {
var ta = document.createElement("textarea");
ta.value = text;
ta.setAttribute("readonly", "");
ta.style.position = "fixed";
ta.style.opacity = "0";
document.body.appendChild(ta);
ta.select();
try { if (document.execCommand("copy")) done(); } catch (e) { /* 복사 불가 — 조용히 무시 */ }
document.body.removeChild(ta);
}
wrap.querySelectorAll(".cf24-v-toggle").forEach(function (btn) {
btn.addEventListener("click", function () {
var on = btn.dataset.on !== "1";