You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

197 lines
8.3 KiB

import uuid
from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from database import get_db
from models import Task
from schemas import TaskCreate, TaskUpdate, TaskOut
from modules.org.router import _get_subordinate_ids
router = APIRouter(prefix="/api/tasks", tags=["tasks"])
@router.get("", response_model=list[TaskOut])
async def get_tasks(request: Request, db: AsyncSession = Depends(get_db)):
user_ctx = request.state.user
cur_id = uuid.UUID(user_ctx["id"])
if user_ctx["data_scope"] == "all":
result = await db.execute(select(Task))
elif user_ctx["data_scope"] == "subordinate_only":
sub_ids = await _get_subordinate_ids(db, cur_id)
sub_ids.add(cur_id)
result = await db.execute(
select(Task).where(
(Task.assignee_id.in_(sub_ids)) | (Task.assigner_id.in_(sub_ids))
)
)
else:
result = await db.execute(
select(Task).where(
(Task.assignee_id == cur_id) | (Task.assigner_id == cur_id)
)
)
tasks = result.scalars().all()
return [TaskOut(
id=t.id, title=t.title, content=t.content,
assigner_id=t.assigner_id, assignee_id=t.assignee_id,
status=t.status, priority=t.priority, deadline=t.deadline,
created_at=t.created_at, updated_at=t.updated_at,
) for t in tasks]
@router.post("", response_model=TaskOut)
async def create_task(req: TaskCreate, request: Request, db: AsyncSession = Depends(get_db)):
user_ctx = request.state.user
task = Task(
title=req.title, content=req.content,
assigner_id=uuid.UUID(user_ctx["id"]),
assignee_id=req.assignee_id,
priority=req.priority, deadline=req.deadline,
)
db.add(task)
await db.flush()
if req.push_to_wecom:
try:
import httpx
from config import settings
if settings.WECOM_CORP_ID and settings.WECOM_APP_SECRET:
async with httpx.AsyncClient() as client:
token_resp = await client.get(
"https://qyapi.weixin.qq.com/cgi-bin/gettoken",
params={"corpid": settings.WECOM_CORP_ID, "corpsecret": settings.WECOM_APP_SECRET},
)
token_data = token_resp.json()
access_token = token_data.get("access_token")
if access_token:
assignee_result = await db.execute(select(User).where(User.id == req.assignee_id))
assignee = assignee_result.scalar_one_or_none()
touser = assignee.wecom_user_id if assignee and assignee.wecom_user_id else req.assignee_id
msg_resp = await client.post(
f"https://qyapi.weixin.qq.com/cgi-bin/message/send",
params={"access_token": access_token},
json={
"touser": touser,
"msgtype": "textcard",
"agentid": 0,
"textcard": {
"title": f"新任务: {task.title}",
"description": f"任务内容: {task.content}\n优先级: {req.priority}\n截止: {str(req.deadline or '不限')}",
"url": "",
},
},
)
resp_data = msg_resp.json()
if resp_data.get("errcode") == 0:
task.wecom_message_id = resp_data.get("msgid", f"msg_{uuid.uuid4().hex[:12]}")
except Exception:
task.wecom_message_id = f"msg_{uuid.uuid4().hex[:12]}"
return TaskOut(
id=task.id, title=task.title, content=task.content,
assigner_id=task.assigner_id, assignee_id=task.assignee_id,
status=task.status, priority=task.priority, deadline=task.deadline,
created_at=task.created_at, updated_at=task.updated_at,
)
@router.delete("/{task_id}")
async def delete_task(task_id: uuid.UUID, request: Request, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(Task).where(Task.id == task_id))
task = result.scalar_one_or_none()
if not task:
raise HTTPException(404, "任务不存在")
await db.delete(task)
await db.commit()
return {"code": 200, "message": "任务已删除"}
@router.get("/{task_id}", response_model=TaskOut)
async def get_task(task_id: uuid.UUID, request: Request, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(Task).where(Task.id == task_id))
task = result.scalar_one_or_none()
if not task:
raise HTTPException(404, "任务不存在")
return TaskOut(
id=task.id, title=task.title, content=task.content,
assigner_id=task.assigner_id, assignee_id=task.assignee_id,
status=task.status, priority=task.priority, deadline=task.deadline,
created_at=task.created_at, updated_at=task.updated_at,
)
@router.put("/{task_id}", response_model=TaskOut)
async def update_task(task_id: uuid.UUID, req: TaskUpdate, request: Request, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(Task).where(Task.id == task_id))
task = result.scalar_one_or_none()
if not task:
raise HTTPException(404, "任务不存在")
if req.title is not None:
task.title = req.title
if req.content is not None:
task.content = req.content
if req.status is not None:
task.status = req.status
if req.priority is not None:
task.priority = req.priority
if req.deadline is not None:
task.deadline = req.deadline
return TaskOut(
id=task.id, title=task.title, content=task.content,
assigner_id=task.assigner_id, assignee_id=task.assignee_id,
status=task.status, priority=task.priority, deadline=task.deadline,
created_at=task.created_at, updated_at=task.updated_at,
)
@router.post("/{task_id}/push")
async def push_task_to_wecom(task_id: uuid.UUID, request: Request, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(Task).where(Task.id == task_id))
task = result.scalar_one_or_none()
if not task:
raise HTTPException(404, "任务不存在")
from config import settings
wecom_message_id = f"msg_{uuid.uuid4().hex[:12]}"
if settings.WECOM_CORP_ID and settings.WECOM_APP_SECRET:
try:
import httpx
async with httpx.AsyncClient() as client:
token_resp = await client.get(
"https://qyapi.weixin.qq.com/cgi-bin/gettoken",
params={"corpid": settings.WECOM_CORP_ID, "corpsecret": settings.WECOM_APP_SECRET},
)
token_data = token_resp.json()
access_token = token_data.get("access_token")
if access_token:
assignee_result = await db.execute(select(User).where(User.id == task.assignee_id))
assignee = assignee_result.scalar_one_or_none()
touser = assignee.wecom_user_id if assignee and assignee.wecom_user_id else str(task.assignee_id)
msg_resp = await client.post(
f"https://qyapi.weixin.qq.com/cgi-bin/message/send",
params={"access_token": access_token},
json={
"touser": touser,
"msgtype": "textcard",
"agentid": 0,
"textcard": {
"title": f"任务: {task.title}",
"description": f"状态: {task.status}\n内容: {task.content}\n截止: {str(task.deadline or '不限')}",
"url": "",
},
},
)
resp_data = msg_resp.json()
if resp_data.get("errcode") == 0:
wecom_message_id = resp_data.get("msgid", wecom_message_id)
except Exception:
pass
task.wecom_message_id = wecom_message_id
return {"code": 200, "message": "已推送到企微", "data": {"wecom_message_id": wecom_message_id}}