6.9 KiB
6.9 KiB
智念商家端 (zhinian_manage)
智念酒店景区管理端 —— 面向度假酒店与景区运营人员的一体化移动管理 App,覆盖 AI 助手、订单核销、工单流转、事件发布、扫码核销与门店运营等场景。
- 应用名:智念商家端
- Bundle ID:
com.lishaohua.zhinianManage.dev - 包名:
com.lishaohua.zhinian_manage - 版本:
1.0.0+1
技术栈
| 分类 | 选型 |
|---|---|
| 框架 | Flutter 3.41.9 / Dart 3.11 |
| 状态管理 | flutter_riverpod + hooks_riverpod + flutter_hooks |
| 路由 | go_router |
| 网络 | dio |
| 本地存储 | hive / hive_flutter / shared_preferences |
| 国际化 | flutter_localizations + intl(中文 / 英文 / 泰语) |
| Markdown 渲染 | flutter_markdown(自封装 MarkdownMessage) |
| 图表 | fl_chart |
| 图片 | cached_network_image / image_picker |
| 扫码 | mobile_scanner |
| 语音 | speech_to_text (iOS) + vosk_flutter_service (Android 离线中文) |
| 权限 | permission_handler |
| 动效 | flutter_animate / lottie / shimmer |
目录结构
zhinian_app/
├── android/ Android 原生工程(含 vivo 真机部署配置)
├── ios/ iOS 原生工程(含 Vosk xcframework、Pod 配置)
├── assets/
│ ├── logo.png
│ └── models/vosk-model-small-cn-0.22.zip 离线中文语音模型
├── lib/
│ ├── main.dart 入口、Riverpod ProviderScope、go_router
│ ├── theme.dart AppColors / 全局主题
│ ├── l10n/ app_zh.arb / app_en.arb / app_th.arb
│ ├── models/ user / message / event / order / work_order
│ ├── providers/ auth / chat / event / order / settings / work_order
│ ├── services/
│ │ ├── api_service.dart 统一 mock API + AI 回复路由
│ │ ├── storage_service.dart Hive 封装
│ │ └── vosk_voice_service.dart 离线语音识别封装
│ ├── widgets/
│ │ ├── markdown_message.dart 自封装的 Markdown 渲染(表格、图片)
│ │ ├── chart_block.dart ```chart``` 代码块渲染为 fl_chart
│ │ └── skeleton.dart 骨架屏
│ └── pages/ 17 个业务页面(登录、首页、订单、工单、事件、扫码、门店、报表、设置等)
└── pubspec.yaml
关键架构说明
1. AI 聊天 + 富文本渲染
聊天内容统一走 Markdown,但 flutter_markdown 对块级标签(pre、table)不会调用注册的 builder,会无脑用 styleSheet.codeblockDecoration 包裹。为此 widgets/markdown_message.dart 做了两层处理:
- 表格:在进入
MarkdownBody之前用正则把 Markdown 切成「文本段」和「表格段」,表格段交给自定义_ScrollableTable(基于Table+IntrinsicColumnWidth+ 横向滚动)渲染,避免裁切。 - 代码块/图表:在
MarkdownStyleSheet上把codeblockDecoration设为透明、codeblockPadding设为零;chart代码块由ChartCodeBuilder拦截 inlinecode元素,解析key: value行后用fl_chart绘制柱状图/折线图/饼图,数据多于可视宽度时同样支持横向滚动。 - 图片:
MarkdownBody.imageBuilder返回_MarkdownImage,点击进入_ImageViewer(PageRouteBuilder+Hero+InteractiveViewer,最大缩放 4 倍);打开/关闭时显式FocusManager.instance.primaryFocus?.unfocus(),避免输入框抢焦点弹出键盘。
2. AI 关键词路由
services/api_service.dart 的 sendMessage 按顺序匹配关键词,命中后返回固定 mock 数据,演示三类富文本:
| 触发词 | 返回 |
|---|---|
| 表格 / 列表 / 清单 / 明细 | _tableReport() 订单明细 + 汇总两张表 |
| 图片 / 照片 / 图像 / 实景 / 环境照 / 相册 | _imageGallery() 三张 picsum 实景图 |
| 报表 / 数据 / 营收 / 趋势 / 占比 / 图表 / 统计 / 分析 | _chartReport() 柱/折/饼三张图表 |
未命中时随机返回一条短文本,用于演示普通对话。
3. 语音输入
- iOS 走
speech_to_text,需要在Info.plist声明NSMicrophoneUsageDescription/NSSpeechRecognitionUsageDescription。 - Android 走
vosk_flutter_service+ 内置离线模型assets/models/vosk-model-small-cn-0.22.zip,首次运行解压到沙盒。 - 麦克风入口位于聊天输入框的
suffixIcon:无边框、纯图标InkWell,激活时图标变色并做呼吸缩放动画。
4. 国际化
通过 flutter gen-l10n 生成,默认中文,Settings 页可切换。新增文案需同步更新 lib/l10n/app_*.arb。
环境准备
- Flutter SDK:3.41.9(channel stable);项目 SDK 约束
>=3.0.0 <4.0.0。 - iOS:Xcode 15+、CocoaPods、苹果开发者账号(Team
UBDH3YTVFW,仅用于真机调试签名)。Vosk 的vosk_flutter.xcframework已在ios/下,执行pod install即可。 - Android:Android SDK + platform-tools(
adb)。已知adb不在用户 PATH,实际使用~/Library/Android/sdk/platform-tools/adb全路径。 - 国内网络:GitHub/CDN 不稳,Flutter / pub / Homebrew / Ruby 镜像配置参考全局笔记。
运行
# 安装依赖
flutter pub get
# 生成本地化代码(如修改了 .arb)
flutter gen-l10n
# iOS Pod
cd ios && pod install && cd ..
# 任意已连接设备调试
flutter run
构建与部署
iOS 真机(已使用过的命令)
# Release 构建
flutter build ios --release
# 用 devicectl 持久化安装(不会随 flutter run 退出而卸载)
xcrun devicectl device install app \
--device 00008110-001055D92183401E \
build/ios/iphoneos/Runner.app
Android 真机(vivo 75b8114)
# 只构建 arm64 加快速度
flutter build apk --target-platform=android-arm64 --release
# 安装到指定设备
~/Library/Android/sdk/platform-tools/adb -s 75b8114 install -r \
build/app/outputs/flutter-apk/app-release.apk
若 adb devices 不显示设备,先 adb kill-server && adb start-server,然后在手机上重新确认 USB 调试授权。
Git 仓库
- 远端:
git.nianxx.cn/lishaohua/zhinian_app.git(私有 Gitea) - 凭证:首次
git push需要在交互式 shell 输入用户名/密码,macOS keychain 之后会记住。
常见问题
- 图表/表格出现灰色背景 → 检查
MarkdownStyleSheet.codeblockDecoration是否设置为Colors.transparent;pre/table是块级标签,builder 不生效。 - 图表/表格被裁切 → 内置横向滚动,直接拖动即可;数据列太多时会按 56px/项 延展。
- 点击图片后输入框弹出键盘 → 已通过
FocusManager.unfocus()+rootNavigator: true+HitTestBehavior.opaque解决,若复现请检查_MarkdownImage的GestureDetector实现。 - Android 启动报麦克风崩溃 → 检查
AndroidManifest.xml是否声明RECORD_AUDIO,以及permission_handler的PERMISSION_MICROPHONE预处理标志是否在ios/Podfile中开启。