912 lines
33 KiB
Markdown
912 lines
33 KiB
Markdown
# 临时工单模块实施计划
|
||
|
||
> **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:** 新增临时质检工单和临时生产工单两个模块,复用现有任务生成机制,在任务表中记录工单来源。
|
||
|
||
**Architecture:** 新建 2 张独立临时工单表(极简字段),现有任务表新增 `order_source` 字段区分入库/临时来源。后端 CRUD 独立,复用现有任务创建函数。前端新增 2 个标准列表页,现有任务列表新增"来源"Tag 列。
|
||
|
||
**Tech Stack:** Python 3.9 / FastAPI / SQLAlchemy / Pydantic v2 / MySQL 5.7 / Vue 3 / TypeScript / Element Plus / Tailwind CSS 4
|
||
|
||
**Design Spec:** `docs/superpowers/specs/2026-05-24-temporary-work-order-design.md`
|
||
|
||
---
|
||
|
||
## File Map
|
||
|
||
### 新建文件
|
||
|
||
| 文件 | 职责 |
|
||
|------|------|
|
||
| `backend/app/crud/temp_qc_work_order.py` | 临时质检工单 CRUD(创建、列表、详情、配置检测项目→生成任务、删除) |
|
||
| `backend/app/crud/temp_production_work_order.py` | 临时生产工单 CRUD(创建、列表、详情、配置→生成任务、删除) |
|
||
| `backend/app/schemas/temp_qc_work_order.py` | 临时质检工单 Pydantic Schema |
|
||
| `backend/app/schemas/temp_production_work_order.py` | 临时生产工单 Pydantic Schema |
|
||
| `web-admin/src/api/temp-qc-work-order.ts` | 临时质检工单前端 API 类型+函数 |
|
||
| `web-admin/src/api/temp-production-work-order.ts` | 临时生产工单前端 API 类型+函数 |
|
||
| `web-admin/src/views/quality-inspection/temp-qc-work-order/index.vue` | 临时质检工单列表页 |
|
||
| `web-admin/src/views/production/temp-production-work-order/index.vue` | 临时生产工单列表页 |
|
||
| `docs/sql/temp_work_order_tables.sql` | 新建表 + ALTER 语句 |
|
||
|
||
### 修改文件
|
||
|
||
| 文件 | 修改内容 |
|
||
|------|---------|
|
||
| `backend/app/models/models.py` | 新增 2 个模型类;4 个现有模型新增 `order_source` 列 |
|
||
| `backend/app/crud/qc_task.py` | `create_task_for_line()` 新增 `order_source` 参数;`_task_to_dict()` 序列化 `order_source`;`list_tasks()` 支持按 `order_source` 过滤 |
|
||
| `backend/app/crud/production_task.py` | `create_production_task()` 新增 `order_source` 参数;序列化 `order_source`;列表支持按来源过滤 |
|
||
| `backend/app/api/qc.py` | 新增临时质检工单路由组(5 个端点) |
|
||
| `backend/app/api/production.py` | 新增临时生产工单路由组(5 个端点) |
|
||
| `web-admin/src/api/qc-task.ts` | 类型新增 `orderSource` 字段 |
|
||
| `web-admin/src/api/production-task.ts` | 类型新增 `orderSource` 字段 |
|
||
| `web-admin/src/views/quality-inspection/qc-task/index.vue` | 列表新增"来源"Tag 列 |
|
||
| `web-admin/src/views/production/production-task/index.vue` | 列表新增"来源"Tag 列 |
|
||
|
||
---
|
||
|
||
### Task 1: 数据库 DDL — 新建表 + ALTER 语句
|
||
|
||
**Files:**
|
||
- Create: `docs/sql/temp_work_order_tables.sql`
|
||
|
||
- [ ] **Step 1: 创建 SQL 文件**
|
||
|
||
```sql
|
||
-- ============================================================
|
||
-- 临时工单模块 DDL
|
||
-- Date: 2026-05-24
|
||
-- ============================================================
|
||
|
||
-- 1. 新建临时质检工单表
|
||
DROP TABLE IF EXISTS biz_temp_qc_work_order;
|
||
CREATE TABLE biz_temp_qc_work_order (
|
||
id VARCHAR(64) NOT NULL COMMENT '主键ID',
|
||
work_order_no VARCHAR(64) NOT NULL COMMENT '工单号(LSZJ+日期+序号)',
|
||
work_order_status VARCHAR(20) NOT NULL DEFAULT 'dpz' COMMENT '状态: dpz=待配置, ypz=已配置, ywc=已完成',
|
||
configured_time DATETIME DEFAULT NULL COMMENT '配置时间',
|
||
configured_by VARCHAR(64) DEFAULT NULL COMMENT '配置人',
|
||
has_lab TINYINT DEFAULT 0 COMMENT '是否含实验室自检: 0=否, 1=是',
|
||
has_third_party TINYINT DEFAULT 0 COMMENT '是否含第三方检测: 0=否, 1=是',
|
||
third_party_fee_total DECIMAL(12,2) DEFAULT NULL COMMENT '第三方费用合计',
|
||
tenant_no VARCHAR(64) NOT NULL DEFAULT '' COMMENT '租户编号',
|
||
order_num INT DEFAULT NULL COMMENT '排序号',
|
||
remark VARCHAR(512) DEFAULT NULL COMMENT '备注',
|
||
create_by VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
|
||
create_dept_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
|
||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
update_by VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
|
||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
del_flag TINYINT NOT NULL DEFAULT 0 COMMENT '删除标记: 0=正常, 1=已删除',
|
||
PRIMARY KEY (id),
|
||
KEY idx_temp_qc_wo_tenant (tenant_no, del_flag),
|
||
KEY idx_temp_qc_wo_no (work_order_no, tenant_no)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='临时质检工单';
|
||
|
||
-- 2. 新建临时生产工单表
|
||
DROP TABLE IF EXISTS biz_temp_production_work_order;
|
||
CREATE TABLE biz_temp_production_work_order (
|
||
id VARCHAR(64) NOT NULL COMMENT '主键ID',
|
||
work_order_no VARCHAR(64) NOT NULL COMMENT '工单号(LSSC+日期+序号)',
|
||
work_order_status VARCHAR(20) NOT NULL DEFAULT 'dpz' COMMENT '状态: dpz=待配置, jxz=进行中, ywc=已完成',
|
||
configured_time DATETIME DEFAULT NULL COMMENT '配置时间',
|
||
configured_by VARCHAR(64) DEFAULT NULL COMMENT '配置人',
|
||
tenant_no VARCHAR(64) NOT NULL DEFAULT '' COMMENT '租户编号',
|
||
order_num INT DEFAULT NULL COMMENT '排序号',
|
||
remark VARCHAR(512) DEFAULT NULL COMMENT '备注',
|
||
create_by VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
|
||
create_dept_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
|
||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
update_by VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
|
||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
del_flag TINYINT NOT NULL DEFAULT 0 COMMENT '删除标记: 0=正常, 1=已删除',
|
||
PRIMARY KEY (id),
|
||
KEY idx_temp_prod_wo_tenant (tenant_no, del_flag),
|
||
KEY idx_temp_prod_wo_no (work_order_no, tenant_no)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='临时生产工单';
|
||
|
||
-- 3. 质检任务表新增来源字段
|
||
ALTER TABLE biz_qc_task
|
||
ADD COLUMN order_source VARCHAR(20) NOT NULL DEFAULT 'inbound'
|
||
COMMENT '工单来源: inbound=入库, temporary=临时' AFTER work_order_id;
|
||
|
||
-- 4. 生产任务表新增来源字段
|
||
ALTER TABLE biz_production_task
|
||
ADD COLUMN order_source VARCHAR(20) NOT NULL DEFAULT 'inbound'
|
||
COMMENT '工单来源: inbound=入库, temporary=临时' AFTER work_order_id;
|
||
|
||
-- 5. 实验室项目明细表新增来源字段
|
||
ALTER TABLE biz_qc_work_order_lab_item
|
||
ADD COLUMN order_source VARCHAR(20) NOT NULL DEFAULT 'inbound'
|
||
COMMENT '工单来源: inbound=入库, temporary=临时' AFTER work_order_id;
|
||
|
||
-- 6. 第三方项目明细表新增来源字段
|
||
ALTER TABLE biz_qc_work_order_third_item
|
||
ADD COLUMN order_source VARCHAR(20) NOT NULL DEFAULT 'inbound'
|
||
COMMENT '工单来源: inbound=入库, temporary=临时' AFTER work_order_id;
|
||
```
|
||
|
||
- [ ] **Step 2: 在数据库执行 DDL**
|
||
|
||
Run: `mysql -u root -p zkxw < docs/sql/temp_work_order_tables.sql`
|
||
Expected: 所有表和字段创建成功,无错误
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add docs/sql/temp_work_order_tables.sql
|
||
git commit -m "feat(db): add temp work order tables and order_source columns"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 2: 后端 Model — 新增模型类 + 修改现有模型
|
||
|
||
**Files:**
|
||
- Modify: `backend/app/models/models.py`
|
||
|
||
- [ ] **Step 1: 在 BizQcTask 模型中新增 `order_source` 列**
|
||
|
||
在 `BizQcTask` 类中,`work_order_id` 行之后添加:
|
||
|
||
```python
|
||
class BizQcTask(Base):
|
||
"""质检任务 biz_qc_task"""
|
||
|
||
__tablename__ = "biz_qc_task"
|
||
|
||
id = Column(String(64), primary_key=True, comment="主键ID")
|
||
work_order_id = Column(String(64), nullable=False, comment="工单ID")
|
||
order_source = Column(String(20), nullable=False, default="inbound", comment="工单来源: inbound=入库, temporary=临时")
|
||
task_no = Column(String(32), nullable=False, comment="任务号")
|
||
# ... 其余字段保持不变
|
||
```
|
||
|
||
- [ ] **Step 2: 在 BizProductionTask 模型中新增 `order_source` 列**
|
||
|
||
在 `BizProductionTask` 类中,`work_order_id` 行之后添加:
|
||
|
||
```python
|
||
class BizProductionTask(Base):
|
||
"""生产任务 biz_production_task"""
|
||
|
||
__tablename__ = "biz_production_task"
|
||
|
||
id = Column(String(64), primary_key=True, comment="主键ID")
|
||
task_no = Column(String(32), nullable=False, comment="任务号")
|
||
work_order_id = Column(String(64), nullable=False, comment="工单ID")
|
||
order_source = Column(String(20), nullable=False, default="inbound", comment="工单来源: inbound=入库, temporary=临时")
|
||
task_type = Column(String(20), nullable=False, default="cell_storage", comment="任务类型")
|
||
# ... 其余字段保持不变
|
||
```
|
||
|
||
- [ ] **Step 3: 在 BizQcWorkOrderLabItem 模型中新增 `order_source` 列**
|
||
|
||
在 `BizQcWorkOrderLabItem` 类中,`work_order_id` 行之后添加:
|
||
|
||
```python
|
||
class BizQcWorkOrderLabItem(Base):
|
||
"""质检工单-实验室项目明细 biz_qc_work_order_lab_item"""
|
||
|
||
__tablename__ = "biz_qc_work_order_lab_item"
|
||
|
||
id = Column(String(64), primary_key=True, comment="主键ID")
|
||
work_order_id = Column(String(64), nullable=False, comment="工单ID")
|
||
order_source = Column(String(20), nullable=False, default="inbound", comment="工单来源: inbound=入库, temporary=临时")
|
||
lab_test_item_id = Column(String(64), nullable=False, comment="实验室项目ID")
|
||
# ... 其余字段保持不变
|
||
```
|
||
|
||
- [ ] **Step 4: 在 BizQcWorkOrderThirdItem 模型中新增 `order_source` 列**
|
||
|
||
在 `BizQcWorkOrderThirdItem` 类中,`work_order_id` 行之后添加:
|
||
|
||
```python
|
||
class BizQcWorkOrderThirdItem(Base):
|
||
"""质检工单-第三方项目明细 biz_qc_work_order_third_item"""
|
||
|
||
__tablename__ = "biz_qc_work_order_third_item"
|
||
|
||
id = Column(String(64), primary_key=True, comment="主键ID")
|
||
work_order_id = Column(String(64), nullable=False, comment="工单ID")
|
||
order_source = Column(String(20), nullable=False, default="inbound", comment="工单来源: inbound=入库, temporary=临时")
|
||
third_party_item_id = Column(String(64), nullable=False, comment="第三方项目ID")
|
||
# ... 其余字段保持不变
|
||
```
|
||
|
||
- [ ] **Step 5: 新增 BizTempQcWorkOrder 模型类**
|
||
|
||
在 `BizQcWorkOrder` 类定义之后(约行 1253)添加:
|
||
|
||
```python
|
||
class BizTempQcWorkOrder(Base):
|
||
"""临时质检工单 biz_temp_qc_work_order"""
|
||
|
||
__tablename__ = "biz_temp_qc_work_order"
|
||
|
||
id = Column(String(64), primary_key=True, comment="主键ID")
|
||
work_order_no = Column(String(64), nullable=False, comment="工单号(LSZJ+日期+序号)")
|
||
work_order_status = Column(String(20), nullable=False, default="dpz", comment="状态: dpz=待配置, ypz=已配置, ywc=已完成")
|
||
configured_time = Column(DateTime, nullable=True, comment="配置时间")
|
||
configured_by = Column(String(64), nullable=True, comment="配置人")
|
||
has_lab = Column(SmallInteger, nullable=False, default=0, comment="是否含实验室自检")
|
||
has_third_party = Column(SmallInteger, nullable=False, default=0, comment="是否含第三方检测")
|
||
third_party_fee_total = Column(Numeric(18, 2), nullable=True, comment="第三方费用合计")
|
||
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
|
||
order_num = Column(Integer, nullable=True, comment="排序号")
|
||
remark = Column(String(512), nullable=True, comment="备注")
|
||
create_by = Column(String(64), nullable=True, comment="创建人id")
|
||
create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
|
||
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
|
||
update_by = Column(String(64), nullable=True, comment="更新人id")
|
||
update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
|
||
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
|
||
```
|
||
|
||
- [ ] **Step 6: 新增 BizTempProductionWorkOrder 模型类**
|
||
|
||
在 `BizProductionWorkOrder` 类定义之后(约行 2292)添加:
|
||
|
||
```python
|
||
class BizTempProductionWorkOrder(Base):
|
||
"""临时生产工单 biz_temp_production_work_order"""
|
||
|
||
__tablename__ = "biz_temp_production_work_order"
|
||
|
||
id = Column(String(64), primary_key=True, comment="主键ID")
|
||
work_order_no = Column(String(64), nullable=False, comment="工单号(LSSC+日期+序号)")
|
||
work_order_status = Column(String(20), nullable=False, default="dpz", comment="状态: dpz=待配置, jxz=进行中, ywc=已完成")
|
||
configured_time = Column(DateTime, nullable=True, comment="配置时间")
|
||
configured_by = Column(String(64), nullable=True, comment="配置人")
|
||
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
|
||
order_num = Column(Integer, nullable=True, comment="排序号")
|
||
remark = Column(String(512), nullable=True, comment="备注")
|
||
create_by = Column(String(64), nullable=True, comment="创建人id")
|
||
create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
|
||
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
|
||
update_by = Column(String(64), nullable=True, comment="更新人id")
|
||
update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
|
||
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
|
||
```
|
||
|
||
- [ ] **Step 7: Commit**
|
||
|
||
```bash
|
||
git add backend/app/models/models.py
|
||
git commit -m "feat(models): add temp work order models and order_source columns to task models"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 3: 后端 — 修改现有 qc_task CRUD 支持 order_source
|
||
|
||
**Files:**
|
||
- Modify: `backend/app/crud/qc_task.py`
|
||
|
||
- [ ] **Step 1: `create_task_for_line()` 新增 `order_source` 参数**
|
||
|
||
将函数签名改为:
|
||
|
||
```python
|
||
def create_task_for_line(
|
||
db: Session,
|
||
*,
|
||
work_order, # BizQcWorkOrder 或 BizTempQcWorkOrder
|
||
task_type: str,
|
||
source_line_id: str,
|
||
item_code: str,
|
||
item_name: str,
|
||
tenant_no: str,
|
||
user_id: Optional[str] = None,
|
||
create_dept_id: str = "",
|
||
seq: int = 1,
|
||
company_id: Optional[str] = None,
|
||
company_name: Optional[str] = None,
|
||
fee_amount: Optional[Decimal] = None,
|
||
order_source: str = "inbound", # 新增参数
|
||
) -> BizQcTask:
|
||
obj = BizQcTask(
|
||
id=generate_uuid(),
|
||
work_order_id=work_order.id,
|
||
order_source=order_source, # 新增
|
||
task_no=_gen_task_no(db, work_order, seq),
|
||
task_type=task_type,
|
||
source_line_id=source_line_id,
|
||
sample_code=getattr(work_order, "sample_code", None) or None,
|
||
item_code=item_code,
|
||
item_name=item_name,
|
||
company_id=company_id,
|
||
company_name=company_name,
|
||
fee_amount=fee_amount,
|
||
task_status="dzx",
|
||
tenant_no=tenant_no,
|
||
order_num=seq,
|
||
create_by=user_id,
|
||
create_dept_id=create_dept_id or "",
|
||
create_time=datetime.now(),
|
||
update_by=user_id,
|
||
update_time=datetime.now(),
|
||
del_flag=0,
|
||
)
|
||
db.add(obj)
|
||
db.flush()
|
||
return obj
|
||
```
|
||
|
||
- [ ] **Step 2: `_task_to_dict()` 序列化 `order_source`**
|
||
|
||
在 `_task_to_dict` 返回的字典中添加 `"orderSource"` 字段:
|
||
|
||
```python
|
||
def _task_to_dict(
|
||
t: BizQcTask,
|
||
work_order_no: str = "",
|
||
db: Optional[Session] = None,
|
||
tenant_no: Optional[str] = None,
|
||
) -> Dict[str, Any]:
|
||
tn = tenant_no or t.tenant_no
|
||
return {
|
||
"id": t.id,
|
||
"workOrderId": t.work_order_id,
|
||
"orderSource": getattr(t, "order_source", "inbound") or "inbound", # 新增
|
||
"workOrderNo": work_order_no,
|
||
# ... 其余字段保持不变
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add backend/app/crud/qc_task.py
|
||
git commit -m "feat(qc-task): support order_source parameter for task creation"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 4: 后端 — 修改现有 production_task CRUD 支持 order_source
|
||
|
||
**Files:**
|
||
- Modify: `backend/app/crud/production_task.py`
|
||
|
||
- [ ] **Step 1: `create_production_task()` 新增 `order_source` 参数**
|
||
|
||
在函数签名中添加 `order_source: str = "inbound"` 参数,在创建 BizProductionTask 时设置:
|
||
|
||
```python
|
||
# 在创建 task 对象时添加 order_source
|
||
task = BizProductionTask(
|
||
id=generate_uuid(),
|
||
task_no=task_no,
|
||
work_order_id=data.get("work_order_id", ""),
|
||
order_source=order_source, # 新增
|
||
task_type=data.get("task_type") or "cell_storage",
|
||
# ... 其余保持不变
|
||
)
|
||
```
|
||
|
||
- [ ] **Step 2: 任务序列化函数添加 `orderSource` 字段**
|
||
|
||
在 `_task_to_dict()` 或相应的序列化函数中添加 `"orderSource"` 字段。
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add backend/app/crud/production_task.py
|
||
git commit -m "feat(production-task): support order_source parameter for task creation"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 5: 后端 — 临时质检工单 Schema + CRUD + API
|
||
|
||
**Files:**
|
||
- Create: `backend/app/schemas/temp_qc_work_order.py`
|
||
- Create: `backend/app/crud/temp_qc_work_order.py`
|
||
- Modify: `backend/app/api/qc.py`
|
||
|
||
- [ ] **Step 1: 创建 Schema**
|
||
|
||
Create `backend/app/schemas/temp_qc_work_order.py`:
|
||
|
||
```python
|
||
"""临时质检工单 Schema"""
|
||
from __future__ import annotations
|
||
|
||
from typing import List, Optional
|
||
|
||
from pydantic import BaseModel, ConfigDict, Field
|
||
|
||
|
||
class TempQcWorkOrderCreateBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
remark: Optional[str] = Field("", alias="remark")
|
||
|
||
|
||
class TempQcWorkOrderConfigureBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
has_lab: bool = Field(False, alias="hasLab")
|
||
has_third_party: bool = Field(False, alias="hasThirdParty")
|
||
lab_item_ids: List[str] = Field(default_factory=list, alias="labItemIds")
|
||
third_party_item_ids: List[str] = Field(default_factory=list, alias="thirdPartyItemIds")
|
||
```
|
||
|
||
- [ ] **Step 2: 创建 CRUD**
|
||
|
||
Create `backend/app/crud/temp_qc_work_order.py`。核心函数:
|
||
|
||
1. `_gen_daily_no(db, tenant_no)` — 生成 `LSZJ{YYYYMMDD}{序号:04d}`
|
||
2. `_wo_to_dict(wo)` — 序列化(极简字段)
|
||
3. `create_temp_qc_work_order(db, *, tenant_no, user_id, create_dept_id, remark)` — 创建
|
||
4. `list_temp_qc_work_orders(db, *, page, page_size, keyword, work_order_status, tenant_no, user_info)` — 列表
|
||
5. `get_temp_qc_work_order(db, id, tenant_no)` — 获取单条
|
||
6. `get_temp_qc_work_order_detail(db, id, tenant_no)` — 详情(含 labItems, thirdPartyItems, tasks)
|
||
7. `configure_temp_qc_work_order(db, id, *, has_lab, has_third_party, lab_item_ids, third_party_item_ids, tenant_no, user_id, create_dept_id)` — 配置检测项目→自动生成任务(复用 `qc_task.create_task_for_line(order_source='temporary')`)
|
||
8. `try_complete_temp_qc_work_order(db, work_order_id, tenant_no)` — 所有临时任务完成时标记工单完成
|
||
9. `delete_temp_qc_work_order(db, id, tenant_no, user_id)` — 软删除
|
||
|
||
配置逻辑参照现有 `qc_work_order.configure_work_order()`,区别:
|
||
- 创建 BizQcWorkOrderLabItem/BizQcWorkOrderThirdItem 时设 `order_source='temporary'`
|
||
- 调用 `task_svc.create_task_for_line(order_source='temporary')`
|
||
- `try_complete` 查询时过滤 `order_source='temporary'`
|
||
|
||
- [ ] **Step 3: 在 api/qc.py 中新增路由组**
|
||
|
||
在文件末尾添加 5 个路由端点:
|
||
|
||
```python
|
||
# ---------- 临时质检工单 ----------
|
||
|
||
@router.post("/temp-qc-work-orders")
|
||
async def create_temp_qc_work_order(
|
||
body: TempQcWorkOrderCreateBody,
|
||
db: Session = Depends(get_db),
|
||
user: dict = Depends(require_menu_code("biz:tempQcWorkOrder:list")),
|
||
):
|
||
...
|
||
|
||
@router.get("/temp-qc-work-orders")
|
||
async def list_temp_qc_work_orders(...):
|
||
...
|
||
|
||
@router.get("/temp-qc-work-orders/{work_order_id}")
|
||
async def get_temp_qc_work_order_detail(...):
|
||
...
|
||
|
||
@router.delete("/temp-qc-work-orders/{work_order_id}")
|
||
async def delete_temp_qc_work_order(...):
|
||
...
|
||
|
||
@router.post("/temp-qc-work-orders/{work_order_id}/configure")
|
||
async def configure_temp_qc_work_order(
|
||
work_order_id: str,
|
||
body: TempQcWorkOrderConfigureBody,
|
||
db: Session = Depends(get_db),
|
||
user: dict = Depends(require_menu_code("biz:tempQcWorkOrder:list")),
|
||
):
|
||
...
|
||
```
|
||
|
||
- [ ] **Step 4: 启动后端验证 API 可达**
|
||
|
||
Run: `cd backend && source venv/bin/activate && python -c "from app.main import app; print('OK')"`
|
||
Expected: OK,无 import 错误
|
||
|
||
- [ ] **Step 5: Commit**
|
||
|
||
```bash
|
||
git add backend/app/schemas/temp_qc_work_order.py backend/app/crud/temp_qc_work_order.py backend/app/api/qc.py
|
||
git commit -m "feat(temp-qc): add temp QC work order backend (schema, CRUD, API)"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 6: 后端 — 临时生产工单 Schema + CRUD + API
|
||
|
||
**Files:**
|
||
- Create: `backend/app/schemas/temp_production_work_order.py`
|
||
- Create: `backend/app/crud/temp_production_work_order.py`
|
||
- Modify: `backend/app/api/production.py`
|
||
|
||
- [ ] **Step 1: 创建 Schema**
|
||
|
||
Create `backend/app/schemas/temp_production_work_order.py`:
|
||
|
||
```python
|
||
"""临时生产工单 Schema"""
|
||
from __future__ import annotations
|
||
|
||
from typing import Optional
|
||
|
||
from pydantic import BaseModel, ConfigDict, Field
|
||
|
||
|
||
class TempProductionWorkOrderCreateBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
remark: Optional[str] = Field("", alias="remark")
|
||
|
||
|
||
class TempProductionWorkOrderConfigureBody(BaseModel):
|
||
"""配置→创建生产任务(与入库生产工单一致:选择工艺路线+克隆步骤)"""
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
task_name: Optional[str] = Field("", alias="taskName")
|
||
task_type: Optional[str] = Field("cell_storage", alias="taskType")
|
||
route_id: Optional[str] = Field(None, alias="routeId")
|
||
description: Optional[str] = Field("", alias="description")
|
||
remark: Optional[str] = Field("", alias="remark")
|
||
```
|
||
|
||
- [ ] **Step 2: 创建 CRUD**
|
||
|
||
Create `backend/app/crud/temp_production_work_order.py`。核心函数:
|
||
|
||
1. `_gen_daily_no(db, tenant_no)` — 生成 `LSSC{YYYYMMDD}{序号:04d}`
|
||
2. `_wo_to_dict(wo)` — 序列化
|
||
3. `create_temp_production_work_order(db, *, tenant_no, user_id, create_dept_id, remark)` — 创建
|
||
4. `list_temp_production_work_orders(db, *, page, page_size, keyword, work_order_status, tenant_no, user_info)` — 列表
|
||
5. `get_temp_production_work_order(db, id, tenant_no)` — 获取单条
|
||
6. `get_temp_production_work_order_detail(db, id, tenant_no)` — 详情(含 tasks,每个 task 含 steps+子表)
|
||
7. `configure_temp_production_work_order(db, id, *, task_name, task_type, route_id, description, remark, tenant_no, user_id, create_dept_id)` — 配置→创建生产任务,**复用 `production_task.create_production_task(order_source='temporary')`,自动触发 `_clone_route_to_task()` 克隆工艺路线步骤+4类子表**
|
||
8. `delete_temp_production_work_order(db, id, tenant_no, user_id)` — 软删除
|
||
|
||
关键:`configure_temp_production_work_order` 直接调用 `production_task.create_production_task()`,传入 `order_source='temporary'` 和 `route_id`,由 `create_production_task` 内部自动执行 `_clone_route_to_task()` 克隆路线步骤。
|
||
|
||
同时需要调用 `sync_production_work_order_status_from_tasks` 的临时版本来同步工单状态。
|
||
|
||
- [ ] **Step 3: 在 api/production.py 中新增路由组**
|
||
|
||
添加 5 个路由端点(POST/GET/GET/{id}/DELETE/{id}/POST/{id}/configure),路由路径前缀 `/temp-production-work-orders`。
|
||
|
||
- [ ] **Step 4: 启动后端验证 API 可达**
|
||
|
||
Run: `cd backend && source venv/bin/activate && python -c "from app.main import app; print('OK')"`
|
||
Expected: OK
|
||
|
||
- [ ] **Step 5: Commit**
|
||
|
||
```bash
|
||
git add backend/app/schemas/temp_production_work_order.py backend/app/crud/temp_production_work_order.py backend/app/api/production.py
|
||
git commit -m "feat(temp-production): add temp production work order with route cloning support"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 7: 前端 — 临时质检工单页面
|
||
|
||
**Files:**
|
||
- Create: `web-admin/src/api/temp-qc-work-order.ts`
|
||
- Create: `web-admin/src/views/quality-inspection/temp-qc-work-order/index.vue`
|
||
|
||
- [ ] **Step 1: 创建 API 文件**
|
||
|
||
Create `web-admin/src/api/temp-qc-work-order.ts`,参照 `api/qc-work-order.ts` 简化版:
|
||
|
||
```typescript
|
||
import request from '@/utils/http'
|
||
|
||
type PageList<T> = {
|
||
list: T[]
|
||
total: number
|
||
page: number
|
||
pageSize: number
|
||
totalPages: number
|
||
}
|
||
|
||
export type TempQcWorkOrder = {
|
||
id: string
|
||
workOrderNo: string
|
||
workOrderStatus: string
|
||
hasLab: boolean
|
||
hasThirdParty: boolean
|
||
configuredTime?: string
|
||
configuredBy?: string
|
||
thirdPartyFeeTotal?: number
|
||
remark?: string
|
||
createTime?: string
|
||
updateTime?: string
|
||
}
|
||
|
||
export type TempQcWorkOrderDetail = TempQcWorkOrder & {
|
||
labItems?: Array<{ id: string; labTestItemId: string; itemCode: string; itemName: string }>
|
||
thirdPartyItems?: Array<{
|
||
id: string
|
||
thirdPartyItemId: string
|
||
companyId: string
|
||
companyName: string
|
||
itemCode: string
|
||
itemName: string
|
||
feeAmount: number
|
||
}>
|
||
tasks?: Array<{
|
||
id: string
|
||
taskNo: string
|
||
taskType: string
|
||
itemCode?: string
|
||
itemName?: string
|
||
taskStatus: string
|
||
conclusion?: string
|
||
conclusionLabel?: string
|
||
}>
|
||
}
|
||
|
||
export function fetchTempQcWorkOrderList(params?: {
|
||
page?: number
|
||
pageSize?: number
|
||
keyword?: string
|
||
workOrderStatus?: string
|
||
}) {
|
||
return request.get<PageList<TempQcWorkOrder>>({
|
||
url: '/web/admin/temp-qc-work-orders',
|
||
params
|
||
})
|
||
}
|
||
|
||
export function fetchTempQcWorkOrderDetail(id: string) {
|
||
return request.get<TempQcWorkOrderDetail>({
|
||
url: `/web/admin/temp-qc-work-orders/${id}`
|
||
})
|
||
}
|
||
|
||
export function fetchCreateTempQcWorkOrder(data: { remark?: string }) {
|
||
return request.post<TempQcWorkOrder>({
|
||
url: '/web/admin/temp-qc-work-orders',
|
||
data
|
||
})
|
||
}
|
||
|
||
export function fetchConfigureTempQcWorkOrder(
|
||
id: string,
|
||
data: {
|
||
hasLab: boolean
|
||
hasThirdParty: boolean
|
||
labItemIds: string[]
|
||
thirdPartyItemIds: string[]
|
||
}
|
||
) {
|
||
return request.post<TempQcWorkOrder>({
|
||
url: `/web/admin/temp-qc-work-orders/${id}/configure`,
|
||
data
|
||
})
|
||
}
|
||
|
||
export function fetchDeleteTempQcWorkOrder(id: string) {
|
||
return request.del({ url: `/web/admin/temp-qc-work-orders/${id}` })
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: 创建列表页面**
|
||
|
||
Create `web-admin/src/views/quality-inspection/temp-qc-work-order/index.vue`
|
||
|
||
参照模板页 `src/views/system/unit/index.vue`(标准列表页模式),包含:
|
||
- **列表列**:工单号、状态(Tag: dpz→info/ypz→warning/ywc→success)、是否含实验室自检、是否含第三方、配置时间、创建时间、操作
|
||
- **创建弹窗**:仅备注字段(el-input type="textarea")
|
||
- **配置弹窗**:复用现有配置检测项目组件逻辑(选择实验室自检/第三方检测项目)
|
||
- **详情弹窗**:工单基本信息 + 关联任务列表
|
||
- **Toolbar**:搜索(keyword)、状态筛选、新增按钮
|
||
- **注意**:遵循 AGENTS.md UI 规范(Tag 用 el-tag、dialog label-position="top"、2列 form-grid 等)
|
||
|
||
- [ ] **Step 3: 验证前端编译**
|
||
|
||
Run: `cd web-admin && pnpm build`
|
||
Expected: 构建成功,无 TypeScript 错误
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add web-admin/src/api/temp-qc-work-order.ts web-admin/src/views/quality-inspection/temp-qc-work-order/index.vue
|
||
git commit -m "feat(temp-qc): add temp QC work order frontend page"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 8: 前端 — 临时生产工单页面
|
||
|
||
**Files:**
|
||
- Create: `web-admin/src/api/temp-production-work-order.ts`
|
||
- Create: `web-admin/src/views/production/temp-production-work-order/index.vue`
|
||
|
||
- [ ] **Step 1: 创建 API 文件**
|
||
|
||
Create `web-admin/src/api/temp-production-work-order.ts`,参照 `api/production-work-order.ts` 简化版:
|
||
|
||
```typescript
|
||
import request from '@/utils/http'
|
||
|
||
type PageList<T> = {
|
||
list: T[]
|
||
total: number
|
||
page: number
|
||
pageSize: number
|
||
totalPages: number
|
||
}
|
||
|
||
export type TempProductionWorkOrder = {
|
||
id: string
|
||
workOrderNo: string
|
||
workOrderStatus: string
|
||
configuredTime?: string
|
||
configuredBy?: string
|
||
remark?: string
|
||
createTime?: string
|
||
updateTime?: string
|
||
}
|
||
|
||
export type TempProductionWorkOrderDetail = TempProductionWorkOrder & {
|
||
tasks?: Array<{
|
||
id: string
|
||
taskNo: string
|
||
taskType: string
|
||
taskName?: string
|
||
taskStatus: string
|
||
}>
|
||
}
|
||
|
||
export function fetchTempProductionWorkOrderList(params?: {
|
||
page?: number
|
||
pageSize?: number
|
||
keyword?: string
|
||
workOrderStatus?: string
|
||
}) {
|
||
return request.get<PageList<TempProductionWorkOrder>>({
|
||
url: '/web/admin/temp-production-work-orders',
|
||
params
|
||
})
|
||
}
|
||
|
||
export function fetchTempProductionWorkOrderDetail(id: string) {
|
||
return request.get<TempProductionWorkOrderDetail>({
|
||
url: `/web/admin/temp-production-work-orders/${id}`
|
||
})
|
||
}
|
||
|
||
export function fetchCreateTempProductionWorkOrder(data: { remark?: string }) {
|
||
return request.post<TempProductionWorkOrder>({
|
||
url: '/web/admin/temp-production-work-orders',
|
||
data
|
||
})
|
||
}
|
||
|
||
export function fetchConfigureTempProductionWorkOrder(
|
||
id: string,
|
||
data: {
|
||
taskName?: string
|
||
taskType?: string
|
||
routeId?: string
|
||
description?: string
|
||
remark?: string
|
||
}
|
||
) {
|
||
return request.post<TempProductionWorkOrder>({
|
||
url: `/web/admin/temp-production-work-orders/${id}/configure`,
|
||
data
|
||
})
|
||
}
|
||
|
||
export function fetchDeleteTempProductionWorkOrder(id: string) {
|
||
return request.del({ url: `/web/admin/temp-production-work-orders/${id}` })
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: 创建列表页面**
|
||
|
||
Create `web-admin/src/views/production/temp-production-work-order/index.vue`
|
||
|
||
参照模板页 `src/views/system/unit/index.vue`(标准列表页),包含:
|
||
- **列表列**:工单号、状态(Tag: dpz→info/jxz→primary/ywc→success)、配置时间、创建时间、操作
|
||
- **创建弹窗**:仅备注字段
|
||
- **配置弹窗**:与入库生产工单的 DispatchTaskDialog 类似,包含任务名称(task_name)、任务类型(task_type cell_storage/outbound)、**工艺路线选择(route_id,选择后自动克隆步骤)**、描述(description)、备注(remark)。参照 `views/production/production-work-order/DispatchTaskDialog.vue` 的表单结构。
|
||
- **详情弹窗**:工单基本信息 + 关联任务列表
|
||
- **遵循 UI 规范**
|
||
|
||
- [ ] **Step 3: 验证前端编译**
|
||
|
||
Run: `cd web-admin && pnpm build`
|
||
Expected: 构建成功
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add web-admin/src/api/temp-production-work-order.ts web-admin/src/views/production/temp-production-work-order/index.vue
|
||
git commit -m "feat(temp-production): add temp production work order frontend page"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 9: 前端 — 现有任务列表新增"来源"Tag 列
|
||
|
||
**Files:**
|
||
- Modify: `web-admin/src/api/qc-task.ts`
|
||
- Modify: `web-admin/src/views/quality-inspection/qc-task/index.vue`
|
||
- Modify: `web-admin/src/api/production-task.ts`
|
||
- Modify: `web-admin/src/views/production/production-task/index.vue`
|
||
|
||
- [ ] **Step 1: qc-task.ts 类型新增 orderSource**
|
||
|
||
在 `QcTask` 类型定义中添加:
|
||
|
||
```typescript
|
||
export type QcTask = {
|
||
// ... 现有字段
|
||
orderSource?: string // 'inbound' | 'temporary'
|
||
// ...
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: 质检任务列表新增"来源"列**
|
||
|
||
在 `quality-inspection/qc-task/index.vue` 的 el-table 中添加列:
|
||
|
||
```vue
|
||
<el-table-column label="来源" prop="orderSource" min-width="100">
|
||
<template #default="{ row }">
|
||
<el-tag
|
||
:type="row.orderSource === 'temporary' ? 'warning' : 'success'"
|
||
size="small"
|
||
>
|
||
{{ row.orderSource === 'temporary' ? '临时' : '入库' }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
```
|
||
|
||
位置放在"工单号"列之后。
|
||
|
||
- [ ] **Step 3: production-task.ts 类型新增 orderSource**
|
||
|
||
同 Step 1,在 ProductionTask 类型中添加 `orderSource`。
|
||
|
||
- [ ] **Step 4: 生产任务列表新增"来源"列**
|
||
|
||
同 Step 2,在 `production/production-task/index.vue` 的 el-table 中添加来源 Tag 列。
|
||
|
||
- [ ] **Step 5: 验证前端编译**
|
||
|
||
Run: `cd web-admin && pnpm build`
|
||
Expected: 构建成功
|
||
|
||
- [ ] **Step 6: Commit**
|
||
|
||
```bash
|
||
git add web-admin/src/api/qc-task.ts web-admin/src/views/quality-inspection/qc-task/index.vue web-admin/src/api/production-task.ts web-admin/src/views/production/production-task/index.vue
|
||
git commit -m "feat(tasks): add orderSource column with tag display to task lists"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 10: 菜单配置 + 最终验证
|
||
|
||
**Files:**
|
||
- Modify: 数据库 `sys_menu` 表(通过 SQL INSERT)
|
||
|
||
- [ ] **Step 1: 插入菜单记录**
|
||
|
||
在数据库中执行 SQL,为临时质检工单和临时生产工单各插入菜单记录。具体 menu_id 和 parent_id 需要根据现有菜单树确定。INSERT 语句参考现有菜单数据格式。
|
||
|
||
- [ ] **Step 2: 全栈验证**
|
||
|
||
1. 启动后端:`cd backend && source venv/bin/activate && ./start-local.sh`
|
||
2. 启动前端:`cd web-admin && pnpm dev`
|
||
3. 登录系统,导航到临时质检工单页面
|
||
4. 测试:创建工单 → 配置检测项目 → 查看生成任务 → 完成任务 → 工单自动完成
|
||
5. 导航到临时生产工单页面
|
||
6. 测试:创建工单 → 配置生成任务 → 查看任务
|
||
7. 导航到质检任务/生产任务页面,确认"来源"Tag 列正确显示
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add docs/sql/temp_work_order_tables.sql
|
||
git commit -m "feat(menu): add temp work order menu items"
|
||
```
|
||
|
||
---
|
||
|
||
## Self-Review Checklist
|
||
|
||
- [x] **Spec coverage**: 每个设计文档章节都有对应 Task(数据库→Task1/2,后端→Task3/4/5/6,前端→Task7/8/9,菜单→Task10)
|
||
- [x] **Placeholder scan**: 无 TBD/TODO,所有步骤有具体代码或指令
|
||
- [x] **Type consistency**: order_source 字段名在 model/schema/crud/api/typescript 中一致使用
|