feat: 双Token认证(Access 2h/Refresh 7d) + 通知系统(转交/驳回自动推送)

This commit is contained in:
2026-08-07 11:44:04 +08:00
parent dc97a7385f
commit b71c5a2d07
16 changed files with 426 additions and 41 deletions

View File

@ -7,6 +7,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from app.models.task import Task, TaskRecord, TASK_STATUS_PENDING, TASK_STATUS_WIP, TASK_STATUS_COMPLETED, TASK_STATUS_REJECTED, TASK_STATUS_CANCELED, TASK_STATUS_ARCHIVED
from app.models.notification import Notification, NOTIFY_TRANSFER, NOTIFY_REJECT
from app.core.time_utils import get_beijing_time
from app.models.product import Product
from app.models.task_log import TaskLog
@ -288,6 +289,12 @@ async def end_task(
"""
task = await _get_task_or_404(db, task_id)
# 校验:仅 SPAWN 协助分支可以结束主分支TRANSFER/RECOVERY不能通过此接口终止
if not task.parent_task_id:
raise HTTPException(status_code=409, detail="根任务无法结束,请使用完工转交")
if task.task_type != "SPAWN":
raise HTTPException(status_code=409, detail="仅协助分支可以结束,主分支请使用完工转交")
# 校验:必须等待所有协助分支完成
await _check_children_done(db, task_id)
@ -562,7 +569,7 @@ async def reject_task(
task_name=task.task_name,
assignee_id=rework_assignee_id,
status=TASK_STATUS_PENDING,
task_type="TRANSFER",
task_type=task.task_type, # 🚀 继承被驳回任务的基因:主线→主线,协助→协助
notify_parent_on_complete=task.notify_parent_on_complete,
is_rework=True,
)
@ -576,6 +583,24 @@ async def reject_task(
remark=f"返工任务(驳回自「{task.task_name}」,原因: {request.reason}),分配给 {rework_assignee_id}",
)
# 🔔 通知:品质驳回
product_sn = ""
try:
product_result = await db.execute(select(Product).where(Product.id == task.product_id))
p = product_result.scalar_one_or_none()
if p:
product_sn = p.serial_number or ""
except Exception:
pass
if rework_assignee_id:
db.add(Notification(
user_id=rework_assignee_id,
title="🔴 品质驳回提醒",
content=f"产品 [{product_sn}] 的「{task.task_name}」被驳回,原因: {request.reason}",
type=NOTIFY_REJECT,
task_id=rework_task.id,
))
await db.commit()
await db.refresh(task)
@ -697,6 +722,21 @@ async def transfer_task(
operator_id=operator_id,
remark=request.note or f"由任务「{task.task_name}」裂变转交创建,分配给 {nt.assignee_id}",
)
# 🔔 通知:新任务派发
if nt.assignee_id:
product_sn = ""
try:
if product:
product_sn = product.serial_number or ""
except Exception:
pass
db.add(Notification(
user_id=nt.assignee_id,
title=f"🟢 新任务派发",
content=f"产品 [{product_sn}] 的「{nt.task_name}」任务已分配给你",
type=NOTIFY_TRANSFER,
task_id=nt.id,
))
# --- 更新 Product 的 current_location_id ---
product_result = await db.execute(