技术文档.md 26.6 KB

周到安排商家(one_key)开发技术文档

本文件供后续协助开发时快速理解项目结构、代码习惯与开发约定。 最后更新:2026-08-21

0. 开发约定(重要,优先遵守)

以下是后续开发必须沿用的约定:

  1. 屏幕适配
    • 新建页面一律使用 w() / font()(来自 lib/utils/screen_util.dart),不要直接写 ScreenUtil().setWidth() / ScreenUtil().setSp()。
    • w() / font() 的入参就是 375 设计稿的数值:w(375) = 整屏宽,font(14) = 14 号字。
    • 同一个文件内绝不混用两种写法:新文件用 w()/font();修改老文件时跟随该文件已有风格(老文件多为 ScreenUtil().setWidth(x),其数值是 750 口径,不用改)。
  2. 间距:一律用 VEmptyView(高度) / HEmptyView(宽度)。
    • 注意口径:这两个组件内部直接 setWidth(数值)(未 ×2),传 750 口径数值 = 375 设计稿数值 ×2。详见 §6.2。
  3. 分割线:一律用 MyDivider(宽, 高, {color}),默认色 MyColours.color_dbe3e3。
  4. 颜色:一律从 MyColours(lib/res/colors.dart)取,不要写裸 Color(0x...)。
  5. 页面导航:新页面三步注册(Routes 常量 → route_handles Handler → NavigatorUtil 方法),见 §7。
  6. 状态管理:ChangeNotifier + provider,页面数据放 Provider,路由级用 ChangeNotifierProvider 包裹,见 §8。
  7. 网络请求:接口地址加在 HttpUrl,请求统一走 DioUtil().request<T>(),返回 BaseResp,成功码 code == 200(Constant.status_success),见 §9。

1. 项目概览

  • 项目名:one_key,App 显示名「周到安排商家」,面向餐厅/商家的预订与经营管理系统。
  • Android 包名:com.naji.one_key;iOS Bundle ID:com.naji.reserveLine。
  • Flutter:3.27.3(通过 fvm 管理,见 .fvmrc);Dart SDK >=3.0.0。
  • 服务端地址:http://xt04.colorcun.com/(lib/net/http_url.dart),请求统一 Method.post,参数作为 query 拼在 URL 上,接口名形如 ?service=Android.X.Y / ?service=App.X.Y。
  • 双版本:正常版 + 极速版(Constant.normalApp 控制,当前为 false 即双版本共存;极速版页面在 lib/pages_sim/,路由名带 _sim)。
  • 微信:AppId wx4d105e36a36a6139,UniversalLink https://xt04.colorcun.com/link/OneKey/。
  • 文案:UI 文案基本硬编码中文,lib/generated/l10n 实际使用很少。
  • 代码规模:lib/pages/ 322 个页面文件、lib/pages_sim/ 80 个、Provider 44 个、模型 202 个(其中 53 个 .g.dart)、公共组件 42 个、路由常量 244 个。

2. 环境与常用命令

fvm flutter run                      # 运行
fvm flutter pub run build_runner build --delete-conflicting-outputs   # 生成 model 的 .g.dart
fvm flutter analyze                  # 静态检查
fvm flutter test                     # 测试(当前 test/widget_test.dart 基本为注释,暂无有效用例)

3. 目录结构

