Files
Neo-ZQYY/apps/backend/app/routers/xcx_tasks.py
2026-04-10 06:24:13 +08:00

118 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
小程序任务路由 —— 任务列表、任务详情、置顶、放弃、取消放弃。
端点清单:
- GET /api/xcx/tasks — 获取任务列表 + 绩效概览TASK-1
- GET /api/xcx/tasks/by-member/{member_id} — 按会员查询最高优先级 active 任务详情
- GET /api/xcx/tasks/{task_id} — 获取任务详情完整版TASK-2
- POST /api/xcx/tasks/{id}/pin — 置顶任务
- POST /api/xcx/tasks/{id}/unpin — 取消置顶
- POST /api/xcx/tasks/{id}/abandon — 放弃任务
- POST /api/xcx/tasks/{id}/restore — 恢复任务
所有端点均需 JWTapproved 状态)。
回访任务通过提交备注自动完成note_service不提供手动完成接口。
"""
from __future__ import annotations
from fastapi import APIRouter, Depends, Query
from app.auth.dependencies import CurrentUser
from app.middleware.permission import require_approved, require_permission
from app.schemas.xcx_tasks import (
AbandonRequest,
TaskDetailResponse,
TaskListResponse,
)
from app.services import task_manager
from app.trace.decorators import trace_service
router = APIRouter(prefix="/api/xcx/tasks", tags=["小程序任务"])
@router.get("", response_model=TaskListResponse)
@trace_service("获取任务列表", "Get task list")
async def get_tasks(
status: str = Query("pending", pattern="^(pending|completed|abandoned)$"),
page: int = Query(1, ge=1),
page_size: int = Query(20, ge=1, le=200),
# CHANGE 2026-03-27 | 权限改造 W4统一权限保护
user: CurrentUser = Depends(require_permission("view_tasks")),
):
"""获取任务列表 + 绩效概览。"""
return await task_manager.get_task_list_v2(
user.user_id, user.site_id, status, page, page_size
)
@router.get("/by-member/{member_id}", response_model=TaskDetailResponse)
@trace_service("按会员查询任务详情", "Get task detail by member")
async def get_task_by_member(
member_id: int,
user: CurrentUser = Depends(require_permission("view_tasks")),
):
"""按 member_id 查询当前助教的最高优先级 active 任务详情。"""
return await task_manager.get_task_by_member(
member_id, user.user_id, user.site_id
)
@router.get("/{task_id}", response_model=TaskDetailResponse)
@trace_service("获取任务详情", "Get task detail")
async def get_task_detail(
task_id: int,
user: CurrentUser = Depends(require_permission("view_tasks")),
):
"""获取任务详情完整版。"""
return await task_manager.get_task_detail(
task_id, user.user_id, user.site_id
)
@router.post("/{task_id}/pin")
@trace_service("置顶任务", "Pin task")
async def pin_task(
task_id: int,
user: CurrentUser = Depends(require_permission("view_tasks")),
):
"""置顶任务。"""
result = await task_manager.pin_task(task_id, user.user_id, user.site_id)
return {"is_pinned": result["is_pinned"]}
@router.post("/{task_id}/unpin")
@trace_service("取消置顶", "Unpin task")
async def unpin_task(
task_id: int,
user: CurrentUser = Depends(require_permission("view_tasks")),
):
"""取消置顶。"""
result = await task_manager.unpin_task(task_id, user.user_id, user.site_id)
return {"is_pinned": result["is_pinned"]}
@router.post("/{task_id}/abandon")
@trace_service("放弃任务", "Abandon task")
async def abandon_task(
task_id: int,
body: AbandonRequest,
user: CurrentUser = Depends(require_permission("view_tasks")),
):
"""放弃任务(需填写原因)。"""
return await task_manager.abandon_task(
task_id, user.user_id, user.site_id, body.reason
)
@router.post("/{task_id}/restore")
@trace_service("恢复任务", "Restore task")
async def restore_task(
task_id: int,
user: CurrentUser = Depends(require_permission("view_tasks")),
):
"""取消放弃,恢复为活跃状态。"""
return await task_manager.cancel_abandon(task_id, user.user_id, user.site_id)