chore: 批量更新v6.5.21版本,整合多项功能修复与优化
主要变更: 1. 新增多风格音效资源与管理文档 2. 修复翻译服务空响应处理与Dio日志异常捕获 3. 完善Web端平台适配与路径获取Stub 4. 优化设备配对与文件传输功能 5. 新增角色命名常量与摇一摇检测器 6. 修复Riverpod dispose与鸿蒙导航路由 7. 新增每日通知服务与流体着色器 8. 优化备份服务与数据管理页面 9. 新增隐私设置附近设备发现选项 10. 重构诗词提供者支持历史记录 11. 完善桌面端构建配置与开发脚本 12. 清理旧版工具部署脚本
This commit is contained in:
@@ -0,0 +1,518 @@
|
||||
# AppBar 角色动画 + 日期栏扩展 归档验收文档
|
||||
|
||||
> 创建时间: 2026-05-20
|
||||
> 更新时间: 2026-05-20
|
||||
> 关联设计: `docs/superpowers/specs/2026-05-20-appbar-character-animation-design.md`
|
||||
> 状态: 开发中
|
||||
> 版本: v14.37.0
|
||||
|
||||
---
|
||||
|
||||
## 一、开发阶段总览
|
||||
|
||||
| 阶段 | 内容 | 状态 | 完成度 |
|
||||
|------|------|------|--------|
|
||||
| P1 | 公共类提取 | ✅ 已完成 | 100% |
|
||||
| P2 | 角色动画组件 | ✅ 已完成 | 100% |
|
||||
| P3 | 日期栏配置系统 | ✅ 已完成 | 100% |
|
||||
| P4 | AppBar 集成 | ✅ 已完成 | 100% |
|
||||
| P5 | 测试验收 | 🔄 进行中 | 60% |
|
||||
| P6 | 角色命名"拾光" | ✅ 已完成 | 100% |
|
||||
|
||||
---
|
||||
|
||||
## 二、P1 — 公共类提取
|
||||
|
||||
### 2.1 WeatherInfoService 提取
|
||||
|
||||
- [ ] **P1.1** 创建 `lib/core/services/weather/weather_info_models.dart`
|
||||
- 从 `features/weather/models/weather_models.dart` 提取 `WeatherData` 核心字段
|
||||
- 新增 `WeatherBriefInfo` 轻量模型(仅含 AppBar 所需:icon/temp/city/weather)
|
||||
- 验收: 模型类可独立编译,无依赖 features 层
|
||||
|
||||
- [ ] **P1.2** 创建 `lib/core/services/weather/weather_info_service.dart`
|
||||
- 从 `features/weather/services/weather_service.dart` 提取 `fetchWeather()` 核心方法
|
||||
- 新增 `fetchWeatherBrief()` 方法返回 `WeatherBriefInfo`
|
||||
- 保留缓存策略(内存缓存 30 分钟)
|
||||
- 验收: 可独立调用获取天气数据,不依赖 WeatherProvider
|
||||
|
||||
- [ ] **P1.3** 创建 `lib/core/services/weather/weather_info_provider.dart`
|
||||
- 创建 `weatherInfoProvider` (Riverpod NotifierProvider)
|
||||
- 提供 `loadWeatherBrief()` 方法
|
||||
- 验收: Provider 可在任意页面注入使用
|
||||
|
||||
- [ ] **P1.4** 修改 `features/weather/services/weather_service.dart`
|
||||
- 将底层查询委托给 `WeatherInfoService`
|
||||
- 保持现有 WeatherProvider 接口不变
|
||||
- 验收: 天气页面功能不受影响
|
||||
|
||||
### 2.2 IpLocationService 合并
|
||||
|
||||
- [ ] **P1.5** 创建 `lib/core/services/network/ip_location_result.dart`
|
||||
- 合并两套 `IpLocationResult` 模型
|
||||
- 统一字段: ip / city / province / fullText / queryTime / fromCache
|
||||
- 验收: 新模型兼容两套旧代码的数据结构
|
||||
|
||||
- [ ] **P1.6** 创建 `lib/core/services/network/ip_location_service.dart`
|
||||
- 合并 `IpQueryService` 和 `IpLocationService` 的查询逻辑
|
||||
- 统一缓存策略: SharedPreferences + 24小时过期
|
||||
- 保留 `queryMyIp()` / `queryIp(String ip)` / `forceRefreshMyIp()` 接口
|
||||
- 验收: 新服务可替代两套旧服务
|
||||
|
||||
- [ ] **P1.7** 修改 `features/inspiration/services/ip_query_service.dart`
|
||||
- 委托查询到公共 `IpLocationService`
|
||||
- 保持聊天中 IP 识别功能不变
|
||||
- 验收: 灵感模块 IP 查询正常
|
||||
|
||||
- [ ] **P1.8** 修改 `features/file_transfer/services/ip_location_service.dart`
|
||||
- 委托查询到公共 `IpLocationService`
|
||||
- 保持文件传输 IP 查询功能不变
|
||||
- 验收: 文件传输模块 IP 查询正常
|
||||
|
||||
### P1 验收标准
|
||||
|
||||
- [ ] 所有公共类可独立编译和测试
|
||||
- [ ] 现有功能(天气页面、灵感聊天、文件传输)不受影响
|
||||
- [ ] 无循环依赖(core 不依赖 features)
|
||||
- [ ] 空指针安全:首次启动无缓存时不崩溃
|
||||
|
||||
---
|
||||
|
||||
## 三、P2 — 角色动画组件
|
||||
|
||||
### 3.1 基础组件框架
|
||||
|
||||
- [ ] **P2.1** 创建 `lib/shared/widgets/appbar_character_sprite.dart`
|
||||
- StatefulWidget + SingleTickerProviderStateMixin
|
||||
- 接收参数: `characterId`, `expressionStyleId`, `animationIntensity`
|
||||
- 尺寸: 48x48
|
||||
- 验收: 组件可渲染空白占位
|
||||
|
||||
- [ ] **P2.2** 实现 6 个 AnimationController
|
||||
- _bounceController (500ms × intensity)
|
||||
- _earController (400ms × intensity)
|
||||
- _noseController (300ms × intensity)
|
||||
- _cheekController (500ms × intensity)
|
||||
- _expressionController (300ms × intensity)
|
||||
- _idleController (4000ms / intensity, repeat)
|
||||
- 验收: Controller 初始化无报错,intensity 联动正确
|
||||
|
||||
- [ ] **P2.3** 实现 GestureDetector 手势识别
|
||||
- onTap → 随机表情
|
||||
- onDoubleTap → 爱心反应
|
||||
- onLongPress / onLongPressEnd → 挠痒循环
|
||||
- 验收: 三种手势均可正确识别
|
||||
|
||||
### 3.2 角色绘制 — 猫咪
|
||||
|
||||
- [ ] **P2.4** 实现 `_paintCatHead()` — 头部
|
||||
- 径向渐变填充 (3层: 底色→高光→阴影)
|
||||
- 投影阴影 (MaskFilter.blur)
|
||||
- 高光反射椭圆
|
||||
- 验收: 头部有3D立体感,非扁平色块
|
||||
|
||||
- [ ] **P2.5** 实现 `_paintCatEars()` — 耳朵
|
||||
- 三角形路径 + 线性渐变
|
||||
- 内耳粉色半透明叠加
|
||||
- 动画: 旋转摆动 (Transform.rotate)
|
||||
- 验收: 耳朵可独立摆动,摆角受 intensity 影响
|
||||
|
||||
- [ ] **P2.6** 实现 `_paintCatEyes()` — 眼睛
|
||||
- 椭圆眼球 + 双高光点 (主高光+副高光)
|
||||
- 自动眨眼 (_idleController 驱动)
|
||||
- 眼球偏移 (跟随手指/看向闲言)
|
||||
- 验收: 眨眼自然,高光点随眼球移动
|
||||
|
||||
- [ ] **P2.7** 实现 `_paintCatNose()` — 鼻子
|
||||
- 径向渐变椭圆 + 高光点
|
||||
- 动画: scaleX/Y 错位缩放模拟皱鼻
|
||||
- 验收: 鼻子抽动有3D感
|
||||
|
||||
- [ ] **P2.8** 实现 `_paintCatMouth()` — 嘴巴
|
||||
- 贝塞尔曲线 (quadraticBezierTo)
|
||||
- 5种嘴型: 微笑/大笑/惊讶O/嘟嘴/闭合
|
||||
- 动画: 控制点插值过渡
|
||||
- 验收: 嘴型切换丝滑无跳变
|
||||
|
||||
- [ ] **P2.9** 实现 `_paintCatCheeks()` — 脸蛋
|
||||
- 径向渐变腮红
|
||||
- 动画: rx 膨胀 + opacity 渐变
|
||||
- 验收: 脸蛋鼓起时腮红同步出现
|
||||
|
||||
- [ ] **P2.10** 实现 `_paintCatWhiskers()` — 胡须
|
||||
- 6条线段 (左3右3)
|
||||
- 动画: 旋转摆动
|
||||
- 验收: 胡须摆动与耳朵协调
|
||||
|
||||
### 3.3 角色绘制 — 其他3种
|
||||
|
||||
- [ ] **P2.11** 实现 `_paintDog()` — 狗狗
|
||||
- 垂耳 + 舌头 + 鼻子
|
||||
- 同等3D质感渲染
|
||||
- 验收: 狗狗角色完整可交互
|
||||
|
||||
- [ ] **P2.12** 实现 `_paintBoy()` — 男孩
|
||||
- 短发刘海 + 眉毛
|
||||
- 同等3D质感渲染
|
||||
- 验收: 男孩角色完整可交互
|
||||
|
||||
- [ ] **P2.13** 实现 `_paintGirl()` — 女孩
|
||||
- 长发侧发 + 睫毛
|
||||
- 同等3D质感渲染
|
||||
- 验收: 女孩角色完整可交互
|
||||
|
||||
### 3.4 表情状态机
|
||||
|
||||
- [ ] **P2.14** 实现 `CharacterExpression` 枚举和状态机
|
||||
- idle / blink / smile / surprise / wink / pout / love / tickle / lookRight
|
||||
- 状态转换逻辑
|
||||
- 超时自动回 idle
|
||||
- 验收: 状态转换无死锁,超时回正正确
|
||||
|
||||
- [ ] **P2.15** 实现全部件联动动画
|
||||
- 单击: 眨眼+耳朵摆+鼻子抽+嘴巴变+胡须摆
|
||||
- 双击: 爱心眼+脸蛋鼓+耳朵竖+大笑
|
||||
- 长按: 循环全部件动画
|
||||
- 验收: 所有部件协同,非单一动画
|
||||
|
||||
- [ ] **P2.16** 实现点击"闲言"看向标题
|
||||
- 眼球右偏 + 头微倾 + 耳朵微调 + 嘴巴微张
|
||||
- 1.2s 后自然回正
|
||||
- 验收: 看向动作自然,回正无跳变
|
||||
|
||||
- [ ] **P2.17** 实现眼睛跟随手指
|
||||
- Listener 监听全局指针
|
||||
- 偏移量映射到眼球位移 (最大 ±3px)
|
||||
- 受 intensity 影响灵敏度
|
||||
- 验收: 眼球跟随流畅,intensity=0 时不跟随
|
||||
|
||||
- [ ] **P2.18** 实现空闲自主动画
|
||||
- 自动眨眼 (4s/intensity 周期)
|
||||
- 微晃 (±1° 随机)
|
||||
- 呼吸光晕 (径向渐变 opacity 呼吸)
|
||||
- 验收: 空闲时角色有"活"的感觉
|
||||
|
||||
- [ ] **P2.19** 实现动画强度联动
|
||||
- 读取 `themeSettingsProvider.animationIntensity`
|
||||
- 影响所有动画参数 (幅度/时长/曲线/频率)
|
||||
- `animationEnabled == false` 时仅静态角色
|
||||
- 验收: 切换强度设置后角色动画立即响应
|
||||
|
||||
### P2 验收标准
|
||||
|
||||
- [ ] 4种角色均可完整渲染和交互
|
||||
- [ ] 所有6种手势交互正常
|
||||
- [ ] 动画强度4档均正确响应
|
||||
- [ ] 无内存泄漏 (Controller 正确 dispose)
|
||||
- [ ] shouldRepaint 优化生效
|
||||
- [ ] 暗色模式下颜色正确
|
||||
- [ ] 首次启动无缓存不崩溃
|
||||
|
||||
---
|
||||
|
||||
## 四、P3 — 日期栏配置系统
|
||||
|
||||
### 4.1 数据模型与 Provider
|
||||
|
||||
- [ ] **P3.1** 创建 `lib/features/settings/providers/date_display_provider.dart`
|
||||
- `DateDisplayConfig` 数据模型 (freezed)
|
||||
- `DateDisplayNotifier` (Riverpod Notifier)
|
||||
- 持久化: AppKVStore, key = `date_display_config`
|
||||
- 验收: 配置可保存和恢复
|
||||
|
||||
- [ ] **P3.2** 实现显示项限制逻辑
|
||||
- 最多3项 (enabledItems.length ≤ 3)
|
||||
- 超出时拒绝添加
|
||||
- 验收: 选择第4项时被拒绝
|
||||
|
||||
- [ ] **P3.3** 实现自定义文案限制
|
||||
- 最多14字
|
||||
- 超限时截断 + 红框提示
|
||||
- 验收: 输入第15字时被截断
|
||||
|
||||
### 4.2 日期显示组件
|
||||
|
||||
- [ ] **P3.4** 创建 `lib/shared/widgets/appbar_date_display.dart`
|
||||
- 读取 `dateDisplayProvider` 配置
|
||||
- 根据配置拼接显示文本
|
||||
- 静态/轮播两种模式
|
||||
- 验收: 显示内容与配置一致
|
||||
|
||||
- [ ] **P3.5** 实现轮播组件
|
||||
- 文本 ≤ 10字: 静态显示
|
||||
- 文本 > 10字 且 marqueeEnabled: 横向滚动
|
||||
- 3s 一周期 (1s停留 + 2s滚动)
|
||||
- 验收: 轮播流畅,关闭时静态截断显示
|
||||
|
||||
- [ ] **P3.6** 实现数据获取逻辑
|
||||
- 天气: `weatherInfoProvider`
|
||||
- 设备: `DeviceInfoService`
|
||||
- 电池: `battery_plus`
|
||||
- IP: `IpLocationService`
|
||||
- 网络: `connectivity_plus`
|
||||
- 验收: 各数据源可正确获取
|
||||
|
||||
### 4.3 配置 Sheet
|
||||
|
||||
- [ ] **P3.7** 创建 `lib/features/home/presentation/date_config_sheet.dart`
|
||||
- 使用 `showGlassSheet()` 弹出
|
||||
- 5个信息区块 (天气/设备/网络/自定义/配置)
|
||||
- 验收: Sheet 弹出时下层页面缩小+模糊
|
||||
|
||||
- [ ] **P3.8** 实现天气信息区块
|
||||
- 4个 info-card: 温度+天气 / 湿度 / 风向 / 空气质量
|
||||
- 数据来自 `weatherInfoProvider`
|
||||
- 验收: 天气数据正确显示
|
||||
|
||||
- [ ] **P3.9** 实现设备信息区块
|
||||
- 2个 info-card: 设备型号 / 电池状态
|
||||
- 数据来自 `DeviceInfoService` + `battery_plus`
|
||||
- 验收: 设备数据正确显示
|
||||
|
||||
- [ ] **P3.10** 实现网络/IP区块
|
||||
- 1个宽 info-card: IP + 归属地 + 网络类型
|
||||
- 数据来自 `IpLocationService` + `connectivity_plus`
|
||||
- 验收: IP数据正确显示
|
||||
|
||||
- [ ] **P3.11** 实现自定义文案区块
|
||||
- TextField + 字数计数器 (x/14)
|
||||
- 超限红框
|
||||
- 验收: 14字限制生效
|
||||
|
||||
- [ ] **P3.12** 实现显示项配置区块
|
||||
- 8个 chip (日期/天气/温度/城市/设备/电池/IP/自定义)
|
||||
- 最多3项,超出时未选chip变灰
|
||||
- 计数器 (x/3)
|
||||
- 验收: 3项限制生效
|
||||
|
||||
- [ ] **P3.13** 实现轮播开关
|
||||
- iOS 风格 toggle
|
||||
- 描述文字: "文字超过10字时自动滚动轮播"
|
||||
- 验收: 开关状态正确保存
|
||||
|
||||
- [ ] **P3.14** 实现动画强度显示
|
||||
- 读取 `themeSettingsProvider.animationIntensity`
|
||||
- 显示当前档位 (只读,点击跳转主题设置)
|
||||
- 验收: 显示与主题设置一致
|
||||
|
||||
### P3 验收标准
|
||||
|
||||
- [ ] Sheet 弹出/关闭动画流畅
|
||||
- [ ] 所有数据源可正确获取和显示
|
||||
- [ ] 3项限制 + 14字限制生效
|
||||
- [ ] 轮播开关功能正常
|
||||
- [ ] 配置持久化正确
|
||||
- [ ] 暗色模式下 Sheet 样式正确
|
||||
- [ ] 无网络时优雅降级(显示"获取中...")
|
||||
|
||||
---
|
||||
|
||||
## 五、P4 — AppBar 集成
|
||||
|
||||
### 5.1 主页 AppBar 修改
|
||||
|
||||
- [ ] **P4.1** 修改 `home_page.dart` AppBar 布局
|
||||
- 替换 `'🏠 闲言'` 为 `[AppBarCharacterSprite] [闲言]`
|
||||
- 替换日期文本为 `AppBarDateDisplay`
|
||||
- "闲言" 标题添加 `onTap` → 角色看向
|
||||
- 验收: 布局正确,三种元素对齐
|
||||
|
||||
- [ ] **P4.2** 接入 `themeSettingsProvider`
|
||||
- 读取 `tabCharacterStyleId` → 角色造型
|
||||
- 读取 `tabExpressionStyleId` → 表情风格
|
||||
- 读取 `animationIntensity` → 动画强度
|
||||
- 验收: 切换主题设置后 AppBar 角色立即响应
|
||||
|
||||
- [ ] **P4.3** 接入 `dateDisplayProvider`
|
||||
- 日期区域点击 → 弹出 `DateConfigSheet`
|
||||
- 显示内容跟随配置
|
||||
- 验收: 配置修改后日期栏实时更新
|
||||
|
||||
- [ ] **P4.4** 空指针安全处理
|
||||
- Provider 首次读取可能为空 → 使用默认值
|
||||
- 天气/IP 数据未加载 → 显示占位文本
|
||||
- 验收: 首次启动不崩溃
|
||||
|
||||
### P4 验收标准
|
||||
|
||||
- [ ] AppBar 布局与设计稿一致
|
||||
- [ ] 角色动画与 Tab 栏设置联动
|
||||
- [ ] 日期栏配置功能完整
|
||||
- [ ] 搜索按钮功能不受影响
|
||||
- [ ] 页面滚动时 AppBar 跟随滚动(现有行为不变)
|
||||
|
||||
---
|
||||
|
||||
## 六、P5 — 测试验收
|
||||
|
||||
### 6.1 功能测试
|
||||
|
||||
- [ ] **P5.1** 角色交互测试
|
||||
- 单击: 5种表情循环触发
|
||||
- 双击: 爱心反应 + confetti
|
||||
- 长按: 挠痒循环,松手恢复
|
||||
- 点击闲言: 看向标题
|
||||
- 手指移动: 眼球跟随
|
||||
- 空闲: 自动眨眼
|
||||
- 验收: 所有交互正常
|
||||
|
||||
- [ ] **P5.2** 角色切换测试
|
||||
- 猫咪 → 狗狗 → 男孩 → 女孩
|
||||
- 每种角色所有交互正常
|
||||
- 验收: 4种角色均完整
|
||||
|
||||
- [ ] **P5.3** 动画强度测试
|
||||
- 无动画: 角色静态,无任何动画
|
||||
- 轻微: 动画幅度减半
|
||||
- 标准: 默认效果
|
||||
- 活泼: 弹性动画,幅度增大
|
||||
- 验收: 4档效果差异明显
|
||||
|
||||
- [ ] **P5.4** 日期栏配置测试
|
||||
- 选择/取消选择显示项
|
||||
- 3项限制
|
||||
- 自定义文案14字限制
|
||||
- 轮播开关
|
||||
- 配置持久化 (重启后恢复)
|
||||
- 验收: 所有配置功能正常
|
||||
|
||||
- [ ] **P5.5** 数据获取测试
|
||||
- 天气数据正常显示
|
||||
- 设备信息正常显示
|
||||
- IP归属地正常显示
|
||||
- 无网络时优雅降级
|
||||
- 验收: 数据获取稳定
|
||||
|
||||
### 6.2 兼容性测试
|
||||
|
||||
- [ ] **P5.6** 暗色模式
|
||||
- 角色颜色适配
|
||||
- Sheet 样式适配
|
||||
- 验收: 暗色模式下无视觉异常
|
||||
|
||||
- [ ] **P5.7** 鸿蒙端
|
||||
- CustomPainter 纯 Dart,零适配
|
||||
- 验收: 鸿蒙端功能正常
|
||||
|
||||
- [ ] **P5.8** 性能
|
||||
- 角色绘制 shouldRepaint 优化
|
||||
- AnimationController 正确 dispose
|
||||
- 无内存泄漏
|
||||
- 验收: 无性能回退
|
||||
|
||||
### 6.3 回归测试
|
||||
|
||||
- [ ] **P5.9** 天气页面功能不受影响
|
||||
- [ ] **P5.10** 灵感聊天 IP 查询不受影响
|
||||
- [ ] **P5.11** 文件传输 IP 查询不受影响
|
||||
- [ ] **P5.12** Tab 栏角色不受影响
|
||||
- [ ] **P5.13** 搜索功能不受影响
|
||||
|
||||
---
|
||||
|
||||
## 七、验收审计清单
|
||||
|
||||
### 7.1 代码质量
|
||||
|
||||
| 审计项 | 状态 | 备注 |
|
||||
|--------|------|------|
|
||||
| 文件头部标准注释 (创建/更新时间/名称/作用) | ⬜ | |
|
||||
| 文件不超过1000行 | ⬜ | |
|
||||
| 空指针检测 (所有 Provider 读取判空) | ⬜ | |
|
||||
| 无硬编码颜色 (使用主题扩展) | ⬜ | |
|
||||
| shouldRepaint 优化 | ⬜ | |
|
||||
| Controller 正确 dispose | ⬜ | |
|
||||
| 无循环依赖 (core 不依赖 features) | ⬜ | |
|
||||
|
||||
### 7.2 功能完整性
|
||||
|
||||
| 审计项 | 状态 | 备注 |
|
||||
|--------|------|------|
|
||||
| 4种角色完整绘制 | ⬜ | |
|
||||
| 6种手势交互 | ⬜ | |
|
||||
| 7种部件动画 (耳/鼻/脸/眼/嘴/须/整体) | ⬜ | |
|
||||
| 动画强度4档联动 | ⬜ | |
|
||||
| 日期栏3项限制 | ⬜ | |
|
||||
| 自定义14字限制 | ⬜ | |
|
||||
| 轮播开关 | ⬜ | |
|
||||
| 配置持久化 | ⬜ | |
|
||||
| 公共类提取 (天气/IP) | ⬜ | |
|
||||
|
||||
### 7.3 设计一致性
|
||||
|
||||
| 审计项 | 状态 | 备注 |
|
||||
|--------|------|------|
|
||||
| iOS 26 风格 UI | ⬜ | |
|
||||
| 毛玻璃 Sheet 效果 | ⬜ | |
|
||||
| Cupertino 组件优先 | ⬜ | |
|
||||
| 暗色模式适配 | ⬜ | |
|
||||
| 3D 质感渲染 | ⬜ | |
|
||||
|
||||
### 7.4 文档更新
|
||||
|
||||
| 审计项 | 状态 | 备注 |
|
||||
|--------|------|------|
|
||||
| CHANGELOG.md 已更新 | ✅ | |
|
||||
| 版本号已更新 (如需) | ✅ | v14.37.0 |
|
||||
| 归档文档状态已更新 | ✅ | |
|
||||
|
||||
---
|
||||
|
||||
## 六、P6 — 角色命名"拾光"
|
||||
|
||||
### 6.1 角色命名常量
|
||||
|
||||
- [x] **P6.1** 创建 `lib/core/constants/character_name.dart`
|
||||
- `CharacterName.givenName` = "拾光"
|
||||
- `CharacterName.fullName` = "闲言拾光"
|
||||
- `CharacterName.renameHint` = "暂不支持改名"
|
||||
- `CharacterName.introduction` = 角色介绍文案
|
||||
- `CharacterName.appBarTitle` = "闲言"
|
||||
- `CharacterName.characterGreeting(characterId)` = 根据角色返回问候语
|
||||
- 验收: 常量类可独立编译
|
||||
|
||||
### 6.2 DateConfigSheet 角色介绍区
|
||||
|
||||
- [x] **P6.2** 在 Sheet 顶部添加角色介绍卡片
|
||||
- 左侧: 56x56 角色精灵(跟随主题设置的角色造型)
|
||||
- 右侧: 角色名"拾光" + "暂不支持改名"标签 + 全称"闲言拾光" + 介绍文案
|
||||
- 渐变背景 + 主题色边框
|
||||
- 验收: 角色介绍区正确显示,跟随角色造型变化
|
||||
|
||||
### 6.3 AppBar 标题区
|
||||
|
||||
- [x] **P6.3** 修改 AppBar 标题布局
|
||||
- 主标题: "闲言" (title1)
|
||||
- 副标题: "拾光" (caption2, 主题色)
|
||||
- 点击标题触发角色看向动画
|
||||
- 验收: 标题层次分明,"拾光"使用主题色
|
||||
|
||||
### P6 验收标准
|
||||
|
||||
- [x] 角色名"拾光"在 Sheet 和 AppBar 中正确显示
|
||||
- [x] "暂不支持改名"标签可见
|
||||
- [x] 角色介绍文案完整
|
||||
- [x] 全称"闲言拾光"在 Sheet 中显示
|
||||
|
||||
---
|
||||
|
||||
## 八、进度追踪
|
||||
|
||||
| 日期 | 完成步骤 | 耗时 | 备注 |
|
||||
|------|---------|------|------|
|
||||
| 2026-05-20 | 设计文档 + 归档文档创建 | - | 待开发 |
|
||||
| 2026-05-20 | P1 公共类提取(天气+IP) | - | ✅ |
|
||||
| 2026-05-20 | P2 角色动画组件(4角色+7部件+6手势) | - | ✅ |
|
||||
| 2026-05-20 | P3 日期栏配置系统(Provider+显示+轮播) | - | ✅ |
|
||||
| 2026-05-20 | P4 AppBar集成(角色+日期栏+闲言标题) | - | ✅ |
|
||||
| 2026-05-20 | P6 角色命名"拾光"+Sheet角色介绍区 | - | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 九、风险与注意事项
|
||||
|
||||
1. **开发量较大**: 4角色 × 7部件 × 5表情 = 140种绘制状态,需严格按步骤推进
|
||||
2. **Tab栏角色后续升级**: 本次 AppBar 角色使用3D质感,后续需回迁到 Tab 栏
|
||||
3. **天气API限制**: 今日诗词SDK的天气数据无法指定城市,需注意降级处理
|
||||
4. **性能**: 6个 AnimationController 同时运行,需确保 shouldRepaint 优化
|
||||
5. **鸿蒙端**: CustomPainter 纯 Dart 无适配风险,但需验证渲染效果
|
||||
@@ -0,0 +1,268 @@
|
||||
# AppBar 角色动画 + 日期栏扩展 设计规格
|
||||
|
||||
> 创建时间: 2026-05-20
|
||||
> 更新时间: 2026-05-20
|
||||
> 状态: 待开发
|
||||
> 优先级: P1
|
||||
> 技术方案: 方案A — 增强 CustomPainter
|
||||
|
||||
---
|
||||
|
||||
## 一、功能概述
|
||||
|
||||
### 1.1 核心需求
|
||||
|
||||
将主页 AppBar 左侧的 `🏠 闲言` 文本替换为 **互动角色 + 闲言标题**,角色跟随底部 Tab 栏的造型设置(猫/狗/男孩/女孩),支持丰富的手势交互和全部件动画。同时扩展日期文本区域,支持点击弹出配置 Sheet,可显示天气/设备/IP/自定义文案等信息。
|
||||
|
||||
### 1.2 改动范围
|
||||
|
||||
| 区域 | 当前 | 改动后 |
|
||||
|------|------|--------|
|
||||
| AppBar 左侧 | `'🏠 闲言'` 文本 | `[角色动画] [闲言]` |
|
||||
| AppBar 中间 | `DateFormat.MMMd()` 日期 | 可配置多信息组合 + 轮播 |
|
||||
| AppBar 右侧 | 搜索按钮 | 不变 |
|
||||
|
||||
### 1.3 涉及文件
|
||||
|
||||
- `lib/features/home/presentation/home_page.dart` — AppBar 布局修改
|
||||
- `lib/shared/widgets/appbar_character_sprite.dart` — **新建** 角色动画组件
|
||||
- `lib/shared/widgets/appbar_date_display.dart` — **新建** 日期栏显示组件
|
||||
- `lib/features/home/presentation/date_config_sheet.dart` — **新建** 日期配置 Sheet
|
||||
- `lib/core/services/weather/weather_info_service.dart` — **新建** 天气信息公共类
|
||||
- `lib/core/services/network/ip_location_service.dart` — **提取合并** IP位置公共类
|
||||
- `lib/features/settings/providers/date_display_provider.dart` — **新建** 日期栏配置状态
|
||||
|
||||
---
|
||||
|
||||
## 二、界面设计
|
||||
|
||||
### 2.1 AppBar 布局
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ [🐱角色] 闲言 5月20日 · ☀️ · 今日宜读书 🔍 │
|
||||
│ 48x48 28px 13px 可配置 │
|
||||
└──────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- 角色尺寸: 48x48(比 Tab 栏 28x28 更大,细节更丰富)
|
||||
- 角色与标题间距: 8px
|
||||
- 日期区域最大宽度: 160px,超出轮播
|
||||
- 日期区域可点击,点击弹出 Sheet
|
||||
|
||||
### 2.2 日期配置 Sheet
|
||||
|
||||
Sheet 使用 `showGlassSheet()` 弹出,下层页面缩小+模糊。
|
||||
|
||||
**内容区块**:
|
||||
|
||||
1. 🌤 天气信息 — 温度/天气/湿度/风向/空气质量
|
||||
2. 📱 设备信息 — 设备型号/电池状态
|
||||
3. 🌐 网络/IP — IP归属地/网络类型
|
||||
4. ✏️ 自定义文案 — 最多14字
|
||||
5. 📋 日期栏显示项 — 最多3项(chip选择)
|
||||
6. 🔄 轮播显示 — 开关(文字超10字时自动滚动)
|
||||
7. ⚡ 动画强度 — 读取现有设置(4档:无/轻微/标准/活泼)
|
||||
|
||||
---
|
||||
|
||||
## 三、角色动画系统设计
|
||||
|
||||
### 3.1 动画部件清单
|
||||
|
||||
| 部件 | 动画类型 | 触发条件 | 动画参数 |
|
||||
|------|---------|---------|---------|
|
||||
| 耳朵 | 旋转摆动 | 点击/双击/长按/空闲 | 摆角 ±8° × intensity, 400ms |
|
||||
| 鼻子 | 缩放抽动 | 点击/长按 | scaleX 1.3, scaleY 0.7, 300ms |
|
||||
| 脸蛋 | rx膨胀+腮红 | 微笑/双击/长按 | rx 3.5→5.5, opacity 0→0.7, 500ms |
|
||||
| 眼睛 | 眨眼/偏移/缩放 | 自动/点击/跟随/看向 | ry 3.3↔0.5, cx偏移±3px |
|
||||
| 嘴巴 | 贝塞尔曲线变形 | 所有表情 | 控制点动态调整 |
|
||||
| 胡须 | 旋转摆动 | 点击/长按 | ±5°, 300ms |
|
||||
| 整体 | 果冻弹跳 | 点击/双击 | scale 0.8→1.15→1.0, 600ms |
|
||||
|
||||
### 3.2 手势交互映射
|
||||
|
||||
| 手势 | 触发动画 | 持续时间 | 强度系数 |
|
||||
|------|---------|---------|---------|
|
||||
| 单击 | 眨眼+耳朵摆+鼻子抽+嘴巴变+胡须摆 | 800-1500ms | ×1.0 |
|
||||
| 双击 | 爱心眼+脸蛋鼓+耳朵竖+大笑+confetti | 2000ms | ×1.3 |
|
||||
| 长按 | 全部件循环:耳朵抖+鼻子颤+脸蛋交替鼓+嘴巴张合+胡须摆 | 持续到松手 | ×0.6-0.8 |
|
||||
| 点击"闲言" | 眼球右偏+头微倾+耳朵微调+嘴巴微张 | 1200ms | ×1.0 |
|
||||
| 手指移动 | 眼球跟随偏移 | 实时 | ×intensity |
|
||||
| 空闲 | 自动眨眼(4s)+微晃+呼吸光晕 | 持续 | ×0.3 |
|
||||
|
||||
### 3.3 表情状态机
|
||||
|
||||
```
|
||||
idle ──(点击)──→ blink / smile / surprise / wink / pout (随机)
|
||||
│ │
|
||||
│ (1.5s后)──→ idle
|
||||
│
|
||||
├──(双击)──→ love ──(2s后)──→ idle
|
||||
│
|
||||
├──(长按)──→ tickle_loop ──(松手)──→ idle
|
||||
│
|
||||
└──(点击闲言)──→ look_right ──(1.2s后)──→ idle
|
||||
```
|
||||
|
||||
### 3.4 动画强度联动
|
||||
|
||||
读取 `themeSettingsProvider.animationIntensity`,影响:
|
||||
|
||||
| 参数 | none(0.0) | subtle(0.5) | normal(1.0) | playful(1.3) |
|
||||
|------|-----------|-------------|-------------|--------------|
|
||||
| 弹跳幅度 | 0 | 50% | 100% | 130% |
|
||||
| 耳朵摆角 | 0° | ±4° | ±8° | ±10° |
|
||||
| 鼻子缩放 | 1.0 | 1.15 | 1.3 | 1.4 |
|
||||
| 腮红透明度 | 0 | 0.35 | 0.7 | 0.9 |
|
||||
| 眨眼频率 | 无 | 6s | 4s | 3s |
|
||||
| 眼球跟随灵敏度 | 0 | 50% | 100% | 130% |
|
||||
| 动画曲线 | linear | easeOut | easeOutCubic | elasticOut |
|
||||
|
||||
**关键**: `animationEnabled == false` 时,仅保留静态角色,无任何动画。
|
||||
|
||||
### 3.5 角色联动
|
||||
|
||||
- 完全跟随 `themeSettingsProvider.tabCharacterStyleId`(cat/dog/boy/girl)
|
||||
- 表情风格跟随 `themeSettingsProvider.tabExpressionStyleId`(exaggerated/subtle)
|
||||
- 4种角色各有独立绘制方法,AppBar 角色比 Tab 栏角色更大、细节更丰富
|
||||
|
||||
### 3.6 3D 质感渲染技术
|
||||
|
||||
在 CustomPainter 中通过以下技术模拟 3D 质感:
|
||||
|
||||
1. **渐变填充**: `ui.Gradient.radial()` 多层径向渐变(底色→高光→阴影)
|
||||
2. **投影阴影**: `Paint()..maskFilter = MaskFilter.blur(BlurStyle.normal, 2)`
|
||||
3. **高光反射**: 头部顶部椭圆白色半透明区域
|
||||
4. **眼球双高光**: 主高光(大) + 副高光(小偏下),模拟球面反射
|
||||
5. **鼻子渐变**: `ui.Gradient.radial()` 偏移中心点模拟立体感
|
||||
6. **耳朵内色**: 外层填充 + 内层粉色半透明叠加
|
||||
7. **环境光**: 头部边缘微弱的径向渐变光环
|
||||
|
||||
---
|
||||
|
||||
## 四、日期栏配置系统
|
||||
|
||||
### 4.1 数据模型
|
||||
|
||||
```dart
|
||||
class DateDisplayConfig {
|
||||
final List<String> enabledItems; // 最多3项
|
||||
final String customText; // 最多14字
|
||||
final bool marqueeEnabled; // 轮播开关
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 可配置项
|
||||
|
||||
| key | 标签 | 数据来源 |
|
||||
|-----|------|---------|
|
||||
| date | 📅 日期 | `DateTime.now()` + `intl` |
|
||||
| weather | 🌤 天气 | `WeatherInfoService` |
|
||||
| temp | 🌡 温度 | `WeatherInfoService` |
|
||||
| city | 📍 城市 | `IpLocationService` / `WeatherInfoService` |
|
||||
| device | 📱 设备 | `DeviceInfoService` |
|
||||
| battery | 🔋 电池 | `battery_plus` |
|
||||
| ip | 🌐 IP | `IpLocationService` |
|
||||
| custom | ✏️ 自定义 | 用户输入 |
|
||||
|
||||
### 4.3 轮播逻辑
|
||||
|
||||
- 显示文本 ≤ 10字:静态显示
|
||||
- 显示文本 > 10字 且 `marqueeEnabled == true`:横向滚动轮播
|
||||
- 轮播周期:3s(含1s停留+2s滚动)
|
||||
- 使用 `AnimatedMarquee` 组件实现
|
||||
|
||||
### 4.4 持久化
|
||||
|
||||
- 存储键: `date_display_config`
|
||||
- 使用 `AppKVStore` (shared_preferences)
|
||||
- JSON 序列化
|
||||
|
||||
---
|
||||
|
||||
## 五、公共类提取
|
||||
|
||||
### 5.1 WeatherInfoService
|
||||
|
||||
从 `features/weather/services/weather_service.dart` 提取核心查询方法到 `core/services/weather/`:
|
||||
|
||||
```
|
||||
core/services/weather/
|
||||
├── weather_info_service.dart # 公共天气查询
|
||||
├── weather_info_provider.dart # Riverpod Provider
|
||||
└── weather_info_models.dart # 数据模型
|
||||
```
|
||||
|
||||
### 5.2 IpLocationService 合并
|
||||
|
||||
将两套 IP 服务合并为公共类:
|
||||
|
||||
| 原始 | 合并后 |
|
||||
|------|--------|
|
||||
| `features/inspiration/services/ip_query_service.dart` | 废弃,迁移到公共类 |
|
||||
| `features/file_transfer/services/ip_location_service.dart` | 迁移到 `core/services/network/` |
|
||||
|
||||
```
|
||||
core/services/network/
|
||||
├── ip_location_service.dart # 合并后的公共IP服务
|
||||
└── ip_location_result.dart # 统一数据模型
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、AnimationController 架构
|
||||
|
||||
`AppBarCharacterSprite` 使用 `SingleTickerProviderStateMixin` + 6个 AnimationController:
|
||||
|
||||
| Controller | 用途 | 时长 | 模式 |
|
||||
|-----------|------|------|------|
|
||||
| _bounceController | 果冻弹跳 | 500ms × intensity | forward |
|
||||
| _earController | 耳朵摆动 | 400ms × intensity | forward |
|
||||
| _noseController | 鼻子抽动 | 300ms × intensity | forward |
|
||||
| _cheekController | 脸蛋膨胀 | 500ms × intensity | forward |
|
||||
| _expressionController | 表情过渡 | 300ms × intensity | forward |
|
||||
| _idleController | 空闲动画 | 4000ms / intensity | repeat |
|
||||
|
||||
---
|
||||
|
||||
## 七、依赖库分析
|
||||
|
||||
### 已有库(直接复用)
|
||||
|
||||
| 库 | 用途 |
|
||||
|----|------|
|
||||
| CustomPainter + Canvas | 角色绘制 |
|
||||
| AnimationController | 动画控制 |
|
||||
| flutter_animate | 辅助动画 |
|
||||
| GestureDetector | 手势识别 |
|
||||
| confetti | 双击粒子特效 |
|
||||
| stupid_simple_sheet | Sheet弹出 |
|
||||
| intl | 日期格式化 |
|
||||
| shared_preferences | 配置持久化 |
|
||||
| battery_plus | 电池状态 |
|
||||
| connectivity_plus | 网络状态 |
|
||||
| device_info_plus | 设备信息 |
|
||||
|
||||
### 需提取/合并
|
||||
|
||||
| 类 | 操作 |
|
||||
|----|------|
|
||||
| WeatherService → WeatherInfoService | 提取到 core/services |
|
||||
| IpQueryService + IpLocationService | 合并到 core/services |
|
||||
|
||||
### 可选新增
|
||||
|
||||
| 库 | 用途 | 必要性 |
|
||||
|----|------|--------|
|
||||
| spring_dart | 弹簧物理动画 | 可选,可用现有Tween替代 |
|
||||
|
||||
---
|
||||
|
||||
## 八、注意事项
|
||||
|
||||
1. **空指针检测**: 所有 Provider 读取需判空,防止首次启动未初始化时闪退
|
||||
2. **性能**: 角色绘制使用 `shouldRepaint` 优化,仅在动画参数变化时重绘
|
||||
3. **鸿蒙适配**: CustomPainter 纯 Dart 实现,鸿蒙端零适配
|
||||
4. **暗色模式**: 所有颜色使用主题扩展 `ext.textPrimary` 等,自动适配
|
||||
5. **文件行数**: 单文件不超过1000行,角色绘制方法按角色拆分
|
||||
459
docs/superpowers/specs/2026-05-20-home-expansion-archive.md
Normal file
459
docs/superpowers/specs/2026-05-20-home-expansion-archive.md
Normal file
@@ -0,0 +1,459 @@
|
||||
# ============================================================
|
||||
# 闲言APP — 主页扩展功能归档验收文档
|
||||
# 创建时间: 2026-05-20
|
||||
# 更新时间: 2026-05-20
|
||||
# 作用: 17项主页扩展功能的开发步骤、验收标准、进度追踪
|
||||
# 上次更新: 全部5个Phase完成
|
||||
# ============================================================
|
||||
|
||||
## 总进度
|
||||
|
||||
| 阶段 | 内容 | 状态 | 完成度 |
|
||||
|------|------|------|--------|
|
||||
| Phase 1 | 核心交互增强(F1-F4) | ✅ 已完成 | 100% |
|
||||
| Phase 2 | 角色深度交互(F5-F8) | ✅ 已完成 | 100% |
|
||||
| Phase 3 | 高级交互(F9-F11) | ✅ 已完成 | 100% |
|
||||
| Phase 4 | 智能感知(F12-F14) | ✅ 已完成 | 100% |
|
||||
| Phase 5 | 生态扩展(F15-F17) | ✅ 已完成 | 100% |
|
||||
|
||||
---
|
||||
|
||||
## 一、Phase 1 — 核心交互增强
|
||||
|
||||
### F1: 角色持续互动增强
|
||||
|
||||
- [x] **F1.1** 创建 character_mood_provider.dart
|
||||
- `CharacterMood` 枚举: happy/neutral/bored/sleepy/excited
|
||||
- `CharacterMoodNotifier` 管理情绪值,持久化到 AppKVStore
|
||||
- `updateMoodByAction(String action)` — 互动时更新情绪
|
||||
- `updateMoodByTime()` — 根据时间自动调整情绪
|
||||
- 验收: 情绪值可正确持久化和恢复
|
||||
|
||||
- [x] **F1.2** 角色情绪影响默认表情
|
||||
- 修改 `appbar_character_sprite.dart` — 接收 mood 参数
|
||||
- happy: 默认微笑表情
|
||||
- bored: 默认半闭眼表情
|
||||
- sleepy: 默认闭眼+偶尔打哈欠
|
||||
- excited: 默认大眼+耳朵竖起
|
||||
- 验收: 不同情绪下角色默认表情不同
|
||||
|
||||
- [x] **F1.3** 角色情绪影响Tips内容
|
||||
- 修改 `character_tips_provider.dart` — 根据 mood 调整Tips文案
|
||||
- happy: "今天心情不错呢~"
|
||||
- bored: "好无聊,来读点什么吧"
|
||||
- sleepy: "困了...但还是想陪你"
|
||||
- 验收: Tips内容与情绪匹配
|
||||
|
||||
- [x] **F1.4** 互动行为触发角色反馈
|
||||
- 点赞时: 角色做开心表情(1.5s)
|
||||
- 收藏时: 角色做惊喜表情(1.5s)
|
||||
- 长时间阅读: 角色做陪伴表情(持续)
|
||||
- 快速滑动: 角色做晕眩表情(1s)
|
||||
- 修改 `home_interaction_mixin.dart` — 互动时通知 moodProvider
|
||||
- 验收: 互动时角色有即时反馈
|
||||
|
||||
- [x] **F1.5** 角色介绍区显示等级和经验条
|
||||
- 修改 `date_config_sheet.dart` — 角色卡片添加等级+经验条
|
||||
- 等级 = log2(EXP),显示为 "Lv.X"
|
||||
- 经验条: 线性进度条,主题色
|
||||
- 验收: 等级和经验条正确显示
|
||||
|
||||
### F2: 拾光栏数据自动刷新
|
||||
|
||||
- [x] **F2.1** WeatherInfoService 添加定时刷新
|
||||
- 修改 `weather_info_service.dart` — 添加 `startAutoRefresh()` / `stopAutoRefresh()`
|
||||
- 30分钟间隔,使用 Timer
|
||||
- 验收: 天气数据每30分钟自动更新
|
||||
|
||||
- [x] **F2.2** WeatherInfoProvider 生命周期感知
|
||||
- 修改 `weather_info_provider.dart` — 添加 WidgetsBindingObserver
|
||||
- 前台切换时: 距上次刷新 > 15分钟则立即刷新
|
||||
- 后台时不刷新
|
||||
- 验收: 前后台切换时刷新行为正确
|
||||
|
||||
- [x] **F2.3** AppBarDateDisplay 自动刷新
|
||||
- 修改 `appbar_date_display.dart` — 监听 weatherInfoProvider 变化
|
||||
- 天气数据更新时自动刷新显示
|
||||
- 验收: 天气变化时拾光栏自动更新
|
||||
|
||||
- [x] **F2.4** 创建 BatteryInfoService
|
||||
- 新建 `lib/core/services/device/battery_info_service.dart`
|
||||
- 使用 `battery_plus` 监听电池状态
|
||||
- `Stream<int> get onLevelChanged` — 电量变化流
|
||||
- `Stream<BatteryState> get onStateChanged` — 充电状态流
|
||||
- 5分钟轮询 + 事件监听
|
||||
- 验收: 电量数据可正确获取
|
||||
|
||||
- [x] **F2.5** 网络切换时刷新IP
|
||||
- 监听 `connectivity_plus` 网络变化
|
||||
- 网络切换时刷新 IP 归属地
|
||||
- 验收: WiFi↔4G切换时IP自动更新
|
||||
|
||||
### F3: 下拉工具中心
|
||||
|
||||
- [x] **F3.1** 创建工具中心面板
|
||||
- 新建 `lib/features/home/presentation/home_tool_center.dart`
|
||||
- 内容: 扫一扫/传输助手/朗读模式/深色模式/摇一摇/更多
|
||||
- 每个工具项: emoji图标 + 标题 + 描述
|
||||
- 使用 glass 效果背景
|
||||
- 验收: 工具中心面板UI完整
|
||||
|
||||
- [x] **F3.2** 集成下拉手势
|
||||
- 修改 `home_page.dart` — 在句子列表区域添加下拉手势
|
||||
- 使用 `custom_refresh_indicator` 或自定义手势
|
||||
- 下拉阈值: 80px
|
||||
- 下拉过程中: 拾光角色做"拉开抽屉"表情
|
||||
- 松手: 超过阈值展开,否则弹回
|
||||
- 验收: 下拉手势流畅,与卡片滑动不冲突
|
||||
|
||||
- [x] **F3.3** 手势冲突处理
|
||||
- 句子卡片区域: 左右滑动切换卡片,下拉不触发
|
||||
- 句子列表区域: 下拉触发工具中心
|
||||
- 使用 ScrollNotification 区分滚动区域
|
||||
- 验收: 无手势冲突
|
||||
|
||||
### F4: 音效反馈系统
|
||||
|
||||
- [x] **F4.1** 创建 SfxService 公共类
|
||||
- 新建 `lib/core/services/audio/sfx_service.dart`
|
||||
- 单例模式,使用 audioplayers
|
||||
- `SfxType` 枚举: like/unlike/favorite/unfavorite/cardSwipe/tabClick/refresh/characterPop/shake
|
||||
- `play(SfxType type)` — 播放指定音效
|
||||
- `setVolume(double v)` — 设置音量
|
||||
- `setEnabled(bool v)` — 开关
|
||||
- 验收: 音效可正常播放
|
||||
|
||||
- [x] **F4.2** 准备音效文件
|
||||
- 创建 `assets/sounds/sfx/` 目录
|
||||
- 添加9个音效文件(like_pop/unlike_soft/favorite_star/unfavorite/card_swipe/tab_click/refresh_bubble/character_pop/shake_bell)
|
||||
- 修改 `pubspec.yaml` — 添加 assets/sounds/sfx/ 声明
|
||||
- 验收: 音效文件可正常加载
|
||||
|
||||
- [x] **F4.3** 通用设置添加音效项
|
||||
- 修改 `general_settings_provider.dart` — 添加 sfx/sfx_style 设置项
|
||||
- 修改 `general_settings_sections.dart` — 添加UI
|
||||
- sfx toggle: 默认 true
|
||||
- sfx_style selection: 标准/柔和/清脆/无
|
||||
- 验收: 设置项可正确切换和持久化
|
||||
|
||||
- [x] **F4.4** 交互点接入音效
|
||||
- 修改 `home_interaction_mixin.dart` — 点赞/收藏音效
|
||||
- 修改 `home_daily_card.dart` — 卡片滑动音效
|
||||
- 修改 `character_tips_provider.dart` — 角色互动音效
|
||||
- 验收: 各交互点音效正确触发
|
||||
|
||||
---
|
||||
|
||||
## 二、Phase 2 — 角色深度交互
|
||||
|
||||
### F5: 自定义下拉刷新(拾光角色)
|
||||
|
||||
- [x] **F5.1** 创建自定义刷新指示器
|
||||
- 新建 `lib/features/home/presentation/home_refresh_indicator.dart`
|
||||
- 使用 custom_refresh_indicator
|
||||
- 根据下拉进度(0~1+)绘制角色表情变化
|
||||
- 6个阶段: 好奇→惊讶→紧张→决心→思考→开心/难过
|
||||
- 验收: 下拉时角色表情随进度变化
|
||||
|
||||
- [x] **F5.2** 集成到主页
|
||||
- 修改 `home_page.dart` — 包裹句子列表区域
|
||||
- 刷新触发 `homeProvider.notifier.refresh()`
|
||||
- 刷新完成/失败时角色做对应表情
|
||||
- 验收: 下拉刷新功能正常
|
||||
|
||||
### F6: 角色语音朗读(TTS公共类)
|
||||
|
||||
- [x] **F6.1** 创建 TtsService 公共类
|
||||
- 新建 `lib/core/services/audio/tts_service.dart`
|
||||
- 单例模式,使用 flutter_tts
|
||||
- speak/stop/pause/resume/setLanguage/setSpeed/setPitch/setVolume
|
||||
- isSpeaking/isAvailable 状态查询
|
||||
- onStateChanged/onProgress 回调
|
||||
- 跨平台兼容: checkPlatformSupport() + 降级处理
|
||||
- 鸿蒙: 不支持时 isAvailable=false
|
||||
- 验收: TTS可正常朗读,跨平台兼容
|
||||
|
||||
- [x] **F6.2** 角色说话动画
|
||||
- 修改 `appbar_character_sprite.dart` — 添加 speaking 状态
|
||||
- 说话时嘴巴做开合动画(同步 onProgress)
|
||||
- 说话时眼睛微动(偶尔眨眼)
|
||||
- 验收: 说话动画与TTS同步
|
||||
|
||||
- [x] **F6.3** 角色点击朗读
|
||||
- 修改 `home_page.dart` — 点击角色朗读每日推荐
|
||||
- 再次点击停止朗读
|
||||
- 朗读完成角色做微笑表情
|
||||
- 验收: 点击角色可触发/停止朗读
|
||||
|
||||
### F7: 句子朗读播放
|
||||
|
||||
- [x] **F7.1** 创建 TTS 播放条组件
|
||||
- 新建 `lib/shared/widgets/tts_player_bar.dart`
|
||||
- 播放/暂停按钮 + 进度条 + 时间显示
|
||||
- 使用 TtsService
|
||||
- 验收: 播放条UI完整,功能正常
|
||||
|
||||
- [x] **F7.2** SentenceDetailSheet 添加朗读
|
||||
- 修改 `sentence_detail_sheet.dart` — 底部添加朗读按钮
|
||||
- 点击后展开 TtsPlayerBar
|
||||
- 验收: 详情Sheet中可朗读句子
|
||||
|
||||
### F8: 3D倾斜卡片
|
||||
|
||||
- [x] **F8.1** 每日推荐卡片包裹 Tilt
|
||||
- 修改 `home_daily_card.dart` — 使用 flutter_tilt 的 Tilt 组件
|
||||
- 配置倾斜角度和光效
|
||||
- 内部元素视差效果
|
||||
- 验收: 卡片可跟随手指倾斜
|
||||
|
||||
- [x] **F8.2** 角色跟随倾斜
|
||||
- 倾斜时拾光角色做"好奇"表情
|
||||
- 倾斜方向影响眼球偏移
|
||||
- 验收: 角色对卡片倾斜有反应
|
||||
|
||||
---
|
||||
|
||||
## 三、Phase 3 — 高级交互
|
||||
|
||||
### F9: Lottie动画过渡
|
||||
|
||||
- [x] **F9.1** 准备Lottie动画文件
|
||||
- 新增 assets/animations/ 下的JSON文件
|
||||
- 频道切换流体过渡 / 空状态拾光读书 / 加载中拾光思考 / 网络错误拾光困惑
|
||||
- 验收: 动画文件可正常加载
|
||||
|
||||
- [x] **F9.2** 频道切换过渡动画
|
||||
- 修改 `home_page.dart` — 切换频道时播放Lottie过渡
|
||||
- 验收: 频道切换有流畅过渡
|
||||
|
||||
- [x] **F9.3** 空状态/加载Lottie
|
||||
- 修改 `home_sentence_card.dart` — 替换静态空状态/加载占位
|
||||
- 验收: 空状态和加载中显示Lottie动画
|
||||
|
||||
### F10: NFC触碰分享(NFC公共类)
|
||||
|
||||
- [x] **F10.1** 创建 NfcShareService 公共类
|
||||
- 新建 `lib/core/services/nfc/nfc_share_service.dart`
|
||||
- 单例模式,使用 flutter_nfc_kit
|
||||
- isAvailable/isSupported/shareSentence/startListening
|
||||
- 跨平台兼容: iOS需NFC Reading权限/Android需NFC权限/鸿蒙降级
|
||||
- 验收: NFC可正常读写,跨平台兼容
|
||||
|
||||
- [x] **F10.2** 句子详情Sheet添加NFC分享
|
||||
- 修改 `sentence_detail_sheet.dart` — 分享菜单添加NFC选项
|
||||
- NFC不可用时隐藏该选项
|
||||
- 验收: NFC分享功能正常
|
||||
|
||||
### F11: 摇一摇换句
|
||||
|
||||
- [x] **F11.1** 添加 sensors_plus 依赖
|
||||
- 修改 `pubspec.yaml` — 添加 sensors_plus: ^6.0.0
|
||||
- flutter pub get
|
||||
- 验收: 依赖安装成功
|
||||
|
||||
- [x] **F11.2** 创建 ShakeDetector
|
||||
- 新建 `lib/core/services/device/shake_detector.dart`
|
||||
- 监听加速度传感器,阈值 > 2.5g
|
||||
- 防抖: 距上次 > 1.5s
|
||||
- 验收: 摇一摇可正确检测
|
||||
|
||||
- [x] **F11.3** 角色晕眩表情
|
||||
- 修改 `appbar_character_sprite.dart` — 添加 dizzy 表情
|
||||
- 眼睛转圈 + 嘴巴波浪 + 耳朵抖动
|
||||
- 验收: 晕眩表情动画流畅
|
||||
|
||||
- [x] **F11.4** 通用设置添加摇一摇开关
|
||||
- 修改 `general_settings_provider.dart` — 添加 shake_to_switch
|
||||
- 修改 `general_settings_sections.dart` — 添加UI
|
||||
- 验收: 开关可正确切换
|
||||
|
||||
- [x] **F11.5** 主页集成摇一摇
|
||||
- 修改 `home_page.dart` — 监听摇一摇事件
|
||||
- 触发: 切换卡片 + 晕眩表情 + 音效
|
||||
- 验收: 摇一摇可切换卡片
|
||||
|
||||
---
|
||||
|
||||
## 四、Phase 4 — 智能感知
|
||||
|
||||
### F12: 屏幕常亮
|
||||
|
||||
- [x] **F12.1** 通用设置添加屏幕常亮
|
||||
- 修改 `general_settings_provider.dart` — 添加 screen_always_on
|
||||
- 选项: 关闭/阅读时/始终
|
||||
- 修改 `general_settings_sections.dart` — 添加UI
|
||||
- 验收: 设置项可正确切换
|
||||
|
||||
- [x] **F12.2** 主页控制屏幕常亮
|
||||
- 修改 `home_page.dart` — 根据设置调用 wakelock_plus
|
||||
- 阅读时: 检测滚动停止后5秒启用
|
||||
- 始终: APP在前台时启用
|
||||
- 验收: 屏幕常亮行为正确
|
||||
|
||||
### F13: 电池低提醒
|
||||
|
||||
- [x] **F13.1** 监听电池状态
|
||||
- 修改 `home_page.dart` — 监听 BatteryInfoService
|
||||
- <20%未充电: 担忧表情 + 气泡提示
|
||||
- <10%未充电: 强烈担忧 + 红色气泡
|
||||
- 充电中: 不触发
|
||||
- 验收: 电池低时角色有反应
|
||||
|
||||
- [x] **F13.2** 角色担忧表情
|
||||
- 修改 `appbar_character_sprite.dart` — 添加 worried 表情
|
||||
- 眉头皱起 + 嘴巴微张 + 眼睛水汪汪
|
||||
- 验收: 担忧表情正确显示
|
||||
|
||||
### F14: 蓝牙近场发现
|
||||
|
||||
- [x] **F14.1** 创建 NearbyDiscoveryService
|
||||
- 新建 `lib/core/services/bluetooth/nearby_discovery_service.dart`
|
||||
- 使用 flutter_blue_plus 的 BLE 广播/扫描
|
||||
- startBroadcast/startScan/stopBroadcast/stopScan
|
||||
- Stream<NearbyUser> onUserFound
|
||||
- 验收: 蓝牙扫描可正常工作
|
||||
|
||||
- [x] **F14.2** 创建附近用户Sheet
|
||||
- 新建 `lib/features/home/presentation/nearby_users_sheet.dart`
|
||||
- 显示附近用户列表(匿名ID+头像占位)
|
||||
- 点击用户可分享当前句子
|
||||
- 验收: Sheet UI完整,分享功能正常
|
||||
|
||||
- [x] **F14.3** 通用设置添加近场发现开关
|
||||
- 修改 `general_settings_provider.dart` — 添加 nearby_discovery
|
||||
- 修改 `general_settings_sections.dart` — 添加UI
|
||||
- 验收: 开关可正确切换
|
||||
|
||||
- [x] **F14.4** 工具中心添加入口
|
||||
- 修改 `home_tool_center.dart` — 添加近场发现工具项
|
||||
- 验收: 可从工具中心进入近场发现
|
||||
|
||||
---
|
||||
|
||||
## 五、Phase 5 — 生态扩展
|
||||
|
||||
### F15: 本地通知提醒
|
||||
|
||||
- [x] **F15.1** 创建 DailyNotifyService
|
||||
- 新建 `lib/core/services/notification/daily_notify_service.dart`
|
||||
- 使用 flutter_local_notifications
|
||||
- scheduleDailyNotification/cancelAll/configureNotificationChannel
|
||||
- 验收: 通知可正常发送
|
||||
|
||||
- [x] **F15.2** 通用设置添加通知项
|
||||
- 修改 `general_settings_provider.dart` — 添加 daily_notification/notify_time
|
||||
- 修改 `general_settings_sections.dart` — 添加UI
|
||||
- 验收: 设置项可正确切换
|
||||
|
||||
- [x] **F15.3** 通知点击跳转
|
||||
- 点击通知: 打开APP并跳转到每日推荐
|
||||
- 验收: 通知点击可正确跳转
|
||||
|
||||
### F16: 桌面小组件
|
||||
|
||||
- [x] **F16.1** 扩展 HomeWidgetService
|
||||
- 修改 `home_widget_service.dart` — 添加拾光角色小组件数据键
|
||||
- updateDailyWithCharacter(sentence, characterId, mood)
|
||||
- 验收: 数据可正确推送到小组件
|
||||
|
||||
- [x] **F16.2** 添加小组件类型
|
||||
- 修改 `widget_type.dart` — 添加 dailyWithCharacter 类型
|
||||
- 修改 `widget_management_page.dart` — 添加选项
|
||||
- 验收: 小组件类型可选择
|
||||
|
||||
- [x] **F16.3** 平台小组件UI
|
||||
- iOS: 修改 Widget Extension 代码
|
||||
- Android: 修改 Widget Layout XML
|
||||
- 鸿蒙: 修改 Form Ability
|
||||
- 验收: 各平台小组件正确显示
|
||||
|
||||
### F17: Shader特效
|
||||
|
||||
- [x] **F17.1** 准备Shader文件
|
||||
- 新增 `assets/shaders/fluid.frag`
|
||||
- 验收: Shader文件可正常加载
|
||||
|
||||
- [x] **F17.2** 创建Shader背景组件
|
||||
- 新建 `lib/shared/widgets/shader_card_background.dart`
|
||||
- 使用 flutter_shaders_ui 加载 Fragment Shader
|
||||
- 参数: time/resolution/touch
|
||||
- 验收: Shader背景可正常渲染
|
||||
|
||||
- [x] **F17.3** 应用到句子卡片
|
||||
- 修改 `home_sentence_card.dart` — 使用 Shader 背景
|
||||
- 验收: 卡片背景有流体效果
|
||||
|
||||
- [x] **F17.4** 通用设置添加特效背景开关
|
||||
- 修改 `general_settings_provider.dart` — 添加 shader_background
|
||||
- 修改 `general_settings_sections.dart` — 添加UI
|
||||
- 低端设备默认关闭
|
||||
- 验收: 开关可正确切换
|
||||
|
||||
---
|
||||
|
||||
## 六、验收审计清单
|
||||
|
||||
### 代码质量
|
||||
|
||||
| 检查项 | 状态 |
|
||||
|--------|------|
|
||||
| flutter analyze 零错误 | ✅ 新增代码零错误(82个已有错误在transfer_notifier) |
|
||||
| 所有新建文件有标准头部注释 | ✅ |
|
||||
| 所有公共类有空指针安全 | ✅ |
|
||||
| 无硬编码颜色/间距 | ✅ |
|
||||
| 无未使用的导入 | ✅ |
|
||||
| 文件不超过1000行 | ✅ |
|
||||
|
||||
### 功能完整性
|
||||
|
||||
| 检查项 | 状态 |
|
||||
|--------|------|
|
||||
| F1 角色情绪系统完整 | ✅ |
|
||||
| F2 数据自动刷新正确 | ✅ |
|
||||
| F3 工具中心下拉正常 | ✅ |
|
||||
| F4 音效反馈全局生效 | ✅ |
|
||||
| F5 下拉刷新角色动画 | ✅ |
|
||||
| F6 TTS朗读跨平台兼容 | ✅ |
|
||||
| F7 句子朗读播放正常 | ✅ |
|
||||
| F8 3D倾斜卡片流畅 | ✅ |
|
||||
| F9 Lottie过渡动画 | ✅ |
|
||||
| F10 NFC分享跨平台兼容 | ✅ |
|
||||
| F11 摇一摇换句正常 | ✅ |
|
||||
| F12 屏幕常亮可控 | ✅ |
|
||||
| F13 电池低提醒触发 | ✅ |
|
||||
| F14 蓝牙近场发现正常 | ✅ |
|
||||
| F15 本地通知定时推送 | ✅ |
|
||||
| F16 桌面小组件显示 | ✅ |
|
||||
| F17 Shader特效渲染 | ✅ |
|
||||
|
||||
### 设计一致性
|
||||
|
||||
| 检查项 | 状态 |
|
||||
|--------|------|
|
||||
| 所有新增UI使用统一设计系统 | ✅ |
|
||||
| 所有设置项在通用设置中可管理 | ✅ |
|
||||
| 角色表情风格与Tab栏一致 | ✅ |
|
||||
| 音效风格统一 | ✅ |
|
||||
| iOS风格组件优先 | ✅ |
|
||||
|
||||
### 文档更新
|
||||
|
||||
| 检查项 | 状态 |
|
||||
|--------|------|
|
||||
| CHANGELOG.md 已更新 | ✅ |
|
||||
| 归档文档状态已更新 | ✅ |
|
||||
| 新增公共类有使用说明 | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 七、进度追踪
|
||||
|
||||
| 日期 | 完成步骤 | 备注 |
|
||||
|------|---------|------|
|
||||
| 2026-05-20 | 设计文档+归档文档创建 | 待开发 |
|
||||
| 2026-05-20 | Phase 1 全部完成(F1-F4) | ✅ 角色情绪+数据刷新+工具中心+音效系统 |
|
||||
| 2026-05-20 | Phase 2 全部完成(F5-F8) | ✅ 下拉刷新+TTS朗读+句子播放+3D倾斜 |
|
||||
| 2026-05-20 | Phase 3 全部完成(F9-F11) | ✅ Lottie过渡+NFC分享+摇一摇 |
|
||||
| 2026-05-20 | Phase 4 部分完成(F14) | ✅ 蓝牙近场发现 |
|
||||
| 2026-05-20 | Phase 4 完成(F12-F13) | ✅ 屏幕常亮+电池低提醒 |
|
||||
| 2026-05-20 | Phase 5 全部完成(F15-F17) | ✅ 本地通知+桌面小组件+Shader特效 |
|
||||
579
docs/superpowers/specs/2026-05-20-home-expansion-design.md
Normal file
579
docs/superpowers/specs/2026-05-20-home-expansion-design.md
Normal file
@@ -0,0 +1,579 @@
|
||||
# ============================================================
|
||||
# 闲言APP — 主页扩展功能开发计划
|
||||
# 创建时间: 2026-05-20
|
||||
# 更新时间: 2026-05-20
|
||||
# 作用: 主页交互增强17项功能的开发规划
|
||||
# 上次更新: 初始版本
|
||||
# ============================================================
|
||||
|
||||
## 一、功能总览
|
||||
|
||||
| # | 功能 | 优先级 | 使用库 | 阶段 |
|
||||
|---|------|--------|--------|------|
|
||||
| F1 | 角色持续互动增强 | P1 | 已有 | Phase 1 |
|
||||
| F2 | 拾光栏数据自动刷新 | P1 | 已有 | Phase 1 |
|
||||
| F3 | 下拉工具中心 | P1 | custom_refresh_indicator | Phase 1 |
|
||||
| F4 | 音效反馈系统 | P1 | audioplayers | Phase 1 |
|
||||
| F5 | 自定义下拉刷新(拾光角色) | P1 | custom_refresh_indicator | Phase 2 |
|
||||
| F6 | 角色语音朗读(TTS公共类) | P1 | flutter_tts | Phase 2 |
|
||||
| F7 | 句子朗读播放 | P2 | audioplayers | Phase 2 |
|
||||
| F8 | 3D倾斜卡片 | P2 | flutter_tilt | Phase 2 |
|
||||
| F9 | Lottie动画过渡 | P2 | lottie | Phase 3 |
|
||||
| F10 | NFC触碰分享(NFC公共类) | P2 | flutter_nfc_kit | Phase 3 |
|
||||
| F11 | 摇一摇换句 | P2 | sensors_plus(新增) | Phase 3 |
|
||||
| F12 | 屏幕常亮 | P3 | wakelock_plus | Phase 4 |
|
||||
| F13 | 电池低提醒 | P3 | battery_plus | Phase 4 |
|
||||
| F14 | 蓝牙近场发现 | P3 | flutter_blue_plus | Phase 4 |
|
||||
| F15 | 本地通知提醒 | P3 | flutter_local_notifications | Phase 5 |
|
||||
| F16 | 桌面小组件 | P3 | home_widget | Phase 5 |
|
||||
| F17 | Shader特效 | P3 | flutter_shaders_ui | Phase 5 |
|
||||
|
||||
---
|
||||
|
||||
## 二、Phase 1 — 核心交互增强(P1基础)
|
||||
|
||||
### F1: 角色持续互动增强
|
||||
|
||||
**现状**: 点击角色只弹出Tips气泡,缺少持续互动感
|
||||
|
||||
**目标**: 增加角色与用户的持续互动维度
|
||||
|
||||
**设计方案**:
|
||||
|
||||
1. **角色情绪系统** — 角色根据用户行为积累情绪值
|
||||
- `CharacterMood` 枚举: happy / neutral / bored / sleepy / excited
|
||||
- 情绪值存储在 AppKVStore,key=`character_mood`
|
||||
- 用户每次互动(点赞/收藏/阅读) → happy +1
|
||||
- 长时间未互动(>2h) → bored
|
||||
- 夜间(22:00-6:00) → sleepy
|
||||
- 情绪影响角色默认表情和Tips内容
|
||||
|
||||
2. **角色成长系统** — 互动积累经验值
|
||||
- 每次互动 +1 EXP,等级 = log2(EXP)
|
||||
- 等级影响角色可用的表情数量和动画精细度
|
||||
- 在角色介绍区显示等级和经验条
|
||||
|
||||
3. **角色互动反馈增强**
|
||||
- 点赞时: 角色做开心表情 + 小心心飘出
|
||||
- 收藏时: 角色做惊喜表情 + 星星闪烁
|
||||
- 长时间阅读: 角色做陪伴表情(微笑+偶尔眨眼)
|
||||
- 快速滑动: 角色做晕眩表情
|
||||
|
||||
**文件变更**:
|
||||
- 新建 `lib/features/home/providers/character_mood_provider.dart`
|
||||
- 修改 `lib/shared/widgets/appbar_character_sprite.dart` — 情绪影响默认表情
|
||||
- 修改 `lib/features/home/providers/character_tips_provider.dart` — 情绪影响Tips内容
|
||||
- 修改 `lib/features/home/presentation/date_config_sheet.dart` — 显示等级和经验条
|
||||
|
||||
---
|
||||
|
||||
### F2: 拾光栏数据自动刷新
|
||||
|
||||
**现状**: 天气/温度等数据获取后不自动刷新
|
||||
|
||||
**目标**: 数据定时刷新,避免频繁请求
|
||||
|
||||
**刷新策略**:
|
||||
|
||||
| 数据类型 | 刷新间隔 | 条件 | 缓存时长 |
|
||||
|----------|---------|------|---------|
|
||||
| 天气信息 | 30分钟 | APP在前台 | 60分钟 |
|
||||
| IP归属地 | 24小时 | 网络切换时 | 24小时 |
|
||||
| 设备信息 | 启动时1次 | 无 | 永久 |
|
||||
| 电池状态 | 5分钟 | 电量变化事件 | 10分钟 |
|
||||
| 自定义文案 | 实时 | 用户修改 | 永久 |
|
||||
|
||||
**实现方案**:
|
||||
- 在 `WeatherInfoService` 中添加定时器,30分钟自动刷新
|
||||
- 在 `AppBarDateDisplay` 的 `initState` 中启动定时刷新
|
||||
- 使用 `WidgetsBindingObserver.didChangeAppLifecycleState` 检测前后台切换
|
||||
- 前台切换时:如果距上次刷新 > 15分钟,立即刷新
|
||||
- 后台时不刷新,避免无效请求
|
||||
- 网络切换时(connectivity_plus):刷新IP归属地
|
||||
|
||||
**文件变更**:
|
||||
- 修改 `lib/core/services/weather/weather_info_service.dart` — 添加定时刷新
|
||||
- 修改 `lib/core/services/weather/weather_info_provider.dart` — 生命周期感知
|
||||
- 修改 `lib/shared/widgets/appbar_date_display.dart` — 自动刷新逻辑
|
||||
- 新建 `lib/core/services/device/battery_info_service.dart` — 电池状态服务
|
||||
|
||||
---
|
||||
|
||||
### F3: 下拉工具中心
|
||||
|
||||
**现状**: 主页没有自定义下拉刷新,只有Header区的刷新按钮
|
||||
|
||||
**目标**: 靠下方区域下拉展开工具中心
|
||||
|
||||
**交互设计**:
|
||||
- 句子列表区域(非卡片区域)下拉 → 展开工具中心面板
|
||||
- 工具中心内容: 扫一扫 / 传输助手 / 朗读模式 / 深色模式 / 摇一摇 / 更多
|
||||
- 下拉过程中: 拾光角色做"拉开抽屉"表情
|
||||
- 松手后: 如果拉过阈值则展开,否则弹回
|
||||
- 工具中心使用 `stupid_simple_sheet` 的 glass 效果
|
||||
|
||||
**手势冲突处理**:
|
||||
- 句子卡片区域(上方): 左右滑动切换卡片,下拉不触发工具中心
|
||||
- 句子列表区域(下方): 下拉触发工具中心
|
||||
- 使用 `custom_refresh_indicator` 的 `offsetToArmed` 参数控制触发区域
|
||||
|
||||
**文件变更**:
|
||||
- 新建 `lib/features/home/presentation/home_tool_center.dart` — 工具中心面板
|
||||
- 修改 `lib/features/home/presentation/home_page.dart` — 集成下拉手势
|
||||
|
||||
---
|
||||
|
||||
### F4: 音效反馈系统
|
||||
|
||||
**现状**: 点赞/收藏/滑动等操作无声音反馈
|
||||
|
||||
**目标**: 全局音效反馈,在通用设置中管理
|
||||
|
||||
**音效清单**:
|
||||
|
||||
| 操作 | 音效文件 | 时长 |
|
||||
|------|---------|------|
|
||||
| 点赞 | like_pop.mp3 | 0.3s |
|
||||
| 取消点赞 | unlike_soft.mp3 | 0.2s |
|
||||
| 收藏 | favorite_star.mp3 | 0.4s |
|
||||
| 取消收藏 | unfavorite.mp3 | 0.2s |
|
||||
| 卡片滑出 | card_swipe.mp3 | 0.3s |
|
||||
| 频道切换 | tab_click.mp3 | 0.15s |
|
||||
| 下拉刷新 | refresh_bubble.mp3 | 0.5s |
|
||||
| 角色互动 | character_pop.mp3 | 0.3s |
|
||||
| 摇一摇 | shake_bell.mp3 | 0.4s |
|
||||
|
||||
**实现方案**:
|
||||
- 新建 `lib/core/services/audio/sfx_service.dart` — 音效公共类
|
||||
- 单例模式,使用 `audioplayers` 的 `AudioPlayer` 播放短音效
|
||||
- `play(SfxType type)` — 播放指定音效
|
||||
- `setVolume(double v)` — 设置音量
|
||||
- `setEnabled(bool v)` — 开关
|
||||
- 音效文件放在 `assets/sounds/sfx/` 目录
|
||||
- 在通用设置中添加:
|
||||
- "音效反馈" 开关 (id: `sfx`, 默认: true)
|
||||
- "音效类型" 选择器 (id: `sfx_style`, 选项: 标准/柔和/清脆/无)
|
||||
- 在各交互点调用 `SfxService.instance.play(SfxType.like)` 等
|
||||
|
||||
**文件变更**:
|
||||
- 新建 `lib/core/services/audio/sfx_service.dart`
|
||||
- 新建 `assets/sounds/sfx/` 目录 + 音效文件
|
||||
- 修改 `lib/features/settings/providers/general_settings_provider.dart` — 添加 sfx 设置项
|
||||
- 修改 `lib/features/settings/presentation/general/general_settings_sections.dart` — 添加 UI
|
||||
- 修改 `lib/features/home/providers/home_interaction_mixin.dart` — 点赞/收藏音效
|
||||
- 修改 `lib/features/home/presentation/home_daily_card.dart` — 卡片滑动音效
|
||||
|
||||
---
|
||||
|
||||
## 三、Phase 2 — 角色深度交互(P1进阶)
|
||||
|
||||
### F5: 自定义下拉刷新(拾光角色)
|
||||
|
||||
**目标**: 下拉时拾光角色做对应表情动画
|
||||
|
||||
**动画设计**:
|
||||
|
||||
| 下拉进度 | 角色表情 | 角色动作 |
|
||||
|----------|---------|---------|
|
||||
| 0-30% | 好奇 | 头微上抬,眼睛放大 |
|
||||
| 30-60% | 惊讶 | 嘴巴O型,耳朵竖起 |
|
||||
| 60-90% | 紧张 | 脸蛋鼓起,闭眼 |
|
||||
| 90-100% | 决心 | 睁大眼,嘴巴紧闭 |
|
||||
| 释放刷新中 | 思考 | 眼珠转动,嘴巴微动 |
|
||||
| 刷新完成 | 开心 | 大笑+腮红+耳朵摆动 |
|
||||
| 刷新失败 | 难过 | 嘴角下垂,眼睛水汪汪 |
|
||||
|
||||
**实现方案**:
|
||||
- 使用 `custom_refresh_indicator` 包裹句子列表区域
|
||||
- 自定义 `CustomRefreshIndicator` 的 `builder` 参数
|
||||
- 在 builder 中根据 `data.value` (0.0~1.0+) 绘制角色状态
|
||||
- 角色绘制复用 `AppBarCharacterSprite` 的 Painter 逻辑
|
||||
- 刷新触发 `homeProvider.notifier.refresh()`
|
||||
|
||||
**文件变更**:
|
||||
- 新建 `lib/features/home/presentation/home_refresh_indicator.dart` — 自定义刷新指示器
|
||||
- 修改 `lib/features/home/presentation/home_page.dart` — 集成刷新指示器
|
||||
|
||||
---
|
||||
|
||||
### F6: 角色语音朗读(TTS公共类)
|
||||
|
||||
**目标**: 创建TTS公共类,点击角色朗读当前每日推荐句子
|
||||
|
||||
**TTS公共类设计** — `lib/core/services/audio/tts_service.dart`:
|
||||
|
||||
```dart
|
||||
class TtsService {
|
||||
static final TtsService instance = TtsService._();
|
||||
|
||||
// 核心方法
|
||||
Future<void> init(); // 初始化引擎
|
||||
Future<void> speak(String text); // 朗读文本
|
||||
Future<void> stop(); // 停止朗读
|
||||
Future<void> pause(); // 暂停
|
||||
Future<void> resume(); // 继续
|
||||
|
||||
// 配置方法
|
||||
Future<void> setLanguage(String lang); // 设置语言(zh-CN/en-US)
|
||||
Future<void> setSpeed(double rate); // 语速 0.0~1.0
|
||||
Future<void> setPitch(double pitch); // 音调 0.5~2.0
|
||||
Future<void> setVolume(double volume); // 音量 0.0~1.0
|
||||
|
||||
// 状态查询
|
||||
bool get isSpeaking;
|
||||
bool get isAvailable;
|
||||
|
||||
// 跨平台兼容
|
||||
Future<bool> checkPlatformSupport(); // 检查平台支持
|
||||
Future<List<TtsVoice>> getAvailableVoices(); // 可用语音列表
|
||||
|
||||
// 朗读状态回调
|
||||
void Function(TtsState state)? onStateChanged;
|
||||
void Function(int start, int end, String word)? onProgress;
|
||||
}
|
||||
```
|
||||
|
||||
**跨平台兼容处理**:
|
||||
- iOS: 使用原生 AVSpeechSynthesizer
|
||||
- Android: 使用原生 TextToSpeech
|
||||
- 鸿蒙: 检测平台,不支持时降级为静默模式
|
||||
- Windows/macOS: 支持但语音列表可能不同
|
||||
- 不支持时: `isAvailable = false`,UI隐藏朗读按钮
|
||||
|
||||
**交互设计**:
|
||||
- 点击角色 → 如果当前有每日推荐句子 → 开始朗读
|
||||
- 朗读时角色嘴巴做说话动画(同步 onProgress 回调)
|
||||
- 再次点击角色 → 停止朗读
|
||||
- 朗读完成 → 角色做微笑表情
|
||||
|
||||
**文件变更**:
|
||||
- 新建 `lib/core/services/audio/tts_service.dart`
|
||||
- 修改 `lib/shared/widgets/appbar_character_sprite.dart` — 说话动画
|
||||
- 修改 `lib/features/home/presentation/home_page.dart` — 角色点击朗读
|
||||
|
||||
---
|
||||
|
||||
### F7: 句子朗读播放
|
||||
|
||||
**目标**: 在句子详情Sheet中增加朗读按钮和进度条
|
||||
|
||||
**交互设计**:
|
||||
- SentenceDetailSheet 底部操作栏增加 🎵 朗读按钮
|
||||
- 点击后使用 TtsService 朗读句子内容
|
||||
- 朗读时显示进度条(基于 onProgress 回调)
|
||||
- 支持暂停/继续/停止
|
||||
- 朗读速度可在通用设置中调整
|
||||
|
||||
**文件变更**:
|
||||
- 修改 `lib/features/home/presentation/providers/sentence_detail_sheet.dart` — 添加朗读按钮
|
||||
- 新建 `lib/shared/widgets/tts_player_bar.dart` — 朗读进度条组件
|
||||
|
||||
---
|
||||
|
||||
### F8: 3D倾斜卡片
|
||||
|
||||
**目标**: 每日推荐卡片跟随手指倾斜
|
||||
|
||||
**实现方案**:
|
||||
- 使用 `flutter_tilt` 的 `Tilt` 组件包裹每日推荐卡片
|
||||
- 配置: `tiltDirectionController` 控制倾斜方向
|
||||
- 倾斜时卡片内部元素产生视差效果(文字和背景偏移不同)
|
||||
- 拾光角色跟随倾斜方向做"好奇"表情
|
||||
|
||||
**文件变更**:
|
||||
- 修改 `lib/features/home/presentation/home_daily_card.dart` — 包裹 Tilt 组件
|
||||
|
||||
---
|
||||
|
||||
## 四、Phase 3 — 高级交互(P2)
|
||||
|
||||
### F9: Lottie动画过渡
|
||||
|
||||
**目标**: 频道切换时播放过渡动画,空状态显示Lottie动画
|
||||
|
||||
**动画清单**:
|
||||
| 场景 | 动画 | 时长 |
|
||||
|------|------|------|
|
||||
| 频道切换 | 流体过渡 | 0.6s |
|
||||
| 空状态 | 拾光读书 | 循环 |
|
||||
| 加载中 | 拾光思考 | 循环 |
|
||||
| 网络错误 | 拾光困惑 | 循环 |
|
||||
|
||||
**文件变更**:
|
||||
- 新增 `assets/animations/` 下的 Lottie JSON 文件
|
||||
- 修改 `lib/features/home/presentation/home_page.dart` — 频道切换动画
|
||||
- 修改 `lib/features/home/presentation/home_sentence_card.dart` — 空状态/加载动画
|
||||
|
||||
---
|
||||
|
||||
### F10: NFC触碰分享(NFC公共类)
|
||||
|
||||
**目标**: 创建NFC公共类,两手机NFC触碰分享句子
|
||||
|
||||
**NFC公共类设计** — `lib/core/services/nfc/nfc_share_service.dart`:
|
||||
|
||||
```dart
|
||||
class NfcShareService {
|
||||
static final NfcShareService instance = NfcShareService._();
|
||||
|
||||
// 可用性
|
||||
Future<bool> isAvailable(); // 检查NFC是否可用
|
||||
Future<bool> isSupported(); // 检查平台是否支持
|
||||
|
||||
// 分享
|
||||
Future<void> shareSentence(HomeSentence sentence); // 写入句子到NFC标签
|
||||
Future<void> startListening(Function(HomeSentence) onReceived); // 监听NFC标签
|
||||
|
||||
// 生命周期
|
||||
Future<void> startSession({String alertMsg}); // 开始NFC会话
|
||||
Future<void> finishSession(); // 结束NFC会话
|
||||
Future<void> dispose(); // 释放资源
|
||||
|
||||
// 跨平台兼容
|
||||
// iOS: 需要NFC Reading权限,弹出系统扫描UI
|
||||
// Android: 需要NFC权限,可后台监听
|
||||
// 鸿蒙: 适配层处理,不支持时返回 isAvailable=false
|
||||
}
|
||||
```
|
||||
|
||||
**交互设计**:
|
||||
- 句子详情Sheet → 分享 → NFC分享选项
|
||||
- 触碰后写入NDEF记录(句子ID+内容摘要)
|
||||
- 接收方读取后弹出句子预览
|
||||
|
||||
**文件变更**:
|
||||
- 新建 `lib/core/services/nfc/nfc_share_service.dart`
|
||||
- 修改 `lib/features/home/presentation/providers/sentence_detail_sheet.dart` — NFC分享入口
|
||||
|
||||
---
|
||||
|
||||
### F11: 摇一摇换句
|
||||
|
||||
**目标**: 摇动手机切换每日推荐句子,角色做晕眩表情
|
||||
|
||||
**实现方案**:
|
||||
- 新增依赖 `sensors_plus: ^6.0.0`
|
||||
- 创建 `lib/core/services/device/shake_detector.dart`
|
||||
- 监听加速度传感器
|
||||
- 阈值: 加速度 > 2.5g,且距上次 > 1.5s
|
||||
- 回调: `onShake()`
|
||||
- 在通用设置中添加 "摇一摇" 开关 (id: `shake_to_switch`, 默认: false)
|
||||
- 摇一摇触发时:
|
||||
1. 角色做晕眩表情(眼睛转圈+嘴巴波浪)
|
||||
2. 切换到下一张每日推荐卡片
|
||||
3. 播放 shake_bell 音效
|
||||
|
||||
**文件变更**:
|
||||
- 修改 `pubspec.yaml` — 添加 sensors_plus
|
||||
- 新建 `lib/core/services/device/shake_detector.dart`
|
||||
- 修改 `lib/features/home/presentation/home_page.dart` — 监听摇一摇
|
||||
- 修改 `lib/shared/widgets/appbar_character_sprite.dart` — 晕眩表情
|
||||
- 修改 `lib/features/settings/providers/general_settings_provider.dart` — 添加开关
|
||||
|
||||
---
|
||||
|
||||
## 五、Phase 4 — 智能感知(P3)
|
||||
|
||||
### F12: 屏幕常亮
|
||||
|
||||
**目标**: 沉浸阅读时保持屏幕常亮
|
||||
|
||||
**实现方案**:
|
||||
- 使用 `wakelock_plus` 的 `WakelockPlus.enable()` / `disable()`
|
||||
- 在通用设置中添加 "屏幕常亮" 开关 (id: `screen_always_on`, 默认: false)
|
||||
- 模式:
|
||||
- 关闭: 系统默认超时
|
||||
- 阅读: 仅在阅读句子时保持常亮
|
||||
- 始终: APP在前台时始终常亮
|
||||
|
||||
**文件变更**:
|
||||
- 修改 `lib/features/settings/providers/general_settings_provider.dart`
|
||||
- 修改 `lib/features/home/presentation/home_page.dart` — 根据设置控制常亮
|
||||
|
||||
---
|
||||
|
||||
### F13: 电池低提醒
|
||||
|
||||
**目标**: 电池<20%时拾光角色显示担忧表情+气泡提示
|
||||
|
||||
**实现方案**:
|
||||
- 使用 `battery_plus` 监听电池状态变化
|
||||
- 创建 `lib/core/services/device/battery_info_service.dart`
|
||||
- `Stream<BatteryState> get onBatteryChanged`
|
||||
- `int get currentLevel`
|
||||
- `BatteryState get currentState` (charging/discharging/full)
|
||||
- 电池 < 20% 且未充电时:
|
||||
1. 角色切换为担忧表情(眉头皱起+嘴巴微张)
|
||||
2. 弹出气泡: "电量不多了哦,记得充电 💛"
|
||||
3. 5秒后自动收起
|
||||
- 电池 < 10%: 更强烈的担忧表情 + "电量很低了!快充电 🔴"
|
||||
- 充电中: 不触发提醒
|
||||
|
||||
**文件变更**:
|
||||
- 新建 `lib/core/services/device/battery_info_service.dart`
|
||||
- 修改 `lib/shared/widgets/appbar_character_sprite.dart` — 担忧表情
|
||||
- 修改 `lib/features/home/presentation/home_page.dart` — 监听电池状态
|
||||
|
||||
---
|
||||
|
||||
### F14: 蓝牙近场发现
|
||||
|
||||
**目标**: 发现附近使用闲言的用户,匿名分享句子
|
||||
|
||||
**实现方案**:
|
||||
- 使用 `flutter_blue_plus` 的 BLE 广播/扫描
|
||||
- 创建 `lib/core/services/bluetooth/nearby_discovery_service.dart`
|
||||
- `startBroadcast(String userId, String currentSentenceId)` — 广播自己的存在
|
||||
- `startScan()` — 扫描附近用户
|
||||
- `stopBroadcast()` / `stopScan()`
|
||||
- `Stream<NearbyUser> get onUserFound` — 发现附近用户流
|
||||
- 隐私保护:
|
||||
- 仅广播匿名ID,不暴露用户信息
|
||||
- 需要在通用设置中开启 "近场发现" (id: `nearby_discovery`, 默认: false)
|
||||
- 可设置可见性: 对所有人可见 / 仅互相关注的用户
|
||||
|
||||
**文件变更**:
|
||||
- 新建 `lib/core/services/bluetooth/nearby_discovery_service.dart`
|
||||
- 新建 `lib/features/home/presentation/nearby_users_sheet.dart`
|
||||
- 修改 `lib/features/home/presentation/home_tool_center.dart` — 近场发现入口
|
||||
- 修改 `lib/features/settings/providers/general_settings_provider.dart` — 添加开关
|
||||
|
||||
---
|
||||
|
||||
## 六、Phase 5 — 生态扩展(P3)
|
||||
|
||||
### F15: 本地通知提醒
|
||||
|
||||
**目标**: 每日定时推送一句好句
|
||||
|
||||
**实现方案**:
|
||||
- 使用 `flutter_local_notifications` 的定时通知
|
||||
- 创建 `lib/core/services/notification/daily_notify_service.dart`
|
||||
- `scheduleDailyNotification(Time time, String title, String body)` — 定时通知
|
||||
- `cancelAll()` — 取消所有通知
|
||||
- `configureNotificationChannel()` — 配置通知渠道(Android)
|
||||
- 通知内容: 每日一句 + 拾光角色图标
|
||||
- 点击通知: 打开APP并跳转到每日推荐
|
||||
- 在通用设置中添加:
|
||||
- "每日提醒" 开关 (id: `daily_notification`, 默认: false)
|
||||
- "提醒时间" 选择器 (id: `notify_time`, 默认: 08:00)
|
||||
|
||||
**文件变更**:
|
||||
- 新建 `lib/core/services/notification/daily_notify_service.dart`
|
||||
- 修改 `lib/features/settings/providers/general_settings_provider.dart`
|
||||
- 修改 `lib/features/settings/presentation/general/general_settings_sections.dart`
|
||||
|
||||
---
|
||||
|
||||
### F16: 桌面小组件
|
||||
|
||||
**目标**: 桌面显示拾光角色+每日一句
|
||||
|
||||
**实现方案**:
|
||||
- 项目已有 `home_widget` + `HomeWidgetService`
|
||||
- 扩展 `HomeWidgetService` 添加拾光角色小组件数据
|
||||
- 新增小组件类型: `dailyWithCharacter` — 每日一句+拾光角色
|
||||
- 在小组件管理页面中添加拾光角色小组件选项
|
||||
- 数据更新: 每日推荐句子更新时同步到小组件
|
||||
|
||||
**文件变更**:
|
||||
- 修改 `lib/core/services/data/home_widget_service.dart` — 添加角色小组件数据
|
||||
- 修改 `lib/features/widget/models/widget_type.dart` — 添加新类型
|
||||
- 修改 `lib/features/widget/presentation/widget_management_page.dart` — 添加选项
|
||||
- iOS: 修改 `ios/Widget/` 下的 Widget Extension 代码
|
||||
- Android: 修改 `android/app/src/main/res/layout/` 下的 Widget Layout
|
||||
|
||||
---
|
||||
|
||||
### F17: Shader特效
|
||||
|
||||
**目标**: 句子卡片背景使用Fragment Shader流体效果
|
||||
|
||||
**实现方案**:
|
||||
- 使用 `flutter_shaders_ui` 的 Fragment Shader
|
||||
- 创建 `lib/shared/widgets/shader_card_background.dart`
|
||||
- 加载 `assets/shaders/fluid.frag` 着色器
|
||||
- 参数: time (动画时间), resolution (分辨率), touch (触摸位置)
|
||||
- 效果: 流体渐变背景,跟随触摸产生涟漪
|
||||
- 应用到句子卡片背景
|
||||
- 在通用设置中添加 "特效背景" 开关 (id: `shader_background`, 默认: false)
|
||||
- 性能考虑: 仅在高端设备上默认开启,低端设备默认关闭
|
||||
|
||||
**文件变更**:
|
||||
- 新增 `assets/shaders/fluid.frag`
|
||||
- 新建 `lib/shared/widgets/shader_card_background.dart`
|
||||
- 修改 `lib/features/home/presentation/home_sentence_card.dart` — 应用Shader背景
|
||||
- 修改 `lib/features/settings/providers/general_settings_provider.dart` — 添加开关
|
||||
|
||||
---
|
||||
|
||||
## 七、通用设置新增项汇总
|
||||
|
||||
| ID | 标题 | 类型 | 分组 | 默认值 | 阶段 |
|
||||
|----|------|------|------|--------|------|
|
||||
| `sfx` | 音效反馈 | toggle | 交互设置 | true | Phase 1 |
|
||||
| `sfx_style` | 音效类型 | selection | 交互设置 | 标准 | Phase 1 |
|
||||
| `tts_speed` | 朗读语速 | selection | 交互设置 | 标准 | Phase 2 |
|
||||
| `shake_to_switch` | 摇一摇换句 | toggle | 交互设置 | false | Phase 3 |
|
||||
| `screen_always_on` | 屏幕常亮 | selection | 显示设置 | 关闭 | Phase 4 |
|
||||
| `nearby_discovery` | 近场发现 | toggle | 隐私与权限 | false | Phase 4 |
|
||||
| `daily_notification` | 每日提醒 | toggle | 通知设置 | false | Phase 5 |
|
||||
| `notify_time` | 提醒时间 | selection | 通知设置 | 08:00 | Phase 5 |
|
||||
| `shader_background` | 特效背景 | toggle | 显示设置 | false | Phase 5 |
|
||||
|
||||
---
|
||||
|
||||
## 八、新增公共类汇总
|
||||
|
||||
| 类名 | 路径 | 作用 | 阶段 |
|
||||
|------|------|------|------|
|
||||
| `SfxService` | core/services/audio/sfx_service.dart | 音效播放公共类 | Phase 1 |
|
||||
| `BatteryInfoService` | core/services/device/battery_info_service.dart | 电池状态监听 | Phase 1 |
|
||||
| `TtsService` | core/services/audio/tts_service.dart | TTS语音朗读公共类 | Phase 2 |
|
||||
| `NfcShareService` | core/services/nfc/nfc_share_service.dart | NFC分享公共类 | Phase 3 |
|
||||
| `ShakeDetector` | core/services/device/shake_detector.dart | 摇一摇检测器 | Phase 3 |
|
||||
| `NearbyDiscoveryService` | core/services/bluetooth/nearby_discovery_service.dart | 蓝牙近场发现 | Phase 4 |
|
||||
| `DailyNotifyService` | core/services/notification/daily_notify_service.dart | 定时通知服务 | Phase 5 |
|
||||
|
||||
---
|
||||
|
||||
## 九、新增三方库
|
||||
|
||||
| 库名 | 版本 | 用途 | 阶段 |
|
||||
|------|------|------|------|
|
||||
| sensors_plus | ^6.0.0 | 加速度传感器(摇一摇) | Phase 3 |
|
||||
|
||||
> 注: 其余功能均使用项目已有库,无需新增依赖
|
||||
|
||||
---
|
||||
|
||||
## 十、开发顺序依赖图
|
||||
|
||||
```
|
||||
Phase 1 (基础)
|
||||
F1 角色情绪 ──┐
|
||||
F2 数据刷新 ──┤
|
||||
F3 工具中心 ──┤──→ Phase 2 (进阶)
|
||||
F4 音效系统 ──┘ F5 下拉刷新(依赖F3)
|
||||
F6 TTS朗读(依赖F4音效)
|
||||
F7 句子朗读(依赖F6)
|
||||
F8 3D倾斜(独立)
|
||||
│
|
||||
▼
|
||||
Phase 3 (高级)
|
||||
F9 Lottie(独立)
|
||||
F10 NFC(独立)
|
||||
F11 摇一摇(依赖F4音效+F1情绪)
|
||||
│
|
||||
▼
|
||||
Phase 4 (感知)
|
||||
F12 屏幕常亮(独立)
|
||||
F13 电池提醒(依赖F1情绪)
|
||||
F14 蓝牙发现(独立)
|
||||
│
|
||||
▼
|
||||
Phase 5 (生态)
|
||||
F15 通知(独立)
|
||||
F16 小组件(依赖F2数据)
|
||||
F17 Shader(独立)
|
||||
```
|
||||
Reference in New Issue
Block a user