From 18015418d9a0c5108ecac3331f59c9b0154b3aaa Mon Sep 17 00:00:00 2001 From: king Date: Fri, 18 Sep 2026 18:13:09 +0900 Subject: [PATCH] =?UTF-8?q?fix(cafe24):=20=EC=98=B5=EC=85=98=EA=B0=92=20?= =?UTF-8?q?=EC=8D=B8=EB=84=A4=EC=9D=BC=20=ED=83=90=EC=83=89=20=ED=99=95?= =?UTF-8?q?=EB=8C=80=20+=20=ED=92=88=EB=AA=A9=EC=9D=84=202=EC=A4=84=20?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=EB=A1=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 옵션값 썸네일이 option_image_file 만 봐서 "없음"으로 나왔다. 카페24 관리자에서 "옵션 연결 이미지"로만 등록한 상품은 그 필드가 비어 있고 품목 image 에만 나타난다(실물). option_image_file → option_link_image → 해당 옵션값을 가진 품목의 image 순으로 찾는다. - 품목 표가 380px 패널에 좁아 옵션값 이름이 아이콘 아래로 꺾여 잘렸다. 품목마다 2줄 카드(아이콘+이름 / 자체코드·추가금액·진열·판매)로 교체. Co-Authored-By: Claude Fable 5.1 --- .../cafe24/templates/cafe24/products.html | 56 ++++++++----- app/static/cafe24.css | 83 +++++++++++++------ docs/CAFE24_MODULE.md | 7 +- 3 files changed, 101 insertions(+), 45 deletions(-) diff --git a/app/modules/cafe24/templates/cafe24/products.html b/app/modules/cafe24/templates/cafe24/products.html index 46e7f66..47fe3aa 100644 --- a/app/modules/cafe24/templates/cafe24/products.html +++ b/app/modules/cafe24/templates/cafe24/products.html @@ -1,7 +1,7 @@ {% extends "erp_base.html" %} {% block head_extra %} - + {% endblock %} {% block content %} @@ -938,6 +938,21 @@ return; } + // 옵션값 썸네일은 세 곳 중 있는 것을 보여준다 — 옵션 버튼 이미지(option_image_file) + // → 옵션 연결 이미지(option_link_image) → 그 옵션값을 가진 품목의 image. + // 카페24 관리자에서 "옵션 연결 이미지"로만 등록한 상품은 option_image_file 이 + // 비어 있고 품목 image 에만 나타난다(실물 — 버튼 이미지만 보면 "없음"으로 오인). + function variantImageFor(name, value) { + for (var i = 0; i < variants.length; i++) { + var v = variants[i]; + if (!v.image) continue; + for (var j = 0; j < v.options.length; j++) { + if (v.options[j].name === name && v.options[j].value === value) return v.image; + } + } + return ""; + } + // 옵션 정의 편집 var html = '
'; opt.options.forEach(function (o, gi) { @@ -947,8 +962,10 @@ ' " + ""; o.option_value.forEach(function (v, vi) { - var thumb = v.option_image_file - ? '' + var thumbSrc = v.option_image_file || v.option_link_image || variantImageFor(o.option_name, v.option_text); + var thumb = thumbSrc + ? '' : '
없음
'; html += '
' + '' + thumb + "" + @@ -966,28 +983,29 @@ '
' + "
"; - // 품목 표 + // 품목 — 패널 폭(380px)에 표는 좁다(실측: 이름이 이미지 아래로 꺾여 잘림). + // 품목마다 2줄 카드: 1줄 아이콘 + 옵션값 이름, 2줄 자체코드·추가금액·진열·판매. html += '
품목 (' + variants.length + ')
'; if (!variants.length) { html += '

품목이 아직 조회되지 않았습니다. 잠시 뒤 「옵션 / 품목」을 접었다 펴서 다시 불러오세요.

