血缘锚定法: task_type字段+迁移+三大接口写入+TreeCanvas基于task_type布局
This commit is contained in:
24
backend/alembic/versions/a7b8c9d0e1f2_add_task_type.py
Normal file
24
backend/alembic/versions/a7b8c9d0e1f2_add_task_type.py
Normal file
@ -0,0 +1,24 @@
|
||||
"""add_task_type
|
||||
|
||||
Revision ID: a7b8c9d0e1f2
|
||||
Revises: f6a7b8c9d0e1
|
||||
Create Date: 2026-08-06
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision: str = "a7b8c9d0e1f2"
|
||||
down_revision: Union[str, None] = "f6a7b8c9d0e1"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column("tasks", sa.Column("task_type", sa.String(20), nullable=True, comment="派生类型: TRANSFER/SPAWN/RECOVERY"))
|
||||
# 刷老数据:parent_task_id 非空的默认为 TRANSFER
|
||||
op.execute("UPDATE tasks SET task_type = 'TRANSFER' WHERE parent_task_id IS NOT NULL AND task_type IS NULL")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("tasks", "task_type")
|
||||
@ -70,6 +70,9 @@ class Task(Base):
|
||||
is_rework: Mapped[bool] = mapped_column(
|
||||
Boolean, default=False, comment="是否为返工任务",
|
||||
)
|
||||
task_type: Mapped[str | None] = mapped_column(
|
||||
String(20), nullable=True, comment="任务派生类型: TRANSFER/SPAWN/RECOVERY/null=历史数据",
|
||||
)
|
||||
remark: Mapped[str | None] = mapped_column(
|
||||
String(2000), nullable=True, comment="任务初始描述/交接备注",
|
||||
)
|
||||
|
||||
@ -131,6 +131,7 @@ class TaskResponse(BaseModel):
|
||||
status: str
|
||||
notify_parent_on_complete: bool
|
||||
is_rework: bool = False
|
||||
task_type: str | None = None
|
||||
remark: str | None = None
|
||||
reject_reason: str | None = None
|
||||
received_at: datetime | None = None
|
||||
|
||||
@ -112,6 +112,7 @@ def _to_flat_response(task: Task) -> TaskResponse:
|
||||
status=task.status,
|
||||
notify_parent_on_complete=task.notify_parent_on_complete,
|
||||
is_rework=task.is_rework,
|
||||
task_type=task.task_type,
|
||||
remark=task.remark,
|
||||
reject_reason=task.reject_reason,
|
||||
received_at=task.received_at,
|
||||
@ -143,6 +144,7 @@ def _to_response(task: Task) -> TaskResponse:
|
||||
status=task.status,
|
||||
notify_parent_on_complete=task.notify_parent_on_complete,
|
||||
is_rework=task.is_rework,
|
||||
task_type=task.task_type,
|
||||
remark=task.remark,
|
||||
reject_reason=task.reject_reason,
|
||||
received_at=task.received_at,
|
||||
@ -335,6 +337,7 @@ async def recall_task(
|
||||
task_name=task.task_name,
|
||||
assignee_id=operator_id,
|
||||
status=TASK_STATUS_WIP,
|
||||
task_type="RECOVERY",
|
||||
notify_parent_on_complete=False,
|
||||
is_rework=False,
|
||||
remark=f"撤回「{task.task_name}」后重新接手",
|
||||
@ -377,6 +380,7 @@ async def spawn_subtask(
|
||||
task_name=data.task_name,
|
||||
assignee_id=data.assignee_id,
|
||||
status=TASK_STATUS_PENDING,
|
||||
task_type="SPAWN",
|
||||
notify_parent_on_complete=False,
|
||||
is_rework=False,
|
||||
remark=data.remark or None,
|
||||
@ -671,6 +675,7 @@ async def transfer_task(
|
||||
task_name=task_name,
|
||||
assignee_id=assignee_id,
|
||||
status=TASK_STATUS_PENDING,
|
||||
task_type="TRANSFER",
|
||||
notify_parent_on_complete=False,
|
||||
is_rework=False,
|
||||
remark=request.note or None,
|
||||
|
||||
Reference in New Issue
Block a user