showroom_flutter 是智能床垫展厅的 Flutter 复刻工程。项目以 Flutter 绘制 1920 x 1080 横屏展示界面,并通过移动端 WebView / Web 端 iframe 承载 Three.js 3D 床垫模型,保持与 App 层交互的 JavaScript API 控制能力。
GitHub 仓库:
https://github.com/Txxyyy/showroom_flutter
- 独立 Flutter 工程,不修改原始 iOS SwiftUI 项目。
- 支持 iOS、Android 横屏沉浸式运行,并支持浏览器端联调展示页。
- 用 Flutter
CustomPainter绘制展厅背景、数据面板、波形、仪表盘、底部控制区等静态与动态 UI。 - 用 WebView 加载 Three.js 场景,展示 GLB 智能床垫模型。
- 通过
window.SmartMattress3D公开 API 控制调节模式、加热区域、复位、视角和动画。 - 支持压电高亮、双侧独立波纹、控制区与产品介绍卡片切换等演示交互。
- Flutter 3.13.9
- Dart 3.1.5
webview_flutterwebview_flutter_android- Three.js r163
- GLB 模型资源:
assets/three_adjustment/smart-mattress-replica.glb
showroom_flutter/
├── android/ Android 工程
├── ios/ iOS 工程
├── lib/
│ ├── main.dart Flutter 展厅 UI、控制区和 3D 页面桥接
│ ├── showroom_scene_embed.dart 3D 场景嵌入入口
│ ├── showroom_scene_embed_mobile.dart
│ ├── showroom_scene_embed_types.dart
│ └── showroom_scene_embed_web.dart
├── assets/
│ └── three_adjustment/
│ ├── index.html Three.js 页面入口
│ ├── scene.bundle.js 打包后的 Three.js 场景逻辑
│ ├── smart-mattress-replica.glb
│ └── vendor/three/ 本地 Three.js 依赖
├── web/ Flutter Web 入口资源
├── tool/
│ ├── preview_three_adjustment.sh 本地 3D 页面预览脚本
│ └── three_adjustment_scene_entry.js
├── pubspec.yaml
└── README.md
当前实现使用 GLB:
- WebView 加载
assets/three_adjustment/index.html - 页面加载
scene.bundle.js - Three.js 使用
GLTFLoader加载同目录下的smart-mattress-replica.glb - Flutter 通过 JavaScript 调用
window.SmartMattress3D控制模型状态
Android 端使用 WebViewAssetLoader 将 Flutter asset 暴露为:
https://appassets.androidplatform.net/flutter_assets/assets/three_adjustment/index.html
iOS 端使用本地 HTTP asset server 加载同一套 Three.js 资源。
Web 端通过 HtmlElementView + iframe 加载同一份 assets/three_adjustment/index.html,用于浏览器里做样式和交互联调。
- 轻智能大屏标题已统一为“智能床垫实时监测”。
- 3D 床垫场景已集成到 Flutter 移动端页面,支持移动端与 Web 端共用同一套 Three.js 资源。
- 压电高亮区域按模型对应侧横向居中展示,并按压电动画尺寸同步。
- 左右两侧压电采集高亮与波点涟漪都支持独立开关,不再互斥。
- 波点效果已调整为更暗的底态、更小的点径、分层高亮和更细更慢的扩散环。
- 轻智能大屏支持在“演示控制区”和“产品功能介绍”之间切换,带切换动画;产品介绍覆盖心率监测、呼吸率监测和睡眠报告输出。
flutter pub get本仓库使用技能编排式移动端开发工作流。流程按轻量、标准、严格三级执行,目标是用最少交付物换取清晰需求、可验证实现和可恢复上下文:
brainstorming:需求收敛、方案比较、设计确认。writing-plans:把确认后的设计拆成可执行的 TDD 任务计划。using-git-worktrees:按功能点创建独立 worktree,支持多会话并行;文档和单点小修可按风险跳过。test-driven-development:按 RED / GREEN / REFACTOR 实现行为变更。verification-before-completion和requesting-code-review:完成前验证和评审。finishing-a-development-branch:决定本地合并、创建 PR、保留或丢弃。
详细流程见:
docs/mobile-development-workflow.md
项目状态更新见:
docs/project-status.md
创建独立任务工作区:
git worktree add .worktrees/<task-name> -b codex/feature-<task-name> main
cd .worktrees/<task-name>
flutter pub get
flutter analyze
flutter testiOS 模拟器:
flutter run -d <ios-simulator-id> --flavor dev --dart-define=APP_ENV=devAndroid 模拟器或设备:
flutter run -d <android-device-id> --flavor dev --dart-define=APP_ENV=dev应用启动后会锁定横屏,并进入沉浸式全屏显示。
flutter run --flavor dev --dart-define=APP_ENV=dev
flutter run --flavor staging --dart-define=APP_ENV=staging
flutter run --flavor prod --dart-define=APP_ENV=prod展厅仪表盘数据已从绘制逻辑中抽离为 MattressDashboardData 和 MattressDashboardController。心率、呼吸、趋势指标、压力折线图、各模式分区压力值和 3D 床垫气囊目标值,都可以通过外部传值更新;Flutter UI 与 WebView Three.js 场景会跟随同一份数据刷新。
dev 环境默认启用 2 秒一次的 mock 数据流,用于在模拟器上观察运行时变化:
flutter run -d <ios-simulator-id> --flavor dev --dart-define=APP_ENV=dev --dart-define=SHOWROOM_MOCK_STREAM=true关闭 mock 数据流:
flutter run -d <ios-simulator-id> --flavor dev --dart-define=APP_ENV=dev --dart-define=SHOWROOM_MOCK_STREAM=false接入真实数据源时,推荐把 HTTP polling、WebSocket、蓝牙、平台通道或本地 fixture replay 适配成 Stream<Map<String, Object?>>,再传入应用:
SmartMattressShowroomApp(
config: AppEnvironmentConfig.current,
dashboardPayloadStream: someStreamOfMapPayloads,
);如果业务侧需要主动推送局部更新,也可以持有 controller:
final MattressDashboardController controller = MattressDashboardController();
SmartMattressShowroomApp(
config: AppEnvironmentConfig.current,
dashboardController: controller,
);
controller.applyPayload(payload);applyPayload 支持增量更新,未传字段会保留当前值。示例 payload:
controller.applyPayload(<String, Object?>{
'realtime': <String, Object?>{
'heartRate': 91,
'breathRate': 20,
},
'trend': <String, Object?>{
'lumbarSupportIndex': 93,
'lumbarSupportStatus': '稳定',
'ergonomicIndex': 86,
'ergonomicStatus': '良好',
},
'pressureChart': <String, Object?>{
'currentValues': <double>[7010, 7450, 8020, 7680, 7220],
'recommendedValues': <double>[6800, 7600, 7400, 8100, 6900],
'markerIndex': 2,
'markerValue': 8020,
},
'modes': <String, Object?>{
'left': <String, Object?>{
'values': <String, int>{
'shoulder': 71,
'back': 72,
'waist': 73,
'hip': 74,
'leg': 75,
},
'targets': <String, Object?>{
'waist': <String, Object?>{
'pressure': 0.77,
'glow': 0.88,
},
},
},
},
});压力分区 key 固定为 shoulder、back、waist、hip、leg;模式 key 使用 auto、zero、left、right、deep、flat。values 范围会限制在 0..100,targets.pressure 和 targets.glow 范围会限制在 0..1。
除了模式、加热和分区压力数据,当前 payload 也支持:
sensorFlow:控制左右压电采集高亮、强度和数据流速率。rippleEffect:控制左右波点涟漪开关和强度,左右状态可同时开启并异步运行。
示例:
controller.applyPayload(<String, Object?>{
'sensorFlow': <String, Object?>{
'enabled': true,
'leftEnabled': true,
'rightEnabled': false,
'intensity': 0.92,
'dataRate': 0.54,
},
'rippleEffect': <String, Object?>{
'enabled': true,
'leftEnabled': true,
'rightEnabled': true,
'intensity': 0.86,
},
});运行 Flutter Web 页面:
flutter run -d chrome --web-hostname 127.0.0.1 --web-port 3000 --dart-define=APP_ENV=dev如果只需要单独预览 Three.js 页面,可以运行:
./tool/preview_three_adjustment.sh脚本会自动选择可用端口,并输出本地预览地址。
普通 release APK:
flutter build apk --release --flavor prod --dart-define=APP_ENV=prod产物位置:
build/app/outputs/flutter-apk/app-prod-release.apk
按 CPU 架构拆包,适合真实设备分发:
flutter build apk --release --flavor prod --dart-define=APP_ENV=prod --split-per-abi产物位置:
build/app/outputs/flutter-apk/app-arm64-v8a-release.apk
build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk
build/app/outputs/flutter-apk/app-x86_64-release.apk
小米电视等真实设备通常优先安装 arm64-v8a 或 armeabi-v7a 包。x86_64 主要用于模拟器。
说明:当前仓库的 Android release 构建仍配置为 debug signing,适合本地安装演示,不适合直接用于应用市场分发。
模拟器运行:
flutter run -d <ios-simulator-id>编译 iOS release:
flutter build ios --release --flavor prod --dart-define=APP_ENV=prod如果需要真机签名,请在 Xcode 中配置 Team、Bundle Identifier 和 Provisioning Profile。
dart format lib test
flutter analyze
flutter test
flutter build apk --debug --flavor dev --dart-define=APP_ENV=dev
flutter build ios --simulator --debug --flavor dev --dart-define=APP_ENV=dev说明:部分本地环境中 flutter test 可能受 Flutter 测试 harness WebSocket 连接影响失败,需要结合当前 Flutter SDK 与本机测试环境排查。
Android 手机、模拟器和 Android TV 的 WebView 能力不完全一致。小米电视上如果出现 3D 模型不显示,优先检查:
- 电视系统内置 Android System WebView 或 Chrome 版本是否过旧。
- WebView 是否支持 WebGL。
smart-mattress-replica.glb是否被 WebView 成功请求。- 是否出现 WebGL context lost、GPU 内存不足或 GLB 解析失败。
建议通过 ADB 抓日志:
adb logcat | grep -i -E "SmartMattress|WebView|GLTF|WebGL|chromium|GL_OUT_OF_MEMORY|context"如果日志显示资源请求失败,问题多半在 WebView asset 加载路径。如果日志显示 WebGL/GPU 错误,问题多半在电视 WebView 或 GPU 能力。
App 侧优先使用细粒度 API:
window.SmartMattress3D.startReveal(...)window.SmartMattress3D.startBladder(...)window.SmartMattress3D.stopBladder(...)window.SmartMattress3D.moveCameraToSide(...)window.SmartMattress3D.moveCameraToOverview(...)window.SmartMattress3D.setHeating(...)window.SmartMattress3D.resetView({ duration: 3000 })
兼容 API:
window.SmartMattress3D.setMode(...)
assets/three_adjustment/smart-mattress-replica.glb 是当前 3D 床垫模型资源,已注册到 Flutter assets 中,release APK 会将其打包进去。
根目录调试截图、构建产物、Pods、Gradle 缓存和 Flutter 缓存均已通过 .gitignore 排除,不会提交到仓库。