From 21e07bcca9120cc9102b3a2b2d25fb74f8d87860 Mon Sep 17 00:00:00 2001 From: thug0bin Date: Sat, 28 Feb 2026 12:01:32 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20admin=5Fproducts.html=20=EC=9D=B8?= =?UTF-8?q?=EC=BD=94=EB=94=A9=20=EC=88=98=EC=A0=95=20+=20=EC=9E=AC?= =?UTF-8?q?=EA=B3=A0=20=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/templates/admin_products.html | 217 +++++++++++++------------- 1 file changed, 110 insertions(+), 107 deletions(-) diff --git a/backend/templates/admin_products.html b/backend/templates/admin_products.html index 2b401ec..d9e5d99 100644 --- a/backend/templates/admin_products.html +++ b/backend/templates/admin_products.html @@ -3,7 +3,7 @@ - ?�품 검??- �?��?�국 + 제품 검색 - 청춘약국 @@ -16,7 +16,7 @@ color: #1e293b; } - /* ?�?� ?�더 ?�?� */ + /* ── 헤더 ── */ .header { background: linear-gradient(135deg, #7c3aed 0%, #8b5cf6 50%, #a78bfa 100%); padding: 28px 32px 24px; @@ -46,14 +46,14 @@ opacity: 0.85; } - /* ?�?� 컨텐�??�?� */ + /* ── 컨텐츠 ── */ .content { max-width: 1100px; margin: 0 auto; padding: 24px 20px 60px; } - /* ?�?� ?�로??챗봇 ?�?� */ + /* ── 플로팅 챗봇 ── */ .chatbot-panel { position: fixed; right: 24px; @@ -224,7 +224,7 @@ 30% { transform: translateY(-6px); opacity: 1; } } - /* ?�?� 챗봇 ?��? 버튼 (??�� ?�시) ?�?� */ + /* ── 챗봇 토글 버튼 (항상 표시) ── */ .chatbot-toggle { position: fixed; bottom: 24px; @@ -253,7 +253,7 @@ box-shadow: 0 4px 20px rgba(239, 68, 68, 0.4); } - /* 모바??*/ + /* 모바일 */ @media (max-width: 640px) { .chatbot-panel { right: 0; @@ -266,7 +266,7 @@ .chatbot-toggle { bottom: 16px; right: 16px; } } - /* ?�?� 검???�역 ?�?� */ + /* ── 검색 영역 ── */ .search-section { background: #fff; border-radius: 14px; @@ -320,7 +320,7 @@ margin-right: 8px; } - /* ?�?� 결과 카운???�?� */ + /* ── 결과 카운트 ── */ .result-count { margin-bottom: 16px; font-size: 14px; @@ -331,7 +331,7 @@ font-weight: 700; } - /* ?�?� ?�이�??�?� */ + /* ── 테이블 ── */ .table-wrap { background: #fff; border-radius: 14px; @@ -362,7 +362,7 @@ tbody tr:hover { background: #faf5ff; } tbody tr:last-child td { border-bottom: none; } - /* ?�?� ?�품 ?�보 ?�?� */ + /* ── 상품 정보 ── */ .product-name { font-weight: 600; color: #1e293b; @@ -377,7 +377,7 @@ font-weight: 500; } - /* ?�?� 코드/바코???�?� */ + /* ── 코드/바코드 ── */ .code { font-family: 'JetBrains Mono', monospace; font-size: 12px; @@ -398,25 +398,22 @@ color: #94a3b8; } - /* 가격 */ + /* ── 가격 ── */ .price { font-weight: 600; color: #1e293b; white-space: nowrap; } - /* 재고 */ + /* ── 재고 ── */ .stock { font-weight: 600; white-space: nowrap; + text-align: center; } - .stock.in-stock { - color: #10b981; - } - .stock.out-stock { - color: #ef4444; - } + .stock.in-stock { color: #10b981; } + .stock.out-stock { color: #ef4444; } - /* QR 버튼 */ + /* ── QR 버튼 ── */ .btn-qr { background: #8b5cf6; color: #fff; @@ -432,7 +429,7 @@ .btn-qr:hover { background: #7c3aed; } .btn-qr:active { transform: scale(0.95); } - /* ?�?� �??�태 ?�?� */ + /* ── 빈 상태 ── */ .empty-state { text-align: center; padding: 60px 20px; @@ -446,7 +443,7 @@ font-size: 15px; } - /* ?�?� 모달 ?�?� */ + /* ── 모달 ── */ .modal-overlay { display: none; position: fixed; @@ -482,7 +479,7 @@ border-radius: 8px; } - /* ?�?� ?�량 ?�택�??�?� */ + /* ── 수량 선택기 ── */ .qty-selector { display: flex; align-items: center; @@ -550,7 +547,7 @@ .modal-btn.confirm { background: #8b5cf6; color: #fff; } .modal-btn.confirm:hover { background: #7c3aed; } - /* ?�?� 반응???�?� */ + /* ── 반응형 ── */ @media (max-width: 768px) { .search-box { flex-direction: column; } .table-wrap { overflow-x: auto; } @@ -561,33 +558,33 @@
-