目录 说明
lib/main.dart 入口:初始化路由、SharedPreferences、全局 Provider、ScreenUtilInit、MaterialApp
lib/app.dart App 全局静态类:App.sp(SharedPreferences)、App.router、App.navigatorKey、屏幕/状态栏信息
lib/pages/ 业务页面,按模块分子目录(home、login、message、notebook、table、feast、my、detail、coupon、order_advance、create_store 等)
lib/pages_sim/ 极速版页面副本,与正常版同名页面需同步维护
lib/provider/ 状态管理:ChangeNotifier 子类,命名 XxxProvider / XxxModel
lib/models/ 数据模型:json_serializable + .g.dart,常见命名 XxxSunModel
lib/net/ 网络层:dio_util.dart(DioUtil 单例)、base_resp.dart(BaseResp)、http_url.dart(接口地址常量)
lib/route/ fluro 路由:routes.dart(路径常量 + 注册)、route_handles.dart(Handler)、navigator_util.dart(跳转方法)
lib/res/ colors.dart(MyColours 色板)、dimens.dart(Dimens 字号/间距常量)、styles.dart、strings.dart
lib/utils/ screen_util.dart(w/h/font 等适配函数)、utils.dart(Utils 工具大集合)、dialog_util.dart、event_bus.dart、misc.dart(权限)等
lib/widgets/ 公共组件:SystemAppBar、RoundButton、CommonButton、VEmptyView、HEmptyView、MyDivider、ExceptionPage 等
lib/constant/ constant.dart(全局常量、权限配置)、state.dart(PageState 等枚举)、error.dart(MyError)
assets/ 图片与音频资源,已在 pubspec 全量声明
library/ 本地依赖插件(webview_flutter 修改版、sendsms、table_calendar 等)
android/ ios/ macos/ ohos/ 原生平台工程;ohos/ 为鸿蒙适配目录
test/ 仅默认 widget_test.dart,基本全注释,暂无有效测试

3.1 业务模块地图

业务模块 页面目录 主要 Provider / Model
登录 / 开店 / 店铺资料 pages/login/、pages/create_store/、pages/enter/ OtherLoginProvider、CreateStoreModel、EnterModel、HomeEnterModel、StoreBaseIndoProvider、BaseIndoProvider
首页 / Tab / 消息角标 pages/home/ MessageModel、MyTableManageHomeModel
消息中心 / 在线订单 pages/message/、pages/online_check/、pages/home_enter_order/ MessageModel、MessageDialogModel、OnlineCheckEditProvider、OrderFoodProvider
预订本 / 预订详情 / 变更预订 pages/notebook/、pages/detail/ NoteBookModel、NotebookDetailModel、NotebookDetailChangeModel*、RemarkManagerModel、BookSetTimeModel、ChooseTableModel
桌位 / 桌位照片 / 区域 pages/table/、pages/my/table_manage/、pages/my/photo_type/ TableManagerModel、TableManagerModelOrReserve、MyTableManageHomeModel、TablePhotoManagerModel
宴会 pages/feast/、pages/my/feast_manage/ FeastModel
客情 / 客户 / 营销记录 pages/my/customer_type/ CustomerProvider、CustomerMakingProvider、MarketingCenterProvider、StatisticsProvider、ContactModel
营销中心(预约通知、短信、充值、设置) pages/my/marketing_center/ MarketingCenterProvider、SmsModel、SmsRechargeModel、CouponProvider、FinanceProvider
优惠券 pages/coupon/ CouponProvider
消费金 / 会员充值 / 收银 pages/my/consume/、pages/my/finance_manage/ FinanceProvider
菜单 / 排菜 / 预点菜 pages/my/menu_type/、pages/my/plan_dish/、pages/order_advance/ MenuManageProvider、PlanDishProvider、OrderFoodProvider
员工 / 权限 / 包间类型 / 存酒 pages/my/personnel_type/、pages/my/room_type/、pages/my/store_wine_manage/ PersonnelProvider、StoreWineProvider
评价管理 pages/my/comment_manage/ CommentManageProvider
统计 pages/notebook/statistics_page.dart、pages/my/customer_type/store_customer/ StatisticsProvider、FinanceProvider
我的 / 个人信息 pages/my/my_page.dart、pages/my/base_info*.dart MyModel、UserModel、UpdateModelMy

