Files
Neo-ZQYY/apps/backend/app/schemas/xcx_tasks.py
Neo 2dfc926f96 feat(ai): W1-AI-CLOSURE 超级 Sprint — 9 APP 全链路收口 + chat 上下文真激活
Phase 2.3 chat 上下文捕获链路从未真正激活到完整工作:
- 14 处 ai-float-button 补 sourcePage,chat.ts 三分支同步设 pageFilters.contextId
- 后端 page_context 4 层 BUG 修(列名错位 + RLS site_id 未重设)
- xcx_chat filters.pop 破坏 body.page_context 引用 — dict() 浅拷贝隔离
- chat 流式 markdown 实时解析(表格/标题/列表/加粗 + KPI 富卡)
- reference_card KPI 富卡接入 SSE 路径,db 真写入
- 维客线索 source 显示规则:AI 来源用机器人 icon 替代长文字

数据库:
- public.member_retention_clue 加 emoji + runtime_mode + sandbox_instance_id
- biz.ai_run_logs 加 assistant_id + 复合索引
- chk_ai_cache_type CHECK 约束 8 类应用名
- cache_type / app_type 命名统一(app6_note / app7_customer / app8_consolidation)
- 历史 emoji 抽取脚本 44/44 成功

后端 silent failure 修:
- cleanup_service WHERE app_type → cache_type(90 天清理 + 20K 上限重新生效)
- _build_ai_insight 字段错位修复(app4 → app7 + 字段对齐 prompt schema)
- task_manager talkingPoints 改 app5_tactics + tactics 字段
- task_manager aiSuggestion 改取 one_line_summary
- cache_service.CACHE_EXPIRY_DAYS 加 app2a_finance_area
- WS /ws/ai-cache 加 token + JWT + site_id 校验(P0 信息泄露漏洞)
- internal_ai token 改 hmac.compare_digest

工具/文档:
- main.py 加 RotatingFileHandler logs/backend.log + uvicorn /health 过滤
- 新建 utils/clue_category.py(VI 6 类配色 + emoji fallback + source 显示规则)
- 新建 utils/markdown.ts(轻量 md 转 rich-text 解析 + streaming 容错)
- audit + 数据库变更说明 + backlog §七 #14 收口 + #15-#38 残余子任务
- backlog 追加 §十一 App1 参数/MCP/沙箱审计 + §十二 百炼/SQL MCP 主任务线

实地 MCP 走查:14 入口数据层 + 5 代表入口 sourcePage 注入 + customer-detail 全模块 + chat md 渲染 + reference_card 富卡 都已验证。9 项预先 BUG/UX 登记 §七 #29-#38 后续修复。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:39:07 +08:00

189 lines
4.4 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.
"""
小程序任务相关 Pydantic 模型。
覆盖:任务列表项、任务详情、绩效概览、放弃请求等场景。
"""
from __future__ import annotations
from pydantic import Field
from app.schemas.base import CamelModel
class TaskListItem(CamelModel):
"""任务列表项(含客户信息 + RS 指数 + 爱心 icon"""
id: int
task_type: str
status: str
priority_score: float | None
is_pinned: bool
expires_at: str | None
created_at: str
# 客户信息FDW 读取)
member_id: int
member_name: str | None
member_phone: str | None
# RS 指数 + 爱心 icon
rs_score: float | None
heart_icon: str # 💖 / 🧡 / 💛 / 💙
# 放弃原因(仅 abandoned 任务有值)
abandon_reason: str | None = None
class AbandonRequest(CamelModel):
"""放弃任务请求reason 必填)。"""
reason: str = Field(..., min_length=1, description="放弃原因(必填)")
# ---------------------------------------------------------------------------
# RNS1.1 扩展模型
# ---------------------------------------------------------------------------
class PerformanceSummary(CamelModel):
"""绩效概览(附带在任务列表响应中)。"""
total_hours: float
total_income: float
total_customers: int
month_label: str
tier_nodes: list[float]
basic_hours: float
bonus_hours: float
current_tier: int
next_tier_hours: float
tier_completed: bool
bonus_money: float
income_trend: str
income_trend_dir: str # 'up' | 'down'
prev_month: str
current_tier_label: str
class TaskItem(CamelModel):
"""任务列表项(扩展版)。"""
id: int
customer_name: str
customer_avatar: str
task_type: str
task_type_label: str
deadline: str | None
heart_score: float
hobbies: list[str]
is_pinned: bool
has_note: bool
status: str
last_visit_days: int | None = None
balance: float | None = None
ai_suggestion: str | None = None
expected_days: int | None = None
ideal_interval_days: int | None = None
# CHANGE 2026-03-27 | 近60天服务汇总口径同 task-detail serviceSummary
recent60d_hours: float = 0.0
recent60d_income: float = 0.0
class TaskListResponse(CamelModel):
"""TASK-1 响应。"""
items: list[TaskItem]
total: int
page: int
page_size: int
performance: PerformanceSummary
class RetentionClue(CamelModel):
"""维客线索。"""
tag: str
tag_color: str
emoji: str
text: str
source: str # 'manual' | 'ai_consumption' | 'ai_note'
desc: str | None = None
class ServiceRecord(CamelModel):
"""服务记录。"""
table: str | None = None
type: str
type_class: str # 'basic' | 'vip' | 'tip' | 'recharge' | 'incentive'
record_type: str | None = None # 'course' | 'recharge'
duration: float
duration_raw: float | None = None
income: float
is_estimate: bool | None = None
drinks: str | None = None
date: str
class TacticItem(CamelModel):
"""App5 话术单条(场景 + 话术)。
W1-AI-CLOSURE 组 3 修正:talking_points 从 list[str] 改为 list[TacticItem],
对齐 App5Result.tactics(prompt schema 权威 — 之前查的 cache_type
'app5_talking_points' 与字段 'talking_points' 全是不存在的幽灵命名,P0-6)。
"""
scenario: str
script: str
class AiAnalysis(CamelModel):
"""AI 分析结果(对齐 App4Result one_line_summary + action_suggestions)。"""
summary: str
suggestions: list[str]
class NoteItem(CamelModel):
"""备注项。"""
id: int
content: str
tag_type: str
tag_label: str
created_at: str
score: int | None = None
class ServiceSummary(CamelModel):
"""服务记录摘要。"""
total_hours: float
total_income: float
avg_income: float
class TaskDetailResponse(CamelModel):
"""TASK-2 响应。"""
# 基础信息
id: int
customer_name: str
customer_phone: str | None = None
customer_avatar: str
task_type: str
task_type_label: str
deadline: str | None
heart_score: float
hobbies: list[str]
is_pinned: bool
has_note: bool
status: str
customer_id: int
balance: float | None = None
# 扩展模块
retention_clues: list[RetentionClue]
talking_points: list[TacticItem]
service_summary: ServiceSummary
service_records: list[ServiceRecord]
ai_analysis: AiAnalysis
notes: list[NoteItem]