?�� ?�품 검??/h1> -

?�체 ?�품 검??· QR ?�벨 ?�쇄 · ?�� ?�물??AI ?�담

+

🔍 제품 검색

+

전체 제품 검색 · QR 라벨 인쇄 · 🐾 동물약 AI 상담

- +
- ?�시 ?�?�레?�, 벤포?�워, 8806418067510, LB000001423 + 예시 타이레놀, 벤포파워, 8806418067510, LB000001423
@@ -595,25 +592,26 @@ + 검색 결과: 0건 +
- - - + + + + + @@ -621,51 +619,51 @@ - +
-

?�� ?�물??AI ?�담

-

?�장?�상�? ?��?기생�? 구충????무엇?�든 물어보세??/p> +

🐾 동물약 AI 상담

+

심장사상충, 외부기생충, 구충제 등 무엇이든 물어보세요

- - - + + +
- ?�녕?�세?? ?�� ?�물???�담 AI?�니??

- 반려?�물???�장?�상�??�방, 벼룩/진드�??�방, 구충??/strong> ?�에 ?�??무엇?�든 물어보세?? + 안녕하세요! 🐾 동물약 상담 AI입니다.

+ 반려동물의 심장사상충 예방, 벼룩/진드기 예방, 구충제 등에 대해 무엇이든 물어보세요!
- -
- - + + - + @@ -679,7 +677,7 @@ function formatPrice(num) { if (!num) return '-'; - return new Intl.NumberFormat('ko-KR').format(num) + '??; + return new Intl.NumberFormat('ko-KR').format(num) + '원'; } function escapeHtml(str) { @@ -690,16 +688,16 @@ function searchProducts() { const search = document.getElementById('searchInput').value.trim(); if (!search) { - alert('검?�어�??�력?�세??); + alert('검색어를 입력하세요'); return; } if (search.length < 2) { - alert('2글???�상 ?�력?�세??); + alert('2글자 이상 입력하세요'); return; } const tbody = document.getElementById('productsTableBody'); - tbody.innerHTML = ''; + tbody.innerHTML = ''; const animalOnly = document.getElementById('animalOnly').checked; fetch(`/api/products?search=${encodeURIComponent(search)}${animalOnly ? '&animal_only=1' : ''}`) @@ -711,11 +709,11 @@ document.getElementById('resultNum').textContent = productsData.length; renderTable(); } else { - tbody.innerHTML = ``; + tbody.innerHTML = ``; } }) .catch(err => { - tbody.innerHTML = ''; + tbody.innerHTML = ''; }); } @@ -723,7 +721,7 @@ const tbody = document.getElementById('productsTableBody'); if (productsData.length === 0) { - tbody.innerHTML = ''; + tbody.innerHTML = ''; return; } @@ -732,24 +730,24 @@ - + `).join(''); } - // ?�?� QR ?�쇄 관???�?� + // ── QR 인쇄 관련 ── function adjustQty(delta) { printQty = Math.max(MIN_QTY, Math.min(MAX_QTY, printQty + delta)); updateQtyUI(); @@ -759,7 +757,7 @@ document.getElementById('qtyValue').textContent = printQty; document.getElementById('qtyMinus').disabled = printQty <= MIN_QTY; document.getElementById('qtyPlus').disabled = printQty >= MAX_QTY; - document.getElementById('printBtn').textContent = printQty > 1 ? `${printQty}???�쇄` : '?�쇄'; + document.getElementById('printBtn').textContent = printQty > 1 ? `${printQty}장 인쇄` : '인쇄'; } function printQR(idx) { @@ -770,12 +768,12 @@ const preview = document.getElementById('qrPreview'); const info = document.getElementById('qrInfo'); - preview.innerHTML = '

미리보기 로딩 �?..

'; + preview.innerHTML = '

미리보기 로딩 중...

'; info.innerHTML = ` ${escapeHtml(selectedItem.product_name)}
- 바코?? ${selectedItem.barcode || selectedItem.drug_code || 'N/A'}
- 가�? ${formatPrice(selectedItem.sale_price)} + 바코드: ${selectedItem.barcode || selectedItem.drug_code || 'N/A'}
+ 가격: ${formatPrice(selectedItem.sale_price)}
`; updateQtyUI(); @@ -796,11 +794,11 @@ if (data.success && data.image) { preview.innerHTML = `QR 미리보기`; } else { - preview.innerHTML = '

미리보기 ?�패

'; + preview.innerHTML = '

미리보기 실패

'; } }) .catch(() => { - preview.innerHTML = '

미리보기 ?�류

'; + preview.innerHTML = '

미리보기 오류

'; }); } @@ -821,7 +819,7 @@ let errorMsg = ''; for (let i = 0; i < totalQty; i++) { - btn.textContent = `?�쇄 �?.. (${i + 1}/${totalQty})`; + btn.textContent = `인쇄 중... (${i + 1}/${totalQty})`; try { const res = await fetch('/api/qr-print', { @@ -839,7 +837,7 @@ if (data.success) { successCount++; } else { - errorMsg = data.error || '?????�는 ?�류'; + errorMsg = data.error || '알 수 없는 오류'; break; } @@ -856,20 +854,21 @@ updateQtyUI(); if (successCount === totalQty) { - alert(`??QR ?�벨 ${totalQty}???�쇄 ?�료!`); + alert(`✅ QR 라벨 ${totalQty}장 인쇄 완료!`); closeQRModal(); } else if (successCount > 0) { - alert(`?�️ ${successCount}/${totalQty}???�쇄 ?�료\n?�류: ${errorMsg}`); + alert(`⚠️ ${successCount}/${totalQty}장 인쇄 완료\n오류: ${errorMsg}`); } else { - alert(`???�쇄 ?�패: ${errorMsg}`); + alert(`❌ 인쇄 실패: ${errorMsg}`); } } - // ?�이지 로드 ??검?�창 ?�커?? document.getElementById('searchInput').focus(); + // 페이지 로드 시 검색창 포커스 + document.getElementById('searchInput').focus(); - // ?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═ - // ?�물??챗봇 - // ?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═?�═ + // ══════════════════════════════════════════════════════════════════ + // 동물약 챗봇 + // ══════════════════════════════════════════════════════════════════ let chatHistory = []; let isChatLoading = false; @@ -878,7 +877,7 @@ const btn = document.getElementById('chatbotToggle'); const isOpen = panel.classList.toggle('open'); btn.classList.toggle('active', isOpen); - btn.innerHTML = isOpen ? '?? : '?��'; + btn.innerHTML = isOpen ? '✕' : '🐾'; if (isOpen) { document.getElementById('chatInput').focus(); } @@ -895,14 +894,14 @@ if (!message || isChatLoading) return; - // ?�용??메시지 ?�시 + // 사용자 메시지 표시 addChatMessage('user', message); input.value = ''; - // ?�스?�리??추�? + // 히스토리에 추가 chatHistory.push({ role: 'user', content: message }); - // 로딩 ?�시 + // 로딩 표시 isChatLoading = true; document.getElementById('chatSendBtn').disabled = true; showTypingIndicator(); @@ -919,22 +918,22 @@ hideTypingIndicator(); if (data.success) { - // AI ?�답 ?�시 + // AI 응답 표시 addChatMessage('assistant', data.message, data.products); - // ?�스?�리??추�? + // 히스토리에 추가 chatHistory.push({ role: 'assistant', content: data.message }); - // ?�스?�리 길이 ?�한 (최근 20�? + // 히스토리 길이 제한 (최근 20개) if (chatHistory.length > 20) { chatHistory = chatHistory.slice(-20); } } else { - addChatMessage('system', '?�️ ' + (data.message || '?�류가 발생?�습?�다')); + addChatMessage('system', '⚠️ ' + (data.message || '오류가 발생했습니다')); } } catch (error) { hideTypingIndicator(); - addChatMessage('system', '?�️ ?�트?�크 ?�류가 발생?�습?�다'); + addChatMessage('system', '⚠️ 네트워크 오류가 발생했습니다'); } isChatLoading = false; @@ -946,19 +945,19 @@ const msgDiv = document.createElement('div'); msgDiv.className = `chat-message ${role}`; - // 줄바�?처리 + // 줄바꿈 처리 let htmlContent = escapeHtml(content).replace(/\n/g, '
'); - // 마크?�운 굵게 처리 + // 마크다운 굵게 처리 htmlContent = htmlContent.replace(/\*\*(.+?)\*\*/g, '$1'); msgDiv.innerHTML = htmlContent; - // ?�급???�품 ?�시 (?��?지 ?�함) + // 언급된 제품 표시 (이미지 포함) if (products && products.length > 0) { const productsDiv = document.createElement('div'); productsDiv.className = 'products-mentioned'; - productsDiv.innerHTML = '?�� 관???�품:'; + productsDiv.innerHTML = '📦 관련 제품:'; const productsGrid = document.createElement('div'); productsGrid.style.cssText = 'display:flex;flex-wrap:wrap;gap:8px;margin-top:8px;'; @@ -969,7 +968,7 @@ card.style.cssText = 'display:flex;align-items:center;gap:8px;padding:8px;background:#f8fafc;border-radius:8px;cursor:pointer;border:1px solid #e2e8f0;'; card.onclick = () => searchProductFromChat(p.name); - // ?��?지 컨테?�너 + // 이미지 컨테이너 const imgContainer = document.createElement('div'); imgContainer.style.cssText = 'width:40px;height:40px;flex-shrink:0;'; @@ -979,14 +978,17 @@ img.src = p.image_url; img.alt = p.name; img.onerror = function() { - // ?��?지 로드 ?�패 ???�이콘으�??��? imgContainer.innerHTML = '
?��
'; + // 이미지 로드 실패 시 아이콘으로 대체 + imgContainer.innerHTML = '
💊
'; }; imgContainer.appendChild(img); } else { - // ?��?지 ?�으�??�이�? imgContainer.innerHTML = '
?��
'; + // 이미지 없으면 아이콘 + imgContainer.innerHTML = '
💊
'; } - // ?�스?? const textDiv = document.createElement('div'); + // 텍스트 + const textDiv = document.createElement('div'); textDiv.innerHTML = `
${p.name}
${formatPrice(p.price)}
`; card.appendChild(imgContainer); @@ -1018,11 +1020,12 @@ } function searchProductFromChat(productName) { - // 챗봇?�서 ?�품 ?�릭 ??검?�창???�력?�고 검?? document.getElementById('searchInput').value = productName; + // 챗봇에서 제품 클릭 시 검색창에 입력하고 검색 + document.getElementById('searchInput').value = productName; document.getElementById('animalOnly').checked = true; searchProducts(); - // 모바?�에??챗봇 ?�기 + // 모바일에서 챗봇 닫기 if (window.innerWidth <= 1100) { document.getElementById('chatbotPanel').classList.remove('open'); }
?�품�?/th> - ?�품코드바코??/th> - ?�고?�매가상품명상품코드바코드재고판매가 QR
-
?��
-

?�품�? 바코?? ?�품코드�?검?�하?�요

+
🔍
+

상품명, 바코드, 상품코드로 검색하세요

검??�?..

검색 중...

?�류: ${data.error}

오류: ${data.error}

검???�패

검색 실패

?��

검??결과가 ?�습?�다

📭

검색 결과가 없습니다

${escapeHtml(item.product_name)} - ${item.is_animal_drug ? '?�� ?�물??/span>' : ''} + ${item.is_animal_drug ? '🐾 동물약' : ''}
${escapeHtml(item.supplier) || ''}
${item.drug_code} ${item.barcode ? `${item.barcode}` - : `?�음`}${item.stock || 0}�?/td> + : `없음`}${item.stock || 0} ${formatPrice(item.sale_price)} - +