Files
conti-retail-app/README.md
T
2026-08-17 15:29:55 +08:00

172 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# conti-retail-app
大陆马门店 App。Flutter + Melos 单仓多包。
架构约束全部来自相邻仓库 `conti-docs/` 的 01–14 号文档。**本仓库对这些文档的
偏离,逐条记在 [SCAFFOLD-NOTES.md](SCAFFOLD-NOTES.md)**——那份文件是回写文档的
依据,改动之前先看一眼。
---
## 怎么跑起来
三步。不要跳过第二步。
```bash
# 0. 工具链(一次性)
fvm use 3.44.9 # 或者保证 PATH 上的 flutter 就是 3.44.9
dart pub global activate melos 8.2.2
# 1. 装依赖
melos bootstrap
# 2. 生成代码(riverpod 的 *.g.dart 不入库,不跑这步全仓库编译不过)
melos run gen
# 3. 跑起来
cd app
flutter run --flavor dev -t lib/main_dev.dart --dart-define-from-file=env/dev.json
```
`--flavor` / `-t` / `--dart-define-from-file` **三个参数缺一不可**
- 少了 `--dart-define-from-file``AppEnv.fromDartDefine` 会在启动瞬间抛错。
这是故意的——带着空 baseUrl 跑起来,问题会在第一个请求 404 时才暴露。
- 少了 `-t`Flutter 会去找 `lib/main.dart`,本仓库没有这个文件。
VS Code / Android Studio 用户建议把三条 flavor 配进 `launch.json`
## 环境与工具链版本
跑通时的实测版本,与 `pubspec.lock` 一致:
| | 版本 | 备注 |
|---|---|---|
| Flutter | 3.44.9 | `.fvmrc` 里锁着 |
| Dart | 3.12.2 | **Flutter 自带的那个**,见下面的坑 |
| Melos | 8.2.2 | 配置内联在根 `pubspec.yaml`,没有 `melos.yaml` |
| flutter_riverpod | 3.3.2 | |
| riverpod_annotation | 4.0.3 | |
| riverpod_generator | 4.0.4 | |
| build_runner | 2.15.1 | |
| analyzer | 12.1.0 | |
> **riverpod 的版本被 `flutter_test` 卡着。** `flutter_test` pin 了
> `test_api 0.7.11`,往上升 riverpod 会拉起不兼容的 `analyzer`,解析直接失败。
> 想升级先确认这条链路,不要只看 pub.dev 上的最新版。
### 坑:机器上有两个 Dart SDK
如果你的 PATH 上装了独立的 Dart SDK`dart --version` 不等于 3.12.2),那么
```bash
dart run build_runner build # ← 会用错 SDK,报一堆看不懂的解析错误
```
要显式用 Flutter 自带的那个:
```bash
export FDART="$(dirname "$(which flutter)")/cache/dart-sdk/bin/dart"
$FDART run build_runner build
# fvm 用户:~/fvm/versions/stable/bin/cache/dart-sdk/bin/dart
```
`melos run gen` 内部走的是 `dart run`,所以同样受影响。最省事的做法是让 PATH
上只有 Flutter 自带的 Dart。
### 坑:melos 命令
pub cache 里只有 `melos.bat`git-bash 下直接敲 `melos` 可能找不到。用:
```bash
dart pub global run melos:melos <cmd>
```
## 常用命令
```bash
melos run gen # 代码生成(riverpod
melos run gen:watch # 开发期常驻
melos run gen:pigeon # native_* 的 Pigeon 产物(产物入库)
melos run analyze # flutter analyze --fatal-infos,含 riverpod_lint
melos run format # dart format --set-exit-if-changed
melos run test # flutter test --coverage
```
`analyze``--fatal-infos`。不加等于没加 lint——绝大多数 riverpod_lint 规则
报的是 info 级。
`riverpod_lint``flutter analyze` 直接执行(顶层 `plugins:` 映射),**不再
需要 `custom_lint`**,也没有 `dart run custom_lint` 这一步。文档 03/14 写的还是
旧方案,见 SCAFFOLD-NOTES §B。
## 包结构与依赖规则
```
app/ 壳工程。唯一知道所有包的地方:环境注入、启动编排、路由聚合
packages/
core_foundation/ AppEnv / AppException 体系 / ApiCode ← 叶子包,谁都能依赖
core_logging/ AppLogger / CrashReporter / 脱敏
core_analytics/ Analytics 接口 + 事件常量表
core_storage/ PrefsKV)。Drift 暂缓,见 SCAFFOLD-NOTES
core_auth/ AppSession 四态 / TokenStorage / SessionNotifier
core_network/ dio + 4 个拦截器 + ApiClient
core_router/ goRouterProvider / menuRouteMap / go_router re-export
core_ui/ 主题 / AsyncValueView / ErrorPresenter
core_webview/ UrlGuard / JSBridge / WebViewSession
feature_auth/ 登录、选店
feature_home/ 工作台
native_scan/ Pigeon 扫码接口(原生实现待补)
```
依赖规则(01):
- `feature_* → core_* / native_*`。**feature 之间禁止互相依赖**——两个 feature
要共享东西,说明那个东西属于某个 core_*。
- `core_* → core_*` 只允许三条边:`core_network → core_auth`
`core_router → core_auth``core_webview → core_auth`。外加所有包都可以依赖
叶子包 `core_foundation`
- `native_* ` 只依赖 Flutter SDK 和 Pigeon 产物,**一个 core_* 都不依赖**。
- feature 的 pubspec 里**不出现 `go_router`**:路由类型由 `core_router`
re-export。
### 这些规则靠 `--fatal-infos` 守,不是靠编译器(实测结论)
直觉上会以为「没在 pubspec 里声明就 import 不到」。**在 Pub Workspace 里这是错的**
所有成员包共用根目录一份 `.dart_tool/package_config.json`,任何成员都能解析到
任何其他成员。实测在 `feature_home` 里 import `feature_auth` 而不声明依赖:
```
flutter test → All tests passed! ← 编译通过,跑得起来
flutter analyze → info: depend_on_referenced_packages
```
只有一条 **info**。所以:
> **`melos run analyze` 的 `--fatal-infos` 是这套包边界唯一的强制点。**
> 谁把它从 CI 里拿掉,或者在某个包里 ignore 掉
> `depend_on_referenced_packages`,边界当天就失效,而且没有任何别的信号。
想自己复现:在 `feature_home/lib/src/` 下扔一个 import `feature_auth` 的文件,
`flutter test` 是绿的,`flutter analyze --fatal-infos` 是红的。
### 那些 `throw UnimplementedError('必须在 bootstrap 里 override')`
依赖规则会挡住一些**合理**的调用(比如 core_auth 想发 HTTP、core_webview 想
换票)。这些地方一律用依赖反转解决:包内声明 `abstract interface` + 一个会抛错
的 provider,实现落在 `app/lib/bootstrap.dart` 里 override 进去。
新增一个这样的端口时,**必须同时在 bootstrap 里接上**——它是运行期才炸的,
编译器帮不了你。
## 待办 / 阻塞项
- **iOS flavor 未配置**Scheme 和 Build Configuration 只能在 Xcode 里建,
步骤见 [`app/ios/FLAVORS.md`](app/ios/FLAVORS.md)。目前没有 Mac 构建机。
- **native_scan 没有原生实现**Pigeon 接口和 Dart 侧齐了,Kotlin/Swift 侧是
模板。现在调 `startScan` 会抛 `MissingPluginException`,属预期。
- **神策 SDK 未采购**`analyticsProvider``NoopAnalytics`。接入时注意必须在
用户同意隐私政策之后再初始化。
- **env/*.json 里全是占位域名**`SENTRY_DSN` 全空,待运维确认。
- **CI 镜像名未定**`.gitlab-ci.yml` 里标了 TODO(ops)。