"""表达层:渐进式通知体系""" from enum import Enum from dataclasses import dataclass from typing import Optional class NotificationLevel(Enum): BREATHING = 1 # 呼吸光效 — 暗示有想法但不打扰 TITLE = 2 # 标题预览 — "关于你明天的会议..." FULL = 3 # 完整消息 — 用户点击后展开 @dataclass class ExpressionOutput: """表达层输出""" level: NotificationLevel title: str body: str reason: Optional[str] = None animation: str = "fade_in" class ExpressionLayer: """ 表达层:将决策转化为用户可感知的交互 三级通知体系: 1. 呼吸光效:仅暗示,不占用注意力 2. 标题预览:一行文字,表明意向 3. 完整消息:用户决定查看后才展开 """ def __init__(self): self._dismissed: set = set() # 已关闭的消息ID def render(self, message: str, decision_confidence: float, should_show_reason: bool = True) -> ExpressionOutput: """根据决策置信度决定通知等级""" # 高置信度 → 直接完整消息 if decision_confidence > 0.85: level = NotificationLevel.FULL title = self._extract_title(message) reason = None if not should_show_reason else "我有把握你会需要这个" # 中等置信度 → 标题预览 elif decision_confidence > 0.70: level = NotificationLevel.TITLE title = message[:40] + ("..." if len(message) > 40 else "") reason = "不太确定是否合适,你先看看标题?" # 低置信度 → 仅呼吸光效 else: level = NotificationLevel.BREATHING title = "" reason = None return ExpressionOutput( level=level, title=title, body=message if level == NotificationLevel.FULL else title, reason=reason, ) def dismiss(self, message_id: str): self._dismissed.add(message_id) def is_dismissed(self, message_id: str) -> bool: return message_id in self._dismissed @staticmethod def _extract_title(text: str, max_len: int = 30) -> str: """提取消息的第一句作为标题""" first = text.split("。")[0].split("!")[0].split("?")[0] return first[:max_len] + ("..." if len(first) > max_len else "")