From 718b5e6d8fded532b5d8825b0906a87346c2476d Mon Sep 17 00:00:00 2001 From: king Date: Fri, 26 Jun 2026 17:11:45 +0900 Subject: [PATCH] =?UTF-8?q?feat(dispatch):=20=EB=B0=9B=EB=8A=94=20?= =?UTF-8?q?=EC=82=AC=EB=9E=8C=20=EC=9D=B4=EB=A6=84=EB=8F=84=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20+=20=EA=B2=80=EC=83=89=EC=B0=BD=20=EC=BB=B4?= =?UTF-8?q?=ED=8C=A9=ED=8A=B8=20=EB=93=9C=EB=A1=AD=EB=8B=A4=EC=9A=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - search_parcels: recipient_name ILIKE 추가(이름·주문·패키지·송장 4개 필드) - batches.html: 큰 카드 → 한 줄 입력창(🔎+clear), 결과는 절대위치 드롭다운으로 본문 안 밀리게. 바깥 클릭·Esc 닫기, 이름 매칭 강조 Co-Authored-By: Claude Opus 4.8 --- app/modules/dispatch/db.py | 11 +-- .../dispatch/templates/dispatch/batches.html | 76 ++++++++++++------- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/app/modules/dispatch/db.py b/app/modules/dispatch/db.py index 811c88c..27eed66 100644 --- a/app/modules/dispatch/db.py +++ b/app/modules/dispatch/db.py @@ -359,9 +359,9 @@ class DispatchStore: ) def search_parcels(self, *, query: str, limit: int = 50) -> list[dict[str, Any]]: - """주문번호/패키지번호/송장번호(부분 일치)로 박스를 찾는다. + """주문번호/패키지번호/송장번호/받는 사람 이름(부분 일치)로 박스를 찾는다. - 3개 식별자 어디든 query 가 포함되면 매칭. 받는 사람(이름/전화/주소)과 + 4개 필드 어디든 query 가 포함되면 매칭. 받는 사람(이름/전화/주소)과 소속 배치(날짜/플랫폼/배치명/id) + 박스 seq 를 함께 돌려준다. 최신 출고일/배치 우선. query 가 비면 빈 리스트. """ @@ -389,9 +389,10 @@ class DispatchStore: b.batch_name FROM dispatch_parcels p JOIN dispatch_batches b ON b.id = p.batch_id - WHERE p.order_id ILIKE %(like)s - OR p.package_id ILIKE %(like)s - OR p.tracking_id ILIKE %(like)s + WHERE p.order_id ILIKE %(like)s + OR p.package_id ILIKE %(like)s + OR p.tracking_id ILIKE %(like)s + OR p.recipient_name ILIKE %(like)s ORDER BY b.dispatch_date DESC, b.id DESC, p.seq ASC LIMIT %(limit)s """, diff --git a/app/modules/dispatch/templates/dispatch/batches.html b/app/modules/dispatch/templates/dispatch/batches.html index 70531a5..5c220df 100644 --- a/app/modules/dispatch/templates/dispatch/batches.html +++ b/app/modules/dispatch/templates/dispatch/batches.html @@ -20,20 +20,25 @@ .dsp-cal-day.has { color:#0f172a;background:#eef2ff;font-weight:700;cursor:pointer;border:1px solid #c7d2fe; } .dsp-cal-day.has:hover { background:#e0e7ff; } .dsp-cal-day.sel { background:#16a34a !important;border-color:#16a34a !important;color:#fff !important; } - /* 검색 */ - .dsp-search { margin:0 0 14px; } - .dsp-search-box { display:flex;gap:8px;align-items:center;flex-wrap:wrap; } - .dsp-search-box input { flex:1 1 320px;min-width:220px;padding:10px 12px;border:1px solid #cbd5e1;border-radius:8px;font-size:15px; } - .dsp-search-note { font-size:12px;color:#94a3b8;margin:6px 2px 0; } - .dsp-search-results { margin-top:10px;display:flex;flex-direction:column;gap:8px; } - .dsp-hit { border:1px solid #e2e8f0;border-radius:10px;padding:10px 12px;background:#fff;display:flex;justify-content:space-between;gap:12px;align-items:flex-start; } - .dsp-hit-name { font-weight:700;font-size:15px;color:#0f172a; } - .dsp-hit-meta { font-size:13px;color:#475569;margin-top:2px;line-height:1.5; } + /* 검색: 한 줄 입력 + 결과는 절대위치 드롭다운(본문 안 밀림) */ + .dsp-search { position:relative;margin:0 0 12px;max-width:520px; } + .dsp-search-box { position:relative; } + .dsp-search-box .dsp-q-ico { position:absolute;left:11px;top:50%;transform:translateY(-50%);font-size:14px;color:#94a3b8;pointer-events:none; } + .dsp-search-box input { width:100%;padding:9px 30px 9px 32px;border:1px solid #cbd5e1;border-radius:8px;font-size:14px;box-sizing:border-box; } + .dsp-search-box input:focus { outline:none;border-color:#6366f1;box-shadow:0 0 0 3px rgba(99,102,241,.15); } + .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 + .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 mark { background:#fde68a;padding:0 1px;border-radius:2px; } - .dsp-hit-batch { font-size:12px;color:#64748b;margin-top:4px; } + .dsp-hit-batch { font-size:11.5px;color:#64748b;margin-top:3px; } .dsp-hit-go { white-space:nowrap;flex:0 0 auto;align-self:center; } - .dsp-hit-empty { color:#94a3b8;font-size:14px;padding:8px 2px; } + .dsp-hit-empty { color:#94a3b8;font-size:13.5px;padding:10px; } {% endblock %} @@ -41,17 +46,15 @@
{% include "dispatch/_nav.html" %} -