# 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 task_type: str task_color: str bg_class: str status: str last_service: str | None = None metrics: list[MetricItem] = [] class FavoriteCoach(CamelModel): # CHANGE 2026-03-20 | M4 修复: emoji 注释与 P6 权威定义对齐(4 级映射) # intent: 注释应反映 compute_heart_icon() 的实际 4 级映射(💖🧡💛💙) emoji: str # 💖 / 🧡 / 💛 / 💙 name: 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: float 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: int | 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 total_amount: float total_orig_price: float pay_method: str recharge_amount: float | None = None class RetentionClue(CamelModel): type: str text: str class CustomerNote(CamelModel): id: int tag_label: 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 records: list[ServiceRecordItem] = [] has_more: bool = False