7.6 KiB
样本卡片 · 协议级附件迷你缩略图展示
日期:2026-07-13
状态:已确认(展示形态 B · 迷你缩略图)
关联:2026-07-13-protocol-consent-health-survey-design.md(孕妇健康调查表字段)、捐赠单传染病检测报告字段
1. 目标
在以下三个卡片场景中,按来源展示协议单级附件,支持点击预览/下载;无附件显示「无」。
| 页面 | 位置 |
|---|---|
| 预产及在途样本 | 紧凑小卡片 + 展开详情卡片 |
| 样本接收 | 待接收 Tab 卡片 + 已接收 Tab 卡片 |
1.1 来源与附件映射
sourceType |
展示标签 | 数据字段 |
|---|---|---|
cell_storage(默认) |
孕妇健康调查表 | healthSurveyAttachmentFiles |
research_donation |
传染病检测报告 | infectiousDiseaseReportAttachmentFiles |
说明:展示的是协议/捐赠单录入的附件,不是样本接收登记时的 receiveAttachmentFiles。
1.2 已确认交互(B · 迷你缩略图)
- 每个附件一张 迷你卡片:缩略图区 + 单行文件名 + 下载图标
- 图片:缩略图
object-fit: cover;文档/视频:与ProtocolAttachmentReadonly相同的类型图标 - 点击缩略图:图片新开页预览;非图片仅下载区可点
- 点击下载图标:走现有
downloadAttachmentFile - 无附件:标签下方显示「无」(不用「暂无附件」)
- 多附件:横向排列,超出宽度换行
2. 现状缺口
2.1 后端
| 接口 | 细胞存储 | 科研捐赠 |
|---|---|---|
| 预产及在途列表 | 仅有 healthSurveyFormUrls 字符串 |
已有 infectiousDiseaseReportAttachmentFiles |
| 样本接收待/已接收列表 | 无协议附件字段 | 无协议附件字段 |
2.2 前端
PreTransitProtocolCardList.vue、SampleReceptionCardList.vue均未展示协议附件ProtocolAttachmentReadonly.vue为标准尺寸(140×96),不适合紧凑卡片
3. 方案(列表 API 补齐 + 共享迷你组件)
采用列表接口直接返回 *AttachmentFiles(与协议 CRUD 字段命名一致),前端新建迷你缩略图组件统一渲染。不做懒加载详情、不做前端 URL 手拆。
4. 后端
4.1 pre_transit_sample.py
细胞存储行构建处(_protocol_to_dict 之后),补充:
d["healthSurveyAttachmentFiles"] = urls_to_attachment_list(
r.health_survey_form_urls, db, tenant_no
)
科研捐赠侧 _donation_to_dict(r, db, tenant_no) 已含 infectiousDiseaseReportAttachmentFiles,无需改动。
4.2 sample_reception.py
在 _rows_to_sample_list_items、_donation_rows_to_sample_list_items 构建 item 时,从已 join 的 protocol / donation 实体补充:
- 细胞存储:
healthSurveyAttachmentFiles←protocol.health_survey_form_urls - 科研捐赠:
infectiousDiseaseReportAttachmentFiles←donation.infectious_disease_report_urls
使用现有 urls_to_attachment_list;协议/捐赠对象已在查询行中,不额外 N+1。
4.3 范围外
- 不修改样本接收登记/编辑 API 写入逻辑
- 不修改 checklist 检查项
- 不修改生产工单、质检工单卡片
5. 前端
5.1 新建 ProtocolAttachmentMiniReadonly.vue
路径:web-admin/src/components/business/protocol-attachment-mini-readonly/index.vue
Props
| 属性 | 类型 | 说明 |
|---|---|---|
label |
string |
字段标签,如「孕妇健康调查表」 |
files |
Array<Record<string, unknown>> |
附件列表 |
emptyText |
string |
默认 '无' |
Events:preview、download(与 ProtocolAttachmentReadonly 一致,由父级或 composable 处理)
尺寸与样式(对齐 Fresh Mint,缩小版 ProtocolAttachmentReadonly)
| 元素 | 尺寸 |
|---|---|
| 单卡宽度 | 80px |
| 缩略图区高度 | 56px |
| 圆角 | 6px |
| 边框 | #e2e8f0,hover #047857 |
| 文件名字号 | 10px,单行 ellipsis |
| 下载图标 | 18×18,与标准组件同色交互 |
| 列表 gap | 6px,横向 flex-wrap |
空态:仅显示 label + emptyText(「无」),不渲染缩略图占位。
逻辑复用:resolveFileUrl、isImageFile、isVideoFile 与 ProtocolAttachmentReadonly.vue 保持一致(可后续抽 util,本期允许组件内复制以保持最小 diff)。
5.2 共享工具
web-admin/src/utils/protocol-source-attachment.ts
export function getSourceProtocolAttachment(row: Record<string, unknown>): {
label: string
files: Array<Record<string, unknown>>
}
按 sourceType 返回标签与 files 数组。
web-admin/src/composables/useAttachmentActions.ts(或复用 qc-work-order/composables/useQcViewAttachmentHelpers.ts 模式)
fullFileUrl(url)handleAttachmentPreview(file)→window.openhandleAttachmentDownload(file)→downloadAttachmentFile
供预产页、样本接收页、卡片组件父级共用。
5.3 PreTransitProtocolCardList.vue
紧凑卡片(protocol-card-compact__body 底部,展开按钮之上):
<ProtocolAttachmentMiniReadonly
:label="attachmentMeta(row).label"
:files="attachmentMeta(row).files"
@preview="emit('attachment-preview', $event)"
@download="emit('attachment-download', $event)"
/>
展开卡片(「基础信息」protocol-card__kv-grid 末尾,占满一行 protocol-card__kv--stack):
- 同上组件;
files较多时可横向换行,不限高度截断
卡片高度:紧凑卡 --compact-card-height 增加约 52px(标签 10px + 缩略图 56px + 间距);has-special-sample 变体同步上调。
事件:组件 emit 上抛 attachment-preview / attachment-download,由 pre-transit-sample/index.vue 接入 composable。
5.4 SampleReceptionCardList.vue
在 sample-reception-card__meta 末尾增加 meta-item(grid-column: 1 / -1 或 minmax(160px, 1fr) 以保证缩略图行宽度):
<div class="sample-reception-card__meta-item sample-reception-card__meta-item--attachment">
<dt>{{ attachmentMeta(row).label }}</dt>
<dd>
<ProtocolAttachmentMiniReadonly
:label="''"
:files="attachmentMeta(row).files"
...
/>
</dd>
</div>
label 放在 dt,组件内 label 传空避免重复。
待接收 / 已接收 同一展示逻辑。
5.5 类型(可选)
web-admin/src/api/pre-transit-sample.ts 可为 PreTransitProtocolRow 补充附件字段注释;样本接收列表仍为 Record<string, unknown>,不强制改类型。
6. 测试要点
- 细胞存储协议有/无孕妇健康调查表:预产紧凑卡、展开卡、样本接收待/已接收均正确
- 科研捐赠有/无传染病检测报告:同上
- 多附件横向换行;图片预览、PDF 下载
- 预产「样本未录入」协议(仅有附件、无样本)仍展示附件
- 列表分页切换后附件仍对应正确协议
- 租户隔离:不串附件
7. 改动文件清单
| 层 | 文件 |
|---|---|
| DB | 无(字段已存在) |
| Backend | pre_transit_sample.py、sample_reception.py |
| Frontend 新建 | protocol-attachment-mini-readonly/index.vue、utils/protocol-source-attachment.ts、composables/useAttachmentActions.ts |
| Frontend 修改 | PreTransitProtocolCardList.vue、SampleReceptionCardList.vue、pre-transit-sample/index.vue、sample-reception/index.vue(或 SampleReceptionCardList 内直接 composable) |
8. 不在本期
- 样本接收 checklist 勾选
- 知情同意书在卡片展示
- 生产/质检工单卡片
- 将
ProtocolAttachmentReadonly改为 size prop(本期独立迷你组件)