feat(pmr): 라벨 인쇄 기능 구현 및 환산계수 개선

- Brother QL 라벨 인쇄 API 추가 (POST /pmr/api/label/print)
- PMR 라벨 인쇄 버튼 동작 구현 (QL-810W)
- 환산계수 sung_code 프론트→백엔드 전달 추가
- 환산계수 모달 제품명 readonly 처리 (MSSQL 원본 보호)
- Pillow 10+ 호환성 패치 (ANTIALIAS → LANCZOS)
This commit is contained in:
thug0bin
2026-03-12 13:41:16 +09:00
parent 98d370104b
commit 17a29f05b8
2 changed files with 168 additions and 7 deletions

View File

@@ -2985,14 +2985,76 @@
document.getElementById('previewModal').style.display = 'none';
}
// 라벨 인쇄 (TODO: 구현)
function printLabels() {
const selected = Array.from(document.querySelectorAll('.med-check:checked')).map(c => c.dataset.code);
if (selected.length === 0) {
// 라벨 인쇄 (Brother QL 프린터)
async function printLabels() {
const checkboxes = document.querySelectorAll('.med-check:checked');
if (checkboxes.length === 0) {
alert('인쇄할 약품을 선택하세요');
return;
}
alert(`선택된 약품 ${selected.length}개 인쇄 기능은 추후 구현 예정입니다.\n\n${selected.join('\n')}`);
const patientName = document.querySelector('.patient-info h2')?.textContent?.trim() || '';
let printedCount = 0;
let failedCount = 0;
for (const checkbox of checkboxes) {
const tr = checkbox.closest('tr');
if (!tr) continue;
const cells = tr.querySelectorAll('td');
const medName = tr.dataset.medName || cells[1]?.querySelector('.med-name')?.textContent?.replace(/^\d+/, '').trim() || '';
const addInfo = tr.dataset.addInfo || '';
const sungCode = tr.dataset.sungCode || '';
const unit = tr.dataset.unit || '정';
// 용량 파싱 (1회 투약량)
const doseText = cells[2]?.textContent || '0';
const dosage = parseFloat(doseText.replace(/[^0-9.]/g, '')) || 0;
// 횟수 파싱
const freqText = cells[3]?.textContent || '0';
const frequency = parseInt(freqText.replace(/[^0-9]/g, '')) || 0;
// 일수 파싱
const durText = cells[4]?.textContent?.replace(/[^0-9]/g, '') || '0';
const duration = parseInt(durText) || 0;
try {
const res = await fetch('/pmr/api/label/print', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
patient_name: patientName,
med_name: medName,
add_info: addInfo,
dosage: dosage,
frequency: frequency,
duration: duration,
unit: unit,
sung_code: sungCode,
printer: '168' // 기본: QL-810W
})
});
const data = await res.json();
if (data.success) {
printedCount++;
console.log('Print success:', medName);
} else {
failedCount++;
console.error('Print failed:', medName, data.error);
}
} catch (err) {
failedCount++;
console.error('Print error:', medName, err);
}
}
if (failedCount === 0) {
alert(`${printedCount}개 라벨 인쇄 완료!`);
} else {
alert(`⚠️ 인쇄 완료: ${printedCount}\n실패: ${failedCount}`);
}
}
// ═══════════════════════════════════════════════════════════════════════════
@@ -3424,8 +3486,8 @@
<input type="text" id="drysyrup_ingredient_name" placeholder="예: 아목시실린">
</div>
<div class="drysyrup-form-row">
<label>제품명</label>
<input type="text" id="drysyrup_product_name" placeholder="예: 오구멘틴듀오시럽">
<label>제품명 <span style="font-size:0.75rem;color:#6b7280;">(MSSQL 원본)</span></label>
<input type="text" id="drysyrup_product_name" placeholder="예: 오구멘틴듀오시럽" readonly style="background:#f3f4f6;cursor:not-allowed;">
</div>
<div class="drysyrup-form-row">
<label>환산계수 (g/ml)</label>