3.2 平台工程与本地依赖

  • 原生目录:android/(包名 com.naji.one_key)、ios/(Bundle ID com.naji.reserveLine)、macos/、ohos/(鸿蒙适配,含 oh_modules 生成物)。
  • pubspec 中实际引用的本地路径依赖:webview_flutter、sendsms、device_utils_my、calendar_date_picker2、table_calendar、azlistview_plus、flutter_lunar_datetime_picker(均在 library/)。
  • library/ 下还保留了高德地图、扫码、语音、TPNS 等插件副本/历史版本;改插件前先确认 pubspec 与 .flutter-plugins-dependencies 是否实际引用,避免改错副本。
  • 语音播报资源:assets/tts_*.mp3(Android/通用)与 ios/tts_*.caf(iOS);新增语音需在 pubspec 声明对应 mp3。

4. 启动流程(main.dart)

  1. FluroRouter 创建并调用 Routes.configureRoutes(router) 注册全部路由,赋给 App.router。
  2. App.initSp() 初始化 SharedPreferences(全局通过 App.sp 访问)。
  3. runApp(MultiProvider(...)) 注册全局 Provider:MessageModel、UserModel、MessageDialogModel、OrderFoodProvider、NotebookDetailModel、CouponProvider、UploadImageProvider、CreateStoreModel、RemarkManagerModel、CustomerMakingProvider、MyTableManageHomeModel。其余 Provider 在路由 Handler 里按页注册。
  4. ScreenUtilInit(designSize: Size(750, 1334), minTextAdapt: true, splitScreenMode: true) 初始化屏幕适配,注意 设计尺寸是 750×1334。
  5. MaterialApp:主题 useMaterial3: false,primaryColor: Colors.white,iOS 转场用 PopScopePageTransitionsBuilder,home 由本地状态决定:
    • 首次打开(isFirst)→ FirstPage(初始化微信/网络等后跳登录);
    • 已登录 → HomePage(initialIndex: 1);
    • 未登录 → LoginPage。
  6. 主页等高频路由在 route_handles.dart 的 Handler 中额外包裹页面级 Provider(HomePage 会包 TableManagerModel、StoreBaseIndoProvider、CollectStoreProvider、BaseIndoProvider、PersonnelProvider)。

5. 整体架构与数据流

页面 (pages/) ── Provider.of / Consumer ──> Provider (provider/)
Provider ── DioUtil().request() ──> HttpUrl 接口 ──> 服务端 (xt04.colorcun.com)
页面状态:PageState 枚举 → ExceptionPage 统一渲染 加载中/网络错误/超时/空页面

关键点:

  • 页面通过 Provider.of<XxxProvider>(context, listen: true/false) 或 Consumer<XxxProvider> 拿数据;Provider 内部 notifyListeners() 驱动刷新。
  • 每个 Provider 通常维护若干 PageState 字段(Loading / ConnectivityError / ConnectivityTimeOut / Empty / Success 等,见 lib/constant/state.dart),页面据此渲染 ExceptionPage 或列表内容。
  • 用户信息:UserModel(全局注册),登录后用户对象 JSON 存 App.sp(key:user),通过 Provider.of<UserModel>(context, listen: false).user! 获取 sellerid / openid / token 等。
  • 权限控制:Constant.authorityConfig(模块 → 角色数组)+ Utils.getAuthority(context, '模块名') 判断当前角色是否有权。

6. UI 规范(重点)

6.1 屏幕适配:w() / font() 与 375 设计稿

lib/utils/screen_util.dart 提供顶层函数(新页面直接 import 使用):

double w(num width)   => ScreenUtil().setWidth(width * 2);   // 宽(宽度等比缩放)
double h(num height)  => ScreenUtil().setWidth(height * 2);  // 高(也是 setWidth!按宽度缩放)
double h2(num height) => ScreenUtil().setHeight(height * 2); // 高(按高度缩放,少用)
double r(num radius)  => ScreenUtil().radius(radius * 2);    // 圆角
double font(num size) => ScreenUtil().setSp(size * 2);       // 字号

由于 ScreenUtilInit 的设计尺寸是 750×1334,而上述函数内部把入参 ×2,所以:

  • w() / font() 的入参即 375 设计稿数值:w(375) = 整屏宽,w(20) = 20 逻辑像素,font(16) = 16 号字,r(8) = 8 圆角。
  • 后续设计稿按 375 宽,新页面直接把稿子上的数值填进 w()/font()/r() 即可,不需要自己换算。
  • h() 实际按宽度等比缩放(与 w() 一致),保证横向适配时高度不溢出;h2() 才是按高度缩放。

