Flutter+开源鸿蒙实战|城市共享驿站智能存取系统 Day1 项目初始化+架构分层+多端适配+全局状态基座
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
html
<!-- Schema.org 结构化数据 -->
<script type="application/ld+json">
{
"@context":"https://schema.org",
"@type":"BlogPosting",
"headline":"Flutter+开源鸿蒙实战 城市共享驿站智能存取系统Day1 项目初始化+架构分层+全局状态+鸿蒙多端基座(超详细)",
"author":{"@type":"Person","name":"鸿蒙跨端开发者"},
"publisher":{"@type":"Organization","name":"开源鸿蒙技术社区"},
"datePublished":"2026-05-09",
"description":"彻底脱离校园场景!全新城市级商业项目:城市共享驿站智能存取系统,支持快递柜智能开箱、快件寄存/取件、超时计费、订单流水、用户会员分级、驿站网点定位、扫码模拟开箱,高含金量无烂大街业务。Day1从零搭建企业级项目架构,超详细步骤拆解、每步带操作说明,新手可直接跟着落地,适配开源鸿蒙全终端",
"keywords":"Flutter,开源鸿蒙,OpenHarmony,共享驿站,智能快递柜,存取件系统,会员分级,超时计费,商业级毕设项目,Flutter项目初始化,鸿蒙多端适配"
}
</script>

