feat: QR 토큰 품목 상세 전송 지원 (items 파라미터)

This commit is contained in:
thug0bin
2026-03-29 12:37:36 +09:00
parent 3871154509
commit 21e1c3adfa
13 changed files with 3955 additions and 52 deletions

View File

@@ -486,6 +486,34 @@
.paai-feedback button:hover { border-color: #10b981; }
.paai-feedback button.selected { background: #d1fae5; border-color: #10b981; }
.paai-feedback button.selected-bad { background: #fee2e2; border-color: #ef4444; }
.paai-reanalyze-btn {
background: linear-gradient(135deg, #3b82f6, #2563eb) !important;
color: #fff !important;
border: none !important;
margin-left: 10px;
}
.paai-reanalyze-btn:hover {
background: linear-gradient(135deg, #2563eb, #1d4ed8) !important;
transform: scale(1.02);
}
.paai-reanalyze-btn:disabled {
background: #9ca3af !important;
cursor: not-allowed;
}
.paai-reprint-btn {
background: linear-gradient(135deg, #10b981, #059669) !important;
color: #fff !important;
border: none !important;
margin-left: 10px;
}
.paai-reprint-btn:hover {
background: linear-gradient(135deg, #059669, #047857) !important;
transform: scale(1.02);
}
.paai-reprint-btn:disabled {
background: #9ca3af !important;
cursor: not-allowed;
}
.paai-timing {
font-size: 0.8rem;
color: #9ca3af;
@@ -1456,6 +1484,8 @@
<span>도움이 되셨나요?</span>
<button onclick="sendPaaiFeedback(true)" id="paaiUseful">👍 유용해요</button>
<button onclick="sendPaaiFeedback(false)" id="paaiNotUseful">👎 아니요</button>
<button onclick="reanalyzePaai()" id="paaiReanalyze" class="paai-reanalyze-btn">🔄 재분석</button>
<button onclick="reprintPaai()" id="paaiReprint" class="paai-reprint-btn">🖨️ 재인쇄</button>
</div>
<div class="paai-timing" id="paaiTiming"></div>
</div>
@@ -2674,6 +2704,146 @@
triggerPaaiAnalysis();
}
// 🖨️ 재인쇄 함수
async function reprintPaai() {
if (!currentPrescriptionData) return;
const btn = document.getElementById('paaiReprint');
const originalText = btn.textContent;
btn.disabled = true;
btn.textContent = '🖨️ 인쇄 중...';
try {
const response = await fetch('/api/paai/reprint', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
pre_serial: currentPrescriptionData.pre_serial
})
});
const result = await response.json();
if (result.success) {
btn.textContent = '✅ 인쇄 완료!';
setTimeout(() => {
btn.textContent = originalText;
btn.disabled = false;
}, 2000);
} else {
btn.textContent = '❌ 실패';
alert('인쇄 실패: ' + (result.error || '알 수 없는 오류'));
setTimeout(() => {
btn.textContent = originalText;
btn.disabled = false;
}, 2000);
}
} catch (error) {
btn.textContent = '❌ 오류';
alert('인쇄 오류: ' + error.message);
setTimeout(() => {
btn.textContent = originalText;
btn.disabled = false;
}, 2000);
}
}
// 🔄 재분석 함수 - 캐시 무시하고 새로 분석
async function reanalyzePaai() {
if (!currentPrescriptionData) return;
const btn = document.getElementById('paaiReanalyze');
const body = document.getElementById('paaiBody');
const footer = document.getElementById('paaiFooter');
// 버튼 비활성화
btn.disabled = true;
btn.textContent = '⏳ 분석 중...';
// 로딩 표시
body.innerHTML = `
<div class="paai-loading">
<div class="spinner"></div>
<div>AI 재분석 중...</div>
<div style="font-size:0.85rem;color:#9ca3af;margin-top:10px;">캐시 무시하고 새로 분석합니다</div>
</div>
`;
footer.style.display = 'none';
const preSerial = currentPrescriptionData.pre_serial;
// 캐시 삭제
delete paaiResultCache[preSerial];
try {
// triggerPaaiAnalysis와 동일한 형식으로 데이터 구성
const requestData = {
pre_serial: preSerial,
cus_code: currentPrescriptionData.cus_code,
patient_name: currentPrescriptionData.name || '환자',
patient_note: currentPrescriptionData.cusetc || '',
disease_info: {
code_1: currentPrescriptionData.st1 || '',
name_1: currentPrescriptionData.st1_name || '',
code_2: currentPrescriptionData.st2 || '',
name_2: currentPrescriptionData.st2_name || ''
},
current_medications: (currentPrescriptionData.medications || []).map(med => ({
code: med.medication_code,
name: med.med_name,
dosage: med.dosage,
frequency: med.frequency,
days: med.duration
})),
previous_medications: (currentPrescriptionData.previous_medications || []).map(med => ({
code: med.medication_code,
name: med.med_name,
dosage: med.dosage,
frequency: med.frequency,
days: med.duration
})),
otc_history: otcData ? {
visit_count: otcData.summary?.total_visits || 0,
frequent_items: otcData.summary?.frequent_items || [],
purchases: otcData.purchases || []
} : {}
};
const response = await fetch('/pmr/api/paai/analyze', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestData)
});
const result = await response.json();
if (result.success) {
// 새 결과 캐시
paaiResultCache[preSerial] = { result, cached: false };
currentPaaiLogId = result.log_id;
currentPaaiResponse = JSON.stringify(result.analysis || {});
displayPaaiResult(result);
// 성공 표시
btn.textContent = '✅ 완료!';
setTimeout(() => {
btn.textContent = '🔄 재분석';
btn.disabled = false;
}, 2000);
} else {
body.innerHTML = `<div style="color:#ef4444;padding:20px;">❌ 재분석 실패: ${result.error}</div>`;
btn.textContent = '🔄 재분석';
btn.disabled = false;
}
} catch (error) {
body.innerHTML = `<div style="color:#ef4444;padding:20px;">❌ 오류: ${error.message}</div>`;
btn.textContent = '🔄 재분석';
btn.disabled = false;
}
footer.style.display = 'flex';
}
function displayPaaiResult(result) {
const body = document.getElementById('paaiBody');
const footer = document.getElementById('paaiFooter');