老文件大量使用 ScreenUtil().setWidth(40)、ScreenUtil().setSp(28) 这种 750 口径写法(数值 ≈ 375 值 ×2)。修改老文件时保持该文件原有写法,不要混入 w()/font();新建文件则统一用 w()/font()。

6.2 间距:VEmptyView / HEmptyView

  • VEmptyView(高度) → SizedBox(height: ScreenUtil().setWidth(高度))
  • HEmptyView(宽度) → SizedBox(width: ScreenUtil().setWidth(宽度))

⚠️ 口径注意:这两个组件内部直接 setWidth(数值),没有 ×2,所以传的是 750 口径数值。换算关系:

375 设计稿间距 代码写法
6px VEmptyView(12) / HEmptyView(12)
12px VEmptyView(24)
24px VEmptyView(48)

也就是说:375 设计稿上的间距数值 ×2 后传给 VEmptyView/HEmptyView。已有代码都是这个口径(例如 w() 风格文件中 VEmptyView(24) 与 w(12) 实际渲染尺寸一致)。

6.3 分割线:MyDivider

MyDivider(宽, 高, {color});
// 例如:MyDivider(w(375), w(1)) 默认颜色 MyColours.color_dbe3e3
// 自定义颜色:MyDivider(w(375), w(1), color: MyColours.color_DBDBDB)

新页面分割线一律用 MyDivider,不要用 Divider() / Container(color:...) 代替。

6.4 颜色:MyColours

色板集中在 lib/res/colors.dart(MyColours 类),命名 color_<十六进制>。常用色:

用途 常量 值
主色(App 主题青绿色) MyColours.app_main 0xFF24A4A8
主操作色(按钮/选中/链接) MyColours.color_199095 0xFF199095
辅助青绿(强调/标签) MyColours.color_438E93 0xFF438E93
正文深色 MyColours.color_333333 / color_353535 / color_515151 0xFF333333 等
次要文字 MyColours.color_666666 / color_777777 0xFF666666 等
弱化文字/占位 MyColours.color_999999 / color_bfbfbf 0xFF999999 等
页面背景 MyColours.color_f5f5f5 / color_f7f7f7 / color_f8f9fd 浅灰
白色 MyColours.color_ffffff 0xFFFFFFFF
红色(错误/删除/未读角标) MyColours.color_E34D59 / color_fa5151 / color_E95750 红系
分割线默认 MyColours.color_dbe3e3 0xFFdbe3e3

6.5 字号与文字

  • 新页面统一 font(数值):常用 font(10) / font(12) / font(14) / font(16) / font(18) / font(22)。
  • lib/res/dimens.dart 中有 Dimens.font_sp10~24 等常量,但页面里使用较少,新代码不强制使用。
  • 文字样式一般直接 TextStyle(fontSize: font(14), color: MyColours.color_333333);不需要 ThemeData.textTheme。

6.6 图片资源

  • 图片在 assets/,pubspec 已声明 - assets/,新图直接放入即可。
  • 加载方式:Image.asset(Utils.getImgPath('xxx'))(自动补 assets/xxx.png),或网络图 CachedNetworkImage。

6.7 常用公共组件

