Files
zkxw/docs/demos/2026-10-09-storage-cert-qc-info-demo.html
T
zlwuandCursor 55ed0d8929 docs: add storage-cert QC info design and HTML demo.
Capture the confirmed sample-level JSON payload approach, field maps from the Excel sheets, and UI entry points for QC fill and market view.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-09 12:22:23 +08:00

856 lines
41 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>储存证质检信息 · 填写 / 查看 Demo</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #10b981;
--primary-dark: #059669;
--primary-bg: #ecfdf5;
--bg-page: #f8fafc;
--panel: #ffffff;
--text: #0f172a;
--text-secondary: #334155;
--text-muted: #64748b;
--border: #e2e8f0;
--border-mint: #d9e8e2;
--radius: 10px;
--radius-sm: 8px;
--shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
--warning: #d97706;
--warning-bg: #fffbeb;
--danger: #dc2626;
--info: #64748b;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 14px;
line-height: 1.5;
color: var(--text);
background: var(--bg-page);
}
.page {
max-width: 1180px;
margin: 0 auto;
padding: 24px 20px 80px;
}
.hero { margin-bottom: 20px; max-width: 920px; }
.hero h1 {
margin: 0 0 8px;
font-size: 22px;
font-weight: 700;
letter-spacing: -0.02em;
}
.hero h1::before {
content: "";
display: inline-block;
width: 4px;
height: 1.1em;
margin-right: 10px;
vertical-align: -0.15em;
border-radius: 2px;
background: var(--primary);
}
.hero p { margin: 0 0 8px; color: var(--text-muted); }
.context-bar { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.pill {
display: inline-flex; align-items: center; gap: 6px;
padding: 4px 10px; border-radius: 999px; font-size: 12px;
background: var(--primary-bg); color: var(--primary-dark);
border: 1px solid #a7f3d0;
}
.pill.muted {
background: #f1f5f9; color: var(--text-muted); border-color: var(--border);
}
/* Scene tabs */
.scene-tabs {
display: flex; flex-wrap: wrap; gap: 8px;
margin-bottom: 16px; padding: 4px;
background: #fff; border: 1px solid var(--border); border-radius: var(--radius);
}
.scene-tab {
border: 1px solid transparent; background: transparent;
padding: 8px 14px; border-radius: 8px; cursor: pointer;
font-size: 13px; font-weight: 500; color: var(--text-secondary);
}
.scene-tab:hover { background: #f8fafc; }
.scene-tab.active {
background: var(--primary-bg); color: var(--primary-dark);
border-color: #a7f3d0;
}
.scene { display: none; }
.scene.active { display: block; }
.section {
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 18px 20px;
margin-bottom: 16px;
box-shadow: var(--shadow);
}
.section-head {
display: flex; align-items: flex-start; justify-content: space-between;
gap: 12px; margin-bottom: 14px;
}
.section-head h2 {
margin: 0; font-size: 16px; font-weight: 600;
}
.section-head .hint { margin: 4px 0 0; font-size: 12px; color: var(--text-muted); }
.note {
padding: 10px 12px; border-radius: 8px;
background: var(--warning-bg); border: 1px solid #fde68a;
color: #92400e; font-size: 13px; margin-bottom: 14px;
}
.note.ok {
background: var(--primary-bg); border-color: #a7f3d0; color: var(--primary-dark);
}
/* QC card mock */
.protocol-bar {
display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center;
padding: 10px 12px; background: #f8fafc; border: 1px solid var(--border);
border-radius: 8px; margin-bottom: 12px; font-size: 13px;
}
.protocol-bar strong { color: var(--text); }
.sample-pills { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.sample-pill {
padding: 6px 12px; border-radius: 999px; font-size: 12px;
border: 1px solid var(--border); background: #fff; color: var(--text-secondary);
cursor: pointer;
}
.sample-pill.active {
border-color: var(--primary); background: var(--primary-bg); color: var(--primary-dark);
font-weight: 600;
}
.wo-card {
border: 1px solid var(--border-mint);
border-radius: 10px;
padding: 14px 16px;
background: #fff;
}
.wo-card-top {
display: flex; flex-wrap: wrap; justify-content: space-between;
gap: 10px; margin-bottom: 10px;
}
.wo-meta { font-size: 13px; color: var(--text-secondary); }
.wo-meta .code { font-weight: 600; color: var(--text); }
.tag {
display: inline-flex; align-items: center;
padding: 2px 8px; border-radius: 4px; font-size: 12px; font-weight: 500;
}
.tag.success { background: var(--primary-bg); color: var(--primary-dark); }
.tag.warning { background: var(--warning-bg); color: var(--warning); }
.tag.info { background: #f1f5f9; color: var(--info); }
.wo-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.btn {
display: inline-flex; align-items: center; gap: 6px;
height: 32px; padding: 0 12px; border-radius: 8px;
border: 1px solid var(--border); background: #fff;
font-size: 13px; color: var(--text-secondary); cursor: pointer;
}
.btn:hover { border-color: #94a3b8; }
.btn.primary {
background: var(--primary); border-color: var(--primary);
color: #fff; font-weight: 500;
}
.btn.primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); }
.btn.accent {
background: var(--primary-bg); border-color: #a7f3d0;
color: var(--primary-dark); font-weight: 500;
}
.btn.ghost { background: transparent; }
.btn.sm { height: 28px; padding: 0 10px; font-size: 12px; }
.btn-icon {
width: 14px; height: 14px; display: inline-block;
border: 1.5px solid currentColor; border-radius: 3px; opacity: 0.85;
}
/* Sample info table mock */
.toolbar {
display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
margin-bottom: 12px;
}
.toolbar .selected { font-size: 13px; color: var(--text-muted); margin-right: 4px; }
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: 8px; }
table.list {
width: 100%; border-collapse: collapse; min-width: 900px;
}
table.list th, table.list td {
padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--border);
font-size: 13px; white-space: nowrap;
}
table.list th {
background: #f8fafc; color: var(--text-muted); font-weight: 600; font-size: 12px;
}
table.list tr:nth-child(even) td { background: #fafafa; }
table.list tr:hover td { background: #f1f5f9; }
table.list tr.highlight td { background: #ecfdf5; }
.ops { display: flex; gap: 6px; flex-wrap: wrap; }
/* Dialog */
.dialog-mask {
position: fixed; inset: 0; background: rgba(15, 23, 42, 0.45);
display: none; align-items: flex-start; justify-content: center;
padding: 40px 16px; z-index: 50; overflow-y: auto;
backdrop-filter: none;
}
.dialog-mask.open { display: flex; }
.dialog {
width: min(920px, 100%);
background: #fff; border-radius: 12px;
box-shadow: 0 20px 40px rgba(15, 23, 42, 0.18);
display: flex; flex-direction: column;
max-height: calc(100vh - 80px);
}
.dialog.wide { width: min(1020px, 100%); }
.dialog-header {
display: flex; align-items: center; justify-content: space-between;
padding: 16px 20px; border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.dialog-header h3 { margin: 0; font-size: 16px; font-weight: 600; }
.dialog-header .sub {
margin: 4px 0 0; font-size: 12px; color: var(--text-muted); font-weight: 400;
}
.dialog-close {
width: 32px; height: 32px; border: none; background: #f1f5f9;
border-radius: 8px; cursor: pointer; font-size: 18px; color: var(--text-muted);
}
.dialog-body {
padding: 16px 20px; overflow-y: auto; flex: 1;
}
.dialog-footer {
display: flex; justify-content: flex-end; gap: 8px;
padding: 12px 20px; border-top: 1px solid var(--border);
flex-shrink: 0;
}
.ctx-row {
display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;
margin-bottom: 16px; padding: 12px; background: #f8fafc;
border: 1px solid var(--border); border-radius: 8px;
}
@media (max-width: 800px) {
.ctx-row { grid-template-columns: 1fr 1fr; }
}
.ctx-item label {
display: block; font-size: 11px; color: var(--text-muted); margin-bottom: 2px;
}
.ctx-item .val { font-size: 13px; font-weight: 500; color: var(--text); }
.field-group {
border: 1px solid var(--border);
border-radius: 10px;
margin-bottom: 14px;
overflow: hidden;
}
.field-group-title {
padding: 10px 14px;
background: var(--primary-bg);
color: var(--primary-dark);
font-size: 13px; font-weight: 600;
border-bottom: 1px solid #a7f3d0;
}
.field-group-title.alt { background: #f1f5f9; color: var(--text-secondary); border-bottom-color: var(--border); }
.field-group-title.meta { background: #fffbeb; color: #92400e; border-bottom-color: #fde68a; }
.form-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px 14px;
padding: 14px;
}
@media (max-width: 900px) {
.form-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
.form-grid { grid-template-columns: 1fr; }
}
.form-item { display: flex; flex-direction: column; gap: 4px; }
.form-item.span-2 { grid-column: span 2; }
.form-item.span-3 { grid-column: 1 / -1; }
.form-item label {
font-size: 11px; color: var(--text-muted); font-weight: 500;
}
.form-item input, .form-item select, .form-item textarea {
height: 36px; padding: 0 10px;
border: 1px solid var(--border); border-radius: 8px;
font-size: 13px; color: var(--text); background: #fff;
font-family: inherit;
}
.form-item textarea {
height: auto; min-height: 72px; padding: 8px 10px; resize: vertical;
}
.form-item input:disabled, .form-item textarea:disabled, .form-item select:disabled {
background: #f8fafc; color: var(--text-secondary);
}
.form-item.readonly .val-box {
min-height: 36px; padding: 8px 10px;
border: 1px solid var(--border); border-radius: 8px;
background: #f8fafc; font-size: 13px; color: var(--text-secondary);
white-space: pre-wrap;
}
.type-switch {
display: inline-flex; gap: 6px; margin-bottom: 12px;
}
.field-count {
font-size: 12px; color: var(--text-muted);
}
.flow {
display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
font-size: 13px; color: var(--text-secondary);
}
.flow .step {
padding: 6px 10px; background: #fff; border: 1px solid var(--border);
border-radius: 8px;
}
.flow .arrow { color: var(--text-muted); }
.legend {
display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
}
@media (max-width: 700px) {
.legend { grid-template-columns: 1fr; }
}
.legend-card {
border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px;
background: #fff;
}
.legend-card h4 { margin: 0 0 8px; font-size: 14px; }
.legend-card ul {
margin: 0; padding-left: 18px; color: var(--text-secondary); font-size: 12px;
}
.legend-card li { margin-bottom: 4px; }
</style>
</head>
<body>
<div class="page">
<div class="hero">
<h1>储存证质检信息 · Demo</h1>
<p>
质检在「细胞存储质检」工单卡片上<strong>填写</strong>储存证质检信息(字段对齐 Excel 两个 sheet);
市场在「样本信息管理 · 细胞存储」上<strong>查看</strong>同一份数据,用于誊写到储存证。
</p>
<div class="context-bar">
<span class="pill">Excel:围产期造血干细胞</span>
<span class="pill">Excel:脐带间充质干细胞</span>
<span class="pill muted">质检工单 / 我的质检任务</span>
<span class="pill muted">样本信息管理</span>
</div>
</div>
<div class="section">
<div class="section-head">
<div>
<h2>业务链路(示意)</h2>
<p class="hint">当前 Demo 不改业务逻辑,只对齐交互与字段分组</p>
</div>
</div>
<div class="flow">
<span class="step">质检完成检测</span>
<span class="arrow">→</span>
<span class="step" style="border-color:#a7f3d0;background:var(--primary-bg);color:var(--primary-dark);font-weight:600;">填写储存证质检信息</span>
<span class="arrow">→</span>
<span class="step">市场「样本信息」查看</span>
<span class="arrow">→</span>
<span class="step">誊写 / 办理储存证</span>
</div>
</div>
<div class="scene-tabs" role="tablist">
<button type="button" class="scene-tab active" data-scene="overview">① 字段对照</button>
<button type="button" class="scene-tab" data-scene="qc-card">② 质检卡片入口</button>
<button type="button" class="scene-tab" data-scene="fill-hsc">③ 填写 · 围产期造血</button>
<button type="button" class="scene-tab" data-scene="fill-msc">④ 填写 · 脐带间充质</button>
<button type="button" class="scene-tab" data-scene="sample-info">⑤ 样本信息查看入口</button>
</div>
<!-- ① overview -->
<div class="scene active" id="scene-overview">
<div class="note ok">
两个 sheet 共用「身份键 + 母亲血检」骨架,检测报告区字段按样本类型分叉;右侧收尾字段也略有差异。
</div>
<div class="legend">
<div class="legend-card">
<h4>围产期造血干细胞(约 34 列)</h4>
<ul>
<li><strong>身份</strong>:序号、实验室流转编码、协议编码、母亲姓名</li>
<li><strong>采集运输</strong>:采集时间、运输温度</li>
<li><strong>造血干细胞检测报告</strong>:接收/处理/冻存时间、重量、冻存体积、TNC、CD34+、CD34+CD45dim、活性、细菌、HBsAg/HCV/TP/HIV、CMV-IgM</li>
<li><strong>母亲血液检测报告</strong>:HBsAg、HBV DNA、抗HCV、HCV RNA、抗TP、CMV IgM、抗HIV、HIV-1RNA</li>
<li><strong>收尾</strong>:HLA 分型、储存日期、储存年限、检测结果评论、报告发出日期</li>
</ul>
</div>
<div class="legend-card">
<h4>脐带间充质干细胞(约 34 列)</h4>
<ul>
<li><strong>额外</strong>:是否邮寄</li>
<li><strong>身份</strong>:序号、实验室流转编码、协议编码、母亲姓名</li>
<li><strong>采集运输</strong>:脐带采集时间、运输温度</li>
<li><strong>脐带间充质检测报告</strong>:接收/处理/冻存时间、储存总量(管)、可提供细胞类型/数量/存活率、内毒素/细菌/真菌/支原体、形态、免疫表型</li>
<li><strong>母亲血液检测报告</strong>:与造血 sheet 同一组 8 项</li>
<li><strong>收尾</strong>:检测结果评判、报告发出日期、储存日期(P2)、冷冻方式、储存温度、储存年限</li>
</ul>
</div>
</div>
<div class="section" style="margin-top:16px;">
<div class="section-head">
<div>
<h2>Demo 建议排除出「质检填写」的列</h2>
<p class="hint">这些更像列表管理列 / 市场侧信息,可在澄清时确认</p>
</div>
</div>
<p style="margin:0;font-size:13px;color:var(--text-secondary);">
建议默认<strong>只读预填、不让质检手填</strong>:序号、协议编码、母亲姓名(从样本/协议带出)。
「是否邮寄」偏市场物流,是否纳入质检表待确认。
「实验室流转编码」是否等于系统样本编码 / 入库编码,待确认。
</p>
</div>
</div>
<!-- ② qc card -->
<div class="scene" id="scene-qc-card">
<div class="section">
<div class="section-head">
<div>
<h2>质检工单 / 我的质检任务 · 细胞存储质检</h2>
<p class="hint">在工单卡片操作区新增「填写储存证质检信息」(示意高亮)</p>
</div>
</div>
<div class="note">入口放在<strong>工单卡片</strong>(非任务子卡「填写结果」),因为储存证信息是样本级整表,不是单项检测任务结果。</div>
<div class="protocol-bar">
<span>协议:<strong>ZKZX34000852</strong></span>
<span>客户:高居巧</span>
<span>来源:细胞存储</span>
</div>
<div class="sample-pills">
<span class="sample-pill active">B0000002 · 围产期造血干细胞</span>
<span class="sample-pill">B0000002-MSC · 脐带间充质(示意)</span>
</div>
<div class="wo-card">
<div class="wo-card-top">
<div class="wo-meta">
<div class="code">入库质检工单 WO-2026-1008-012</div>
<div style="margin-top:4px;">
<span class="tag success">已完成</span>
<span class="tag info" style="margin-left:6px;">结论:通过</span>
</div>
</div>
<div class="field-count">样本类型 → 决定弹窗字段模板</div>
</div>
<div class="wo-actions">
<button type="button" class="btn">查看</button>
<button type="button" class="btn">特殊样本</button>
<button type="button" class="btn accent" onclick="openFill('hsc')">
<span class="btn-icon"></span> 填写储存证质检信息
</button>
<button type="button" class="btn ghost">更多</button>
</div>
</div>
<div style="height:14px;"></div>
<div class="wo-card" style="opacity:0.92;">
<div class="wo-card-top">
<div class="wo-meta">
<div class="code">入库质检工单 WO-2026-1009-003</div>
<div style="margin-top:4px;">
<span class="tag warning">进行中</span>
</div>
</div>
</div>
<div class="wo-actions">
<button type="button" class="btn primary">配置检测</button>
<button type="button" class="btn accent" onclick="openFill('msc')">
<span class="btn-icon"></span> 填写储存证质检信息
</button>
</div>
</div>
</div>
</div>
<!-- ③ fill HSC summary (opens dialog) -->
<div class="scene" id="scene-fill-hsc">
<div class="section">
<div class="section-head">
<div>
<h2>填写弹窗 · 围产期造血干细胞</h2>
<p class="hint">分组 = Excel 合并表头;三列栅格;长文本(HLA / 评论)跨列</p>
</div>
<button type="button" class="btn primary" onclick="openFill('hsc')">打开填写弹窗</button>
</div>
<p style="margin:0;font-size:13px;color:var(--text-muted);">
字段按 Excel sheet「围产期造血干细胞」展开:造血检测报告 15 项 + 母亲血检 8 项 + HLA/储存/评论/报告日。
</p>
</div>
</div>
<!-- ④ fill MSC -->
<div class="scene" id="scene-fill-msc">
<div class="section">
<div class="section-head">
<div>
<h2>填写弹窗 · 脐带间充质干细胞</h2>
<p class="hint">与造血模板共用母亲血检区块;检测报告与收尾字段不同</p>
</div>
<button type="button" class="btn primary" onclick="openFill('msc')">打开填写弹窗</button>
</div>
<p style="margin:0;font-size:13px;color:var(--text-muted);">
含「是否邮寄」、储存总量(管)、可提供细胞*、内毒素/真菌/支原体、冷冻方式、储存温度等。
</p>
</div>
</div>
<!-- ⑤ sample info -->
<div class="scene" id="scene-sample-info">
<div class="section">
<div class="section-head">
<div>
<h2>样本信息管理 · 细胞存储 Tab</h2>
<p class="hint">行操作增加「查看储存证的质检信息」;无数据时按钮可禁用或提示未填写</p>
</div>
</div>
<div class="toolbar">
<span class="selected">已选 0 项</span>
<button type="button" class="btn primary">登记入库</button>
<button type="button" class="btn">登记储存证</button>
<button type="button" class="btn">登记保险</button>
</div>
<div class="table-wrap">
<table class="list">
<thead>
<tr>
<th>样本编码</th>
<th>协议编码</th>
<th>母亲姓名</th>
<th>样本类型</th>
<th>质检</th>
<th>储存证</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr class="highlight">
<td>B0000002</td>
<td>ZKZX34000852</td>
<td>高居巧</td>
<td>围产期造血干细胞</td>
<td><span class="tag success">已完成</span></td>
<td><span class="tag warning">未办理</span></td>
<td>
<div class="ops">
<button type="button" class="btn sm">查看</button>
<button type="button" class="btn sm accent" onclick="openView('hsc')">查看储存证的质检信息</button>
</div>
</td>
</tr>
<tr>
<td>BC0000003</td>
<td>ZKQD34000831</td>
<td>牛晨晨</td>
<td>脐带间充质干细胞</td>
<td><span class="tag success">已完成</span></td>
<td><span class="tag success">已办理</span></td>
<td>
<div class="ops">
<button type="button" class="btn sm">查看</button>
<button type="button" class="btn sm accent" onclick="openView('msc')">查看储存证的质检信息</button>
</div>
</td>
</tr>
<tr>
<td>B0000099</td>
<td>ZKZX34000999</td>
<td>示例未填</td>
<td>围产期造血干细胞</td>
<td><span class="tag warning">进行中</span></td>
<td><span class="tag info">—</span></td>
<td>
<div class="ops">
<button type="button" class="btn sm">查看</button>
<button type="button" class="btn sm" disabled style="opacity:0.45;cursor:not-allowed;">查看储存证的质检信息</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Fill dialog -->
<div class="dialog-mask" id="fillMask" onclick="maskClose(event,'fillMask')">
<div class="dialog wide" role="dialog" aria-modal="true">
<div class="dialog-header">
<div>
<h3 id="fillTitle">填写储存证质检信息</h3>
<div class="sub" id="fillSub">按样本类型切换字段模板</div>
</div>
<button type="button" class="dialog-close" onclick="closeMask('fillMask')" aria-label="关闭">×</button>
</div>
<div class="dialog-body">
<div class="ctx-row">
<div class="ctx-item"><label>实验室流转编码</label><div class="val" id="ctxLab">B0000002</div></div>
<div class="ctx-item"><label>协议编码</label><div class="val" id="ctxProto">ZKZX34000852</div></div>
<div class="ctx-item"><label>母亲姓名</label><div class="val" id="ctxMother">高居巧</div></div>
<div class="ctx-item"><label>样本类型</label><div class="val" id="ctxType">围产期造血干细胞</div></div>
</div>
<div id="formHsc">
<div class="field-group">
<div class="field-group-title alt">采集与运输</div>
<div class="form-grid">
<div class="form-item"><label>造血干细胞采集时间</label><input value="2025年9月7日15时36分" /></div>
<div class="form-item"><label>运输温度 /℃</label><input value="17" /></div>
</div>
</div>
<div class="field-group">
<div class="field-group-title">造血干细胞检测报告</div>
<div class="form-grid">
<div class="form-item"><label>造血干细胞接收时间</label><input value="2025.9.8 9:00" /></div>
<div class="form-item"><label>处理时间</label><input value="2025.9.8 9:30" /></div>
<div class="form-item"><label>冻存时间</label><input value="2025.9.8 11:57" /></div>
<div class="form-item"><label>造血干细胞重量/g</label><input value="56" /></div>
<div class="form-item"><label>造血干细胞冻存体积/mL</label><input value="21.8" /></div>
<div class="form-item"><label>有核细胞数 TNC / *10E8</label><input value="2.28" /></div>
<div class="form-item"><label>CD34+ 细胞计数 / *10E6</label><input value="16.3" /></div>
<div class="form-item"><label>CD34+ CD45dim / *10E5</label><input value="1.27" /></div>
<div class="form-item"><label>细胞活性/%</label><input value="90.44" /></div>
<div class="form-item"><label>细菌检测</label><select><option>阴</option><option>阳</option><option>/</option></select></div>
<div class="form-item"><label>乙型肝炎病毒表面抗原(HBsAg)</label><select><option>阴</option><option>阳</option><option>/</option></select></div>
<div class="form-item"><label>丙型肝炎病毒抗体(抗HCV)</label><select><option>阴</option><option>阳</option><option>/</option></select></div>
<div class="form-item"><label>梅毒螺旋体特异性抗体(抗TP)</label><select><option>阴</option><option>阳</option><option>/</option></select></div>
<div class="form-item"><label>人类免疫缺陷病毒抗体(抗HIV-1/2)</label><select><option>阴</option><option>阳</option><option>/</option></select></div>
<div class="form-item"><label>巨细胞病毒 IgM 抗体 (CMV-IgM)</label><select><option>阴</option><option>阳</option><option>/</option></select></div>
</div>
</div>
<div class="field-group">
<div class="field-group-title">母亲血液检测报告</div>
<div class="form-grid">
<div class="form-item"><label>乙型肝炎病毒表面抗原(HBsAg)</label><select><option>阴</option><option>/</option></select></div>
<div class="form-item"><label>乙型肝炎病毒核酸(HBV DNA)</label><select><option>阴</option><option>/</option></select></div>
<div class="form-item"><label>丙型肝炎病毒抗体(抗HCV)</label><select><option>阴</option><option>/</option></select></div>
<div class="form-item"><label>丙型肝炎病毒核酸(HCV RNA)</label><select><option>阴</option><option>/</option></select></div>
<div class="form-item"><label>梅毒螺旋体特异性抗体(抗TP)</label><select><option>阴</option><option>/</option></select></div>
<div class="form-item"><label>巨细胞病毒 IgM 抗体 (CMV IgM)</label><select><option>阴</option><option>/</option></select></div>
<div class="form-item"><label>人类免疫缺陷病毒抗体(抗HIV-1/2)</label><select><option>阴</option><option>/</option></select></div>
<div class="form-item"><label>人类免疫缺陷病毒核酸(1型) (HIV-1RNA)</label><select><option>阴</option><option>/</option></select></div>
</div>
</div>
<div class="field-group">
<div class="field-group-title meta">储存证收尾信息</div>
<div class="form-grid">
<div class="form-item span-3"><label>HLA 分型</label><textarea>A 02:06/24:02
B 07:02(M)/57:01(T)
C 06:02/07:02
DRB1 13:01/15:01
DQB1 06:02/06:03</textarea></div>
<div class="form-item"><label>储存日期</label><input placeholder="YYYY-MM-DD" /></div>
<div class="form-item"><label>储存年限</label><input value="20" /></div>
<div class="form-item"><label>检测结果评论</label><input value="合格" /></div>
<div class="form-item"><label>报告发出日期</label><input placeholder="YYYY-MM-DD" /></div>
</div>
</div>
</div>
<div id="formMsc" style="display:none;">
<div class="field-group">
<div class="field-group-title alt">采集与运输 / 邮寄</div>
<div class="form-grid">
<div class="form-item"><label>是否邮寄</label><select><option>是</option><option selected>否</option></select></div>
<div class="form-item"><label>脐带采集时间</label><input value="2025.11.25 15:49" /></div>
<div class="form-item"><label>运输温度 /℃</label><input value="" placeholder="可填「常温」或数值" /></div>
</div>
</div>
<div class="field-group">
<div class="field-group-title">脐带间充质干细胞检测报告</div>
<div class="form-grid">
<div class="form-item"><label>脐带接收时间</label><input value="2025.11.26 10:00" /></div>
<div class="form-item"><label>处理时间</label><input value="2025.11.26 16:00" /></div>
<div class="form-item"><label>冻存时间</label><input value="2025.12.21" /></div>
<div class="form-item"><label>储存总量(管)</label><input value="17" placeholder="Excel 中有 =0+17 公式" /></div>
<div class="form-item"><label>可提供细胞类型</label><input value="间充质干细胞" /></div>
<div class="form-item"><label>可提供细胞数量 / *10E7</label><input value="8.5" /></div>
<div class="form-item"><label>可提供细胞存活率 %</label><input value="97.1" /></div>
<div class="form-item"><label>内毒素检测</label><select><option>阴</option><option>阳</option><option>/</option></select></div>
<div class="form-item"><label>细菌检测</label><select><option>阴</option><option>/</option></select></div>
<div class="form-item"><label>真菌检测</label><select><option>阴</option><option>/</option></select></div>
<div class="form-item"><label>支原体检测</label><select><option>阴</option><option>/</option></select></div>
<div class="form-item"><label>可提供细胞形态</label><input value="短梭/贴壁型" /></div>
<div class="form-item span-2"><label>可提供细胞免疫表型特征</label><input value="符合间充质干细胞表型特性" /></div>
</div>
</div>
<div class="field-group">
<div class="field-group-title">母亲血液检测报告</div>
<div class="form-grid">
<div class="form-item"><label>乙型肝炎病毒表面抗原(HBsAg)</label><select><option>阴</option></select></div>
<div class="form-item"><label>乙型肝炎病毒核酸(HBV DNA)</label><select><option>/</option><option>阴</option></select></div>
<div class="form-item"><label>丙型肝炎病毒抗体(抗HCV)</label><select><option>阴</option></select></div>
<div class="form-item"><label>丙型肝炎病毒核酸(HCV RNA)</label><select><option>/</option><option>阴</option></select></div>
<div class="form-item"><label>梅毒螺旋体特异性抗体(抗TP)</label><select><option>阴</option></select></div>
<div class="form-item"><label>巨细胞病毒 IgM 抗体 (CMV IgM)</label><select><option>阴</option></select></div>
<div class="form-item"><label>人类免疫缺陷病毒抗体(抗HIV-1/2)</label><select><option>阴</option></select></div>
<div class="form-item"><label>人类免疫缺陷病毒核酸(1型) (HIV-1RNA)</label><select><option>阴</option></select></div>
</div>
</div>
<div class="field-group">
<div class="field-group-title meta">储存证收尾信息</div>
<div class="form-grid">
<div class="form-item"><label>检测结果评判</label><input value="合格" /></div>
<div class="form-item"><label>报告发出日期</label><input value="2026-03-14" /></div>
<div class="form-item"><label>储存日期 (P2冻存日期)</label><input value="2025.12.22" /></div>
<div class="form-item"><label>冷冻方式</label><input value="程序降温盒降温" /></div>
<div class="form-item"><label>储存温度</label><input value="-196℃" /></div>
<div class="form-item"><label>储存年限</label><input value="20" /></div>
</div>
</div>
</div>
</div>
<div class="dialog-footer">
<button type="button" class="btn" onclick="closeMask('fillMask')">取消</button>
<button type="button" class="btn primary" onclick="alert('Demo:保存成功(未接后端)'); closeMask('fillMask');">确定</button>
</div>
</div>
</div>
<!-- View dialog -->
<div class="dialog-mask" id="viewMask" onclick="maskClose(event,'viewMask')">
<div class="dialog wide" role="dialog" aria-modal="true">
<div class="dialog-header">
<div>
<h3>查看储存证的质检信息</h3>
<div class="sub" id="viewSub">只读 · 字段与质检填写一致</div>
</div>
<button type="button" class="dialog-close" onclick="closeMask('viewMask')" aria-label="关闭">×</button>
</div>
<div class="dialog-body" id="viewBody">
<!-- filled by JS -->
</div>
<div class="dialog-footer">
<button type="button" class="btn primary" onclick="closeMask('viewMask')">关闭</button>
</div>
</div>
</div>
<script>
// Scene tabs
document.querySelectorAll('.scene-tab').forEach(function (tab) {
tab.addEventListener('click', function () {
document.querySelectorAll('.scene-tab').forEach(function (t) { t.classList.remove('active'); });
document.querySelectorAll('.scene').forEach(function (s) { s.classList.remove('active'); });
tab.classList.add('active');
document.getElementById('scene-' + tab.dataset.scene).classList.add('active');
});
});
function closeMask(id) {
document.getElementById(id).classList.remove('open');
}
function maskClose(e, id) {
if (e.target.id === id) closeMask(id);
}
function openFill(type) {
var isHsc = type === 'hsc';
document.getElementById('formHsc').style.display = isHsc ? '' : 'none';
document.getElementById('formMsc').style.display = isHsc ? 'none' : '';
document.getElementById('fillTitle').textContent = '填写储存证质检信息';
document.getElementById('fillSub').textContent = isHsc
? '模板:围产期造血干细胞(对齐 Excel sheet)'
: '模板:脐带间充质干细胞(对齐 Excel sheet)';
document.getElementById('ctxLab').textContent = isHsc ? 'B0000002' : 'BC0000003';
document.getElementById('ctxProto').textContent = isHsc ? 'ZKZX34000852' : 'ZKQD34000831';
document.getElementById('ctxMother').textContent = isHsc ? '高居巧' : '牛晨晨';
document.getElementById('ctxType').textContent = isHsc ? '围产期造血干细胞' : '脐带间充质干细胞';
document.getElementById('fillMask').classList.add('open');
}
function ro(label, val, span) {
var cls = 'form-item readonly' + (span ? ' span-' + span : '');
return '<div class="' + cls + '"><label>' + label + '</label><div class="val-box">' + (val || '—') + '</div></div>';
}
function openView(type) {
var isHsc = type === 'hsc';
document.getElementById('viewSub').textContent = isHsc
? '样本 B0000002 · 围产期造血干细胞 · 只读'
: '样本 BC0000003 · 脐带间充质干细胞 · 只读';
var html = '';
html += '<div class="ctx-row">' +
'<div class="ctx-item"><label>实验室流转编码</label><div class="val">' + (isHsc ? 'B0000002' : 'BC0000003') + '</div></div>' +
'<div class="ctx-item"><label>协议编码</label><div class="val">' + (isHsc ? 'ZKZX34000852' : 'ZKQD34000831') + '</div></div>' +
'<div class="ctx-item"><label>母亲姓名</label><div class="val">' + (isHsc ? '高居巧' : '牛晨晨') + '</div></div>' +
'<div class="ctx-item"><label>样本类型</label><div class="val">' + (isHsc ? '围产期造血干细胞' : '脐带间充质干细胞') + '</div></div>' +
'</div>';
if (isHsc) {
html += '<div class="field-group"><div class="field-group-title alt">采集与运输</div><div class="form-grid">' +
ro('造血干细胞采集时间', '2025年9月7日15时36分') +
ro('运输温度 /℃', '17') +
'</div></div>';
html += '<div class="field-group"><div class="field-group-title">造血干细胞检测报告</div><div class="form-grid">' +
ro('造血干细胞接收时间', '2025.9.8 9:00') +
ro('处理时间', '2025.9.8 9:30') +
ro('冻存时间', '2025.9.8 11:57') +
ro('造血干细胞重量/g', '56') +
ro('造血干细胞冻存体积/mL', '21.8') +
ro('有核细胞数 TNC / *10E8', '2.28') +
ro('CD34+ 细胞计数 / *10E6', '16.3') +
ro('CD34+ CD45dim / *10E5', '1.27') +
ro('细胞活性/%', '90.44') +
ro('细菌检测', '阴') +
ro('乙型肝炎病毒表面抗原(HBsAg)', '阴') +
ro('丙型肝炎病毒抗体(抗HCV)', '阴') +
ro('梅毒螺旋体特异性抗体(抗TP)', '阴') +
ro('人类免疫缺陷病毒抗体(抗HIV-1/2)', '阴') +
ro('巨细胞病毒 IgM 抗体 (CMV-IgM)', '阴') +
'</div></div>';
html += '<div class="field-group"><div class="field-group-title">母亲血液检测报告</div><div class="form-grid">' +
ro('HBsAg', '阴') + ro('HBV DNA', '阴') + ro('抗HCV', '阴') + ro('HCV RNA', '阴') +
ro('抗TP', '阴') + ro('CMV IgM', '阴') + ro('抗HIV-1/2', '阴') + ro('HIV-1RNA', '阴') +
'</div></div>';
html += '<div class="field-group"><div class="field-group-title meta">储存证收尾信息</div><div class="form-grid">' +
ro('HLA 分型', 'A 02:06/24:02\\nB 07:02(M)/57:01(T)\\nC 06:02/07:02\\nDRB1 13:01/15:01\\nDQB1 06:02/06:03', 3) +
ro('储存日期', '—') + ro('储存年限', '20') + ro('检测结果评论', '合格') + ro('报告发出日期', '—') +
'</div></div>';
} else {
html += '<div class="field-group"><div class="field-group-title alt">采集与运输 / 邮寄</div><div class="form-grid">' +
ro('是否邮寄', '—') + ro('脐带采集时间', '2025.11.25 15:49') + ro('运输温度 /℃', '—') +
'</div></div>';
html += '<div class="field-group"><div class="field-group-title">脐带间充质干细胞检测报告</div><div class="form-grid">' +
ro('脐带接收时间', '2025.11.26 10:00') + ro('处理时间', '2025.11.26 16:00') + ro('冻存时间', '2025.12.21') +
ro('储存总量(管)', '17') + ro('可提供细胞类型', '间充质干细胞') +
ro('可提供细胞数量 / *10E7', '8.5') + ro('可提供细胞存活率 %', '97.1') +
ro('内毒素检测', '阴') + ro('细菌检测', '阴') + ro('真菌检测', '阴') + ro('支原体检测', '阴') +
ro('可提供细胞形态', '短梭/贴壁型') +
ro('可提供细胞免疫表型特征', '符合间充质干细胞表型特性', 2) +
'</div></div>';
html += '<div class="field-group"><div class="field-group-title">母亲血液检测报告</div><div class="form-grid">' +
ro('HBsAg', '阴') + ro('HBV DNA', '/') + ro('抗HCV', '阴') + ro('HCV RNA', '/') +
ro('抗TP', '阴') + ro('CMV IgM', '阴') + ro('抗HIV-1/2', '阴') + ro('HIV-1RNA', '阴') +
'</div></div>';
html += '<div class="field-group"><div class="field-group-title meta">储存证收尾信息</div><div class="form-grid">' +
ro('检测结果评判', '合格') + ro('报告发出日期', '2026-03-14') +
ro('储存日期 (P2冻存日期)', '2025.12.22') + ro('冷冻方式', '程序降温盒降温') +
ro('储存温度', '-196℃') + ro('储存年限', '20') +
'</div></div>';
}
document.getElementById('viewBody').innerHTML = html;
document.getElementById('viewMask').classList.add('open');
}
</script>
</body>
</html>