# 基础实验业务 — 功能设计文档 > 日期:2026-06-10 > 状态:已确认(2026-06-10:一产品一售卖计划) > 模块:基础实验(新增一级菜单,独立于中试服务 / 临床应用) > 需求来源:客户新增「基础实验」业务线(细胞产品售卖给客户做基础实验) --- ## 1. 背景与目标 ### 1.1 业务定义 **基础实验**:将细胞产品售卖给客户用于基础实验。与中试服务(渠道 B 端)、临床应用(患者 C 端输注)不同,属于 **B2B 一次性售卖 + 出库交付** 模式。 ### 1.2 与现有业务对比 | 维度 | 中试服务 | 临床应用(已隐藏) | 基础实验 | |------|---------|-------------------|---------| | `biz_type` | `pilot_service` | `clinical_application` | `basic_experiment` | | 申请单号前缀 | `ZSSQ` | `LCSQ` | **`JCSY`** | | 渠道 | 必选 + 服务订单扣费 | 选渠道,不绑订单 | **无** | | 知情同意书 / 其他附件 | 有 | 有 | **无** | | 标准附件 | — | — | **有(单上传区,图片/PDF)** | | 患者信息 | 有 | 有 | **无** | | 客户信息 | 走渠道 | 走渠道 | **自由填写:客户名称/联系人/联系方式** | | 课题名称 | — | — | **有** | | 方案语义 | 输注方案(多疗程) | 输注方案(多疗程) | **售卖方案(一次性多产品)** | | 计划粒度 | 每疗程一条输注计划 | 每疗程一条输注计划 | **每个细胞产品一条售卖计划(独立提货时间)** | | 产品费用 | 协议价/订单持仓 | 手填 | **从细胞产品价格体系带入,可修改** | | 体检 | 有 | 无 | **无** | | 缴费 / 财务确认 | 渠道扣费 | 独立缴费闭环 | **独立缴费闭环(同临床模式)** | | 交付确认 | 有 | 有 | **有** | | 输注确认 | 有 | 有 | **无** | | 出库生产/质检工单 | 有 | 有 | **有** | | 出库放行审核 | 有 | 有 | **有** | | 出库交接 | 有 | 有 | **有** | ### 1.3 目标 1. 在现有 `biz_pilot_*` 表结构与出库链路上,通过 `biz_type=basic_experiment` 新增第三条业务变体。 2. 最大化复用中试/临床已验证的页面、API、出库组件;UI 文案按「售卖 / 提货 / 交付」映射,代码层可保留 `infusion_*` 命名。 3. 前端采用 `bizType` 策略配置,避免 `ApplicationFormDialog.vue` 继续堆叠 `if` 分支。 ### 1.4 非目标(本期不做) - 客户主数据关联(`biz_customer`) - 渠道、体检、输注确认 - 小程序端(若需要,另开需求) --- ## 2. 核心业务流程 ``` 基础实验申请单(JCSY,课题/客户/标准附件) └─ 售卖方案:多种细胞产品(价格可改) └─ 每个产品 → 一条售卖计划(独立提货时间) ├─ 自动:出库生产工单 + 出库质检工单(biz_type 继承) ├─ 自动:缴费记录(biz_pilot_payment,pay_status=dfj) ├─ 生产 / 质检执行 ├─ 出库物料准备 ├─ 出库交接 ├─ 出库放行审核 └─ 交付确认(biz_pilot_delivery,无输注确认) ``` ### 2.1 售卖计划粒度(已确认) - **一个申请单** 对应 **一个售卖方案**(多产品行)。 - **每个细胞产品** 独立生成 **一条售卖计划**(复用 `biz_pilot_infusion_schedule`),各自拥有: - 独立 **提货时间**(映射 `infusion_time`) - 独立 **费用**(映射 `amount`,由产品价格带入后可改) - 独立 **出库生产/质检工单、缴费、交付、放行** 链路 > 说明:与「一个批次共用一个提货时间」不同;当前采用产品级提货时间,故以「一产品一计划」驱动下游工单,避免单计划多提货时间的生产调度歧义。 --- ## 3. 数据库变更 ### 3.1 ALTER `biz_pilot_application` — 扩展 `biz_type` 与客户字段 ```sql -- biz_type 注释扩展(值域新增 basic_experiment) ALTER TABLE biz_pilot_application MODIFY COLUMN biz_type VARCHAR(20) NOT NULL DEFAULT 'pilot_service' COMMENT '业务类型: pilot_service=中试服务, clinical_application=临床应用, basic_experiment=基础实验'; ALTER TABLE biz_pilot_application ADD COLUMN project_title VARCHAR(200) DEFAULT NULL COMMENT '课题名称(基础实验)' AFTER application_name, ADD COLUMN customer_name VARCHAR(200) DEFAULT NULL COMMENT '客户名称(基础实验,自由文本)' AFTER project_title, ADD COLUMN customer_contact VARCHAR(100) DEFAULT NULL COMMENT '客户联系人(基础实验)' AFTER customer_name, ADD COLUMN customer_phone VARCHAR(32) DEFAULT NULL COMMENT '客户联系方式(基础实验)' AFTER customer_contact; ``` **字段使用约定(`basic_experiment`)** | 字段 | 用法 | |------|------| | `channel_id` / `channel_name` / `channel_service_order_id` | 留空,不校验 | | `consent_form_urls` | 不使用 | | `attachment_urls` | 承载 **标准附件**(单上传区,逗号分隔 URL) | | `project_title` | 课题名称,必填 | | `customer_name` / `customer_contact` / `customer_phone` | 客户信息,必填 | | `application_name` | 可选,申请单名称 | ### 3.2 `biz_pilot_infusion_plan` — 售卖方案容器 不新增表。基础实验创建申请单时自动创建 **一条** `biz_pilot_infusion_plan` 作为售卖方案容器: - `total_course_count` 固定为产品行数或 `1`(实现时取产品行数,便于统计) - `course_interval` / `infusion_start_date` / `infusion_route` 留空 - UI 不展示「疗程」概念 ### 3.3 `biz_pilot_infusion_schedule` — 售卖计划(一产品一条) 复用现有表,语义映射: | DB 字段 | 基础实验 UI 文案 | |---------|-----------------| | `infusion_time` | 提货时间 | | `amount` | 售卖金额(元) | | `cell_type` / `spec_text` | 取自产品行 | | `infusion_location` / `infusion_method` | 不展示(可留空) | | `schedule_status` | 待生产 / 已生产 / 已交付 / 已取消(文案可映射为「待出库」等,码值不变) | | `infusion_status` | **基础实验不使用输注确认**;列表/查看态映射为「—」或隐藏 | | `qc_status` | 同中试/临床 | ### 3.4 `biz_pilot_infusion_schedule_product` — 产品明细 每条 schedule 关联 **一条** product 记录(一产品一计划)。价格字段: - `price_id` → `biz_cell_product_price.id` - `agreement_price` → 价格体系参考价(带入) - `actual_price` → 用户可修改的实际单价 - `quantity` → 份数,默认 1 ### 3.5 `biz_pilot_payment` — 缴费记录 复用 `biz_pilot_payment`,扩展 `biz_type` 支持 `basic_experiment`: ```sql ALTER TABLE biz_pilot_payment MODIFY COLUMN biz_type VARCHAR(20) NOT NULL DEFAULT 'clinical_application' COMMENT '业务类型: clinical_application=临床应用, basic_experiment=基础实验'; ``` - 每个售卖计划(schedule)创建时自动插入一条 `pay_status=dfj` 记录。 - `amount` 取自对应 schedule 的 `amount`。 ### 3.6 不使用的表(`basic_experiment`) | 表 | 说明 | |----|------| | `biz_pilot_patient` | 不创建 | | `biz_pilot_checkup` | 不创建 | | `biz_pilot_infusion_confirm` | 不创建、不展示 | ### 3.7 复用的出库/交付表 | 表 | 关联键 | 说明 | |----|--------|------| | `biz_production_work_order` | `infusion_schedule_id`, `biz_type=basic_experiment` | 出库生产工单 | | `biz_qc_work_order` | `infusion_schedule_id`, `biz_type=basic_experiment` | 出库质检工单 | | `biz_outbound_release_review` | `infusion_schedule_id` | 出库放行审核 | | `biz_outbound_release_material` | 放行审核 | 出库物料 | | `biz_outbound_handover` | 交接 | 出库交接 | | `biz_pilot_delivery` | `infusion_schedule_id` | 交付确认 | --- ## 4. 后端 API 设计 ### 4.1 申请单 / 售卖计划 — 扩展 `pilot_application` CRUD **文件**:`backend/app/crud/pilot_application.py`、`backend/app/api/pilot_application.py` | 变更点 | 说明 | |--------|------| | `_generate_application_no` | `biz_type=basic_experiment` → 前缀 `JCSY` | | `create_application` | 跳过渠道/服务订单校验;校验课题/客户/标准附件;不写 patient | | `update_application` | 支持 `projectTitle/customerName/customerContact/customerPhone` | | `_row_to_dict_application` | 输出新字段 | | 售卖计划创建 | 按产品行批量创建 schedule + product + 工单 + payment | | `list` / `get` | `bizType=basic_experiment` 过滤 | **售卖计划创建规则** 1. 用户在一个表单中维护多行产品(细胞产品、参考价、实际价、份数、提货时间)。 2. 保存时:每个产品行 → 1 条 `BizPilotInfusionSchedule` + 1 条 `BizPilotInfusionScheduleProduct`。 3. 每条 schedule 自动调用现有: - `create_outbound_production_work_order(..., biz_type='basic_experiment')` - `create_outbound_qc_work_order(..., biz_type='basic_experiment')` - `clinical_payment.auto_create_payment`(扩展支持 `basic_experiment`) **产品选型**:从 `biz_cell_product_price` 加载(同临床),`actual_price` 默认等于 `unit_price`,前端可改。 ### 4.2 缴费 API — 扩展 `clinical_payment` **文件**:`backend/app/crud/clinical_payment.py`(或重命名为 `pilot_payment`)、`backend/app/api/clinical_payment.py` - 列表/详情/确认/退费接口增加 `bizType` 查询参数,默认不过滤;基础实验菜单请求时传 `bizType=basic_experiment`。 - `auto_create_payment`:`biz_type in ('clinical_application', 'basic_experiment')` 时创建。 - 列表列:基础实验展示 **课题名称、客户名称** 替代患者/渠道。 ### 4.3 出库放行审核 — 扩展 `outbound_release_review` - `_BIZ_TYPE_LABELS` 增加 `basic_experiment: 基础实验`。 - 列表 `bizType=basic_experiment` 过滤(已有模式)。 - 详情聚合:申请单新字段 + 售卖计划(提货时间、金额)+ 产品明细;**不返回患者**。 ### 4.4 出库工单查看 — 扩展 QC / 生产 CRUD **文件**:`qc_work_order.py`、`production_work_order.py`、`pilot_infusion_schedule_mgmt.py` - 出库详情接口返回 `application` 时包含 `projectTitle/customerName/...`。 - `patient` 对 `basic_experiment` 返回 `null`。 - `infusionPlan` 可返回简化字段或 `null`(查看弹窗按 variant 决定是否展示)。 ### 4.5 交付 API — 复用 `pilot_delivery` - 不按 `biz_type` 限制;基础实验在申请单详情 / 售卖计划操作中进入「交付确认」。 - 每条 schedule 独立维护 `biz_pilot_delivery`(与中试一致)。 - **不调用** `pilot_infusion_confirm` 相关接口。 ### 4.6 状态同步 — 扩展 `pilot_outbound_status_sync` `_OUTBOUND_BIZ_TYPES` 增加 `basic_experiment`。 --- ## 5. 前端设计 ### 5.1 菜单结构 ``` 基础实验(一级菜单) ├── 基础实验申请单 menuCode: basic-experiment:application:list ├── 缴退费财务确认 menuCode: basic-experiment:payment-confirm:list └── 出库放行审核 menuCode: basic-experiment:outbound-release-review:list ``` 路由模块 `sqxp.ts`(`props.bizType: 'basic_experiment'`): | 路由 name | path | 组件 | |-----------|------|------| | `BasicExperiment` | `/basic-experiment` | layout | | `BasicExperimentApplication` | `application` | `pilot-application/index` | | `BasicExperimentPaymentConfirm` | `payment-confirm` | `clinical-payment-confirm/index`(传 bizType) | | `BasicExperimentOutboundRelease` | `outbound-release-review` | `outbound-release-review/index` | 缴费信息 Tab 内嵌于申请单页(同临床),不单独做侧栏菜单;旧路径可做重定向。 ### 5.2 申请单页 Tab 结构 | Tab | 组件 | 说明 | |-----|------|------| | 基础实验申请单 | `PilotApplicationTab` | 列表 + 新增/编辑/查看 | | 售卖计划管理 | `InfusionScheduleTab` | 文案改为「售卖计划」;列含提货时间、金额、缴费状态 | | 缴费信息 | `ClinicalPaymentTab` 或抽取共用 Tab | `bizType=basic_experiment` | **不展示**:体检 Tab、输注确认相关入口。 ### 5.3 `bizType` 策略配置(推荐新建) 新建 `web-admin/src/config/pilot-biz-type.ts`(名称可调整),集中定义: ```ts export type PilotBizType = 'pilot_service' | 'clinical_application' | 'basic_experiment' export interface PilotBizTypeConfig { applicationNoPrefix: string showChannel: boolean showPatient: boolean showConsent: boolean showOtherAttachments: boolean showStandardAttachments: boolean showCheckup: boolean showInfusionConfirm: boolean showDelivery: boolean showPayment: boolean planLabel: string // 输注方案 / 售卖方案 scheduleLabel: string // 输注计划 / 售卖计划 pickupTimeLabel: string // 输注时间 / 提货时间 // ... } ``` `ApplicationFormDialog.vue`、`ApplicationViewDialog.vue`、`InfusionScheduleTab.vue` 等读取配置,替代散落 `isClinical`。 ### 5.4 申请单表单字段(`basic_experiment`) **申请单区块** | 字段 | 必填 | 说明 | |------|------|------| | 申请单号 | 自动 | `JCSY` + 日期 + 序号 | | 申请单名称 | 否 | | | 课题名称 | 是 | `projectTitle` | | 客户名称 | 是 | 自由文本 | | 客户联系人 | 是 | | | 客户联系方式 | 是 | | | 标准附件 | 否 | 单上传区,图片/PDF,卡片布局同规范 | | 备注 | 否 | | **隐藏**:渠道、服务订单、知情同意书、其他附件、患者信息整块。 **售卖方案区块**(原输注方案 Tab 内) | 列 | 说明 | |----|------| | 细胞产品 | 从 `biz_cell_product_price` 选择 | | 规格 | 随产品带入 | | 参考单价 | 只读 | | 实际单价 | 可编辑,默认=参考单价 | | 份数 | 默认 1 | | 提货时间 | 每行独立 `datetime` | | 金额 | 可 `实际单价 × 份数` 自动算,可改(写入 schedule.amount) | 保存逻辑:N 行产品 → N 条 schedule(见 §4.1)。 ### 5.5 出库质检 / 生产工单 — 查看弹窗 扩展 `outbound-qc-pilot-view-sections.ts`: ```ts export type OutboundViewContextVariant = | 'pilot_service' | 'clinical_application' | 'basic_experiment' ``` **`basic_experiment` 展示区块** 1. **基础实验申请信息**:申请单号、课题名称、客户名称、联系人、联系方式、申请单状态 2. **售卖计划信息**:提货时间、售卖金额、计划/质检状态 3. **细胞产品明细**:项目、规格、参考价、实际价、份数 **不展示**:患者信息、输注方案(疗程)、输注地点/方式。 使用处: - `qc-work-order/OutboundQcViewDialog.vue` - `production-work-order/index.vue` 出库查看 - `outbound-release-review` 查看弹窗(若共用 section builder) ### 5.6 缴退费财务确认 复用 `clinical-payment-confirm/index.vue` + `RefundConfirmTab.vue`: - 路由 `props: { bizType: 'basic_experiment' }` - 列表 API 带 `bizType=basic_experiment` - 表格列:申请单号、课题名称、客户名称、细胞产品、提货时间、金额、缴费状态 ### 5.7 交付确认 复用 `ApplicationDetailDialog.vue` 内交付 Tab / 交付弹窗逻辑: - `basic_experiment` 显示「交付信息」Tab - 隐藏「输注确认」Tab(若有) - 交付操作粒度:**按售卖计划(schedule)**,与中试一致 ### 5.8 状态标签 `status-tag-registry.ts` 增加: ```ts basic_experiment: { label: '基础实验', tagType: 'primary' } // 色值待定,勿与中试重复语义 ``` --- ## 6. 权限与菜单码 | menuCode | 菜单 | |----------|------| | `basic-experiment:application:list` | 基础实验申请单 | | `basic-experiment:payment-confirm:list` | 缴退费财务确认 | | `basic-experiment:outbound-release-review:list` | 出库放行审核 | 角色授权需同步 `sys_menu`(SQL 迁移脚本)。 --- ## 7. 实现策略与文件清单 ### 7.1 推荐方案 **`biz_type` 扩展 + 前端 `bizType` 策略配置**(参见临床应用设计,避免独立建表)。 ### 7.2 改动清单(按优先级) | 优先级 | 层级 | 文件/模块 | |--------|------|-----------| | P0 | SQL | `docs/sql/migrations/2026-06-10-basic-experiment.sql` | | P0 | Model | `backend/app/models/models.py` | | P0 | CRUD | `pilot_application.py`, `clinical_payment.py` | | P0 | API Schema | `pilot_application` Create/Update body | | P0 | 路由 | `sqxp.ts`, `menu.py` | | P0 | 前端配置 | `pilot-biz-type.ts`(新) | | P0 | 表单/列表 | `ApplicationFormDialog.vue`, `PilotApplicationTab.vue`, `InfusionScheduleTab.vue` | | P1 | 出库查看 | `outbound-qc-pilot-view-sections.ts`, QC/生产查看弹窗 | | P1 | 放行审核 | `outbound-release-review/*` | | P1 | 缴费 | `clinical-payment-confirm/*`, `ClinicalPaymentTab.vue` | | P1 | 交付 | `ApplicationDetailDialog.vue` | | P1 | 状态同步 | `pilot_outbound_status_sync.py`, `outbound_release_review.py` | | P2 | 字段一致性 | `check_field_consistency.py` | | P2 | 测试 | 申请单创建、多产品多计划、工单/auto payment 联动 | ### 7.3 风险与缓解 | 风险 | 缓解 | |------|------| | `ApplicationFormDialog.vue` 过大 | 本期引入 `pilot-biz-type.ts` 配置;后续可拆子表单组件 | | `infusion_*` 命名与售卖语义不符 | UI 全面使用「售卖/提货」;DB/代码保留旧名 | | 一产品一计划导致列表行数多 | 售卖计划 Tab 按产品行展示,申请单列表仍按申请单聚合 | | 缴费模块命名 `clinical_*` | API 层扩展 `bizType` 参数,暂不 rename 模块 | --- ## 8. 验收标准 1. 侧栏可见「基础实验」一级菜单及三个二级菜单;临床应用仍隐藏。 2. 可创建 `JCSY` 前缀申请单,填写课题/客户/标准附件,无渠道与患者字段。 3. 售卖方案可添加多行细胞产品,每行独立提货时间与可改价格;保存后生成 N 条售卖计划。 4. 每条售卖计划自动产生出库生产工单、出库质检工单、待缴费记录。 5. 出库质检/生产工单「查看」弹窗展示基础实验申请信息 + 售卖计划 + 产品明细,无患者区块。 6. 出库放行审核、出库交接、交付确认可按 schedule 正常操作。 7. 缴费信息 + 缴退费财务确认流程与临床一致(状态机 `dfj→jfqrz→yjf→tfqrz→ytf`),数据按 `biz_type` 隔离。 8. 中试/临床列表不出现 `JCSY` 申请单;基础实验列表不出现 `ZSSQ`/`LCSQ`。 --- ## 9. 已确认需求摘要(2026-06-10) | 问题 | 结论 | |------|------| | 缴费/财务确认 | 需要 | | 体检 | 无 | | 交付/输注确认 | 有交付确认,无输注确认 | | 申请单号前缀 | `JCSY` | | 客户信息 | 自由文本 | | 售卖计划粒度 | 每细胞产品一个提货时间 → **一产品一售卖计划** | | 标准附件 | 单上传区,图片/PDF,卡片布局 | | 产品费用 | 从细胞产品价格体系带入,可修改 | | 客户主数据 | 不关联 | --- ## 10. 后续步骤 1. **用户审阅本 spec** — 确认后进入实现计划(`writing-plans`)。 2. 编写 `docs/superpowers/plans/2026-06-10-basic-experiment.md` 任务拆解。 3. 按 P0 → P1 分期实现与联调。