组件 文件 说明
SystemAppBar lib/widgets/system_app_bar.dart 标准导航栏(AppBar 实现),标题居中,返回键 assets/icon_back.png,可配右侧文字/图片按钮
MyAppBar lib/widgets/app_bar.dart 自绘导航栏,可自定义背景/字体色/右侧按钮
RoundButton lib/widgets/round_button.dart 圆角渐变按钮,常用参数 text/width/height/radius/fontSize/onPressed;w 风格文件里 width: w(48), height: h(18), radius: r(7)
CommonButton lib/widgets/common_button.dart 状态按钮,state:-1 灰禁、0 描边、1 实心主色、-3 红色
GradientButton lib/widgets/gradient_button.dart 纯渐变容器按钮
ExceptionPage lib/widgets/page_exception.dart 按 PageState 渲染 加载中/网络错误/超时/空页面,带重试回调
LoadingPage / EmptyPage / ErrorPage lib/widgets/ 状态页基础组件
Loading lib/widgets/loading.dart 全局 loading 弹层:Loading.showLoading(context) / hideLoading
MyItem lib/widgets/my_item.dart 「标题 + 内容 + 右箭头」列表行
RowMultiText lib/widgets/row_multi_text.dart 左右两段文字行
TextInputFieldWidget lib/widgets/text_input_field_widget.dart 无边框输入框
FixedText lib/widgets/fixed_text.dart 固定字号文本(textScaleFactor: 1.0)
CustomTabIndicator lib/widgets/custom_tab_indicator.dart 自定义 Tab 指示器

6.8 页面骨架模板(新页面按此写)

import 'package:flutter/material.dart';
import 'package:one_key/res/colors.dart';
import 'package:one_key/utils/screen_util.dart';          // w()/font()
import 'package:one_key/widgets/MyDivider.dart';          // 分割线
import 'package:one_key/widgets/h_empty_view.dart';       // 水平间距
import 'package:one_key/widgets/v_empty_view.dart';       // 垂直间距
import 'package:one_key/widgets/system_app_bar.dart';     // 导航栏

class DemoPage extends StatefulWidget {
  const DemoPage({super.key});

  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      // 初始化请求
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: MyColours.color_f5f5f5,
      appBar: SystemAppBar('页面标题'),
      body: Column(
        children: [
          Container(
            width: w(375),                                   // 375 设计稿直接填
            height: w(48),
            padding: EdgeInsets.symmetric(horizontal: w(20)),
            alignment: Alignment.centerLeft,
            child: Text('内容',
                style: TextStyle(
                    fontSize: font(16), color: MyColours.color_333333)),
          ),
          MyDivider(w(375), w(1)),                           // 分割线
          VEmptyView(24),                                    // 间距 = 375稿 12px
          Row(children: [
            HEmptyView(20),                                  // 水平间距 = 375稿 10px
            const Text('另一段'),
          ]),
        ],
      ),
    );
  }
}

6.9 首页 Tab 结构

HomePage(lib/pages/home/home_page.dart):PageView(NeverScrollableScrollPhysics)+ BottomNavigationBar,共 5 个 Tab:

index 页面 底部图标
0 消息 MessagePage message_default/selected.png
1 预订本 NoteBookPage(默认页) notebook_default/selected.png
2 桌位 TableManagerPage tablemanage_default/selected.png
3 宴会 FeastPage y_feast_un/sel.png
4 我的 MyPage my_default/selected.png

7. 路由规范(fluro)

当前规模:routes.dart 244 个路径常量;route_handles.dart 248 个 Handler;navigator_util.dart 245 个跳转方法。Routes.configureRoutes(router) 位于 routes.dart 文件底部,统一执行 router.define(...)。

新增页面三步:

  1. lib/route/routes.dart:定义路径常量,如 static String demo_page = "/demo_page";。
  2. lib/route/route_handles.dart:定义 Handler,构造页面并包上需要的 ChangeNotifierProvider;然后在 Routes.configureRoutes 里 router.define(Routes.demo_page, handler: xxxHandler);。
  3. lib/route/navigator_util.dart:写 static void goDemoPage(BuildContext context, {参数}),内部 App.router.navigateTo(context, "...")。

传参规则:

  • 简单参数拼在路径 query 上,如 ${Routes.demo_page}?id=$id,Handler 里 params["id"]!.first 取。
  • 复杂对象先 json.encode + FluroConvertUtils.fluroCnParamsDecode 编码,Handler 里 FluroConvertUtils.fluroCnParamsDecode(...) 解码后 XxxModel.fromJson。
  • 跳转前 NavigatorUtil 内部会先 Utils.changeStatusColor(color: MyColours.color_ffffff)。

