From 4fb34d5e17f587d423fab9564839569ab1c304ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B2=AD=EC=B6=98=EC=95=BD=EA=B5=AD?= Date: Wed, 18 Mar 2026 23:19:22 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=99=84?= =?UTF-8?q?=EC=A0=84=20=EC=9E=AC=EC=9E=91=EC=84=B1=20-=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EB=8B=B9=204=EA=B0=9C=20=EA=B3=A0=EC=A0=95?= =?UTF-8?q?=20=EC=98=81=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- animal_med/renderer_v2.py | 9 +- templates/medication_guide_v2.html | 578 +++++++++++------------------ 2 files changed, 210 insertions(+), 377 deletions(-) diff --git a/animal_med/renderer_v2.py b/animal_med/renderer_v2.py index 39011d7..8e3059e 100644 --- a/animal_med/renderer_v2.py +++ b/animal_med/renderer_v2.py @@ -122,14 +122,7 @@ class AnimalMedRendererV2: await page.set_content(html_content, wait_until='networkidle') - # 콘텐츠 크기 확인 - rect = await page.evaluate('''() => { - const el = document.querySelector('.container'); - const rect = el.getBoundingClientRect(); - return { width: rect.width, height: rect.height }; - }''') - - # scale 고정 (자연스러운 페이지 분할) + # scale 고정 (페이지 분할을 위해) scale = 1.0 await page.pdf( diff --git a/templates/medication_guide_v2.html b/templates/medication_guide_v2.html index 434e11a..2fda5e0 100644 --- a/templates/medication_guide_v2.html +++ b/templates/medication_guide_v2.html @@ -9,8 +9,6 @@ * { margin: 0; padding: 0; box-sizing: border-box; } html, body { - width: 210mm; - height: 297mm; font-family: 'Noto Sans KR', sans-serif; font-size: 9pt; color: #333; @@ -18,16 +16,14 @@ background: #fff; } - .container { - width: 210mm; - padding: 5mm; - } - + /* 페이지 */ .page { - width: 200mm; - height: 287mm; + width: 210mm; + height: 297mm; + padding: 5mm; page-break-after: always; position: relative; + box-sizing: border-box; } .page:last-child { @@ -39,85 +35,79 @@ display: flex; justify-content: space-between; align-items: center; - border-bottom: 3px solid #1565C0; - padding-bottom: 3mm; - margin-bottom: 4mm; + border-bottom: 2px solid #1565C0; + padding-bottom: 2mm; + margin-bottom: 3mm; + height: 15mm; } .header-left .patient-name { - font-size: 16pt; + font-size: 14pt; font-weight: 700; color: #0D47A1; } .header-left .patient-info { - font-size: 8pt; - color: #666; - margin-top: 1mm; - } - - .header-center { - text-align: center; - } - - .header-center .pharmacy-name { - font-size: 14pt; - font-weight: 700; - color: #1565C0; - } - - .header-center .pharmacy-slogan { - font-size: 8pt; - color: #42A5F5; - } - - .header-right { - text-align: right; font-size: 7pt; color: #666; } - /* 약품 카드 그리드 */ - .drug-cards-grid { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 3mm; + .header-center .pharmacy-name { + font-size: 12pt; + font-weight: 700; + color: #1565C0; } - /* 약품 카드 공통 */ + .header-right { + font-size: 7pt; + color: #666; + } + + /* 카드 그리드 영역 - 고정 높이 */ + .cards-area { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr 1fr; + gap: 2mm; + height: 265mm; /* 297 - 5*2(패딩) - 15(헤더) - 7(푸터) */ + } + + .cards-area.no-header { + height: 280mm; /* 헤더 없을 때 */ + } + + /* 약품 카드 */ .drug-card { border: 1px solid #E0E0E0; border-radius: 2mm; overflow: hidden; - page-break-inside: avoid; + display: flex; + flex-direction: column; } .drug-card-header { background: linear-gradient(135deg, #1565C0, #42A5F5); color: white; - padding: 2mm; + padding: 1.5mm; display: flex; align-items: center; gap: 2mm; + flex-shrink: 0; } .drug-icon { - width: 8mm; - height: 8mm; + width: 7mm; + height: 7mm; background: white; - border-radius: 1.5mm; + border-radius: 1mm; display: flex; align-items: center; justify-content: center; - font-size: 12pt; - } - - .drug-title-area { - flex: 1; + font-size: 10pt; } .drug-name { - font-size: 9pt; + font-size: 8pt; font-weight: 700; } @@ -129,489 +119,339 @@ .drug-badges { display: flex; gap: 0.5mm; - margin-top: 0.5mm; flex-wrap: wrap; } .badge { background: rgba(255,255,255,0.2); - padding: 0.3mm 1mm; + padding: 0.2mm 1mm; border-radius: 0.5mm; - font-size: 5pt; + font-size: 4.5pt; } .drug-card-body { - padding: 2mm; - font-size: 6pt; - } - - /* 구충제 전용 - 커버리지 표 */ - .coverage-section { - margin-bottom: 3mm; + padding: 1.5mm; + font-size: 5.5pt; + flex: 1; + overflow: hidden; } + /* 섹션들 */ .coverage-title { - font-size: 9pt; + font-size: 6pt; font-weight: 700; color: #1565C0; - margin-bottom: 2mm; - display: flex; - align-items: center; - gap: 1mm; + margin-bottom: 1mm; } .coverage-table { display: grid; grid-template-columns: repeat(4, 1fr); - gap: 1mm; + gap: 0.5mm; background: #F5F5F5; - padding: 2mm; - border-radius: 2mm; + padding: 1mm; + border-radius: 1mm; + margin-bottom: 1.5mm; } .coverage-item { background: white; - padding: 1.5mm; - border-radius: 1mm; + padding: 1mm; + border-radius: 0.5mm; text-align: center; - font-size: 7pt; + font-size: 5pt; } - .coverage-item.covered { - border-left: 2px solid #4CAF50; - } + .coverage-item.covered { border-left: 1.5px solid #4CAF50; } + .coverage-item.not-covered { border-left: 1.5px solid #F44336; background: #FFEBEE; } - .coverage-item.not-covered { - border-left: 2px solid #F44336; - background: #FFEBEE; - } - - .coverage-icon { - font-size: 10pt; - display: block; - } - - .coverage-name { - font-weight: 500; - margin-top: 0.5mm; - } + .coverage-icon { font-size: 7pt; } + .coverage-name { font-weight: 500; } /* 갭 경고 */ .gap-warning { background: #FFF3E0; border: 1px solid #FFB74D; - border-radius: 2mm; - padding: 2mm; - margin-top: 2mm; - font-size: 7pt; + border-radius: 1mm; + padding: 1mm; + margin-bottom: 1.5mm; + font-size: 5pt; } - .gap-warning-title { - font-weight: 700; - color: #E65100; - } - - .gap-solution { - color: #F57C00; - margin-top: 1mm; - } + .gap-warning-title { font-weight: 700; color: #E65100; } + .gap-solution { color: #F57C00; } /* 투약 정보 */ .dosing-section { background: #E3F2FD; - border-radius: 2mm; - padding: 2mm 3mm; - margin-bottom: 3mm; + border-radius: 1mm; + padding: 1mm 1.5mm; + margin-bottom: 1.5mm; } - .dosing-title { - font-weight: 700; - color: #1565C0; - font-size: 8pt; - } - - .dosing-main { - font-size: 11pt; - font-weight: 700; - color: #0D47A1; - margin: 1mm 0; - } - - .dosing-note { - font-size: 7pt; - color: #1976D2; - } + .dosing-title { font-weight: 700; color: #1565C0; font-size: 5.5pt; } + .dosing-main { font-size: 8pt; font-weight: 700; color: #0D47A1; } + .dosing-note { font-size: 5pt; color: #1976D2; } /* 체중별 제품 */ .weight-products { display: flex; - gap: 1mm; + gap: 0.5mm; flex-wrap: wrap; - margin-top: 2mm; + margin-top: 1mm; } .weight-product { background: #E8F5E9; - padding: 1mm 2mm; - border-radius: 1mm; - font-size: 6pt; - border: 1px solid #A5D6A7; - } - - /* NSAIDs 전용 - 용량표 */ - .dosage-table-section { - margin-bottom: 3mm; + padding: 0.5mm 1mm; + border-radius: 0.5mm; + font-size: 4.5pt; + border: 0.5px solid #A5D6A7; } + /* 용량표 */ .dosage-grid { display: grid; grid-template-columns: repeat(3, 1fr); - gap: 1mm; + gap: 0.5mm; background: #E3F2FD; - padding: 2mm; - border-radius: 2mm; + padding: 1mm; + border-radius: 1mm; + margin-bottom: 1.5mm; } .dosage-cell { background: white; - padding: 1.5mm; - border-radius: 1mm; + padding: 1mm; + border-radius: 0.5mm; text-align: center; - font-size: 7pt; + font-size: 5pt; } - .dosage-weight { - font-weight: 500; - color: #1565C0; - } - - .dosage-amount { - font-weight: 700; - color: #0D47A1; - font-size: 9pt; - } + .dosage-weight { font-weight: 500; color: #1565C0; } + .dosage-amount { font-weight: 700; color: #0D47A1; font-size: 6pt; } /* 절대 금기 */ .contraindication-box { background: #FFEBEE; - border: 2px solid #F44336; - border-radius: 2mm; - padding: 2mm 3mm; - margin-bottom: 3mm; + border: 1px solid #F44336; + border-radius: 1mm; + padding: 1mm; + margin-bottom: 1.5mm; } - .contraindication-title { - font-weight: 900; - color: #C62828; - font-size: 9pt; - margin-bottom: 1mm; - } + .contraindication-title { font-weight: 900; color: #C62828; font-size: 6pt; } .contraindication-list { list-style: none; - } - - .contraindication-list li { - font-size: 8pt; + font-size: 5pt; color: #B71C1C; - padding: 1mm 0; - border-bottom: 1px dashed #FFCDD2; - display: flex; - align-items: flex-start; - gap: 1mm; } - .contraindication-list li:last-child { - border-bottom: none; - } + .contraindication-list li { padding: 0.3mm 0; } /* 주의사항 */ .warnings-section { background: #FFF8E1; border: 1px solid #FFE082; - border-radius: 2mm; - padding: 2mm 3mm; + border-radius: 1mm; + padding: 1mm; } - .warnings-title { - font-weight: 700; - color: #F57F17; - font-size: 8pt; - margin-bottom: 1mm; - } + .warnings-title { font-weight: 700; color: #F57F17; font-size: 5.5pt; } .warnings-list { list-style: none; - } - - .warnings-list li { - font-size: 7pt; + font-size: 5pt; color: #795548; - padding: 0.5mm 0; - padding-left: 2mm; - position: relative; } - .warnings-list li::before { - content: "•"; - position: absolute; - left: 0; - color: #FF9800; + .warnings-list li { padding: 0.2mm 0; } + + /* 외용제 용법 */ + .usage-box { + background: #E8F5E9; + padding: 1mm; + border-radius: 1mm; + font-size: 5pt; + margin-bottom: 1.5mm; } /* 푸터 */ .footer { position: absolute; - bottom: 4mm; - left: 6mm; - right: 6mm; + bottom: 3mm; + left: 5mm; + right: 5mm; text-align: center; - font-size: 6pt; + font-size: 5pt; color: #9E9E9E; - border-top: 1px solid #E0E0E0; - padding-top: 2mm; + border-top: 0.5px solid #E0E0E0; + padding-top: 1mm; + height: 7mm; } - .footer-logo { - font-weight: 700; - color: #1565C0; - font-size: 8pt; - } + .footer-logo { font-weight: 700; color: #1565C0; font-size: 6pt; } -
- - {% for drug in drugs %} - {% if loop.index0 % 4 == 0 %} -
- {% if loop.index0 == 0 %} - -
-
-
{{ patient_name }} 보호자님
-
- 🐾 {{ pet_name }} ({{ pet_species }}, {{ pet_age }}) | 📅 {{ issue_date }} -
-
-
-
🏥 {{ pharmacy_name }}
-
-
{{ pharmacy_tel }}
-
- {% endif %} -
- {% endif %} +{% set drugs_per_page = 4 %} +{% set total_pages = ((drugs|length - 1) // drugs_per_page) + 1 %} + +{% for page_num in range(total_pages) %} +
+ {% if page_num == 0 %} + +
+
+
{{ patient_name }} 보호자님
+
🐾 {{ pet_name }} ({{ pet_species }}, {{ pet_age }}) | 📅 {{ issue_date }}
+
+
+
🏥 {{ pharmacy_name }}
+
+
{{ pharmacy_tel }}
+
+ {% endif %} + +
+ {% set start_idx = page_num * drugs_per_page %} + {% set end_idx = [start_idx + drugs_per_page, drugs|length] | min %} + + {% for drug in drugs[start_idx:end_idx] %}
💊
-
+
{{ drug.name }}
{{ drug.english_name }}
{{ drug.category_display }} - {% for animal in drug.target_animal %} - {{ animal }} - {% endfor %} - {{ drug.administration }} + {% for animal in drug.target_animal %}{{ animal }}{% endfor %}
{% if drug.category == 'antiparasitic' %} - -
-
🎯 구충 범위
-
- {% for item in drug.coverage_summary.covered %} -
- - {{ item }} -
- {% endfor %} - {% for item in drug.coverage_summary.not_covered %} -
- - {{ item }} -
- {% endfor %} + +
🎯 구충 범위
+
+ {% for item in drug.coverage_summary.covered %} +
+ + {{ item }}
- - {% if drug.coverage_summary.not_covered %} -
-
⚠️ 미커버 항목
-
💡 {{ drug.coverage_summary.gap_solution }}
+ {% endfor %} + {% for item in drug.coverage_summary.not_covered %} +
+ + {{ item }}
- {% endif %} + {% endfor %}
+ {% if drug.coverage_summary.gap_solution %} +
+ ⚠️ 보완: + {{ drug.coverage_summary.gap_solution }} +
+ {% endif %} +
-
📅 투약 주기
+
📅 투약
{{ drug.dosing.interval }}
-
- {{ drug.dosing.interval_reason }}
- 최소 연령: {{ drug.dosing.minimum_age }} / 최소 체중: {{ drug.dosing.minimum_weight }} -
- {% if drug.weight_products %}
- {% for wp in drug.weight_products %} -
{{ wp.size }} ({{ wp.weight_range }})
- {% endfor %} + {% for wp in drug.weight_products %}
{{ wp.size }}({{ wp.weight_range }})
{% endfor %}
{% endif %}
{% elif drug.category == 'nsaid' %} - -
-
⚖️ 체중별 용량 ({{ drug.dosage.standard }})
-
- {% for row in drug.dosage_table %} -
-
{{ row.weight }}
-
{{ row.tablets }}
-
- {% endfor %} + +
⚖️ 용량 ({{ drug.dosage.standard }})
+
+ {% for row in drug.dosage_table[:6] %} +
+
{{ row.weight }}
+
{{ row.tablets }}
+ {% endfor %}
{% if drug.absolute_contraindications %}
🚫 절대 금기
    - {% for contra in drug.absolute_contraindications %} -
  • ❌ {{ contra.item }} — {{ contra.reason }}
  • + {% for c in drug.absolute_contraindications[:3] %} +
  • ❌ {{ c.item }}
  • {% endfor %}
{% endif %} {% elif drug.category == 'antibiotic' %} - +
-
📋 적응증
-
{{ drug.indication }}
-
- -
-
⚖️ 체중별 용량 ({{ drug.dosage.standard }})
-
- {% for row in drug.dosage_table %} -
-
{{ row.weight }}
-
{{ row.tablets }}
-
- {% endfor %} -
-
- 투약 기간: {{ drug.dosage.duration }} -
+
📋 {{ drug.indication[:30] }}...
+
{{ drug.dosage.standard }}
+
기간: {{ drug.dosage.duration }}
{% if drug.cat_warning %}
-
🐱 고양이 특별 주의
-
    -
  • ❌ 최대 용량: {{ drug.cat_warning.max_dose }}
  • -
  • ❌ 위험: {{ drug.cat_warning.risk }}
  • -
+
🐱 고양이 주의
+
최대: {{ drug.cat_warning.max_dose }} ({{ drug.cat_warning.risk }})
{% endif %} {% elif drug.category == 'antiemetic' %} - +
-
📋 적응증
-
{{ drug.indication }}
+
📋 {{ drug.indication }}
- -
-
💊 용법용량
-
-
- 급성 구토 - {{ drug.dosage.acute_vomiting.dose }} - 최대 {{ drug.dosage.acute_vomiting.duration }} -
-
- 멀미 예방 - {{ drug.dosage.motion_sickness.dose }} - {{ drug.dosage.motion_sickness.timing }} -
-
-
- - {% if drug.clinical_notes %} -
-
💡 임상 참고
- {% for note in drug.clinical_notes %} -
• {{ note }}
- {% endfor %} -
- {% endif %} - - {% elif drug.category in ['otic', 'antifungal', 'topical'] %} - -
-
📋 적응증
-
{{ drug.indication }}
-
- -
-
💊 용법
-
- {% if drug.dosage.frequency %} -
빈도: {{ drug.dosage.frequency }}
- {% endif %} - {% if drug.dosage.duration %} -
기간: {{ drug.dosage.duration }}
- {% endif %} - {% if drug.dosage.contact_time %} -
접촉시간: {{ drug.dosage.contact_time }}
- {% endif %} - {% if drug.dosage.amount %} -
용량: {{ drug.dosage.amount }}
- {% endif %} -
+
+ 급성구토: {{ drug.dosage.acute_vomiting.dose }} ({{ drug.dosage.acute_vomiting.duration }})
+ 멀미예방: {{ drug.dosage.motion_sickness.dose }} ({{ drug.dosage.motion_sickness.timing }})
{% else %} - +
-
📋 적응증
-
{{ drug.indication }}
+
📋 {{ drug.indication }}
+
+ {% if drug.dosage %} +
+ {% if drug.dosage.frequency %}빈도: {{ drug.dosage.frequency }}
{% endif %} + {% if drug.dosage.duration %}기간: {{ drug.dosage.duration }}
{% endif %} + {% if drug.dosage.contact_time %}접촉: {{ drug.dosage.contact_time }}{% endif %}
{% endif %} + {% endif %} - + {% if drug.warnings %}
-
⚠️ 주의사항
+
⚠️ 주의
    - {% for warning in drug.warnings %} -
  • {{ warning }}
  • - {% endfor %} + {% for w in drug.warnings[:3] %}
  • {{ w[:40] }}{% if w|length > 40 %}...{% endif %}
  • {% endfor %}
{% endif %}
- {% if loop.index % 4 == 0 or loop.last %} -
- {% if loop.last %} - - - {% endif %} -
- {% endif %} {% endfor %} - -
+ + {% if loop.last %} + + + {% endif %} +
+{% endfor %}