一、前言
哈喽小伙伴们,这次咱们彻底打破"校园项目"的局限,不做任何和校园相关的功能,直接切入城市民生商业场景 ,打造一套城市共享驿站智能存取系统------完全对标现实生活中,小区、商圈、写字楼楼下的智能快递柜+共享寄存驿站,是一套真正能落地、有商业价值的项目。
为什么说这个项目含金量高、不烂大街?
第一,场景稀缺:不同于外卖、商城、校园管理这类同质化严重的项目,共享驿站聚焦"城市便民存取",覆盖快递寄存、临时物品存放、大件行李暂存等高频需求,贴近真实商业逻辑;
第二,技术点全面:集成定位、扫码、权限、缓存、状态管理、多端适配等多个实用技术,不是简单的页面堆砌,而是有完整的业务闭环和复杂逻辑;
第三,架构规范:按企业级开发标准搭建分层架构,不是新手杂乱的代码堆放,后期可扩展、可维护,不管是毕设答辩、课程设计,还是求职作品集,都能脱颖而出。
全程依旧保持咱们的固定风格,同时做了全面升级,重点突出"详细、落地、易懂":
- 口语化叙事,不机械、不生硬,前言铺垫充足、结尾总结饱满,每一步都像我在旁边手把手教你;
- 每一段代码上方,都配有超详细的文字讲解,不光说"这段代码做什么",还说"为什么这么写、新手容易哪里出错、怎么规避",彻底打消新手的疑惑;
- 代码板块拆分极细,每段只保留核心5--6行,简洁不堆砌,方便直接复制使用,同时标注关键代码的作用,避免复制后看不懂;
- 全程基于Flutter开发,集成多个商业级第三方库,每一个库的用途、配置方法都讲清楚,适配开源鸿蒙手机、平板、智能终端设备;
- 分点清晰,不管是开发任务、操作步骤,还是常见问题,都用明确的标题和分点拆解,一眼就能找到重点;
- 预判新手开发时的所有疑惑和报错,逐点给出"问题原因+具体解决步骤",跟着写就能完整跑通,不用自己查资料踩坑。
今天Day1,我们不急于写任何业务功能,核心目标是打好企业级项目的底层基座------把项目从0到1初始化、规范目录、配置依赖、搭建骨架,为后续Day2到Day7的复杂业务(扫码开箱、定位找驿站、超时计费、会员权益)铺好路,避免后期代码杂乱、难以维护。
今日Day1 核心开发任务(分点清晰,逐一落地)
- 全新创建纯净Flutter项目,配置开源鸿蒙编译运行环境(含具体操作步骤);
- 引入项目必备的6个商业级第三方库,逐一说明每个库的用途、版本选择原因;
- 搭建企业级分层工程目录,详细说明每个文件夹的作用、文件存放规范;
- 设计用户身份实体模型,明确普通用户/会员用户的权限差异,完善模型字段;
- 搭建全局认证GetX控制器,详细讲解响应式变量、方法的作用,实现全局状态管理;
- 全局集成屏幕适配框架,说明适配原理、基准尺寸选择,实现鸿蒙全终端适配;
- 初始化全局主题、路由配置,注入全局控制器,讲解配置逻辑;
- 搭建五大核心业务页面空壳,封装全局底部导航栏,实现页面切换逻辑;
- 整理新手新建项目、配置依赖、适配鸿蒙时的5个高频问题,逐点给出具体解决步骤。
二、版块1:新建Flutter项目(超详细步骤,新手零踩坑)
文字讲解(一步一操作,跟着来就对了)
我们从"新建项目"开始,全程不跳过任何一个步骤,确保新手也能顺利创建并运行项目,同时适配开源鸿蒙环境,避免出现"新建项目后无法运行"的问题。
步骤1:打开Android Studio,创建新项目
- 打开Android Studio(确保已安装Flutter插件、鸿蒙SDK);
- 点击首页"Start a new Flutter project",选择"Flutter Application",点击Next;
- 填写项目基本信息(重点注意3点):
- Project name:填写"city_share_station"(小写+下划线,符合Flutter命名规范,避免中文、大写);
- Flutter SDK path:选择自己电脑上的Flutter SDK路径(找不到可通过"flutter doctor"命令查询);
- Project location:选择自己的项目保存路径(不要有中文、空格,避免后期编译报错);
- 点击Next,填写Package name(包名,格式如"com.example.city_share_station",后期打包、上架需要,建议固定);
- 点击Finish,等待项目初始化(首次初始化可能需要几分钟,耐心等待,不要中途中断)。
步骤2:删除默认冗余代码(规范项目初始状态)
项目初始化完成后,默认会有一些示例代码(如计数器、默认图标),这些代码对我们的项目没用,而且会导致项目杂乱,我们统一删除,保留纯净的项目结构:
- 打开lib/main.dart文件,删除默认的_MyHomePageState类、MyHomePage类;
- 保留main函数和MyApp类的空壳,删除里面的所有冗余代码(如AppBar标题、body内容);
- 删除assets文件夹(暂时用不到,后期需要再创建);
- 检查pubspec.yaml文件,删除默认的assets配置、flutter_test依赖(暂时用不到)。
步骤3:配置鸿蒙运行环境(关键步骤,避免无法运行)
确保项目能在鸿蒙手机、平板、模拟器上正常运行,重点配置2点:
- 打开pubspec.yaml文件,在flutter节点下添加鸿蒙适配配置(自动兼容鸿蒙终端):
yaml
flutter:
uses-material-design: true
# 鸿蒙适配配置(新增)
plugin:
platforms:
ohos:
package: com.example.city_share_station
moduleName: city_share_station_ohos
distributedNotificationEnabled: true
- 配置鸿蒙模拟器/真机:
- 打开鸿蒙模拟器(或连接鸿蒙真机),确保模拟器/真机已开启开发者模式;
- 在Android Studio顶部,选择对应的鸿蒙设备(如"HarmonyOS Emulator");
- 点击运行按钮(绿色三角),测试项目是否能正常启动(启动成功会显示空白页面,说明配置无误)。
三、版块2:引入项目必备第三方依赖库(逐库讲解,用途清晰)
文字讲解
这套共享驿站系统用到的技术点比普通项目多很多,需要提前引入全套第三方库,每一个库都是商业级项目常用的,后续网点定位、扫码开箱、本地记录缓存、权限判断都要依赖这些库支撑。
下面逐一讲解每个库的用途、版本选择原因,然后给出完整的依赖配置,新手直接复制即可,不要随意改动版本号(避免版本冲突)。
各依赖库详细说明(分点清晰)
- get: ^4.6.6
- 用途:全局状态管理、路由跳转、依赖注入,是Flutter商业级项目最常用的状态管理库,比Provider、Bloc更简洁,新手容易上手;
- 版本选择:4.6.6是稳定版,兼容性强,不会出现和鸿蒙环境冲突的问题,避免使用最新版(可能有未修复的bug)。
- flutter_screenutil: ^5.9.0
- 用途:全局屏幕适配,一套尺寸代码,自动适配鸿蒙手机、平板、智能大屏终端,不用手动计算不同分辨率的尺寸;
- 版本选择:5.9.0支持Flutter最新版本,适配鸿蒙全终端,不会出现布局拉伸、错乱的问题。
- shared_preferences: ^2.2.2
- 用途:本地缓存,用于保存用户登录状态、会员信息、常用驿站、历史订单等数据,即使退出APP、重启鸿蒙设备,数据也不会丢失;
- 版本选择:稳定版,兼容性强,无需额外配置,直接调用即可。
- permission_handler: ^10.4.0
- 用途:权限管理,用于申请手机定位、相机(扫码)、存储等权限,鸿蒙系统需要手动申请权限才能使用相关功能;
- 版本选择:支持鸿蒙系统权限申请,调用方法简单,新手容易上手。
- flutter_map: ^6.1.0
- 用途:地图定位,用于展示城市内所有共享驿站网点、定位用户当前位置、规划前往驿站的路线;
- 版本选择:轻量级地图库,比高德、百度地图SDK更简洁,无需申请第三方密钥,适合快速开发。
- qr_code_scanner: ^1.0.1
- 用途:扫码功能,用于扫描驿站快递柜的二维码,实现智能开箱、取件、寄存操作;
- 版本选择:稳定版,支持鸿蒙系统相机调用,扫码速度快,无卡顿。
完整依赖配置代码(直接复制)
打开pubspec.yaml文件,找到"dependencies"节点,删除默认冗余依赖,粘贴下面的完整配置:
yaml
dependencies:
flutter:
sdk: flutter
# 状态管理+路由
get: ^4.6.6
# 屏幕适配
flutter_screenutil: ^5.9.0
# 本地缓存
shared_preferences: ^2.2.2
# 权限管理
permission_handler: ^10.4.0
# 地图定位
flutter_map: ^6.1.0
# 扫码功能
qr_code_scanner: ^1.0.1
依赖安装操作步骤
- 粘贴完依赖配置后,点击pubspec.yaml文件顶部的"Pub get"按钮(或在终端输入命令);
- 终端执行安装命令(推荐,避免点击按钮出现安装失败):
bash
flutter pub get
- 安装完成后,查看控制台输出,若显示"Process finished with exit code 0",说明依赖安装成功;
- 若出现安装失败、版本冲突,不要慌,解决方案:关闭Android Studio,清空项目缓存(File → Invalidate Caches...),重新打开项目,再次执行flutter pub get即可。
四、版块3:搭建企业级分层工程目录(规范结构,后期好维护)
文字讲解
商业级项目绝对不能把所有页面、代码都堆在lib根目录,否则后期功能增多后,代码会变得杂乱不堪,找文件、改bug都要花大量时间。
下面我给你规划好标准的企业级分层目录,每一个文件夹各司其职,详细说明每个文件夹的作用、文件存放规范,新手严格按照这个结构创建,养成正规开发习惯。
步骤1:创建目录结构(逐一创建,不遗漏)
打开lib文件夹,右键新建文件夹,按以下结构逐一创建(文件夹名称全部小写+下划线,符合Flutter命名规范):
lib/
├── core/ # 全局核心配置(整个项目的基础配置,只放全局通用的内容)
├── models/ # 数据实体模型(所有业务的数据模板,如用户、快件、驿站)
├── controller/ # GetX全局状态控制器(管理所有页面的状态、业务逻辑)
├── pages/ # 所有业务页面(存放首页、存取件、地图、订单等页面)
├── utils/ # 公共工具类(存放通用方法,如格式化、校验、权限申请)
└── main.dart # 项目全局入口(整个项目的启动入口,初始化所有配置)