8. 状态管理规范(provider)

  • 全局状态:main.dart 的 MultiProvider 注册(共 11 个,见 §4)。
  • 页面级状态:路由 Handler 里用 ChangeNotifierProvider<XxxProvider>(create: (_) => XxxProvider(), child: XxxPage()) 包裹(可多层嵌套)。
  • 页面取数据:Provider.of<XxxProvider>(context, listen: true)(监听)或 listen: false(不监听,如请求方法内);列表用 Consumer<XxxProvider> 更清晰。
  • Provider 内请求完成后 notifyListeners();页面 setState 一般只在页面自身状态变化时调用。
  • 页面初始化请求放在 initState + WidgetsBinding.instance.addPostFrameCallback 中(避免 build 前请求)。

9. 网络请求规范

9.1 接口定义

lib/net/http_url.dart:static const String xxx = "?service=App.X.Y"; // 注释。 基础地址 HttpUrl.server_address = "http://xt04.colorcun.com/",请求统一 Method.post,data 参数会作为 query 拼在 URL 上(DioUtil 内部 queryParameters: data)。

9.2 发起请求

BaseResp<dynamic> baseResp = await DioUtil().request<dynamic>(
    context, Method.post, HttpUrl.xxx,
    data: params,            // Map<String, String?>,会作为 queryParameters
    showLoading: true,       // 是否显示全局 loading
);
if (baseResp.code == Constant.status_success) {   // 200
  // baseResp.data / baseResp.responseData
} else {
  Utils.showToast(baseResp.msg ?? "");
}

要点:

  • BaseResp 字段:status / code / msg / data / responseData;响应结构 {ret, msg, data},ret == 200 为成功(HttpConfig 在 main.dart 的 initDio() 里配置:status: "ret", code: "ret", msg: "msg", data: "data")。
  • 常见参数:sellerid / openid 从 Provider.of<UserModel>(context, listen: false).user! 取;部分接口要 sid、uid、token。
  • 错误处理:请求抛 MyError(lib/constant/error.dart),type: 1 = 网络错误,type: 2 = 超时;Provider 里通常据此把 pageState 置为 PageState.ConnectivityError / ConnectivityTimeOut,再 notifyListeners()。
  • 断网时 DioUtil 内部会 Utils.showToast("网络错误,请稍后重试")。
  • 上传文件(FormData)可参考 FinanceProvider.upLoadApplyments / UploadImageProvider(七牛上传)。

10. 数据模型规范

  • 文件在 lib/models/,类名多为 Xxx / XxxSunModel;当前约 202 个模型文件、53 个 .g.dart。命名不统一,新增时按同类模块现有命名。
  • 使用 json_serializable:类上加 @JsonSerializable(),文件末尾 part 'xxx.g.dart';,提供 factory Xxx.fromJson(...) 与 toJson()。
  • 修改模型字段后运行 build_runner 重新生成 .g.dart: fvm flutter pub run build_runner build --delete-conflicting-outputs

11. 常用工具速查

  • Utils(lib/utils/utils.dart):
    • Utils.showToast(msg):Toast 提示;
    • Utils.changeStatusColor({color}):状态栏颜色;
    • Utils.getImgPath(name):拼 assets/name.png;
    • Utils.getAuthority(context, key):角色权限判断;
    • Utils.keySort(map):参数签名排序(部分接口需要);
    • Utils.compressImage / compressImageToFile:图片压缩;
    • 时间/农历/正则/手机号脱敏等大量工具方法。
  • DialogUtil(lib/utils/dialog_util.dart):标签选择、滚轮选择器、消息弹窗、日历选择等。
  • EventBus(lib/utils/event_bus.dart):全局 bus.on(事件名, cb) / bus.emit(事件名, arg)。
  • 权限:lib/utils/misc.dart 的 requestPermission(Permission.xxx)(带使用目的说明弹窗)。
  • 全局存储:App.sp!.getString / setString / getBool ...(SharedPreferences 单例)。