'; } else { - html += '
' + - "" + - ''; + html += '
'; variants.forEach(function (v) { var label = v.options.map(function (o) { return o.value; }).join(" / ") || v.variant_code; var amount = String(parseInt(v.additional_amount || "0", 10) || 0); - html += '
' + - '" + - '' + - '' + - '" + - '" + - ""; + html += '
' + + '
' + + (v.image ? '' : '') + + '' + escHtml(label) + "
" + + '
' + + '' + + '' + + '' + + '" + + '" + + "
"; }); - html += "
옵션자체코드추가금액진열판매
' + - (v.image ? '' : "") + - escHtml(label) + "
" + + html += "
" + '
' + '
'; } @@ -1085,7 +1103,7 @@ var msg = body.querySelector("#cf24-var-msg"); var rows = []; var lines = []; - wrap.querySelectorAll("tr[data-code]").forEach(function (tr) { + wrap.querySelectorAll(".cf24-v-item[data-code]").forEach(function (tr) { var row = { variant_code: tr.dataset.code }; var any = false; var code = tr.querySelector('[name="custom_variant_code"]'); @@ -1111,7 +1129,7 @@ var updated = data.updated || {}; Object.keys(updated).forEach(function (code) { var u = updated[code]; - var tr = wrap.querySelector('tr[data-code="' + code + '"]'); + var tr = wrap.querySelector('.cf24-v-item[data-code="' + code + '"]'); if (!tr) return; var codeEl = tr.querySelector('[name="custom_variant_code"]'); var amountEl = tr.querySelector('[name="additional_amount"]'); diff --git a/app/static/cafe24.css b/app/static/cafe24.css index 8212a48..9718ed4 100644 --- a/app/static/cafe24.css +++ b/app/static/cafe24.css @@ -1106,33 +1106,61 @@ font-size: 12px; } -/* 품목 표 — 좁은 칸에 맞춘 작은 글자 */ -.cf24-variants { - width: 100%; - border-collapse: collapse; - font-size: 12px; - table-layout: fixed; -} - -.cf24-variants th, -.cf24-variants td { - padding: 4px 4px; +/* 품목 — 380px 패널에 표는 좁다(실측: 옵션값 이름이 아이콘 아래로 꺾여 "그/1개"로 + 잘렸다). 품목마다 2줄 카드로 그린다. 1줄: 아이콘 + 이름(남는 폭 전부), + 2줄: 자체코드 · 추가금액 · 진열/판매 토글. */ +.cf24-v-item { + padding: 6px 0; border-bottom: 1px solid var(--color-subtle-ash, #e5e5e5); - vertical-align: middle; - text-align: left; } -.cf24-variants th { +.cf24-v-head { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 4px; + min-width: 0; +} + +.cf24-v-img { + flex: 0 0 auto; + width: 32px; + height: 32px; + object-fit: cover; + border: 1px solid var(--color-subtle-ash, #e5e5e5); + border-radius: var(--r-sm, 4px); + background: var(--color-ghost-gray, #f6f8fa); + display: block; +} + +.cf24-v-img-empty { + border-style: dashed; +} + +.cf24-v-name { + flex: 1 1 auto; + min-width: 0; + font-size: 13px; font-weight: 500; - color: var(--color-midtone-gray, #737373); - white-space: nowrap; -} - -.cf24-variants td.cf24-v-name { word-break: break-word; } -.cf24-variants input[type="text"] { +.cf24-v-row { + display: flex; + align-items: flex-end; + gap: 6px; +} + +.cf24-v-row label { + display: flex; + flex-direction: column; + gap: 2px; + font-size: 11px; + color: var(--color-midtone-gray, #737373); + min-width: 0; +} + +.cf24-v-row input[type="text"] { height: 28px; box-sizing: border-box; width: 100%; @@ -1142,11 +1170,16 @@ font-size: 12px; } -.cf24-variants .cf24-v-amount input { text-align: right; } -/* "미진열"(3글자)이 한 줄에 들어가는 폭. 실측: 44px 에서는 두 줄로 꺾였다. */ -.cf24-variants .cf24-v-flag { text-align: center; width: 54px; } -.cf24-variants .cf24-v-code { width: 92px; } -.cf24-variants .cf24-v-amount { width: 76px; } +.cf24-v-code { flex: 1 1 110px; } +.cf24-v-amount { flex: 0 0 84px; } +.cf24-v-amount input { text-align: right; } + +.cf24-v-flags { + flex: 0 0 auto; + display: flex; + gap: 4px; + padding-bottom: 3px; /* 토글을 입력칸 세로 중심에 맞춘다 */ +} /* 진열/판매 토글 — 저장 전까지는 화면만 바뀐다(배지와 같은 색 규칙) */ .cf24-v-toggle { diff --git a/docs/CAFE24_MODULE.md b/docs/CAFE24_MODULE.md index ee15cdf..ac67ace 100644 --- a/docs/CAFE24_MODULE.md +++ b/docs/CAFE24_MODULE.md @@ -456,7 +456,12 @@ cafe24_oauth_tokens 저장 "requests":[{variant_code, custom_variant_code, additional_amount, display, selling…}]}` 1회 100건(초과 시 나눠 보냄). 재고(`quantity`)는 이 화면에서 건드리지 않는다. - "옵션별 상품 이름" 은 옵션값(`option_text`)이고, "옵션별 썸네일" 은 `option_image_file` - (+ `option_link_image` 에도 같은 경로) 이며, "옵션별 상품코드/추가금액/진열" 은 품목 + (+ `option_link_image` 에도 같은 경로) 이며, + 화면의 옵션값 썸네일은 **`option_image_file` → `option_link_image` → 그 옵션값을 가진 + 품목의 `image`** 순으로 있는 것을 보여준다. 카페24 관리자에서 "옵션 연결 이미지"로만 + 등록한 상품은 `option_image_file` 이 비어 있고 품목 `image` 에만 나타난다(실물 — + 버튼 이미지만 보면 "없음"으로 오인했던 사고). 품목은 380px 패널에 표가 좁아 + 품목마다 2줄 카드(아이콘+이름 / 코드·금액·진열·판매)로 그린다. "옵션별 상품코드/추가금액/진열" 은 품목 (`custom_variant_code`/`additional_amount`/`display`)이다 — 카페24 모델상 둘은 다른 리소스라 화면에서도 「옵션 저장」과 「품목 저장」이 따로 있다.