From 6141f0e38a3af393c365a4d04e432a21587b96e8 Mon Sep 17 00:00:00 2001 From: king Date: Fri, 19 Jun 2026 19:17:43 +0900 Subject: [PATCH] =?UTF-8?q?feat(dispatch):=20=EC=86=A1=EC=9E=A5=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AD=20=EC=8B=9C=20=ED=81=B4=EB=A6=BD=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20=EB=B3=B5=EC=82=AC=20+=20J&T=20=EA=B3=B5=EC=8B=9D?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - J&T 를 공식 조회 페이지(jtexpress.my/tracking)로 되돌림 - 송장번호 클릭 시 클립보드에 자동 복사 후 새 탭 열기(공식 페이지에 붙여넣기) 복사 완료 토스트 표시. Ninja Van 등 자동입력 되는 곳도 복사는 동작. - 송장 링크 굵기 800 + 밑줄 2px 로 강조 Co-Authored-By: Claude Opus 4.8 --- app/modules/dispatch/store.py | 5 +-- .../dispatch/templates/dispatch/detail.html | 33 +++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/app/modules/dispatch/store.py b/app/modules/dispatch/store.py index f959076..dd4e90a 100644 --- a/app/modules/dispatch/store.py +++ b/app/modules/dispatch/store.py @@ -264,8 +264,9 @@ def courier_logo_url(provider: Any) -> str: # 매핑 없는 배송사는 링크 없이 텍스트로 표시(courier_tracking_url 가 "" 반환). _COURIER_TRACK_URL: dict[str, str] = { "ninjavan": "https://www.ninjavan.co/en-my/tracking?id={t}", - # J&T MY 공식 딥링크는 송장 자동입력이 안 돼 17TRACK 으로(범용, #nums 자동조회). - "jnt": "https://t.17track.net/en#nums={t}", + # J&T MY 공식 페이지는 송장 자동입력이 안 된다 → 클릭 시 송장번호를 클립보드에 + # 복사하고 공식 조회 페이지를 연다(직원이 붙여넣기). 복사는 템플릿 JS 가 처리. + "jnt": "https://www.jtexpress.my/tracking?billcode={t}", "flash": "https://www.flashexpress.my/fle/tracking?se={t}", "citylink": "https://www.citylinkexpress.com/tracking-result/?track_no={t}", "poslaju": "https://track.pos.com.my/postal-services/quick-access/?track-trace&trackingNo03={t}", diff --git a/app/modules/dispatch/templates/dispatch/detail.html b/app/modules/dispatch/templates/dispatch/detail.html index 9095b55..978e95f 100644 --- a/app/modules/dispatch/templates/dispatch/detail.html +++ b/app/modules/dispatch/templates/dispatch/detail.html @@ -16,8 +16,13 @@ .dsp-order { font-size:15px;line-height:1.3;color:#334155;word-break:break-all; } .dsp-order b { display:block;font-size:14px;font-weight:700;color:#475569;letter-spacing:.5px; } .dsp-order span { font-size:27px;font-weight:800;color:#0f172a;letter-spacing:.2px; } - .dsp-track-link { color:#2563eb;font-weight:700;text-decoration:underline; + .dsp-track-link { color:#2563eb;font-weight:800;text-decoration:underline; text-decoration-thickness:2px;text-underline-offset:3px;cursor:pointer; } + .dsp-toast { position:fixed;left:50%;bottom:24px;transform:translateX(-50%); + background:#0f172a;color:#fff;padding:10px 18px;border-radius:9px; + font-size:14px;font-weight:600;opacity:0;pointer-events:none; + transition:opacity .18s;z-index:9999;box-shadow:0 4px 16px rgba(0,0,0,.25); } + .dsp-toast.show { opacity:.96; } .dsp-items { list-style:none;margin:0;padding:8px 0;border-top:1px dashed #e2e8f0;border-bottom:1px dashed #e2e8f0; } .dsp-items li { font-size:16px;font-weight:600;color:#0f172a;padding:2px 0; } .dsp-items .qty { color:#2563eb; } @@ -75,7 +80,7 @@
Package {{ p.package_id or '—' }}
Tracking {% set turl = p.tracking_id | courier_track(p.shipping_provider) %} - {% if turl %}{{ p.tracking_id }} + {% if turl %}{{ p.tracking_id }} {% else %}{{ p.tracking_id or '—' }}{% endif %}
@@ -104,6 +109,7 @@ {% endif %} +
{% endblock %} @@ -185,6 +191,29 @@ }); document.getElementById('dsp-search').addEventListener('input', applyFilter); + + // ── 송장번호 클릭 시 클립보드 복사(공식 페이지에 붙여넣기용) ── + var toast = document.getElementById('dsp-toast'); + var toastTimer = null; + function showToast(msg) { + if (!toast) return; + toast.textContent = msg; + toast.classList.add('show'); + clearTimeout(toastTimer); + toastTimer = setTimeout(function () { toast.classList.remove('show'); }, 1600); + } + document.addEventListener('click', function (e) { + var a = e.target.closest('.dsp-track-link'); + if (!a) return; + var num = (a.getAttribute('data-copy') || a.textContent || '').trim(); + if (!num) return; + // 링크는 그대로 새 탭으로 열리고(preventDefault 안 함), 송장번호만 복사한다. + if (navigator.clipboard && navigator.clipboard.writeText) { + navigator.clipboard.writeText(num) + .then(function () { showToast('송장번호 복사됨: ' + num); }) + .catch(function () {}); + } + }); })(); {% endblock %}