""" 维客线索路由。 - POST /api/retention-clue — 提交维客线索(UPSERT) - GET /api/retention-clue/{member_id} — 查询某会员的全部维客线索 - DELETE /api/retention-clue/{clue_id} — 删除单条线索 """ import logging from fastapi import APIRouter, HTTPException, status from app.database import get_connection from app.schemas.member_retention_clue import RetentionClueSubmit, RetentionClueOut logger = logging.getLogger(__name__) router = APIRouter(prefix="/api", tags=["维客线索"]) @router.post("/retention-clue") async def submit_retention_clue(body: RetentionClueSubmit): """ 提交维客线索(INSERT)。 同一会员可有多条不同大类的线索。 """ sql = """ INSERT INTO member_retention_clue (member_id, category, summary, detail, recorded_by_assistant_id, recorded_by_name, site_id, source) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) RETURNING id """ conn = get_connection() try: with conn.cursor() as cur: cur.execute(sql, ( body.member_id, body.category.value, body.summary, body.detail, body.recorded_by_assistant_id, body.recorded_by_name, body.site_id, body.source.value, )) row = cur.fetchone() conn.commit() return {"status": "ok", "id": row[0] if row else None} except Exception: conn.rollback() logger.exception("维客线索写入失败: member_id=%s", body.member_id) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="线索提交失败,请稍后重试", ) finally: conn.close() @router.get("/retention-clue/{member_id}", response_model=list[RetentionClueOut]) async def get_retention_clues(member_id: int, site_id: int): """查询某会员的全部维客线索,按录入时间倒序。""" sql = """ SELECT id, member_id, category, summary, detail, recorded_by_assistant_id, recorded_by_name, recorded_at, site_id, source FROM member_retention_clue WHERE member_id = %s AND site_id = %s ORDER BY recorded_at DESC """ conn = get_connection() try: with conn.cursor() as cur: cur.execute(sql, (member_id, site_id)) rows = cur.fetchall() cols = [d[0] for d in cur.description] return [dict(zip(cols, r)) for r in rows] finally: conn.close() @router.delete("/retention-clue/{clue_id}") async def delete_retention_clue(clue_id: int): """删除单条维客线索。""" sql = "DELETE FROM member_retention_clue WHERE id = %s" conn = get_connection() try: with conn.cursor() as cur: cur.execute(sql, (clue_id,)) if cur.rowcount == 0: raise HTTPException(status_code=404, detail="线索不存在") conn.commit() return {"status": "ok"} except HTTPException: raise except Exception: conn.rollback() logger.exception("维客线索删除失败: id=%s", clue_id) raise HTTPException(status_code=500, detail="删除失败") finally: conn.close()