# 智念商家端 (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` 拦截 inline `code` 元素,解析 `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`。 ## 环境准备 1. **Flutter SDK**:3.41.9(channel stable);项目 SDK 约束 `>=3.0.0 <4.0.0`。 2. **iOS**:Xcode 15+、CocoaPods、苹果开发者账号(Team `UBDH3YTVFW`,仅用于真机调试签名)。Vosk 的 `vosk_flutter.xcframework` 已在 `ios/` 下,执行 `pod install` 即可。 3. **Android**:Android SDK + platform-tools(`adb`)。已知 `adb` 不在用户 PATH,实际使用 `~/Library/Android/sdk/platform-tools/adb` 全路径。 4. **国内网络**:GitHub/CDN 不稳,Flutter / pub / Homebrew / Ruby 镜像配置参考全局笔记。 ## 运行 ```bash # 安装依赖 flutter pub get # 生成本地化代码(如修改了 .arb) flutter gen-l10n # iOS Pod cd ios && pod install && cd .. # 任意已连接设备调试 flutter run ``` ## 构建与部署 ### iOS 真机(已使用过的命令) ```bash # Release 构建 flutter build ios --release # 用 devicectl 持久化安装(不会随 flutter run 退出而卸载) xcrun devicectl device install app \ --device 00008110-001055D92183401E \ build/ios/iphoneos/Runner.app ``` ### Android 真机(vivo 75b8114) ```bash # 只构建 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` 中开启。