12. 注意事项与常见坑

  1. 适配写法不要混用:w() 是 375 口径、ScreenUtil().setWidth() 是 750 口径,混用会直接导致尺寸差一倍。同一文件保持一种风格。
  2. VEmptyView/HEmptyView 是 750 口径:按 375 稿子写间距要 ×2(§6.2 有对照表)。
  3. h() 是宽度等比缩放:不要用它做需要按屏幕高度伸缩的布局;需要高度适配用 h2()。
  4. 极速版同步:lib/pages_sim/ 是极速版副本,修改正常版核心页面时注意是否需要在 sim 版同步;路由常量带 _sim 后缀。
  5. 老页面是状态机:列表页先判 PageState 再渲染 ExceptionPage / ListView,不要绕过直接写列表。
  6. 接口地址都在 HttpUrl:不要在新代码里硬编码 URL。
  7. 模型改了记得跑 build_runner,否则 fromJson 不会更新。
  8. 打包注意事项(lib/constant/constant.dart 注释):Constant.normalApp 控制极速版是否打包;测试账号已由 0001 换成 0019;微信小程序类型 Constant.wxMiniProgramType 分正式/体验/开发。
  9. 新建图片记得放 assets/(目录已全量声明,无需改 pubspec,除非新增音频 mp3 需单独声明)。
  10. 请求里传 sellerid/openid 前判空,UserModel 未登录时 user 可能为 null。

13. 高频改动定位

目标 入口
新增接口 lib/net/http_url.dart
新增页面/跳转 lib/route/routes.dart + route_handles.dart + navigator_util.dart
用户登录/微信/店铺绑定 lib/pages/login/、lib/provider/user_model.dart
首页 Tab、底部导航、消息角标 lib/pages/home/home_page.dart、lib/provider/message_model.dart
预订本列表 lib/pages/notebook/notebook_page.dart、lib/provider/notebook_model.dart
订单详情/变更预订/处理在线预订 lib/pages/detail/、lib/provider/notebook_detail_model.dart、notebook_detail_change_model*.dart
桌位/区域/照片 lib/pages/table/、lib/pages/my/table_manage/、lib/pages/my/photo_type/
宴会 lib/pages/feast/、lib/pages/my/feast_manage/、lib/provider/feast_model.dart
客情/客户/营销 lib/pages/my/customer_type/、lib/provider/customer_provider.dart
营销中心/预约通知/短信 lib/pages/my/marketing_center/、lib/provider/marketing_center_provider.dart
优惠券 lib/pages/coupon/、lib/provider/coupon_provider.dart
消费金/会员充值/收银 lib/pages/my/consume/、lib/pages/my/finance_manage/、lib/provider/finance_provider.dart
我的页面/个人信息 lib/pages/my/my_page.dart、lib/pages/my/base_info.dart、lib/provider/my_model.dart
权限配置 lib/constant/constant.dart 的 Constant.authorityConfig
极速版 对应页面在 lib/pages_sim/,路由带 _sim

14. 新页面开发 Checklist

  • 页面文件放对应业务目录(lib/pages/模块/xxx_page.dart),类名 XxxPage;
  • import utils/screen_util.dart,全程用 w()/font()/r(),不写 ScreenUtil().setWidth;
  • 间距用 VEmptyView/HEmptyView(375 稿数值 ×2),分割线用 MyDivider;
  • 颜色只从 MyColours 取;
  • 导航栏用 SystemAppBar(普通页)/ MyAppBar(自定义样式);
  • 请求方法放对应 Provider,HttpUrl 加接口,成功判断 code == Constant.status_success;
  • 页面状态用 PageState + ExceptionPage;
  • 在 routes.dart、route_handles.dart、navigator_util.dart 完成三步注册;
  • 需要权限的入口用 Utils.getAuthority(context, key) 过滤;
  • 涉及正常版/极速版双端时,检查 pages_sim 是否需要同步。