diff --git a/app/modules/dispatch/router.py b/app/modules/dispatch/router.py index 9aa8148..31eb161 100644 --- a/app/modules/dispatch/router.py +++ b/app/modules/dispatch/router.py @@ -726,7 +726,13 @@ async def api_search( query = (q or "").strip() if len(query) < 2: return JSONResponse({"query": query, "results": []}) - return JSONResponse({"query": query, "results": st.search_parcels(query=query)}) + results = st.search_parcels(query=query) + # 송장 조회 딥링크는 배송사 맵(store)에서 만든다 — 프런트엔 맵이 없다. + for r in results: + r["tracking_url"] = store.courier_tracking_url( + r.get("tracking_id", ""), r.get("shipping_provider", "") + ) + return JSONResponse({"query": query, "results": results}) @router.get("/health") diff --git a/app/modules/dispatch/templates/dispatch/batches.html b/app/modules/dispatch/templates/dispatch/batches.html index 5c220df..2935422 100644 --- a/app/modules/dispatch/templates/dispatch/batches.html +++ b/app/modules/dispatch/templates/dispatch/batches.html @@ -29,16 +29,25 @@ .dsp-q-clear { position:absolute;right:8px;top:50%;transform:translateY(-50%);border:0;background:transparent;color:#94a3b8;font-size:18px;cursor:pointer;line-height:1;padding:0 4px;display:none; } .dsp-search-results { position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:40;background:#fff;border:1px solid #e2e8f0;border-radius:10px;box-shadow:0 8px 24px rgba(15,23,42,.12);max-height:64vh;overflow:auto;display:none;padding:6px; } .dsp-search-results.open { display:block; } - .dsp-hit { border-radius:8px;padding:9px 10px;display:flex;justify-content:space-between;gap:12px;align-items:flex-start; } + .dsp-hit { border-radius:8px;padding:11px 12px;display:flex;justify-content:space-between;gap:12px;align-items:flex-start; } .dsp-hit + .dsp-hit { border-top:1px solid #f1f5f9; } .dsp-hit:hover { background:#f8fafc; } - .dsp-hit-name { font-weight:700;font-size:14px;color:#0f172a; } - .dsp-hit-meta { font-size:12.5px;color:#475569;margin-top:2px;line-height:1.5; } - .dsp-hit-meta code { background:#f1f5f9;padding:1px 5px;border-radius:4px;font-size:12px; } + .dsp-hit-body { min-width:0; } + .dsp-hit-name { font-weight:700;font-size:17px;color:#0f172a; } + .dsp-hit-meta { font-size:14px;color:#475569;margin-top:3px;line-height:1.5; } + /* Order / Pkg / 송장 — 한 줄씩 */ + .dsp-id { font-size:14.5px;margin-top:4px;display:flex;gap:8px;align-items:baseline;flex-wrap:wrap; } + .dsp-id-k { color:#94a3b8;font-size:12px;min-width:42px;flex:0 0 auto; } + .dsp-id code { background:#f1f5f9;padding:2px 7px;border-radius:5px;font-size:14px;color:#0f172a; } + .dsp-id-track code { font-weight:700; } + .dsp-track-lnk { text-decoration:none; } + .dsp-track-lnk code { color:#4f46e5;text-decoration:underline;cursor:pointer; } + .dsp-track-lnk:hover code { background:#e0e7ff; } + .dsp-courier { font-size:12.5px;font-weight:600;color:#475569;background:#eef2ff;border:1px solid #c7d2fe;border-radius:999px;padding:1px 9px; } .dsp-hit mark { background:#fde68a;padding:0 1px;border-radius:2px; } - .dsp-hit-batch { font-size:11.5px;color:#64748b;margin-top:3px; } + .dsp-hit-batch { font-size:13px;color:#475569;margin-top:5px; } .dsp-hit-go { white-space:nowrap;flex:0 0 auto;align-self:center; } - .dsp-hit-empty { color:#94a3b8;font-size:13.5px;padding:10px; } + .dsp-hit-empty { color:#94a3b8;font-size:14.5px;padding:11px; } {% endblock %} @@ -294,11 +303,26 @@ } function en() { return (window.dspLang && window.dspLang() === 'en'); } + function idLine(label, value, q) { + if (!value) return ''; + return '
' + hi(value, q) + '' + hi(r.tracking_id, q) + '';
+ // 송장번호 클릭 → 배송사 조회 페이지(딥링크 있으면).
+ var inner = r.tracking_url
+ ? '' + num + ''
+ : num;
+ var courier = r.shipping_provider
+ ? '' + esc(r.shipping_provider) + ''
+ : '';
+ return '' + hi(r.order_id, q) + '');
- if (r.package_id) ids.push('Pkg ' + hi(r.package_id, q) + '');
- if (r.tracking_id) ids.push((en() ? 'Track ' : '송장 ') + '' + hi(r.tracking_id, q) + '');
var name = r.recipient_name
? hi(r.recipient_name, q)
: esc(en() ? '(no recipient name)' : '(받는 사람 정보 없음)');
@@ -306,14 +330,17 @@
if (r.recipient_phone) contact.push(esc(r.recipient_phone));
if (r.recipient_address) contact.push(esc(r.recipient_address));
var done = r.label_attached && r.handed_to_kagayaku;
- var batchLine = esc(r.dispatch_date) + ' · ' + esc(r.platform) + ' · ' + esc(r.batch_name || '')
- + ' · ' + (en() ? 'Box #' : '박스 #') + esc(r.seq)
- + (done ? ' · ✓' : '');
+ // 날짜·쇼핑몰은 굵게.
+ var batchLine = '' + esc(r.dispatch_date) + ' · ' + esc(r.platform) + ' · '
+ + esc(r.batch_name || '') + ' · ' + (en() ? 'Box #' : '박스 #') + esc(r.seq)
+ + (done ? ' · ✓' : '');
return '