Preformu / templates /report_template.html
Kevinshh's picture
Upload full project
aecf8ce verified
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>药物-辅料相容性预测报告 | API Excipient Compatibility Assessment</title>
<style>
/* ========================================
Global Styles
======================================== */
:root {
--primary-color: #1a5f7a;
--secondary-color: #2d8bb8;
--accent-color: #57c5b6;
--warning-color: #ffc107;
--danger-color: #dc3545;
--success-color: #28a745;
--text-primary: #333333;
--text-secondary: #666666;
--bg-light: #f8f9fa;
--border-color: #dee2e6;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', 'Microsoft YaHei', Arial, sans-serif;
line-height: 1.6;
color: var(--text-primary);
background: #ffffff;
font-size: 14px;
}
/* ========================================
Report Container
======================================== */
.report-container {
max-width: 1000px;
margin: 0 auto;
padding: 40px;
background: #ffffff;
}
/* ========================================
Header Styles
======================================== */
.report-header {
border-bottom: 3px solid var(--primary-color);
padding-bottom: 20px;
margin-bottom: 30px;
}
.report-title {
font-size: 24px;
font-weight: bold;
color: var(--primary-color);
margin-bottom: 5px;
}
.report-subtitle {
font-size: 14px;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 1px;
}
.report-meta {
float: right;
text-align: right;
font-size: 12px;
color: var(--text-secondary);
}
.report-meta .meta-item {
margin-bottom: 3px;
}
.report-meta .meta-label {
font-weight: normal;
}
.report-meta .meta-value {
font-weight: bold;
color: var(--primary-color);
}
.clearfix::after {
content: "";
display: table;
clear: both;
}
/* ========================================
Section Styles
======================================== */
.section {
margin-bottom: 30px;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: var(--primary-color);
margin-bottom: 15px;
padding-bottom: 8px;
border-bottom: 2px solid var(--accent-color);
}
.section-title .en-title {
font-weight: normal;
color: var(--text-secondary);
margin-left: 10px;
}
/* ========================================
Two Column Layout
======================================== */
.two-column {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
}
.column {
min-width: 0;
}
/* ========================================
Structure Display
======================================== */
.structure-box {
background: var(--bg-light);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 20px;
text-align: center;
min-height: 200px;
}
.structure-image {
max-width: 100%;
max-height: 180px;
margin-bottom: 10px;
}
.structure-caption {
font-size: 11px;
color: var(--text-secondary);
font-style: italic;
}
.smiles-display {
font-family: 'Courier New', monospace;
font-size: 11px;
word-break: break-all;
color: var(--text-secondary);
margin-top: 10px;
padding: 8px;
background: #ffffff;
border-radius: 4px;
}
/* ========================================
Properties Table
======================================== */
.properties-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
.properties-table th,
.properties-table td {
padding: 10px 12px;
text-align: left;
border-bottom: 1px solid var(--border-color);
}
.properties-table th {
background: var(--bg-light);
font-weight: 600;
color: var(--text-secondary);
width: 40%;
}
.properties-table td {
color: var(--text-primary);
}
/* ========================================
Risk Profile Chart
======================================== */
.risk-chart {
margin-top: 15px;
padding: 15px;
background: var(--bg-light);
border-radius: 8px;
}
.risk-chart-title {
font-size: 12px;
font-weight: 600;
color: var(--text-secondary);
margin-bottom: 10px;
}
.risk-item {
display: flex;
align-items: center;
margin-bottom: 8px;
font-size: 12px;
}
.risk-label {
width: 120px;
color: var(--text-secondary);
}
.risk-bar {
flex: 1;
height: 8px;
background: #e9ecef;
border-radius: 4px;
overflow: hidden;
}
.risk-fill {
height: 100%;
border-radius: 4px;
transition: width 0.3s ease;
}
.risk-fill.low { background: var(--success-color); }
.risk-fill.medium { background: var(--warning-color); }
.risk-fill.high { background: var(--danger-color); }
/* ========================================
Reactive Groups Display
======================================== */
.reactive-groups {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
}
.group-card {
background: var(--bg-light);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 15px;
}
.group-name {
font-weight: 600;
color: var(--primary-color);
margin-bottom: 5px;
}
.group-property {
font-size: 12px;
color: var(--text-secondary);
margin-bottom: 8px;
}
.group-reactions {
font-size: 11px;
}
.reaction-tag {
display: inline-block;
background: var(--secondary-color);
color: white;
padding: 2px 8px;
border-radius: 3px;
margin: 2px;
font-size: 10px;
}
/* ========================================
Excipient Profile
======================================== */
.excipient-box {
background: var(--bg-light);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 20px;
}
.excipient-name {
font-size: 16px;
font-weight: 600;
color: var(--primary-color);
margin-bottom: 15px;
}
.impurity-alert {
background: #fff3cd;
border: 1px solid #ffc107;
border-radius: 6px;
padding: 12px 15px;
margin-top: 15px;
}
.impurity-alert-title {
font-weight: 600;
color: #856404;
margin-bottom: 8px;
font-size: 13px;
}
.impurity-item {
font-size: 12px;
color: #856404;
margin: 4px 0;
}
/* ========================================
Interaction Mechanism Table
======================================== */
.mechanism-table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
margin-top: 15px;
}
.mechanism-table th,
.mechanism-table td {
padding: 12px;
text-align: left;
border: 1px solid var(--border-color);
vertical-align: top;
}
.mechanism-table th {
background: var(--primary-color);
color: white;
font-weight: 600;
}
.mechanism-table tbody tr:nth-child(even) {
background: var(--bg-light);
}
.risk-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 4px;
font-size: 11px;
font-weight: 600;
}
.risk-badge.none { background: #d4edda; color: #155724; }
.risk-badge.low { background: #d1ecf1; color: #0c5460; }
.risk-badge.medium { background: #fff3cd; color: #856404; }
.risk-badge.high { background: #f8d7da; color: #721c24; }
/* ========================================
Formulation Strategy
======================================== */
.strategy-box {
background: #e8f4f8;
border-left: 4px solid var(--primary-color);
padding: 20px;
margin-top: 15px;
}
.strategy-title {
font-weight: 600;
color: var(--primary-color);
margin-bottom: 10px;
}
.strategy-list {
list-style: none;
}
.strategy-list li {
margin: 10px 0;
padding-left: 25px;
position: relative;
}
.strategy-list li::before {
content: "●";
position: absolute;
left: 0;
color: var(--accent-color);
}
.strategy-number {
display: inline-block;
width: 20px;
height: 20px;
background: var(--primary-color);
color: white;
border-radius: 50%;
text-align: center;
line-height: 20px;
font-size: 11px;
margin-right: 8px;
}
/* ========================================
Footer & Disclaimer
======================================== */
.report-footer {
margin-top: 40px;
padding-top: 20px;
border-top: 1px solid var(--border-color);
font-size: 11px;
color: var(--text-secondary);
}
.disclaimer {
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
margin-top: 15px;
}
.disclaimer-title {
font-weight: 600;
margin-bottom: 8px;
}
/* ========================================
Print Styles
======================================== */
@media print {
body {
font-size: 12px;
}
.report-container {
padding: 20px;
}
.section {
page-break-inside: avoid;
}
}
</style>
</head>
<body>
<div class="report-container">
<!-- Header -->
<header class="report-header clearfix">
<div class="report-meta">
<div class="meta-item">
<span class="meta-label">Report ID:</span>
<span class="meta-value">{{ report_id }}</span>
</div>
<div class="meta-item">
<span class="meta-label">Date:</span>
<span class="meta-value">{{ date }}</span>
</div>
<div class="meta-item">
<span class="meta-label">Target:</span>
<span class="meta-value">{{ excipient_name_en }}</span>
</div>
</div>
<h1 class="report-title">药物-辅料相容性预测报告</h1>
<p class="report-subtitle">API Excipient Compatibility Assessment</p>
</header>
<!-- Section 1 & 2: API Structure and Properties -->
<div class="two-column">
<div class="column">
<section class="section">
<h2 class="section-title">
1. API 结构与反应活性基团
<span class="en-title">(Reactive Moieties)</span>
</h2>
<div class="structure-box">
{% if structure_image %}
<img src="{{ structure_image }}" alt="Molecular Structure" class="structure-image">
<p class="structure-caption">Structure Rendered by MolRenderer</p>
{% else %}
<div style="padding: 40px 0; color: #999;">
[结构图待生成]
</div>
{% endif %}
{% if api_smiles %}
<div class="smiles-display">
SMILES: {{ api_smiles }}
</div>
{% endif %}
</div>
<div class="reactive-groups" style="margin-top: 20px;">
{% for group in reactive_groups %}
<div class="group-card">
<div class="group-name">{{ group.name.cn }}</div>
<div class="group-property">({{ group.name.en }})</div>
<div class="group-property">性质: {{ group.property_type }}</div>
<div class="group-reactions">
{% for reaction in group.potential_reactions %}
<span class="reaction-tag">{{ reaction.cn }}</span>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</section>
</div>
<div class="column">
<section class="section">
<h2 class="section-title">
2. 理化性质概览
<span class="en-title">(Basic)</span>
</h2>
<table class="properties-table">
<tr>
<th>酸碱性:</th>
<td>{{ physicochemical.acidity_basicity.cn if physicochemical else '-' }}</td>
</tr>
<tr>
<th>LogP (Est):</th>
<td>~{{ physicochemical.logp if physicochemical and physicochemical.logp else '-' }}</td>
</tr>
<tr>
<th>H-Bond Donors:</th>
<td>{{ physicochemical.h_bond_donors if physicochemical and physicochemical.h_bond_donors else '-' }} (~NH2)</td>
</tr>
<tr>
<th>H-Bond Acceptors:</th>
<td>{{ physicochemical.h_bond_acceptors if physicochemical and physicochemical.h_bond_acceptors else '-' }}</td>
</tr>
</table>
<div class="risk-chart">
<div class="risk-chart-title">风险评价 (Risk Profile)</div>
<div class="risk-item">
<span class="risk-label">Maillard Reaction</span>
<div class="risk-bar">
<div class="risk-fill {{ maillard_risk_class }}" style="width: {{ maillard_risk_width }}%;"></div>
</div>
</div>
<div class="risk-item">
<span class="risk-label">Hygroscopicity</span>
<div class="risk-bar">
<div class="risk-fill {{ hygro_risk_class }}" style="width: {{ hygro_risk_width }}%;"></div>
</div>
</div>
<div class="risk-item">
<span class="risk-label">Chemisorption</span>
<div class="risk-bar">
<div class="risk-fill {{ chem_risk_class }}" style="width: {{ chem_risk_width }}%;"></div>
</div>
</div>
<div class="risk-item">
<span class="risk-label">Oxidation</span>
<div class="risk-bar">
<div class="risk-fill {{ oxid_risk_class }}" style="width: {{ oxid_risk_width }}%;"></div>
</div>
</div>
<div class="risk-item">
<span class="risk-label">Hydrolysis</span>
<div class="risk-bar">
<div class="risk-fill {{ hydro_risk_class }}" style="width: {{ hydro_risk_width }}%;"></div>
</div>
</div>
</div>
</section>
</div>
</div>
<!-- Section 3: Excipient Properties -->
<section class="section">
<h2 class="section-title">
3. 辅料属性:{{ excipient_name }}
<span class="en-title">({{ excipient_name_en }})</span>
</h2>
<div class="two-column">
<div class="column">
<div class="excipient-box">
<h3 style="color: var(--text-secondary); font-size: 13px; margin-bottom: 10px;">关键特性:</h3>
{% if excipient_profile %}
<ul style="font-size: 13px; padding-left: 20px;">
{% if excipient_profile.formula %}
<li>化学式: {{ excipient_profile.formula }}</li>
{% endif %}
{% for prop in excipient_profile.key_properties %}
<li>{{ prop }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
<div class="column">
<div class="impurity-alert">
<div class="impurity-alert-title">⚠ 关键杂质警示 (Impurity Profile)</div>
<p style="font-size: 12px; color: #856404; margin-bottom: 10px;">
辅料的杂质谱是影响相容性的关键因素,需评估风险级别或查阅COA确认。
</p>
{% if excipient_profile and excipient_profile.impurity_profile %}
<div class="impurity-item">Fe²⁺: ≤ {{ excipient_profile.impurity_profile.fe_ppm }} ppm &nbsp;&nbsp; Mn²⁺: ≤ {{ excipient_profile.impurity_profile.mn_ppm }} ppm</div>
{% endif %}
<div class="impurity-item">H₂O: ~0.5%</div>
</div>
</div>
</div>
</section>
<!-- Section 4: Mechanism of Interaction -->
<section class="section">
<h2 class="section-title">
4. 相容性机制预测
<span class="en-title">(Mechanism of Interaction)</span>
</h2>
<table class="mechanism-table">
<thead>
<tr>
<th style="width: 15%;">相互作用类型</th>
<th style="width: 10%;">风险等级</th>
<th style="width: 40%;">机制分析与专家点评</th>
</tr>
</thead>
<tbody>
{% for interaction in interactions %}
<tr>
<td>
<strong>{{ interaction.reaction_type.cn }}</strong><br>
<small style="color: #666;">({{ interaction.reaction_type.en }})</small>
</td>
<td>
<span class="risk-badge {{ interaction.risk_level.value }}">
{% if interaction.risk_level.value == 'none' %}无风险
{% elif interaction.risk_level.value == 'low' %}低风险
{% elif interaction.risk_level.value == 'medium' %}中等/关注
{% else %}高风险{% endif %}
</span>
</td>
<td>
<p style="margin-bottom: 8px;">{{ interaction.mechanism_analysis }}</p>
<p style="color: #666; font-size: 11px;"><em>点评: {{ interaction.expert_notes }}</em></p>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
<!-- Section 5: Formulation Strategy -->
<section class="section">
<div class="strategy-box">
<h2 class="strategy-title">FORMULATION STRATEGY (处方策略建议)</h2>
<ol style="padding-left: 20px; font-size: 13px;">
{% for strategy in formulation_strategies %}
<li style="margin: 12px 0;">
<strong>{{ strategy.title }}</strong>: {{ strategy.description }}
{% if strategy.rationale %}
<br><small style="color: #666;">{{ strategy.rationale }}</small>
{% endif %}
</li>
{% endfor %}
</ol>
</div>
</section>
<!-- Footer -->
<footer class="report-footer">
<div class="disclaimer">
<div class="disclaimer-title">报告说明 (Disclaimer)</div>
<p>本报告基于SMILES结构推断与药学通用知识生成,文献和药典等第三方数据库收录的数据进行分析。实验验证(如Stress Testing)仍为相容性评估的最终标准。</p>
<p style="margin-top: 8px;">
<strong>假设:</strong> {{ assumptions | join('; ') }}
</p>
<p style="margin-top: 5px;">
<strong>局限性:</strong> {{ limitations | join('; ') }}
</p>
</div>
</footer>
</div>
</body>
</html>