Files
crm_project/backend/app/api/v1/endpoints/logs.py
T
hankin 423baff73b v0.1.0: CRM/ERP 系统内测版本 - 安全加固完成
- Docker bridge 网络隔离(8000 端口封死)
- Gunicorn 4 Worker 多进程
- Alembic 数据库迁移基线
- 日志轮转 20m×3
- JWT 密钥 + DB 密码 + CORS 收紧
- 3-2-1 备份链路(NAS + R740-B 冷备)
- 连接池 pool_pre_ping + pool_recycle=3600
2026-03-16 07:31:37 +00:00

82 lines
2.4 KiB
Python

# -*- coding: utf-8 -*-
"""
客户沟通日志 API
POST /api/v1/logs - 提交日志并触发后台 AI 标签提取
"""
import uuid
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, status
from pydantic import BaseModel, Field
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.deps import get_current_user
from app.core.database import get_db
from app.models.crm_business import CustomerLog
from app.services.ai_workflow import process_log_with_ai
router = APIRouter()
# ---- 请求/响应模型 ----
class LogCreate(BaseModel):
"""提交沟通日志请求"""
customer_id: uuid.UUID = Field(..., description="关联客户 ID")
content: str = Field(..., min_length=5, max_length=5000, description="沟通日志内容")
class LogResponse(BaseModel):
"""提交成功响应"""
id: uuid.UUID
message: str = "日志已提交,AI 正在后台分析标签和待办"
# ---- 路由 ----
@router.post(
"",
response_model=LogResponse,
status_code=status.HTTP_200_OK,
summary="提交客户沟通日志",
tags=["客户日志"],
)
async def create_customer_log(
body: LogCreate,
background_tasks: BackgroundTasks,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(get_current_user),
):
"""
接收前端提交的客户沟通日志:
1. 立即存入 customer_logs 表
2. 将 AI 标签提取任务加入 BackgroundTasks 后台队列
3. 立即返回 200 OK(不等待 AI 处理完成)
AI 后台任务会:
- 调用 qwen3:14b 分析日志内容
- 自动提取最多 3 个客户标签 → customer_tags
- 自动生成 1 个跟进待办 → follow_up_todos
"""
# Step 1: 立即写入日志记录
log = CustomerLog(
customer_id=body.customer_id,
content=body.content,
)
db.add(log)
await db.flush()
await db.refresh(log)
# Step 2: 将 AI 处理加入后台队列
# *** 关键:传入 log.id / body.content / body.customer_id 三个值 ***
# process_log_with_ai 会创建独立的 DB Session,不与当前请求的 db 共享
background_tasks.add_task(
process_log_with_ai,
log_id=log.id,
content=body.content,
customer_id=body.customer_id,
)
# Step 3: 立即返回(不等待 AI)
return LogResponse(id=log.id)