From 7810097b39a004c1bc2cd3961e1b083ccea21718 Mon Sep 17 00:00:00 2001 From: duxingchen Date: Wed, 5 Aug 2026 15:59:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=A8=E6=A0=88=E4=BF=AE=E5=A4=8D:=20remark?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=85=A8=E9=93=BE=E8=B7=AF=E6=89=93=E9=80=9A?= =?UTF-8?q?=20=E2=80=94=20TaskCreate+TransferRequest+transfer=5Ftask+?= =?UTF-8?q?=E5=89=8D=E7=AB=AFPayload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/endpoints/tasks.py | 1 + backend/app/schemas/task.py | 14 +++++++-- backend/app/services/task_service.py | 39 +++++++++++++++----------- track-uniapp/src/pages/scan/detail.vue | 1 + 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/backend/app/api/v1/endpoints/tasks.py b/backend/app/api/v1/endpoints/tasks.py index 99b73d0..6ffe78e 100644 --- a/backend/app/api/v1/endpoints/tasks.py +++ b/backend/app/api/v1/endpoints/tasks.py @@ -11,6 +11,7 @@ from app.schemas.task import ( TaskCompleteRequest, TaskRejectRequest, TaskTransferRequest, + TaskTransferBranch, SubtaskCreate, TaskRecordCreate, TaskResponse, diff --git a/backend/app/schemas/task.py b/backend/app/schemas/task.py index 62d7ba1..3ea2bf8 100644 --- a/backend/app/schemas/task.py +++ b/backend/app/schemas/task.py @@ -18,6 +18,7 @@ class TaskCreate(BaseModel): assignee_id: str | None = Field(None, max_length=64, description="负责人ID(逻辑外键→老系统)") notify_parent_on_complete: bool = Field(False, description="完成后是否通知父任务") is_rework: bool = Field(False, description="是否为返工任务") + remark: str | None = Field(None, max_length=2000, description="初始描述/交接备注") model_config = {"from_attributes": True} @@ -52,10 +53,17 @@ class TaskRejectRequest(BaseModel): reason: str = Field(..., min_length=1, max_length=500, description="驳回原因(必填)") +class TaskTransferBranch(BaseModel): + """裂变分支""" + task_name: str = Field(..., max_length=200, description="工序名称") + assignees: list[str] = Field(..., min_length=1, description="接收人列表") + + class TaskTransferRequest(BaseModel): - """完工裂变转交请求""" - next_assignees: list[str] = Field(..., min_length=1, description="下一道工序接收人列表(必填)") - next_task_name: str = Field(..., min_length=1, max_length=200, description="下一道工序名称(必填)") + """完工裂变转交请求 — 支持多分支 next_tasks 和旧版单线兼容""" + next_assignees: list[str] | None = Field(None, description="[旧版] 下一道工序接收人列表") + next_task_name: str | None = Field(None, max_length=200, description="[旧版] 下一道工序名称") + next_tasks: list[TaskTransferBranch] | None = Field(None, description="[新版] 多分支任务列表") note: str | None = Field(None, description="交接备注") diff --git a/backend/app/services/task_service.py b/backend/app/services/task_service.py index f6ca62c..e928ab5 100644 --- a/backend/app/services/task_service.py +++ b/backend/app/services/task_service.py @@ -397,35 +397,44 @@ async def transfer_task( ) # --- 动作 2:解析下家 & 裂变 --- - has_warehouse = VIRTUAL_WAREHOUSE in request.next_assignees - real_assignees = [a for a in request.next_assignees if a != VIRTUAL_WAREHOUSE] + # 兼容新旧格式 + if request.next_tasks: + branches = [ + (b.task_name, a) + for b in request.next_tasks + for a in (b.assignees or []) + ] + else: + branches = [ + (request.next_task_name, a) + for a in (request.next_assignees or []) + ] - # 判断是否需要裂变(树状结构) - is_fission = len(real_assignees) > 1 + has_warehouse = any(a == VIRTUAL_WAREHOUSE for _, a in branches) + real_branches = [(tn, a) for tn, a in branches if a != VIRTUAL_WAREHOUSE] + + is_fission = len(real_branches) > 1 or (request.next_tasks and len(request.next_tasks) > 1) is_child_task = task.parent_task_id is not None created_tasks: list[Task] = [] - for assignee_id in real_assignees: - # 确定新任务的 parent_task_id(裂变逻辑) + for task_name, assignee_id in real_branches: if is_fission: - # 多路裂变:所有新任务挂在当前任务下,形成树状分支 new_parent_task_id = task.id elif is_child_task: - # 当前任务是子任务,单路转交也保持在同一父任务下 new_parent_task_id = task.parent_task_id else: - # 顶层单路转交:同级 new_parent_task_id = None new_task = Task( product_id=task.product_id, parent_task_id=new_parent_task_id, - task_name=request.next_task_name, + task_name=task_name, assignee_id=assignee_id, status=TASK_STATUS_PENDING, notify_parent_on_complete=False, is_rework=False, + remark=request.note or None, ) db.add(new_task) created_tasks.append(new_task) @@ -438,7 +447,7 @@ async def transfer_task( db, nt.id, action_type="create", operator_id=operator_id, - remark=f"由任务「{task.task_name}」裂变转交创建,分配给 {nt.assignee_id}", + remark=request.note or f"由任务「{task.task_name}」裂变转交创建,分配给 {nt.assignee_id}", ) # --- 更新 Product 的 current_location_id --- @@ -447,12 +456,10 @@ async def transfer_task( ) product = product_result.scalar_one_or_none() if product: - if has_warehouse and not real_assignees: - # 只有仓库,没有实际人员 → 入库 + if has_warehouse and not real_branches: product.current_location_id = VIRTUAL_WAREHOUSE - elif real_assignees: - # 有实际人员 → 指向第一个人员(或可考虑指向多人中的主负责人) - product.current_location_id = real_assignees[0] + elif real_branches: + product.current_location_id = real_branches[0][1] await db.commit() diff --git a/track-uniapp/src/pages/scan/detail.vue b/track-uniapp/src/pages/scan/detail.vue index c7087f9..70dceb8 100644 --- a/track-uniapp/src/pages/scan/detail.vue +++ b/track-uniapp/src/pages/scan/detail.vue @@ -509,6 +509,7 @@ export default { task_name: this.firstForm.task_name, assignee_id: this.firstForm.assignee_id, notify_parent_on_complete: false, + remark: this.firstForm.note.trim() || undefined, }); // 场景B: 立即接收 if (this.firstForm.autoReceive) {