步骤2:各目录详细说明(分点讲解,明确用途)
- core/(全局核心配置)
- 作用:存放整个项目的全局配置,所有页面都能复用,不用重复编写;
- 里面需要创建的子文件夹/文件(后续逐步完善):
- route/:全局路由配置(管理所有页面的路由跳转);
- theme/:全局主题配置(统一APP的颜色、字体、按钮样式);
- constants/:全局常量(如接口地址、固定文字、颜色值);
- utils/:核心工具类(如全局Toast、网络请求工具)。
- models/(数据实体模型)
- 作用:为所有业务数据定义固定模板,确保数据格式统一,后期对接后端接口、处理数据更规范;
- 后续会创建的模型:用户模型(UserModel)、快件模型(ExpressModel)、驿站模型(StationModel)、订单模型(OrderModel)。
- controller/(GetX状态控制器)
- 作用:统一管理所有页面的状态和业务逻辑,实现"逻辑与UI分离",让页面代码更简洁,后期维护更方便;
- 后续会创建的控制器:认证控制器(AuthController)、驿站控制器(StationController)、订单控制器(OrderController)。
- pages/(业务页面)
- 作用:存放所有业务页面,每个页面单独创建一个文件夹,里面放页面文件和对应的组件;
- 后续会创建的页面:首页(home)、智能存取件(deposit)、网点地图(map)、订单流水(order)、个人中心(mine)。
- utils/(公共工具类)
- 作用:存放所有页面都能复用的通用方法,避免重复编写代码;
- 后续会创建的工具:权限申请工具、日期格式化工具、扫码工具、缓存工具。
步骤3:目录创建验证
创建完成后,检查lib文件夹下的目录结构,确保没有遗漏、没有命名错误;
重点注意:文件夹名称全部小写+下划线,不要用中文、大写字母,避免后期编译报错。
五、版块4:创建用户身份实体模型(核心基础,权限区分)
文字讲解
我们的项目分为普通用户、会员用户两种身份,两种身份的权限、权益有明显差异(核心业务逻辑):
- 普通用户:可正常寄存、取件,有超时计费(超过24小时收取少量费用),无专属优惠;
- 会员用户:免超时费、优先存取件、驿站消费优惠、可预约大件寄存柜,会员等级越高,权益越多。
第一步先建立用户模型,固定核心字段,后续登录、个人中心、权限判断、会员权益展示,都基于这个模型,确保数据格式统一。
模型字段详细说明(分点讲解,明确用途)
- userId:用户唯一ID(字符串类型),用于区分不同用户,后续对接后端接口时,作为用户标识;
- userName:用户昵称(字符串类型),显示在个人中心,可修改;
- phone:用户手机号(字符串类型),用于登录、接收取件验证码,是用户的核心身份凭证;
- memberLevel:会员等级(整数类型),0=普通用户,1=初级会员,2=高级会员,3=VIP会员,用于判断会员权益;
- memberExpireTime:会员过期时间(字符串类型,格式:yyyy-MM-dd),用于判断会员是否有效;
- avatar:用户头像(字符串类型,存放头像图片路径或网络地址),显示在个人中心。
用户模型核心代码(每句带注释,易懂)
在models文件夹下,新建文件"user_model.dart",粘贴以下代码,每句代码都标注了作用,新手能轻松看懂:
dart
// 用户身份实体模型(普通用户/会员用户)
class UserModel {
final String userId; // 用户唯一ID(区分不同用户)
final String userName; // 用户昵称
final String phone; // 用户手机号(登录凭证)
final int memberLevel; // 会员等级(0=普通,1=初级,2=高级,3=VIP)
final String memberExpireTime; // 会员过期时间(yyyy-MM-dd)
final String avatar; // 用户头像路径/网络地址
// 构造方法(必填字段加required,确保创建模型时必须传入)
UserModel({
required this.userId,
required this.userName,
required this.phone,
required this.memberLevel,
required this.memberExpireTime,
required this.avatar,
});
}
模型使用说明(新手必看)
- 后续创建用户实例时,必须传入所有必填字段,例如:
dart
// 示例:创建普通用户实例
UserModel normalUser = UserModel(
userId: "10001",
userName: "小番茄",
phone: "13800138000",
memberLevel: 0,
memberExpireTime: "2026-05-09",
avatar: "assets/images/avatar.png",
);
- 若需要修改用户信息(如昵称、会员等级),可新增copyWith方法(后续Day2完善,今天先搭建基础模型);
- 模型字段不要随意修改,后期对接后端接口时,需要和后端字段保持一致,避免数据错乱。
六、版块5:搭建全局认证GetX控制器(全局状态管理核心)
文字讲解
用GetX创建全局认证控制器(AuthController),专门管理用户的登录状态、会员身份判断、用户信息存储,是整个项目的"状态核心"。
核心优势:把用户状态设为响应式变量,任意页面都能实时监听登录状态、判断是否是会员,不用页面层层传参,全局随时调用,实现"逻辑与UI完全分离",让页面代码更简洁。
控制器核心功能(分点说明)
- 存储用户信息:用响应式变量(Rx)存储用户模型实例,用户登录后赋值,退出登录后清空;
- 登录/退出登录:提供登录、退出登录的方法,统一管理用户状态的变化;
- 会员权限判断:提供getter方法,快速判断用户是否是会员、会员等级是否有效;
- 全局可访问:通过Get.find(),任意页面都能获取控制器实例,调用里面的方法和变量。
全局认证控制器核心代码(每句带注释)
在controller文件夹下,新建文件"auth_controller.dart",粘贴以下代码,详细注释每句作用:
dart
// 全局认证控制器(管理用户登录状态、会员权限)
import 'package:get/get.dart';
import '../models/user_model.dart';
class AuthController extends GetxController {
// 响应式变量:存储用户信息(null表示未登录,非null表示已登录)
final Rx<UserModel?> userInfo = Rx(null);
// 登录方法:传入用户模型,赋值给userInfo,完成登录
void login(UserModel user) {
userInfo.value = user; // 响应式变量赋值,页面会自动监听变化
}
// 退出登录方法:清空用户信息,返回首页
void logout() {
userInfo.value = null; // 清空用户信息,标记为未登录
Get.offAllNamed("/home"); // 跳转首页,清空页面栈,避免返回登录页
}
// 判断是否已登录(getter方法,直接调用,不用加括号)
bool get isLogin => userInfo.value != null;
// 判断是否为会员用户(会员等级>0即为会员)
bool get isMember => userInfo.value?.memberLevel ?? 0 > 0;
// 判断会员是否有效(过期时间>当前时间)
bool get isMemberValid {
if (!isMember) return false; // 非会员,直接返回无效
// 后续Day2完善:对比当前时间和会员过期时间,判断是否有效
return true;
}
}
控制器使用说明(新手必看,重点)
- 控制器必须全局注册,才能在任意页面调用,注册方法在main.dart中(后续版块7讲解);
- 页面中获取控制器实例,调用方法/变量:
dart
// 1. 获取控制器实例
final AuthController authCtrl = Get.find<AuthController>();
// 2. 调用登录方法
authCtrl.login(normalUser); // normalUser是前面创建的用户实例
// 3. 判断是否登录、是否是会员
if (authCtrl.isLogin) {
// 已登录,执行后续操作
if (authCtrl.isMember) {
// 是会员,显示会员权益
}
}
- 响应式变量(userInfo)变化时,页面会自动刷新,无需手动调用setState,这是GetX的核心优势。
七、版块6:项目入口全局初始化配置(main.dart完善)
文字讲解
在main.dart项目入口,我们需要一次性完成所有全局配置:初始化Flutter绑定、全局注册GetX控制器、配置屏幕适配、主题、路由,确保整个项目启动时,所有基础配置都已就绪,避免后期页面调用控制器、适配尺寸时出现报错。
初始化配置详细说明(分点讲解,每步作用)
- WidgetsFlutterBinding.ensureInitialized():初始化Flutter绑定,确保在启动APP前,所有Flutter组件都已初始化完成,避免出现"组件未初始化"报错;
- Get.lazyPut(() => AuthController()):全局懒加载注册认证控制器,"懒加载"表示只有在使用时才会初始化控制器,节省内存,而且全局只能有一个实例,任意页面都能获取;
- ScreenUtilInit:初始化屏幕适配,设置设计稿基准尺寸,自动适配鸿蒙全终端;
- GetMaterialApp:整合路由、主题,替代原生的MaterialApp,支持GetX路由跳转、状态管理。
main.dart完整核心代码(每句带注释)
打开main.dart文件,粘贴以下完整代码,替换之前的空壳代码:
dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'controller/auth_controller.dart';
void main() async {
// 1. 初始化Flutter绑定,确保组件正常加载
WidgetsFlutterBinding.ensureInitialized();
// 2. 全局懒加载注册认证控制器(全局唯一实例,任意页面可获取)
Get.lazyPut(() => AuthController());
// 3. 启动APP
runApp(const MyMainApp());
}
// APP根组件
class MyMainApp extends StatelessWidget {
const MyMainApp({super.key});
@override
Widget build(BuildContext context) {
// 4. 初始化屏幕适配(基准设计稿尺寸:375×812,主流手机尺寸)
return ScreenUtilInit(
designSize: const Size(375, 812), // 基准尺寸,不要随意修改
minTextAdapt: true, // 自动适配文字大小
splitScreenMode: true, // 支持分屏适配(鸿蒙平板分屏)
builder: (ctx, child) => GetMaterialApp(
// 5. 全局主题配置(统一APP主色调,后续可修改)
theme: ThemeData(
primarySwatch: Colors.blueGrey, // 主色调(蓝色灰色,贴合驿站简约风格)
scaffoldBackgroundColor: Colors.grey[50], // 页面背景色
appBarTheme: AppBarTheme(
elevation: 2.h, // 导航栏阴影高度(适配单位)
centerTitle: true, // 导航栏标题居中
),
),
// 6. 路由配置(后续Day2完善,今天先留空)
initialRoute: "/home", // 初始页面(首页)
debugShowCheckedModeBanner: false, // 隐藏调试横幅(上线时必加)
),
);
}
}
关键注意事项(新手必看,避免报错)
- 基准设计稿尺寸(375×812)不要随意修改,后续所有页面的尺寸都基于这个基准,用.w/.h/.sp适配,才能实现多端适配;
- Get.lazyPut注册控制器的代码,必须放在runApp之前,否则页面启动时无法获取控制器,会出现null报错;
- debugShowCheckedModeBanner: false,用于隐藏页面右上角的"Debug"横幅,上线时必须保留,让APP更专业。
八、版块7:搭建五大核心业务页面空壳(基础骨架)
文字讲解
根据共享驿站的实际商业业务,我们提前搭建五个核心页面空壳,先把页面架子建好,后续Day2开始往里面填充地图、扫码、寄存计费等复杂功能。
每个页面单独创建文件,放在pages文件夹下,页面结构统一,都是Scaffold+AppBar+空body,后期逐步完善内容。
五大核心页面说明(分点讲解,明确业务用途)
- 首页(HomePage):展示附近驿站推荐、驿站分类、公告通知,是用户进入APP的第一个页面;
- 智能存取件(DepositPage):核心业务页面,实现扫码开箱、快件寄存、取件、超时计费等功能;
- 网点地图(MapPage):展示城市内所有共享驿站网点,定位用户当前位置,规划前往驿站的路线;
- 订单流水(OrderPage):展示用户所有寄存/取件订单,包含订单状态、金额、时间、驿站信息;
- 个人中心(MinePage):展示用户信息、会员权益、我的订单、设置等功能。
五大页面核心代码(逐一创建,单独文件)
1. 首页(home_page.dart)
在pages文件夹下,新建文件"home_page.dart",粘贴以下代码:
dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
// 驿站首页(展示附近驿站、分类)
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
// 导航栏(统一风格,后续全局美化)
appBar: AppBar(
title: Text(
"城市共享驿站",
style: TextStyle(fontSize: 18.sp, fontWeight: FontWeight.w500),
),
),
// 页面主体(后续Day2填充内容,今天先留空)
body: Center(
child: Text(
"首页骨架,后续填充驿站列表",
style: TextStyle(fontSize: 14.sp, color: Colors.grey),
),
),
);
}
}
2. 智能存取件页(deposit_page.dart)
在pages文件夹下,新建文件"deposit_page.dart",粘贴以下代码:
dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
// 智能存取件页(扫码开箱、寄存、取件)
class DepositPage extends StatelessWidget {
const DepositPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"智能存取件",
style: TextStyle(fontSize: 18.sp, fontWeight: FontWeight.w500),
),
),
body: Center(
child: Text(
"存取件页面骨架,后续添加扫码功能",
style: TextStyle(fontSize: 14.sp, color: Colors.grey),
),
),
);
}
}
3. 网点地图页(map_page.dart)
在pages文件夹下,新建文件"map_page.dart",粘贴以下代码:
dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
// 网点地图页(展示所有驿站、定位)
class MapPage extends StatelessWidget {
const MapPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"驿站网点",
style: TextStyle(fontSize: 18.sp, fontWeight: FontWeight.w500),
),
),
body: Center(
child: Text(
"地图页面骨架,后续添加地图定位",
style: TextStyle(fontSize: 14.sp, color: Colors.grey),
),
),
);
}
}
4. 订单流水页(order_page.dart)
在pages文件夹下,新建文件"order_page.dart",粘贴以下代码:
dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
// 订单流水页(展示所有寄存/取件订单)
class OrderPage extends StatelessWidget {
const OrderPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"我的订单",
style: TextStyle(fontSize: 18.sp, fontWeight: FontWeight.w500),
),
),
body: Center(
child: Text(
"订单页面骨架,后续填充订单列表",
style: TextStyle(fontSize: 14.sp, color: Colors.grey),
),
),
);
}
}
5. 个人中心页(mine_page.dart)
在pages文件夹下,新建文件"mine_page.dart",粘贴以下代码:
dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
// 个人中心页(用户信息、会员权益、设置)
class MinePage extends StatelessWidget {
const MinePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"个人中心",
style: TextStyle(fontSize: 18.sp, fontWeight: FontWeight.w500),
),
),
body: Center(
child: Text(
"个人中心骨架,后续填充用户信息",
style: TextStyle(fontSize: 14.sp, color: Colors.grey),
),
),
);
}
}
页面创建验证
- 确保每个页面都单独创建文件,文件名格式为"页面名_page.dart"(小写+下划线);
- 每个页面都继承StatelessWidget(无状态组件),后续需要状态管理时,再改为StatefulWidget;
- 所有文字大小都用.sp适配单位,确保鸿蒙多端适配,不要写固定数字。
九、版块8:封装全局底部导航栏(实现页面切换)
文字讲解
底部导航栏是APP的核心导航组件,用户通过底部导航,可快速切换五大核心页面(首页、存取件、地图、订单、个人中心)。
我们把底部导航栏封装成全局组件,放在core/utils文件夹下,任意页面都能复用,统一导航风格,避免重复编写代码。
底部导航栏核心功能(分点说明)
- 五个导航项,对应五大核心页面,图标+文字结合,清晰直观;
- 点击导航项,切换对应页面,同时高亮当前选中项;
- 适配鸿蒙手机、平板,导航栏高度、图标大小自动适配;
- 结合GetX路由,实现无上下文跳转,切换页面无卡顿。
全局底部导航栏核心代码
在core文件夹下,新建utils文件夹,然后在utils文件夹下新建文件"bottom_nav_bar.dart",粘贴以下代码:
dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../pages/home_page.dart';
import '../../pages/deposit_page.dart';
import '../../pages/map_page.dart';
import '../../pages/order_page.dart';
import '../../pages/mine_page.dart';
// 全局底部导航栏(统一导航,切换五大页面)
class GlobalBottomNavBar extends StatefulWidget {
const GlobalBottomNavBar({super.key});
@override
State<GlobalBottomNavBar> createState() => _GlobalBottomNavBarState();
}
class _GlobalBottomNavBarState extends State<GlobalBottomNavBar> {
// 当前选中的导航索引(0=首页,1=存取件,2=地图,3=订单,4=个人中心)
int _currentIndex = 0;
// 导航项对应的页面列表
final List<Widget> _pages = const [
HomePage(),
DepositPage(),
MapPage(),
OrderPage(),
MinePage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
// 底部导航栏
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex, // 当前选中索引
type: BottomNavigationBarType.fixed, // 固定所有导航项(不滚动)
elevation: 5.h, // 阴影高度
selectedFontSize: 12.sp, // 选中文字大小
unselectedFontSize: 11.sp, // 未选中文字大小
// 导航项列表
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
BottomNavigationBarItem(icon: Icon(Icons.inventory), label: "存取件"),
BottomNavigationBarItem(icon: Icon(Icons.map), label: "网点"),
BottomNavigationBarItem(icon: Icon(Icons.list_alt), label: "订单"),
BottomNavigationBarItem(icon: Icon(Icons.person), label: "我的"),
],
// 点击导航项,切换页面
onTap: (index) {
setState(() {
_currentIndex = index; // 更新选中索引
});
},
),
// 展示当前选中的页面
body: _pages[_currentIndex],
);
}
}
底部导航栏使用说明(关键步骤)
- 修改main.dart中的初始页面,将initialRoute对应的页面改为GlobalBottomNavBar,确保APP启动后,默认显示底部导航栏:
dart
// 在GetMaterialApp中修改initialRoute和home
GetMaterialApp(
initialRoute: "/",
home: const GlobalBottomNavBar(), // 启动默认显示底部导航栏
// 其他配置不变...
)
- 运行项目,点击底部导航项,可正常切换五大页面,选中项会自动高亮,适配鸿蒙设备尺寸;
- 后续可修改导航栏的颜色、图标、文字样式,统一APP风格(Day2优化)。
十、版块9:新手新建项目高频问题(口语化详解,附解决步骤)
问题1:引入依赖后,执行flutter pub get报错,提示版本冲突?
解答:新手最容易踩的坑,原因和解决步骤分3步:
- 原因:要么是随意修改了我给的库版本号,要么是Flutter版本和库版本不兼容;
- 解决步骤1:恢复我给的依赖版本号,不要随意升级、降级;
- 解决步骤2:关闭Android Studio,点击File → Invalidate Caches...,勾选"Clear cached files"和"Clear local history",点击Invalidate and Restart,清空缓存;
- 解决步骤3:重启项目后,再次执行flutter pub get,基本都能解决;若还是报错,升级Flutter到稳定版(终端执行flutter upgrade)。
问题2:项目能正常启动,但鸿蒙模拟器/真机上显示空白页面?
解答:原因有2种,逐一排查:
- 原因1:删除默认代码后,没有完善MyMainApp类,body为空;
解决:确保MyMainApp中,ScreenUtilInit的builder返回GetMaterialApp,且home设置为GlobalBottomNavBar; - 原因2:鸿蒙设备权限未开启,导致页面无法渲染;
解决:打开鸿蒙设备设置,找到当前APP,开启"显示权限""存储权限",重启APP即可。
问题3:全局控制器找不到,页面调用Get.find()报错"找不到控制器"?
解答:核心原因是控制器未全局注册,解决步骤:
- 检查main.dart中,是否有Get.lazyPut(() => AuthController())这句代码;
- 确保这句代码放在runApp(const MyMainApp())之前,顺序不能颠倒;
- 若还是报错,重启项目,清空编译缓存(终端执行flutter clean),再重新运行。
问题4:屏幕适配失效,鸿蒙平板上布局错乱、文字太小?
解答:新手容易忽略的2个关键点:
- 原因1:没有用.w/.h/.sp适配单位,还是用了固定数字(如16、20);
解决:所有尺寸(宽高、间距、文字大小)都改为适配单位,如18.sp、15.w; - 原因2:ScreenUtilInit的designSize设置错误,或没有包裹GetMaterialApp;
解决:确保designSize为const Size(375, 812),且GetMaterialApp在ScreenUtilInit的builder中。
问题5:底部导航栏切换页面时,页面报错"找不到页面"?
解答:原因是底部导航栏的_pages列表中,页面实例创建错误,解决步骤:
- 检查每个页面的导入路径是否正确(如import '.../.../pages/home_page.dart');
- 确保_pages列表中的页面顺序,和BottomNavigationBarItem的顺序一致;
- 检查每个页面是否正确继承StatelessWidget,没有语法错误。
十一、Day1 开发总结(详细全面,复盘今日成果)
今天我们彻底脱离校园场景,成功落地城市共享驿站智能存取系统 Day1的全部开发任务,搭建了企业级项目的完整底层基座,为后续复杂业务开发铺好了路,没有任何同质化、烂大街的功能,技术含金量和项目实用性拉满。

