606 lines
21 KiB
Markdown
606 lines
21 KiB
Markdown
# 基础实验业务 Implementation Plan
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** 新增 `biz_type=basic_experiment` 基础实验业务线:B2B 细胞产品售卖、一产品一售卖计划、独立缴费/出库/交付闭环。
|
||
|
||
**Architecture:** 复用 `biz_pilot_*` 表与中试/临床出库链路;申请单扩展课题/客户字段;售卖方案保存时按产品行批量 `create_schedule`(每行 → 1 条 `infusion_schedule` + 工单 + 缴费)。前端通过 `pilot-biz-type.ts` 策略配置 + 路由 `props.bizType` 隔离 UI。
|
||
|
||
**Tech Stack:** FastAPI + SQLAlchemy + Pydantic v2(后端),Vue 3 + Element Plus + TypeScript(前端),MySQL 5.7
|
||
|
||
**Design Spec:** `docs/superpowers/specs/2026-06-10-basic-experiment-design.md`
|
||
|
||
---
|
||
|
||
## File Structure
|
||
|
||
### SQL — New
|
||
- `docs/sql/migrations/2026-06-10-basic-experiment.sql` — ALTER `biz_pilot_application`、扩展 `biz_type` 注释、`biz_pilot_payment` 注释
|
||
- `docs/sql/migrations/2026-06-10-basic-experiment-menu.sql` — `sys_menu` 基础实验菜单(可选,与 `menu.py` 对齐)
|
||
|
||
### Backend — Modified
|
||
- `backend/app/models/models.py` — `BizPilotApplication` 新增客户/课题字段;`biz_type` 注释扩展
|
||
- `backend/app/crud/pilot_application.py` — JCSY 前缀、`basic_experiment` 校验、售卖计划批量创建、`_row_to_dict` 新字段
|
||
- `backend/app/api/pilot_application.py` — Create/Update schema 新字段
|
||
- `backend/app/crud/clinical_payment.py` — `auto_create_payment` / 列表支持 `basic_experiment`
|
||
- `backend/app/api/clinical_payment.py` — 列表接口 `bizType` 过滤
|
||
- `backend/app/crud/outbound_release_review.py` — `_BIZ_TYPE_LABELS`、详情聚合
|
||
- `backend/app/crud/pilot_outbound_status_sync.py` — `_OUTBOUND_BIZ_TYPES`
|
||
- `backend/app/crud/qc_work_order.py` — 出库详情 `basic_experiment` 上下文
|
||
- `backend/app/crud/production_work_order.py` — 出库详情 `basic_experiment` 上下文
|
||
- `backend/app/crud/pilot_infusion_schedule_mgmt.py` — 详情/列表 `basic_experiment` 字段
|
||
- `backend/app/api/menu.py` — 基础实验菜单树
|
||
|
||
### Backend — New Tests
|
||
- `backend/tests/test_basic_experiment_application.py` — 申请单创建、多产品多计划、工单/缴费联动
|
||
|
||
### Frontend — New
|
||
- `web-admin/src/config/pilot-biz-type.ts` — `bizType` 策略配置表
|
||
|
||
### Frontend — Modified
|
||
- `web-admin/src/router/modules/sqxp.ts` — 基础实验一级菜单 + 子路由
|
||
- `web-admin/src/utils/status-tag-registry.ts` — `basic_experiment` 标签
|
||
- `web-admin/src/utils/outbound-qc-pilot-view-sections.ts` — `basic_experiment` variant
|
||
- `web-admin/src/views/pilot-service/pilot-application/index.vue` — Tab/卡片按 config 渲染
|
||
- `web-admin/src/views/pilot-service/pilot-application/PilotApplicationTab.vue`
|
||
- `web-admin/src/views/pilot-service/pilot-application/ApplicationFormDialog.vue` — 基础实验表单 + 售卖产品子表
|
||
- `web-admin/src/views/pilot-service/pilot-application/ApplicationViewDialog.vue`
|
||
- `web-admin/src/views/pilot-service/pilot-application/ApplicationDetailDialog.vue` — 交付 Tab 显隐
|
||
- `web-admin/src/views/pilot-service/pilot-application/InfusionScheduleTab.vue` — 售卖计划文案/列
|
||
- `web-admin/src/views/pilot-service/pilot-application/ClinicalPaymentTab.vue` — `bizType` 列展示
|
||
- `web-admin/src/views/pilot-service/clinical-payment-confirm/index.vue` — 接收 `bizType` prop
|
||
- `web-admin/src/views/pilot-service/outbound-release-review/index.vue`
|
||
- `web-admin/src/views/quality-inspection/qc-work-order/OutboundQcViewDialog.vue`
|
||
- `web-admin/src/views/production/production-work-order/index.vue`
|
||
- `web-admin/src/api/business.ts` — 类型/请求参数(若需)
|
||
|
||
---
|
||
|
||
## Task 1: 数据库迁移
|
||
|
||
**Files:**
|
||
- Create: `docs/sql/migrations/2026-06-10-basic-experiment.sql`
|
||
- Modify: `docs/sql/zkxw.sql`(全量基线同步)
|
||
|
||
- [ ] **Step 1: 编写迁移 SQL**
|
||
|
||
```sql
|
||
-- 基础实验:biz_pilot_application 扩展
|
||
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;
|
||
|
||
ALTER TABLE biz_pilot_payment
|
||
MODIFY COLUMN biz_type VARCHAR(20) NOT NULL DEFAULT 'clinical_application'
|
||
COMMENT '业务类型: clinical_application=临床应用, basic_experiment=基础实验';
|
||
```
|
||
|
||
- [ ] **Step 2: 在测试库执行迁移**
|
||
|
||
Run: `mysql -u root -p zkxw < docs/sql/migrations/2026-06-10-basic-experiment.sql`
|
||
|
||
Expected: 无报错;`DESCRIBE biz_pilot_application` 可见四个新字段。
|
||
|
||
- [ ] **Step 3: 同步 `docs/sql/zkxw.sql` 中对应表定义**
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add docs/sql/migrations/2026-06-10-basic-experiment.sql docs/sql/zkxw.sql
|
||
git commit -m "feat: add basic experiment DB migration for application customer fields"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 2: 后端模型与 `_row_to_dict`
|
||
|
||
**Files:**
|
||
- Modify: `backend/app/models/models.py`
|
||
- Modify: `backend/app/crud/pilot_application.py`
|
||
|
||
- [ ] **Step 1: 在 `BizPilotApplication` 增加四列**
|
||
|
||
```python
|
||
project_title = Column(String(200), nullable=True, comment="课题名称(基础实验)")
|
||
customer_name = Column(String(200), nullable=True, comment="客户名称(基础实验)")
|
||
customer_contact = Column(String(100), nullable=True, comment="客户联系人(基础实验)")
|
||
customer_phone = Column(String(32), nullable=True, comment="客户联系方式(基础实验)")
|
||
```
|
||
|
||
更新 `biz_type` 列 comment 含 `basic_experiment`。
|
||
|
||
- [ ] **Step 2: 扩展 `_row_to_dict_application`**
|
||
|
||
```python
|
||
"projectTitle": row.project_title or "",
|
||
"customerName": row.customer_name or "",
|
||
"customerContact": row.customer_contact or "",
|
||
"customerPhone": row.customer_phone or "",
|
||
```
|
||
|
||
- [ ] **Step 3: 扩展 `_generate_application_no`**
|
||
|
||
```python
|
||
if biz_type == "clinical_application":
|
||
prefix = f"LCSQ{today_str}"
|
||
elif biz_type == "basic_experiment":
|
||
prefix = f"JCSY{today_str}"
|
||
else:
|
||
prefix = f"ZSSQ{today_str}"
|
||
```
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add backend/app/models/models.py backend/app/crud/pilot_application.py
|
||
git commit -m "feat: extend pilot application model for basic experiment fields"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 3: 申请单创建/更新 — `basic_experiment` 校验
|
||
|
||
**Files:**
|
||
- Modify: `backend/app/crud/pilot_application.py`
|
||
- Modify: `backend/app/api/pilot_application.py`
|
||
|
||
- [ ] **Step 1: 写失败测试**
|
||
|
||
Create `backend/tests/test_basic_experiment_application.py`:
|
||
|
||
```python
|
||
import pytest
|
||
from app.crud import pilot_application as crud
|
||
|
||
|
||
def test_generate_application_no_basic_experiment_prefix():
|
||
# mock db session 或集成测试:biz_type=basic_experiment 时前缀 JCSY
|
||
assert "JCSQ" not in "JCSY202606100001" # placeholder; 实现后用真实调用断言
|
||
```
|
||
|
||
实现时改为:调用 `_generate_application_no` 或 create API 返回 `applicationNo.startswith("JCSY")`。
|
||
|
||
- [ ] **Step 2: 修改 `create_application` 分支**
|
||
|
||
```python
|
||
biz_type = data.get("bizType") or "pilot_service"
|
||
|
||
if biz_type == "basic_experiment":
|
||
if not (data.get("projectTitle") or "").strip():
|
||
raise ValueError("请填写课题名称")
|
||
if not (data.get("customerName") or "").strip():
|
||
raise ValueError("请填写客户名称")
|
||
if not (data.get("customerContact") or "").strip():
|
||
raise ValueError("请填写客户联系人")
|
||
if not (data.get("customerPhone") or "").strip():
|
||
raise ValueError("请填写客户联系方式")
|
||
channel_service_order_id = ""
|
||
channel_id = ""
|
||
channel_name = ""
|
||
elif biz_type == "clinical_application":
|
||
# 保持现有逻辑
|
||
...
|
||
else:
|
||
if not channel_service_order_id:
|
||
raise ValueError("请选择渠道服务订单")
|
||
```
|
||
|
||
创建 `BizPilotApplication` 时写入 `project_title/customer_*`;`consent_form_urls=None`。
|
||
|
||
- [ ] **Step 3: 修改 `update_application` 支持新字段**
|
||
|
||
- [ ] **Step 4: API schema `CreateBody`/`UpdateBody` 增加**
|
||
|
||
```python
|
||
project_title: Optional[str] = Field(None, alias="projectTitle")
|
||
customer_name: Optional[str] = Field(None, alias="customerName")
|
||
customer_contact: Optional[str] = Field(None, alias="customerContact")
|
||
customer_phone: Optional[str] = Field(None, alias="customerPhone")
|
||
```
|
||
|
||
- [ ] **Step 5: 运行测试**
|
||
|
||
Run: `cd backend && source venv/bin/activate && pytest tests/test_basic_experiment_application.py -v`
|
||
|
||
- [ ] **Step 6: Commit**
|
||
|
||
---
|
||
|
||
## Task 4: 售卖计划批量创建(一产品一计划)
|
||
|
||
**Files:**
|
||
- Modify: `backend/app/crud/pilot_application.py`
|
||
- Modify: `backend/app/api/pilot_application.py`
|
||
|
||
- [ ] **Step 1: 新增 `create_basic_experiment_sale_schedules`**
|
||
|
||
在 `pilot_application.py` 中实现(或扩展现有 save infusion API):
|
||
|
||
```python
|
||
def create_basic_experiment_sale_schedules(
|
||
db: Session,
|
||
application_id: str,
|
||
product_lines: list,
|
||
tenant_no: str,
|
||
user_id: str,
|
||
dept_id: str,
|
||
) -> list:
|
||
"""每个产品行调用一次 create_schedule,cellProducts 仅含一行。"""
|
||
plan = _get_or_create_infusion_plan(db, application_id, tenant_no, user_id, dept_id)
|
||
results = []
|
||
for idx, line in enumerate(product_lines):
|
||
schedule_data = {
|
||
"cellType": line.get("cellTypeName") or "",
|
||
"specText": line.get("specText") or "",
|
||
"infusionTime": line.get("pickupTime"), # 提货时间 → infusion_time
|
||
"amount": line.get("amount"),
|
||
"sortNo": idx + 1,
|
||
"cellProducts": [{
|
||
"priceId": line.get("priceId"),
|
||
"projectCode": line.get("projectCode"),
|
||
"projectName": line.get("projectName"),
|
||
"cellTypeName": line.get("cellTypeName"),
|
||
"specText": line.get("specText"),
|
||
"agreementPrice": line.get("agreementPrice"),
|
||
"actualPrice": line.get("actualPrice"),
|
||
"quantity": line.get("quantity") or 1,
|
||
}],
|
||
}
|
||
results.append(
|
||
create_schedule(db, plan.id, schedule_data, tenant_no, user_id, dept_id)
|
||
)
|
||
return results
|
||
```
|
||
|
||
- [ ] **Step 2: 扩展 `create_schedule` 缴费自动创建**
|
||
|
||
将条件从仅 `clinical_application` 扩展为:
|
||
|
||
```python
|
||
if application and application.biz_type in ("clinical_application", "basic_experiment") and data.get("amount"):
|
||
auto_create_payment(..., biz_type=application.biz_type)
|
||
```
|
||
|
||
- [ ] **Step 3: API 端点**
|
||
|
||
新增或扩展 `POST /pilot-application/{id}/sale-schedules`(body: `productLines: [...]`),仅 `biz_type=basic_experiment` 可用。
|
||
|
||
- [ ] **Step 4: 测试 — 2 行产品生成 2 条 schedule + 2 组工单**
|
||
|
||
```python
|
||
def test_basic_experiment_two_products_create_two_schedules(db_session, ...):
|
||
# 创建申请单后提交 2 行产品
|
||
# 断言 schedule 数量 == 2
|
||
# 断言 production_work_order / qc_work_order 各 2 条
|
||
# 断言 biz_pilot_payment 2 条
|
||
```
|
||
|
||
- [ ] **Step 5: Commit**
|
||
|
||
---
|
||
|
||
## Task 5: 缴费模块扩展
|
||
|
||
**Files:**
|
||
- Modify: `backend/app/crud/clinical_payment.py`
|
||
- Modify: `backend/app/api/clinical_payment.py`
|
||
|
||
- [ ] **Step 1: `auto_create_payment` 增加 `biz_type` 参数**
|
||
|
||
默认 `clinical_application`;基础实验传 `basic_experiment`。
|
||
|
||
- [ ] **Step 2: 列表查询支持 `bizType` 过滤**
|
||
|
||
所有 `list_*` 函数增加 `biz_type: Optional[str]`,过滤 `BizPilotPayment.biz_type`。
|
||
|
||
- [ ] **Step 3: 列表 `_row_to_dict` 关联申请单输出 `projectTitle/customerName`**
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
---
|
||
|
||
## Task 6: 出库链路扩展
|
||
|
||
**Files:**
|
||
- Modify: `backend/app/crud/pilot_outbound_status_sync.py`
|
||
- Modify: `backend/app/crud/outbound_release_review.py`
|
||
- Modify: `backend/app/crud/qc_work_order.py`
|
||
- Modify: `backend/app/crud/production_work_order.py`
|
||
- Modify: `backend/app/crud/pilot_infusion_schedule_mgmt.py`
|
||
|
||
- [ ] **Step 1: 元组/字典加入 `basic_experiment`**
|
||
|
||
```python
|
||
_OUTBOUND_BIZ_TYPES = ("pilot_service", "clinical_application", "basic_experiment")
|
||
_BIZ_TYPE_LABELS = {..., "basic_experiment": "基础实验"}
|
||
```
|
||
|
||
- [ ] **Step 2: 出库详情接口 — `patient` 对 `basic_experiment` 返回 null**
|
||
|
||
详情 `application` 含 `projectTitle/customerName/customerContact/customerPhone`。
|
||
|
||
- [ ] **Step 3: `pilot_infusion_schedule_mgmt` 完成逻辑 — 跳过渠道扣费**
|
||
|
||
与 `clinical_application` 相同:`biz_type == basic_experiment` 时不扣服务订单。
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
---
|
||
|
||
## Task 7: 菜单与路由
|
||
|
||
**Files:**
|
||
- Modify: `web-admin/src/router/modules/sqxp.ts`
|
||
- Modify: `backend/app/api/menu.py`
|
||
- Create: `docs/sql/migrations/2026-06-10-basic-experiment-menu.sql`(可选)
|
||
|
||
- [ ] **Step 1: `sqxp.ts` 新增一级菜单「基础实验」**
|
||
|
||
```ts
|
||
{
|
||
id: 'BEX00000000000000000000000000001',
|
||
name: 'BasicExperiment',
|
||
path: '/basic-experiment',
|
||
component: '/index/index',
|
||
meta: { title: '基础实验', icon: 'ri:flask-line', keepAlive: false, roles: ['admin'] },
|
||
children: [
|
||
{
|
||
id: 'BEX00000000000000000000000000002',
|
||
name: 'BasicExperimentApplication',
|
||
path: 'application',
|
||
component: '/pilot-service/pilot-application/index',
|
||
meta: { title: '基础实验申请单', keepAlive: true, menuCode: 'basic-experiment:application:list' },
|
||
props: { bizType: 'basic_experiment' }
|
||
},
|
||
{
|
||
id: 'BEX00000000000000000000000000003',
|
||
name: 'BasicExperimentPaymentConfirm',
|
||
path: 'payment-confirm',
|
||
component: '/pilot-service/clinical-payment-confirm/index',
|
||
meta: { title: '缴退费财务确认', keepAlive: true, menuCode: 'basic-experiment:payment-confirm:list' },
|
||
props: { bizType: 'basic_experiment' }
|
||
},
|
||
{
|
||
id: 'BEX00000000000000000000000000004',
|
||
name: 'BasicExperimentOutboundRelease',
|
||
path: 'outbound-release-review',
|
||
component: '/pilot-service/outbound-release-review/index',
|
||
meta: { title: '出库放行审核', keepAlive: true, menuCode: 'basic-experiment:outbound-release-review:list' },
|
||
props: { bizType: 'basic_experiment' }
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: 同步 `backend/app/api/menu.py`**
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
---
|
||
|
||
## Task 8: 前端 `pilot-biz-type.ts` 策略配置
|
||
|
||
**Files:**
|
||
- Create: `web-admin/src/config/pilot-biz-type.ts`
|
||
|
||
- [ ] **Step 1: 定义配置表**
|
||
|
||
```ts
|
||
export type PilotBizType = 'pilot_service' | 'clinical_application' | 'basic_experiment'
|
||
|
||
export const PILOT_BIZ_TYPE_CONFIG: Record<PilotBizType, {
|
||
label: string
|
||
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
|
||
}> = {
|
||
pilot_service: { /* 现有默认 */ showStandardAttachments: false, ... },
|
||
clinical_application: { showStandardAttachments: false, ... },
|
||
basic_experiment: {
|
||
label: '基础实验',
|
||
applicationNoPrefix: 'JCSY',
|
||
showChannel: false,
|
||
showPatient: false,
|
||
showConsent: false,
|
||
showOtherAttachments: false,
|
||
showStandardAttachments: true,
|
||
showCheckup: false,
|
||
showInfusionConfirm: false,
|
||
showDelivery: true,
|
||
showPayment: true,
|
||
planLabel: '售卖方案',
|
||
scheduleLabel: '售卖计划',
|
||
pickupTimeLabel: '提货时间',
|
||
}
|
||
}
|
||
|
||
export function getPilotBizConfig(bizType?: string) {
|
||
return PILOT_BIZ_TYPE_CONFIG[(bizType as PilotBizType) || 'pilot_service']
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: `status-tag-registry.ts` 增加 `basic_experiment`**
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
---
|
||
|
||
## Task 9: 申请单表单与列表
|
||
|
||
**Files:**
|
||
- Modify: `web-admin/src/views/pilot-service/pilot-application/index.vue`
|
||
- Modify: `web-admin/src/views/pilot-service/pilot-application/PilotApplicationTab.vue`
|
||
- Modify: `web-admin/src/views/pilot-service/pilot-application/ApplicationFormDialog.vue`
|
||
- Modify: `web-admin/src/views/pilot-service/pilot-application/ApplicationViewDialog.vue`
|
||
|
||
- [ ] **Step 1: `index.vue` 用 `getPilotBizConfig` 控制 Tab 卡片**
|
||
|
||
基础实验:申请单 | 售卖计划 | 缴费信息(无体检)。
|
||
|
||
- [ ] **Step 2: `ApplicationFormDialog.vue` — 基础实验区块**
|
||
|
||
- 显示:课题名称、客户名称/联系人/联系方式、标准附件(单上传区,图片/PDF,卡片布局)
|
||
- 隐藏:渠道、服务订单、知情同意书、其他附件、患者
|
||
- 售卖产品子表:细胞产品(`biz_cell_product_price`)、参考价、实际价(可改)、份数、提货时间、金额
|
||
- 保存:先 create/update application,再调 `sale-schedules` API 批量创建计划
|
||
|
||
- [ ] **Step 3: `PilotApplicationTab` 列表列**
|
||
|
||
基础实验列表展示:申请单号、课题名称、客户名称、状态(隐藏渠道列)。
|
||
|
||
- [ ] **Step 4: `ApplicationViewDialog` 只读态对齐**
|
||
|
||
- [ ] **Step 5: 手动验证**
|
||
|
||
1. 打开 `/#/basic-experiment/application`
|
||
2. 新增申请单,添加 2 行产品不同提货时间
|
||
3. 保存后在售卖计划 Tab 看到 2 条计划
|
||
|
||
- [ ] **Step 6: Commit**
|
||
|
||
---
|
||
|
||
## Task 10: 售卖计划 Tab + 缴费
|
||
|
||
**Files:**
|
||
- Modify: `web-admin/src/views/pilot-service/pilot-application/InfusionScheduleTab.vue`
|
||
- Modify: `web-admin/src/views/pilot-service/pilot-application/ClinicalPaymentTab.vue`
|
||
- Modify: `web-admin/src/views/pilot-service/clinical-payment-confirm/index.vue`
|
||
|
||
- [ ] **Step 1: `InfusionScheduleTab` 文案与列**
|
||
|
||
- `scheduleLabel` / `pickupTimeLabel` 从 config 读取
|
||
- 隐藏输注地点/方式/输注状态(`basic_experiment`)
|
||
- 展示:细胞产品、金额、提货时间、缴费状态
|
||
|
||
- [ ] **Step 2: `ClinicalPaymentTab` + 缴退费页**
|
||
|
||
- 请求带 `bizType: 'basic_experiment'`
|
||
- 列:课题名称、客户名称(替代患者/渠道)
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
---
|
||
|
||
## Task 11: 出库查看弹窗 + 放行审核
|
||
|
||
**Files:**
|
||
- Modify: `web-admin/src/utils/outbound-qc-pilot-view-sections.ts`
|
||
- Modify: `web-admin/src/views/quality-inspection/qc-work-order/OutboundQcViewDialog.vue`
|
||
- Modify: `web-admin/src/views/production/production-work-order/index.vue`
|
||
- Modify: `web-admin/src/views/pilot-service/outbound-release-review/index.vue`
|
||
|
||
- [ ] **Step 1: 扩展 `OutboundViewContextVariant`**
|
||
|
||
```ts
|
||
basic_experiment: {
|
||
application: '基础实验申请信息',
|
||
schedule: '售卖计划信息'
|
||
}
|
||
```
|
||
|
||
新增 section builder:申请信息含课题/客户;无患者;计划含提货时间/金额;产品明细表。
|
||
|
||
- [ ] **Step 2: QC/生产查看传入 `variant='basic_experiment'`**
|
||
|
||
当 `detail.application.bizType === 'basic_experiment'`。
|
||
|
||
- [ ] **Step 3: 放行审核列表 `bizType` 过滤 + 查看弹窗**
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
---
|
||
|
||
## Task 12: 交付确认
|
||
|
||
**Files:**
|
||
- Modify: `web-admin/src/views/pilot-service/pilot-application/ApplicationDetailDialog.vue`
|
||
|
||
- [ ] **Step 1: `getPilotBizConfig(bizType).showDelivery` 控制交付 Tab**
|
||
|
||
- [ ] **Step 2: 隐藏输注确认 Tab(`showInfusionConfirm: false`)**
|
||
|
||
- [ ] **Step 3: 按 schedule 粒度操作交付(复用现有 `pilot_delivery` API)**
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
---
|
||
|
||
## Task 13: 字段一致性检查与收尾
|
||
|
||
**Files:**
|
||
- Run: `backend/scripts/check_field_consistency.py`
|
||
- Run: `./scripts/update-graph.sh frontend` + `backend`
|
||
|
||
- [ ] **Step 1: 运行字段一致性脚本并修复遗漏**
|
||
|
||
Run: `cd backend && python scripts/check_field_consistency.py`
|
||
|
||
- [ ] **Step 2: 更新知识图谱**
|
||
|
||
Run: `./scripts/update-graph.sh all`
|
||
|
||
- [ ] **Step 3: 验收清单(对照 design spec §8)**
|
||
|
||
| # | 验收项 | 通过 |
|
||
|---|--------|------|
|
||
| 1 | 侧栏「基础实验」三菜单可见 | |
|
||
| 2 | JCSY 申请单 + 课题/客户/标准附件 | |
|
||
| 3 | 2 行产品 → 2 条售卖计划 | |
|
||
| 4 | 每计划自动工单 + 待缴费 | |
|
||
| 5 | QC/生产查看弹窗无患者、有基础实验信息 | |
|
||
| 6 | 放行/交接/交付可用 | |
|
||
| 7 | 缴退费流程可用且数据隔离 | |
|
||
| 8 | 中试/临床列表无 JCSY | |
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
git commit -m "feat: complete basic experiment business line"
|
||
```
|
||
|
||
---
|
||
|
||
## Spec Coverage Self-Review
|
||
|
||
| Spec 章节 | 对应 Task |
|
||
|-----------|-----------|
|
||
| §2 业务流程 / 一产品一计划 | Task 4 |
|
||
| §3 数据库 | Task 1–2 |
|
||
| §4.1 申请单 API | Task 3–4 |
|
||
| §4.2 缴费 | Task 5 |
|
||
| §4.3–4.6 出库/交付 | Task 6, 11–12 |
|
||
| §5 前端菜单/表单/查看 | Task 7–12 |
|
||
| §6 权限 menuCode | Task 7 |
|
||
| §8 验收标准 | Task 13 |
|
||
|
||
无 TBD/占位;类型命名统一 camelCase API / snake_case DB。
|
||
|
||
---
|
||
|
||
## Execution Handoff
|
||
|
||
Plan complete and saved to `docs/superpowers/plans/2026-06-10-basic-experiment.md`. Two execution options:
|
||
|
||
**1. Subagent-Driven (recommended)** — 每个 Task 派发独立 subagent,任务间做代码审查,迭代快
|
||
|
||
**2. Inline Execution** — 本会话按 Task 顺序直接实现,每 2–3 个 Task 设检查点
|
||
|
||
Which approach?
|