
- 个人首页: 永远都不秃头的程序员(互关)
- C语言专栏:从零开始学习C语言
- C++专栏:C++的学习之路
- K-Means专栏:K-Means深度探索系列
- 本章所属专栏:Flutter for Harmony 系列
文章目录
-
-
- [1. 项目概览与数据模型设计](#1. 项目概览与数据模型设计)
-
- [1.1 `Product` 类:商品数据的核心](#1.1
Product类:商品数据的核心) - 解读:
- [1.1 `Product` 类:商品数据的核心](#1.1
- [2. 响应式导航框架:多设备无缝体验](#2. 响应式导航框架:多设备无缝体验)
- [3. 核心功能模块一:仪表盘 (`DashboardScreen`)](#3. 核心功能模块一:仪表盘 (
DashboardScreen)) - [4. 核心功能模块二:商品管理 (`ProductsScreen`)](#4. 核心功能模块二:商品管理 (
ProductsScreen)) - [5. 核心功能模块三:库存管理 (`InventoryScreen`) 📦](#5. 核心功能模块三:库存管理 (
InventoryScreen) 📦) - [6. 部署到 HarmonyOS:Flutter 的跨平台魔力 ✨](#6. 部署到 HarmonyOS:Flutter 的跨平台魔力 ✨)
- [7. 总结与展望](#7. 总结与展望)
-

1. 项目概览与数据模型设计
这个仓库管理系统旨在提供一个跨平台、响应式的解决方案,管理商品信息和库存状态。
-
技术栈:Flutter 3.x、Dart 2.x
-
主题:浅色模式,以蓝色为主色调,简洁专业。
-
核心功能:
- 响应式导航:根据屏幕宽度动态切换导航方式(底部导航、侧边抽屉、固定侧边栏)。
- 模块化页面:包括仪表盘、商品管理、库存管理和设置。
- 商品数据模型 :
Product类定义商品属性。 - 商品管理:增、删、改商品信息,支持搜索。
- 库存管理:更新商品库存,显示库存状态(低库存警告),支持搜索。
DataTable展示:清晰有效地展示商品和库存列表。
1.1 Product 类:商品数据的核心
Product 类是应用中存储每个商品信息的骨架。
dart
// lib/main.dart (Product类)
class Product {
final int id; // 商品唯一ID
final String name; // 商品名称
final String category; // 商品类别
final int stock; // 库存数量
final double price; // 价格
final int minStock; // 最小库存(用于低库存预警)
Product({
required this.id,
required this.name,
required this.category,
required this.stock,
required this.price,
this.minStock = 20, // 默认最小库存
});
}
解读:
id字段确保了每个商品的唯一性。minStock是一个重要的业务字段,用于在库存管理模块中判断商品是否处于低库存状态。
2. 响应式导航框架:多设备无缝体验
仓库管理系统往往需要在各种设备上运行,从移动设备到桌面大屏。因此,一个能智能适配屏幕尺寸的导航框架至关重要。
2.1 MainScreen 的核心逻辑:MediaQuery 驱动
MainScreen 作为应用的入口,通过 MediaQuery 判断屏幕宽度,动态构建不同的导航UI。
dart
// lib/main.dart (_MainScreenState 的 build 方法片段)
class _MainScreenState extends State<MainScreen> {
int _selectedIndex = 0; // 当前选中的导航项索引
final List<NavigationItem> _navigationItems = [ /* ... 仪表盘、商品管理等导航项 ... */ ];
// ... _onItemTapped 方法
@override
Widget build(BuildContext context) {
// 根据屏幕宽度判断是否为移动设备
final isMobile = MediaQuery.of(context).size.width < 600; // 小于600px视为移动端
return Scaffold(
appBar: AppBar( /* ... 标题和移动端的汉堡菜单 ... */ ),
drawer: isMobile ? _buildDrawer() : null, // 移动端显示侧边抽屉
body: Row( // 主体内容区域
children: [
if (!isMobile) _buildSidebar(), // 非移动端显示固定侧边栏
Expanded( // 填充剩余空间显示当前页面
child: Container(
color: Colors.white,
padding: const EdgeInsets.all(16),
child: _navigationItems[_selectedIndex].screen, // 根据索引显示对应页面
),
),
],
),
bottomNavigationBar: isMobile ? _buildBottomNavigation() : null, // 移动端显示底部导航栏
);
}
// ... _buildDrawer, _buildSidebar, _buildBottomNavigation 方法
}
解读:
MediaQuery.of(context).size.width < 600是判断设备类型(移动端/非移动端)的核心逻辑。- 根据
isMobile的值,Scaffold的drawer和bottomNavigationBar属性被条件性地设置。 body使用Row布局:非移动端时,左侧会渲染一个固定宽度的_buildSidebar(),右侧的Expanded区域则显示当前选中的页面。这种模式非常适合桌面应用和大型平板。
2.2 多种导航模式 (_buildDrawer, _buildSidebar, _buildBottomNavigation)
无论是侧边抽屉、固定侧边栏还是底部导航栏,它们都共享 _navigationItems 列表,并通过 _onItemTapped 更新 _selectedIndex 来切换中间显示的内容。
dart
// lib/main.dart (_buildDrawer 方法片段)
Widget _buildDrawer() {
return Drawer(
child: ListView(
children: [
const DrawerHeader(/* ... 用户信息 ... */),
..._navigationItems.map((item) {
final index = _navigationItems.indexOf(item);
return ListTile(
leading: Icon(item.icon),
title: Text(item.title),
selected: _selectedIndex == index,
onTap: () {
_onItemTapped(index);
Navigator.pop(context); // 点击后关闭抽屉
},
);
}).toList(),
],
),
);
}
// lib/main.dart (_buildSidebar 方法片段)
Widget _buildSidebar() {
return Container(
width: 240, // 固定侧边栏宽度
decoration: BoxDecoration(color: Colors.white, border: Border(right: BorderSide(color: Colors.grey[200]!))),
child: ListView(
children: [
Container(/* ... 用户信息 ... */),
..._navigationItems.map((item) {
final index = _navigationItems.indexOf(item);
return ListTile(
leading: Icon(item.icon, color: _selectedIndex == index ? Colors.blue : Colors.grey),
title: Text(item.title, style: TextStyle(color: _selectedIndex == index ? Colors.blue : Colors.black)),
selected: _selectedIndex == index,
onTap: () => _onItemTapped(index), // 点击切换页面
);
}).toList(),
],
),
);
}
// lib/main.dart (_buildBottomNavigation 方法片段)
Widget _buildBottomNavigation() {
return BottomNavigationBar(
items: _navigationItems.map((item) => BottomNavigationBarItem(icon: Icon(item.icon), label: item.title)).toList(),
currentIndex: _selectedIndex,
selectedItemColor: Colors.blue,
unselectedItemColor: Colors.grey,
onTap: _onItemTapped,
);
}
解读:
- 所有导航组件都遍历
_navigationItems列表来动态生成菜单项,实现了代码复用和维护便利性。 _onItemTapped方法是所有导航模式切换页面的统一入口,它更新_selectedIndex并触发setState刷新MainScreen的body内容。
3. 核心功能模块一:仪表盘 (DashboardScreen)
仪表盘提供仓库概览,显示关键指标。
dart
// lib/main.dart (DashboardScreen的build方法片段)
class DashboardScreen extends StatelessWidget {
const DashboardScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(24),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('仓库管理系统', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
const SizedBox(height: 24),
Row( // 关键指标卡片
children: [
Expanded(child: Card( /* ... 总商品数卡片 ... */ )),
const SizedBox(width: 16),
Expanded(child: Card( /* ... 总库存卡片 ... */ )),
const SizedBox(width: 16),
Expanded(child: Card( /* ... 低库存商品卡片 ... */ )),
],
),
const SizedBox(height: 24),
Card( /* ... 最近操作列表 ... */ ),
],
),
),
);
}
}
解读:
- 使用
Row包裹Expanded的Card来创建响应式的多列布局,即使在窄屏上也能适应。 Card用于展示各项指标,提升视觉整洁度。
4. 核心功能模块二:商品管理 (ProductsScreen)
商品管理模块实现商品的增删改查。
4.1 增删改查商品 (_addProduct, _editProduct, _deleteProduct)
添加和编辑功能通过 AlertDialog 中的 TextField 实现表单输入,删除功能则有确认提示。
dart
// lib/main.dart (_ProductsScreenState 的 _addProduct 方法片段)
void _addProduct() {
showDialog(
context: context,
builder: (context) {
TextEditingController nameController = TextEditingController();
// ... 其他控制器
return AlertDialog(
title: const Text('添加商品'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(controller: nameController, decoration: const InputDecoration(labelText: '商品名称')),
// ... 其他输入框
],
),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text('取消')),
ElevatedButton(
onPressed: () {
// ... 创建新Product对象
setState(() => _products.add(newProduct)); // 添加到列表
Navigator.pop(context);
},
child: const Text('添加'),
),
],
);
},
);
}
// lib/main.dart (_ProductsScreenState 的 _editProduct 方法片段)
void _editProduct(Product product) {
showDialog(
context: context,
builder: (context) {
TextEditingController nameController = TextEditingController(text: product.name); // 预填充数据
// ...
return AlertDialog(
title: const Text('编辑商品'),
content: Column(/* ... 类似添加商品的输入框,但预填充 ... */),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text('取消')),
ElevatedButton(
onPressed: () {
setState(() { // 更新列表中的对应商品
int index = _products.indexWhere((p) => p.id == product.id);
if (index != -1) _products[index] = Product(/* ... 更新后的数据 ... */);
});
Navigator.pop(context);
},
child: const Text('保存'),
),
],
);
},
);
}
// lib/main.dart (_ProductsScreenState 的 _deleteProduct 方法片段)
void _deleteProduct(int id) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('删除商品'),
content: const Text('确定要删除这个商品吗?'),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text('取消')),
ElevatedButton(
onPressed: () {
setState(() => _products.removeWhere((p) => p.id == id)); // 从列表移除
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
child: const Text('删除'),
),
],
),
);
}
解读:
- 使用
showDialog弹出模态对话框,包含TextField用于数据输入。 - 添加和编辑功能复用类似的 UI 结构,编辑时通过
TextEditingController的text属性预填充现有数据。 setState在每次数据变更后更新 UI。- 删除功能带有确认弹窗,防止误操作。
4.2 搜索与 DataTable 展示
商品列表使用 DataTable 进行展示,支持按名称和类别搜索。
dart
// lib/main.dart (_ProductsScreenState 的 _getFilteredProducts 方法片段)
List<Product> _getFilteredProducts() {
if (_searchController.text.isEmpty) return _products;
return _products.where((product) {
return product.name.toLowerCase().contains(_searchController.text.toLowerCase()) ||
product.category.toLowerCase().contains(_searchController.text.toLowerCase());
}).toList();
}
// lib/main.dart (_ProductsScreenState 的 build 方法片段)
@override
Widget build(BuildContext context) {
List<Product> filteredProducts = _getFilteredProducts();
return Container(
padding: const EdgeInsets.all(24),
child: SingleChildScrollView(
child: Column(
children: [
Row( /* ... 标题和添加商品按钮 ... */ ),
const SizedBox(height: 24),
Card(
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
TextField(controller: _searchController, decoration: const InputDecoration(labelText: '搜索商品', prefixIcon: Icon(Icons.search)), onChanged: (value) => setState(() {})),
const SizedBox(height: 16),
DataTable( // 数据表格展示
columns: const [
DataColumn(label: Text('ID')), DataColumn(label: Text('商品名称')), DataColumn(label: Text('类别')),
DataColumn(label: Text('库存')), DataColumn(label: Text('价格')), DataColumn(label: Text('操作')),
],
rows: filteredProducts.map((product) { // 映射数据到DataRow
return DataRow(cells: [
DataCell(Text(product.id.toString())),
DataCell(Text(product.name)),
// ... 其他DataCell
DataCell(
Row(children: [ // 操作按钮
TextButton(onPressed: () => _editProduct(product), child: const Text('编辑')),
TextButton(onPressed: () => _deleteProduct(product.id), child: const Text('删除')),
]),
),
]);
}).toList(),
),
],
),
),
),
],
),
),
);
}
解读:
_getFilteredProducts方法根据搜索框内容过滤_products列表,支持不区分大小写的模糊搜索。DataTable提供了一个结构化的表格视图来展示数据,非常适合管理系统。DataColumn定义了表格的列头,DataRow通过DataCell填充每一行的数据。onChanged触发setState刷新表格,实现实时搜索。
5. 核心功能模块三:库存管理 (InventoryScreen) 📦
库存管理模块专注于商品库存的更新和状态监控。
5.1 更新库存 (_updateStock)
dart
// lib/main.dart (_InventoryScreenState 的 _updateStock 方法片段)
void _updateStock(Product product) {
showDialog(
context: context,
builder: (context) {
TextEditingController stockController = TextEditingController(text: product.stock.toString());
return AlertDialog(
title: const Text('更新库存'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [TextField(controller: stockController, decoration: const InputDecoration(labelText: '新库存数量'), keyboardType: TextInputType.number)],
),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text('取消')),
ElevatedButton(
onPressed: () {
setState(() {
int index = _products.indexWhere((p) => p.id == product.id);
if (index != -1) { // 创建一个带有新库存的Product副本
_products[index] = Product(
id: product.id, name: product.name, category: product.category,
stock: int.tryParse(stockController.text) ?? 0, // 更新库存
price: product.price, minStock: product.minStock,
);
}
});
Navigator.pop(context);
},
child: const Text('更新'),
),
],
);
},
);
}
解读:
- 同样使用
showDialog和TextField进行库存数量输入。 - 更新时会创建一个
Product的新实例来替换旧实例,因为Product的属性是final的(不可变)。
5.2 库存状态显示 (_getStockStatus, _getStockStatusColor)
在 DataTable 中直观展示库存状态,并用颜色进行区分。
dart
// lib/main.dart (_InventoryScreenState 的 _getStockStatus 方法片段)
String _getStockStatus(int stock, int minStock) {
return stock < minStock ? '低库存' : '正常';
}
Color _getStockStatusColor(int stock, int minStock) {
return stock < minStock ? Colors.red : Colors.green;
}
// lib/main.dart (_InventoryScreenState 的 build 方法片段)
@override
Widget build(BuildContext context) {
// ... 其他UI,搜索框
DataTable(
columns: const [ /* ... ID, 商品名称, 当前库存, 最小库存, 状态, 操作 ... */ ],
rows: filteredProducts.map((product) {
return DataRow(cells: [
// ... 其他DataCell
DataCell(
Text(
_getStockStatus(product.stock, product.minStock),
style: TextStyle(color: _getStockStatusColor(product.stock, product.minStock)), // 动态颜色
),
),
DataCell(
TextButton(onPressed: () => _updateStock(product), child: const Text('更新库存')),
),
]);
}).toList(),
);
}
解读:
_getStockStatus根据当前库存和最小库存判断是"低库存"还是"正常"。_getStockStatusColor则根据状态返回红色(低库存)或绿色(正常),提供清晰的视觉警告。
6. 部署到 HarmonyOS:Flutter 的跨平台魔力 ✨
现在,我们将把这个 Flutter 仓库管理系统部署到 HarmonyOS 平台。得益于 Flutter 优秀的跨平台能力以及华为对 Flutter 生态的支持,这个过程变得越来越便捷!
前提条件:
- Flutter SDK:确保您的开发环境中已安装 Flutter SDK,并推荐使用最新稳定版以获得最佳的 HarmonyOS 兼容性。
- DevEco Studio:已安装并配置好 HarmonyOS 开发环境。
- HarmonyOS SDK:在 DevEco Studio 中下载并配置好对应的 HarmonyOS SDK。
- Flutter for HarmonyOS 适配:请关注 Flutter for HarmonyOS 官方文档或社区指引,获取最准确和最新的部署方法。
部署步骤:
-
创建或导入 Flutter 项目:
- 如果你还没有这个 Flutter 项目,请先通过命令行创建:
flutter create my_warehouse_app。 - 在 DevEco Studio 中打开 Flutter 项目 :启动 DevEco Studio,选择
File->Open,然后导航到你的 Flutter 项目的根目录并打开。
- 如果你还没有这个 Flutter 项目,请先通过命令行创建:
-
DevEco Studio 自动识别与导入:
- DevEco Studio 会智能识别这是一个 Flutter 项目,并提示你将其导入为 HarmonyOS 应用。点击
Import或Yes。 - 根据提示选择 HarmonyOS SDK 版本和模块类型(通常默认
entry模块即可),DevEco Studio 会在你的 Flutter 项目内部创建harmony文件夹及必要的配置文件。
- DevEco Studio 会智能识别这是一个 Flutter 项目,并提示你将其导入为 HarmonyOS 应用。点击
-
配置与同步:
- DevEco Studio 会自动进行项目同步,下载所有 HarmonyOS 相关的依赖和适配组件。确保网络连接稳定。
- 对于调试目的,DevEco Studio 通常会处理调试签名。如果遇到签名问题,请在 DevEco Studio 的项目结构中检查并配置你的 HarmonyOS 模块的调试签名。
-
选择目标设备并运行:
- 在 DevEco Studio 顶部的设备选择下拉菜单中,选择一个可用的 HarmonyOS 模拟器或连接你的 HarmonyOS 真机设备。
- 点击绿色的"运行"按钮。DevEco Studio 将会编译你的 Flutter 代码,将其集成到 HarmonyOS 项目中,然后构建并部署最终的 HarmonyOS 应用包(HAP)到你选择的设备上。
-
查看效果:
- 稍等片刻(首次构建可能需要较长时间),你的 Flutter 仓库管理系统应用就会在 HarmonyOS 模拟器或真机上启动并运行起来!
7. 总结与展望
这个仓库管理系统只是一个起点,你可以继续探索和扩展:
- 数据持久化 :集成
shared_preferences或sqflite,甚至连接后端数据库,确保数据永久存储。 - 用户认证:添加登录功能,支持多用户管理。
- 高级搜索与筛选:支持按日期、价格范围等进行高级搜索和筛选。
- 报告与图表:在仪表盘中添加库存趋势、销售额等可视化图表。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net