# AI_CHANGELOG # - 2026-03-20 | Prompt: M4 emoji 注释修复 | FavoriteCoach.emoji 注释从旧 2 级(💖/💛) # 改为 P6 权威定义的 4 级(💖/🧡/💛/💙),与 compute_heart_icon() 实际逻辑对齐。 from __future__ import annotations from app.schemas.base import CamelModel class AiStrategy(CamelModel): color: str text: str class AiInsight(CamelModel): summary: str = "" strategies: list[AiStrategy] = [] class MetricItem(CamelModel): label: str value: str color: str | None = None class CoachTask(CamelModel): name: str level: str # star / senior / middle / junior level_color: str heart_score: float = 0.0 # CHANGE 2026-03-29 | RSI 关系指数,用于爱心标识 task_type: str task_color: str bg_class: str status: str last_service: str | None = None metrics: list[MetricItem] = [] class FavoriteCoach(CamelModel): emoji: str name: str heart_score: float = 0.0 level: str = "" relation_index: str index_color: str bg_class: str stats: list[MetricItem] = [] class CoachServiceItem(CamelModel): name: str level: str level_color: str course_type: str # "基础课" / "激励课" hours: str # "2.5h" 格式 perf_hours: float | None = None fee: float class ConsumptionRecord(CamelModel): id: str type: str # table / shop / recharge date: str table_name: str | None = None start_time: str | None = None end_time: str | None = None duration: str | None = None table_fee: float | None = None table_orig_price: float | None = None coaches: list[CoachServiceItem] = [] food_amount: float | None = None food_orig_price: float | None = None food_detail: str | None = None total_amount: float total_orig_price: float | None = None pay_method: str | None = None recharge_amount: float | None = None class RetentionClue(CamelModel): type: str text: str class CustomerNote(CamelModel): id: int tag_label: str creator_name: str = "" creator_role: str = "" created_at: str content: str class CustomerDetailResponse(CamelModel): """CUST-1 响应。""" # 基础信息 id: int name: str phone: str phone_full: str avatar: str member_level: str relation_index: str tags: list[str] = [] # Banner 概览 balance: float | None = None consumption_60d: float | None = None ideal_interval: int | None = None days_since_visit: int | None = None # 扩展模块 ai_insight: AiInsight = AiInsight() coach_tasks: list[CoachTask] = [] favorite_coaches: list[FavoriteCoach] = [] retention_clues: list[RetentionClue] = [] consumption_records: list[ConsumptionRecord] = [] notes: list[CustomerNote] = [] class ServiceRecordItem(CamelModel): id: str date: str time_range: str | None = None table: str | None = None type: str type_class: str record_type: str | None = None # course / recharge duration: float duration_raw: float | None = None income: float is_estimate: bool = False drinks: str | None = None class CustomerRecordsResponse(CamelModel): """CUST-2 响应。""" customer_name: str customer_phone: str customer_phone_full: str relation_index: str tables: list[dict] = [] total_service_count: int month_count: int month_hours: float month_income: float = 0.0 records: list[ServiceRecordItem] = [] has_more: bool = False class CustomerConsumptionRecordsResponse(CamelModel): """CUST-3 响应:客户消费记录(按月)。""" # Banner id: int name: str phone: str phone_full: str balance: float | None = None consumption_60d: float | None = None ideal_interval: int | None = None days_since_visit: int | None = None # 月度汇总 visit_count: int = 0 consume_total: float = 0.0 recharge_total: float = 0.0 # 消费记录 records: list[ConsumptionRecord] = []