# 2026-10-17 K7 首页轮播图 + 站内信通知 ## 一、目标与边界 本批只完成 Flutter 客户端两项能力: - K7-A:增强现有 `CoverCarousel`,继续使用 `feed.banners` 和 3D 翻转风格, 增加自动轮播、交互暂停、指示器、失败占位和语义。 - K7-B:新增匿名站内信分页页,接入 `GET /app/notices`,在我的页增加通知入口。 - K7-C:补轮播/通知/响应式与 locale 时间测试。 不做已读未读、红点、FCM、通知设置、`/app/config noticeEnabled`、首页铃铛、 新 banner 接口、后端、Web 或 specs 修改。 ## 二、契约口径 ### Banner - 数据源:`GET /app/home/feed` / `GET /app/discover/feed` 的 `banners[]`。 - 无独立接口;空列表继续 `SizedBox.shrink()`。 - 点击继续沿用 `linkType=DRAMA` + `linkValue` 的现有 `onOpen`。 ### Notices - `GET /app/notices?pageIndex=1&pageSize=20`,匿名。 - 响应:`{total, list:[{id,title,content,type,publishAt,expireAt}]}`。 - ID 全部按字符串;`total` 是数字。 - `list.length` 用于判断当前页是否有数据;是否加载更多按 “已加载数量 < total”判断。 - `type` 原样展示,不建立客户端枚举映射。 ## 三、预计影响文件 轮播: - `lib/pages/discover/widgets/cover_carousel.dart` - `lib/pages/discover/discover_view.dart` - `lib/core/widgets/remote_image.dart`(可选失败图标参数) - `test/discover/cover_carousel_test.dart` 通知: - `lib/core/data/models/notice.dart` - `lib/core/data/remote/notice_api.dart` - `lib/core/data/repositories/notice_repository.dart` - `lib/core/data/services/notices_controller.dart` - `lib/pages/notices/notices_page.dart` - `lib/pages/mine/mine_view.dart` - `lib/app.dart`(NoticeRepository Provider) - `test/notice/**` - `lib/l10n/app_{en,zh,id}.arb` 与生成文件 ## 四、实现口径 ### 轮播 - `Timer.periodic` 4.5s;单张不创建定时器;`dispose` 取消。 - 使用 `TickerMode.of(context)`/`Visibility` 语义监听页面可见性; 不可见时取消,恢复时重新启动。 - pointer down 暂停,up/cancel 恢复;拖拽时沿用现有 3D 翻转。 - 指示器采用底部圆点,使用 `AppColors.onPrimary` + `muted` 低透明度。 - 语义标签进入三语 arb。 - 图片失败使用现有 `RemoteImage` 并显示图标占位。 ### 通知 - `NoticesController` 管理首屏、分页、加载更多、刷新、错误。 - `NoticesPage` 深色页,保留 K5/K6 主题与 Haptics 不触发滑动振动。 - 列表项标题/类型/时间/两行摘要;点击打开详情 Dialog。 - 详情 `content` 用可滚动 `Text` 保留 `\n`,长内容不溢出。 - `publishAt` / `expireAt` 使用现有 `formatLocalizedDateTime`。 - 我的页 `_menuCard` 增加通知入口,匿名可进入。 ## 五、TDD 顺序 1. 轮播:自动切页、单张无 Timer、指示器、触摸暂停、点击回调、失败占位。 2. 通知 API/model:分页字段、字符串 ID、时间解析。 3. Controller:首屏、追加、加载更多条件、空/失败/刷新。 4. NoticesPage:三态、列表、分页、详情、长内容、小屏。 5. 我的页入口与三语文案。 6. 门禁:`dart analyze lib test`、`flutter test`、 `flutter build apk --debug`。 ## 六、风险与待确认 - 自动轮播 Timer 与 3D AnimationController 并存,需避免 dispose 后 setState。 - 页面用 `IndexedStack` 保持状态,需通过 `TickerMode` 判断真实可见性。 - `total` 可能在分页期间变化,以本次响应 total 与已加载数量比较。 - 详情长内容必须可滚动,避免小屏 overflow。 - `noticeEnabled` 属 `/app/config`,本批不接;通知入口暂时常驻,已登记后续。 - 无独立 banner 接口和已读接口,不自行扩展契约。