今日完整成果复盘(分点清晰,一目了然)
- 项目初始化:从0新建纯净Flutter项目,删除冗余代码,配置鸿蒙运行环境,确保项目能在鸿蒙手机、平板上正常启动;
- 依赖配置:引入6个商业级第三方库,逐一讲解每个库的用途、版本选择原因,完成依赖安装,解决版本冲突问题;
- 目录规范:搭建企业级分层工程目录,详细说明每个文件夹的作用、文件存放规范,养成正规开发习惯;
- 模型设计:创建用户身份实体模型,划分普通用户/会员用户两级权限,定义核心字段,为后续登录、会员权益功能奠定基础;
- 状态管理:搭建全局认证GetX控制器,实现用户登录/退出登录、会员权限判断,全局可访问,逻辑与UI分离;
- 全局配置:在main.dart中完成Flutter绑定、控制器注册、屏幕适配、主题、路由初始化,确保全局配置就绪;
- 页面骨架:搭建五大核心业务页面空壳,每个页面单独创建文件,统一结构,为后续业务填充铺路;
- 导航封装:封装全局底部导航栏,实现五大页面快速切换,适配鸿蒙多端,统一导航风格;
- 避坑指南:整理新手新建项目、配置依赖、适配鸿蒙的5个高频问题,给出具体解决步骤,避免新手踩坑。
今日核心收获(新手必看)
- 掌握Flutter项目初始化、鸿蒙环境配置的详细步骤,能独立创建并运行项目;
- 理解企业级分层目录的作用和规范,学会按正规开发标准存放文件;
- 掌握GetX控制器的创建、全局注册、使用方法,理解响应式状态管理的核心优势;
- 掌握屏幕适配的配置方法,学会用.w/.h/.sp适配单位,实现鸿蒙多端适配;
- 学会封装全局组件(底部导航栏),实现代码复用,简化开发流程。
十二、下期Day2预告(详细明确,提前剧透)
Day2我们正式进入业务开发阶段,重点完善基础业务骨架,实现页面交互和数据模拟,具体任务如下:
- 完善全局路由配置,实现页面无上下文跳转,配置路由守卫(未登录无法进入个人中心、订单页面);
- 创建驿站实体模型、快件实体模型,定义核心字段,规范数据格式;
- 模拟城市驿站网点数据(10条真实风格数据),存入GetX控制器;
- 完善首页布局,实现驿站列表展示,封装通用驿站卡片组件;
- 新增驿站分类筛选功能(快递寄存、临时存放、大件寄存),实现筛选逻辑;
- 优化底部导航栏样式,统一图标、颜色、文字风格,适配鸿蒙多端;
- 整理Day2开发中的高频问题,给出详细解决步骤,确保新手能顺利落地。