<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>각굴에 대한 페라스타 관능 영향 평가</title>
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Plotly.js -->
<script src="https://cdn.plot.ly/plotly-2.27.0.min.js"></script>
<!-- html2pdf.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
<style>
body { font-family: 'Noto Sans KR', sans-serif; background-color: #525659; }
/* A4 Landscape Fixed Layout */
#contentToPrint {
width: 270mm;
min-height: 180mm;
margin: 0 auto;
background: white;
box-sizing: border-box;
/* 인쇄 시 배경색/그래픽 강제 출력 설정 */
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
/* 차트 높이 */
.chart-container { height: 260px; }
/* Original CSS Gradient Bar */
.gradient-bar {
width: 100%;
height: 12px;
background: linear-gradient(to right, #3b82f6 0%, #ffffff 50%, #ef4444 100%);
border: 1px solid #e5e7eb;
border-radius: 6px;
margin-bottom: 4px;
}
</style>
</head>
<body class="p-4 md:p-8">
<!-- Control Panel -->
<div class="w-[270mm] mx-auto mb-6 bg-white p-4 rounded-lg shadow-lg border border-gray-200 flex flex-col md:flex-row justify-between items-center gap-4" data-html2canvas-ignore="true">
<div>
<h3 class="font-bold text-gray-800 flex items-center">
<svg class="w-5 h-5 mr-2 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z"></path></svg>
PDF 출력 설정
</h3>
<p class="text-xs text-gray-500 mt-1">세로 범례를 제거하여 차트 영역을 확보했습니다.</p>
</div>
<div class="flex gap-3 items-center">
<div class="flex flex-col gap-1">
<label class="text-[10px] font-semibold text-gray-500">파일명</label>
<input type="text" id="pdfFilename" value="각굴_페라스타_영향평가_보고서" class="border border-gray-300 rounded px-2 py-1 text-xs w-48 focus:border-blue-500 outline-none">
</div>
<button onclick="downloadPDF()" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-6 rounded shadow flex items-center transition h-[38px] mt-4">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg>
PDF 다운로드
</button>
</div>
</div>
<!-- Main Report Area -->
<div id="contentToPrint" class="p-8 shadow-2xl relative">
<!-- Header -->
<div class="flex justify-between items-end border-b-2 border-gray-800 pb-3 mb-4">
<div>
<h1 class="text-2xl font-extrabold text-gray-900 tracking-tight">각굴에 대한 페라스타 관능 영향 평가</h1>
<p class="text-sm text-gray-600 mt-1 font-medium">대조군 대비 관능적 특성(비린내/이취) 상대 비교 분석</p>
</div>
<div class="text-right text-xs text-gray-500">
<p><strong>작성일:</strong> 2025.03.12</p>
<p><strong>소속:</strong> 헬스케어연구소</p>
</div>
</div>
<!-- Summary Section -->
<div class="bg-gray-50 rounded-lg border-l-4 border-gray-700 p-3 mb-5 text-xs shadow-sm">
<h3 class="font-bold text-gray-800 mb-2 flex items-center text-sm">
<svg class="w-4 h-4 mr-1.5 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path></svg>
평가 기준 및 요약
</h3>
<!-- Original Visual Legend (CSS Gradient) - 유지 -->
<div class="mb-3 px-2">
<div class="gradient-bar"></div>
<div class="flex justify-between text-[10px] font-bold text-gray-600">
<span class="text-blue-600">1점 (매우 약함)</span>
<span class="text-gray-500">2점</span>
<span class="text-gray-800 bg-white px-1 border rounded shadow-sm">3점 (대조군 동일)</span>
<span class="text-gray-500">4점</span>
<span class="text-red-600">5점 (매우 강함)</span>
</div>
</div>
<ul class="grid grid-cols-1 gap-1 text-gray-700 ml-1 leading-relaxed">
<li class="flex items-start"><span class="text-blue-600 mr-1.5 font-bold">●</span> <span><strong>비린내:</strong> 1~2점 구간이 대조군(3점)보다 비린내 감소 (긍정적 결과).</span></li>
<li class="flex items-start"><span class="text-red-500 mr-1.5 font-bold">●</span> <span><strong>초산 냄새:</strong> 4~5점 구간은 대조군(3점)보다 약품 냄새 강함 (부정적 결과).</span></li>
<li class="flex items-start"><span class="text-green-600 mr-1.5 font-bold">●</span> <span><strong>결론:</strong> <u>100ppm / 30초</u> 조건이 최적 (비린내 2점, 초산냄새 1점).</span></li>
</ul>
</div>
<!-- Charts Grid -->
<div class="grid grid-cols-2 gap-6">
<!-- Chart 1: Fishy Smell -->
<div class="bg-white rounded-lg border border-gray-200 p-3 shadow-sm relative">
<div class="flex items-center justify-between mb-1 border-b pb-1 border-gray-100">
<h2 class="text-sm font-bold text-gray-800 flex items-center">
🐟 어패류 비린내 <span class="text-[10px] font-normal text-gray-500 ml-1">(Fishy Smell)</span>
</h2>
<span class="text-[10px] font-bold text-blue-700 bg-blue-50 px-2 py-0.5 rounded border border-blue-100">Target: 1~2점</span>
</div>
<div id="fishyChart" class="chart-container"></div>
</div>
<!-- Chart 2: Acetic Acid Smell -->
<div class="bg-white rounded-lg border border-gray-200 p-3 shadow-sm relative">
<div class="flex items-center justify-between mb-1 border-b pb-1 border-gray-100">
<h2 class="text-sm font-bold text-gray-800 flex items-center">
🧪 초산 냄새 <span class="text-[10px] font-normal text-gray-500 ml-1">(Acetic Smell)</span>
</h2>
<span class="text-[10px] font-bold text-gray-700 bg-gray-50 px-2 py-0.5 rounded border border-gray-100">Target: 3점 이하</span>
</div>
<div id="aceticChart" class="chart-container"></div>
</div>
</div>
<!-- Footer -->
<div class="absolute bottom-4 left-0 w-full text-center text-[10px] text-gray-400">
Generated by Sensory Analysis Report Tool
</div>
</div>
<script>
// --- Data & Charts ---
const xValues = ['50 ppm', '100 ppm', '200 ppm'];
const yValues = ['30초', '1분', '5분', '10분'];
const zFishy = [[3, 2, 5], [5, 3, 5], [5, 3, 3], [4, 4, 4]];
const zAcetic = [[3, 1, 4], [3, 1, 1], [3, 1, 1], [3, 3, 3]];
function renderCharts() {
const commonLayout = {
// 오른쪽 여백을 줄임 (세로 범례가 없어졌으므로 공간 확보 불필요)
margin: { t: 15, b: 25, l: 35, r: 15 },
xaxis: { side: 'bottom', title: '' },
yaxis: { autorange: 'reversed', title: '' },
font: { family: 'Noto Sans KR', size: 11 },
paper_bgcolor: 'rgba(0,0,0,0)',
plot_bgcolor: 'rgba(0,0,0,0)'
};
const divergingColorScale = [
[0, '#3b82f6'], // 1점: 파란색
[0.5, '#ffffff'], // 3점: 흰색
[1, '#ef4444'] // 5점: 빨간색
];
const fishyTrace = {
z: zFishy, x: xValues, y: yValues, type: 'heatmap',
colorscale: divergingColorScale,
zmin: 1, zmax: 5,
text: zFishy.map(row => row.map(val => String(val))),
texttemplate: "%{text}", textfont: { color: 'black', size: 14, weight: 'bold' },
hovertemplate: '시간: %{y}<br>농도: %{x}<br><b>비린내: %{z}점</b><extra></extra>',
ygap: 2, xgap: 2,
showscale: false // 세로 범례 제거
};
const aceticTrace = {
z: zAcetic, x: xValues, y: yValues, type: 'heatmap',
colorscale: divergingColorScale,
zmin: 1, zmax: 5,
text: zAcetic.map(row => row.map(val => String(val))),
texttemplate: "%{text}", textfont: { color: 'black', size: 14, weight: 'bold' },
hovertemplate: '시간: %{y}<br>농도: %{x}<br><b>초산냄새: %{z}점</b><extra></extra>',
ygap: 2, xgap: 2,
showscale: false // 세로 범례 제거
};
Plotly.newPlot('fishyChart', [fishyTrace], commonLayout, {responsive: true, displayModeBar: false});
Plotly.newPlot('aceticChart', [aceticTrace], commonLayout, {responsive: true, displayModeBar: false});
}
function downloadPDF() {
const filenameInput = document.getElementById('pdfFilename').value || 'report';
const element = document.getElementById('contentToPrint');
const opt = {
margin: 0,
filename: `${filenameInput}.pdf`,
image: { type: 'jpeg', quality: 1 },
html2canvas: { scale: 2, useCORS: true, logging: false },
jsPDF: { unit: 'mm', format: 'a4', orientation: 'landscape' }
};
const btn = document.querySelector('button[onclick="downloadPDF()"]');
const originalContent = btn.innerHTML;
btn.innerHTML = `<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> 저장 중...`;
btn.disabled = true;
html2pdf().set(opt).from(element).save().then(() => {
btn.innerHTML = originalContent;
btn.disabled = false;
}).catch(err => {
console.error(err);
alert("PDF 생성 중 오류가 발생했습니다.");
btn.innerHTML = originalContent;
btn.disabled = false;
});
}
setTimeout(renderCharts, 100);
</script>
</body>
</html>