Flutter 框架跨平台鸿蒙开发 - 本地商超优惠推送
运行效果图本地商超优惠推送是一款专为本地生活设计的商超优惠信息聚合应用,实时推送周边超市、商场的优惠活动、折扣信息、限时特价。应用以热情的红色为主色调,象征优惠与实惠。序号类型名称Emoji描述1超市🛒综合超市2便利店🏪24小时便利店3商场🏬大型购物中心4生鲜店🥬生鲜果蔬店5药店💊药店药房6餐饮店🍜餐饮美食店7服装店👕服装鞋帽店8其他🏪其他类型店铺序号类型名称Emoji描述1折扣?
本地商超优惠推送应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图



1.1 应用简介
本地商超优惠推送是一款专为本地生活设计的商超优惠信息聚合应用,实时推送周边超市、商场的优惠活动、折扣信息、限时特价。应用内置定位服务、优惠分类、收藏关注、到期提醒,让用户不错过任何省钱机会。
应用以热情的红色为主色调,象征优惠与实惠。涵盖附近优惠、分类浏览、收藏关注、个人中心四大模块。用户可以查看周边商超优惠、按类别筛选、收藏心仪商品、设置到期提醒。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 附近优惠 | 查看周边商超优惠 | 定位+列表 |
| 分类浏览 | 按类别筛选优惠 | 分类筛选 |
| 优惠详情 | 查看优惠详细信息 | 详情页面 |
| 收藏关注 | 收藏心仪优惠 | 收藏系统 |
| 到期提醒 | 设置到期提醒 | 提醒服务 |
1.3 商超类型定义
| 序号 | 类型名称 | Emoji | 描述 |
|---|---|---|---|
| 1 | 超市 | 🛒 | 综合超市 |
| 2 | 便利店 | 🏪 | 24小时便利店 |
| 3 | 商场 | 🏬 | 大型购物中心 |
| 4 | 生鲜店 | 🥬 | 生鲜果蔬店 |
| 5 | 药店 | 💊 | 药店药房 |
| 6 | 餐饮店 | 🍜 | 餐饮美食店 |
| 7 | 服装店 | 👕 | 服装鞋帽店 |
| 8 | 其他 | 🏪 | 其他类型店铺 |
1.4 优惠类型定义
| 序号 | 类型名称 | Emoji | 描述 |
|---|---|---|---|
| 1 | 折扣 | 🏷️ | 打折优惠 |
| 2 | 满减 | 💰 | 满额减免 |
| 3 | 买赠 | 🎁 | 买就送 |
| 4 | 秒杀 | ⚡ | 限时秒杀 |
| 5 | 团购 | 👥 | 拼团优惠 |
| 6 | 优惠券 | 🎫 | 领券优惠 |
| 7 | 会员价 | 👑 | 会员专享 |
| 8 | 其他 | 📌 | 其他优惠 |
1.5 优惠状态定义
| 序号 | 状态名称 | Emoji | 描述 |
|---|---|---|---|
| 1 | 进行中 | 🔥 | 优惠进行中 |
| 2 | 即将开始 | ⏳ | 即将开始 |
| 3 | 已结束 | ❌ | 已结束 |
| 4 | 已抢完 | 😔 | 库存已抢完 |
1.6 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 本地存储 | shared_preferences | - |
| 定位服务 | geolocator | - |
| 目标平台 | 鸿蒙OS / Web | API 21+ |
1.7 项目结构
lib/
└── main_store_promotion.dart
├── StorePromotionApp # 应用入口
├── Store # 商超模型
├── Promotion # 优惠模型
├── StoreType # 商超类型枚举
├── PromotionType # 优惠类型枚举
├── PromotionStatus # 优惠状态枚举
├── PromotionService # 优惠服务
├── PromotionController # 优惠控制器
├── StorePromotionHomePage # 主页面
├── _buildNearbyPage # 附近优惠页面
├── _buildCategoryPage # 分类浏览页面
├── _buildFavoritesPage # 收藏关注页面
└── _buildProfilePage # 个人中心页面
二、系统架构
2.1 整体架构图
2.2 类图设计
2.3 页面导航流程
2.4 优惠推送流程
三、核心模块设计
3.1 数据模型设计
3.1.1 商超模型 (Store)
class Store {
final String id;
final String name;
final StoreType type;
final String address;
final double latitude;
final double longitude;
final String phone;
final double rating;
final String businessHours;
final String logo;
final List<String> images;
Store({
required this.id,
required this.name,
required this.type,
required this.address,
required this.latitude,
required this.longitude,
required this.phone,
required this.rating,
required this.businessHours,
required this.logo,
required this.images,
});
}
3.1.2 优惠模型 (Promotion)
class Promotion {
final String id;
final String storeId;
final String storeName;
final String title;
final String description;
final PromotionType type;
final double originalPrice;
final double discountPrice;
final double discountRate;
final DateTime startTime;
final DateTime endTime;
PromotionStatus status;
final int stock;
int soldCount;
final List<String> images;
final List<String> tags;
Promotion({
required this.id,
required this.storeId,
required this.storeName,
required this.title,
required this.description,
required this.type,
required this.originalPrice,
required this.discountPrice,
required this.discountRate,
required this.startTime,
required this.endTime,
required this.status,
required this.stock,
required this.soldCount,
required this.images,
required this.tags,
});
}
3.1.3 商超类型枚举 (StoreType)
enum StoreType {
supermarket(label: '超市', emoji: '🛒'),
convenience(label: '便利店', emoji: '🏪'),
mall(label: '商场', emoji: '🏬'),
fresh(label: '生鲜店', emoji: '🥬'),
pharmacy(label: '药店', emoji: '💊'),
restaurant(label: '餐饮店', emoji: '🍜'),
clothing(label: '服装店', emoji: '👕'),
other(label: '其他', emoji: '🏪');
final String label;
final String emoji;
const StoreType({required this.label, required this.emoji});
}
3.1.4 优惠类型枚举 (PromotionType)
enum PromotionType {
discount(label: '折扣', emoji: '🏷️'),
fullReduction(label: '满减', emoji: '💰'),
gift(label: '买赠', emoji: '🎁'),
flashSale(label: '秒杀', emoji: '⚡'),
groupBuy(label: '团购', emoji: '👥'),
coupon(label: '优惠券', emoji: '🎫'),
member(label: '会员价', emoji: '👑'),
other(label: '其他', emoji: '📌');
final String label;
final String emoji;
const PromotionType({required this.label, required this.emoji});
}
3.1.5 优惠状态枚举 (PromotionStatus)
enum PromotionStatus {
active(label: '进行中', emoji: '🔥'),
upcoming(label: '即将开始', emoji: '⏳'),
ended(label: '已结束', emoji: '❌'),
soldOut(label: '已抢完', emoji: '😔');
final String label;
final String emoji;
const PromotionStatus({required this.label, required this.emoji});
}
3.2 页面结构设计
3.2.1 主页面布局
3.2.2 附近优惠页面结构
3.2.3 分类浏览页面结构
3.2.4 收藏关注页面结构
3.3 优惠筛选逻辑
3.4 收藏提醒逻辑
四、UI设计规范
4.1 配色方案
应用以热情的红色为主色调,象征优惠与实惠:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #F44336 (Red) | 导航、主题元素 |
| 辅助色 | #EF5350 | 按钮、强调 |
| 第三色 | #E57373 | 背景、卡片 |
| 背景色 | #F5F5F5 | 页面背景 |
| 卡片背景 | #FFFFFF | 信息卡片 |
4.2 优惠类型色彩映射
| 类型 | 色值 | 视觉效果 |
|---|---|---|
| 折扣 | #FF5722 | 深橙色 |
| 满减 | #4CAF50 | 绿色 |
| 买赠 | #9C27B0 | 紫色 |
| 秒杀 | #F44336 | 红色 |
| 团购 | #2196F3 | 蓝色 |
| 优惠券 | #FF9800 | 橙色 |
| 会员价 | #FFD700 | 金色 |
| 其他 | #607D8B | 蓝灰色 |
4.3 优惠状态色彩映射
| 状态 | 色值 | 视觉效果 |
|---|---|---|
| 进行中 | #4CAF50 | 绿色 |
| 即将开始 | #FF9800 | 橙色 |
| 已结束 | #9E9E9E | 灰色 |
| 已抢完 | #F44336 | 红色 |
4.4 字体规范
| 元素 | 字号 | 字重 | 颜色 |
|---|---|---|---|
| 页面标题 | 24px | Bold | 主色 |
| 优惠标题 | 16px | Medium | #333333 |
| 原价 | 14px | Regular | #999999 |
| 优惠价 | 20px | Bold | #F44336 |
| 店铺名称 | 14px | Medium | #666666 |
| 距离信息 | 12px | Regular | #999999 |
4.5 组件规范
4.5.1 优惠卡片
┌─────────────────────────────────────┐
│ ┌──────────┐ 🛒 永辉超市 │
│ │ │ ⭐ 4.8分 1.2km │
│ │ 商品图片 │ │
│ │ │ 🏷️ 5折特惠 │
│ └──────────┘ │
│ │
│ 新鲜进口香蕉 500g │
│ ¥9.9 ~~¥19.9~~ 🔥 进行中 │
│ │
│ [收藏] [查看详情] │
└─────────────────────────────────────┘
4.5.2 类型标签
┌─────────────────────────────────────┐
│ 🏷️ 折扣 💰 满减 ⚡ 秒杀 👥 团购 │
│ 🎁 买赠 🎫 优惠券 👑 会员价 📌 其他 │
└─────────────────────────────────────┘
4.5.3 店铺卡片
┌─────────────────────────────────────┐
│ 🛒 沃尔玛超市 │
│ ⭐ 4.9分 | 2.5km | 营业中 │
│ 📍 中山路123号 │
│ 📞 021-12345678 │
│ │
│ [查看优惠] [导航前往] │
└─────────────────────────────────────┘
五、核心功能实现
5.1 优惠服务实现
class PromotionService {
final List<Store> _stores = [];
final List<Promotion> _promotions = [];
List<Store> getNearbyStores(double lat, double lng, {double radius = 5000}) {
return _stores.where((store) {
final distance = calculateDistance(lat, lng, store.latitude, store.longitude);
return distance <= radius;
}).toList();
}
List<Promotion> getPromotions(String storeId) {
return _promotions.where((p) => p.storeId == storeId).toList();
}
List<Promotion> getPromotionsByType(PromotionType type) {
return _promotions.where((p) => p.type == type).toList();
}
List<Promotion> getActivePromotions() {
return _promotions.where((p) => p.status == PromotionStatus.active).toList();
}
double calculateDistance(double lat1, double lng1, double lat2, double lng2) {
// 计算两点间距离
const double earthRadius = 6371000; // 地球半径(米)
final double dLat = (lat2 - lat1) * pi / 180;
final double dLng = (lng2 - lng1) * pi / 180;
final double a = sin(dLat / 2) * sin(dLat / 2) +
cos(lat1 * pi / 180) * cos(lat2 * pi / 180) *
sin(dLng / 2) * sin(dLng / 2);
final double c = 2 * atan2(sqrt(a), sqrt(1 - a));
return earthRadius * c;
}
}
5.2 优惠控制器实现
class PromotionController {
final PromotionService _promotionService;
final DataManager _dataManager;
List<Store> stores = [];
List<Promotion> promotions = [];
List<String> favorites = [];
double currentLat = 31.2304; // 默认上海坐标
double currentLng = 121.4737;
PromotionController(this._promotionService, this._dataManager);
Future<void> initialize() async {
await loadNearbyStores();
await loadPromotions();
await loadFavorites();
}
Future<void> loadNearbyStores() async {
stores = _promotionService.getNearbyStores(currentLat, currentLng);
}
Future<void> loadPromotions() async {
promotions = _promotionService.getActivePromotions();
}
Future<void> loadFavorites() async {
favorites = await _dataManager.loadFavorites();
}
void filterByStoreType(StoreType type) {
final storeIds = stores
.where((s) => s.type == type)
.map((s) => s.id)
.toList();
promotions = _promotionService.getActivePromotions()
.where((p) => storeIds.contains(p.storeId))
.toList();
}
void filterByPromotionType(PromotionType type) {
promotions = _promotionService.getPromotionsByType(type);
}
void sortByPrice() {
promotions.sort((a, b) => a.discountPrice.compareTo(b.discountPrice));
}
void sortByDistance() {
// 按距离排序
}
void collectPromotion(String id) {
if (!favorites.contains(id)) {
favorites.add(id);
_dataManager.saveFavorites(favorites);
}
}
void removeFavorite(String id) {
favorites.remove(id);
_dataManager.saveFavorites(favorites);
}
bool isFavorite(String id) {
return favorites.contains(id);
}
List<Promotion> getFavoritePromotions() {
return promotions.where((p) => favorites.contains(p.id)).toList();
}
}
5.3 数据管理实现
class DataManager {
static const String _favoritesKey = 'favorites';
static const String _remindersKey = 'reminders';
static Map<String, String> _storage = {};
Future<List<String>> loadFavorites() async {
final jsonString = _storage[_favoritesKey];
if (jsonString == null) return [];
final jsonList = json.decode(jsonString) as List;
return jsonList.map((item) => item.toString()).toList();
}
Future<void> saveFavorites(List<String> favorites) async {
_storage[_favoritesKey] = json.encode(favorites);
}
Future<Map<String, DateTime>> loadReminders() async {
final jsonString = _storage[_remindersKey];
if (jsonString == null) return {};
final jsonMap = json.decode(jsonString) as Map<String, dynamic>;
return jsonMap.map((k, v) => MapEntry(k, DateTime.parse(v)));
}
Future<void> saveReminders(Map<String, DateTime> reminders) async {
final jsonMap = reminders.map((k, v) => MapEntry(k, v.toIso8601String()));
_storage[_remindersKey] = json.encode(jsonMap);
}
}
六、交互设计
6.1 附近优惠浏览交互流程
6.2 优惠收藏交互流程
6.3 优惠详情查看交互流程
七、扩展功能规划
7.1 后续版本规划
7.2 功能扩展建议
7.2.1 优惠券领取
优惠券功能:
- 在线领取优惠券
- 优惠券使用记录
- 优惠券到期提醒
- 优惠券转赠
7.2.2 积分系统
积分功能:
- 浏览获得积分
- 分享获得积分
- 积分兑换优惠
- 积分排行榜
7.2.3 分享功能
分享功能:
- 分享优惠给好友
- 生成分享海报
- 邀请好友奖励
- 社交分享
八、注意事项
8.1 开发注意事项
-
定位权限:需要获取用户定位权限
-
数据更新:优惠信息需要及时更新
-
缓存策略:合理设置数据缓存
-
用户体验:优惠筛选需要快速响应
-
数据安全:用户位置信息需要安全存储
8.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 定位失败 | 权限未开启 | 提示开启权限 |
| 优惠不显示 | 网络问题 | 检查网络连接 |
| 收藏丢失 | 存储失败 | 增加错误处理 |
| 提醒不生效 | 时间设置错误 | 检查时间设置 |
| 应用崩溃 | 空指针异常 | 增加空值检查 |
8.3 使用技巧
🛒 本地商超优惠推送使用技巧 🛒
附近优惠
- 开启定位获取周边优惠
- 使用筛选缩小范围
- 按距离排序找最近的
- 关注店铺获取推送
优惠收藏
- 收藏心仪优惠
- 设置到期提醒
- 及时使用避免过期
- 分享给好友
分类浏览
- 按类型筛选优惠
- 按价格排序
- 查看最新优惠
- 关注热门店铺
个人中心
- 完善个人信息
- 设置偏好类型
- 管理收藏列表
- 查看使用记录
九、运行说明
9.1 环境要求
| 环境 | 版本要求 |
|---|---|
| Flutter SDK | >= 3.0.0 |
| Dart SDK | >= 2.17.0 |
| 鸿蒙OS | API 21+ |
| Web浏览器 | Chrome 90+ |
9.2 运行命令
# 查看可用设备
flutter devices
# 运行到Web服务器
flutter run -d web-server -t lib/main_store_promotion.dart --web-port 8162
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_store_promotion.dart
# 代码分析
flutter analyze lib/main_store_promotion.dart
十、总结
本地商超优惠推送应用通过附近优惠、分类浏览、收藏关注、个人中心四大模块,为用户提供了一个便捷的本地商超优惠信息聚合平台。用户可以查看周边商超优惠、按类别筛选、收藏心仪商品、设置到期提醒。
核心功能包括定位服务、优惠筛选、收藏管理、到期提醒等。应用采用热情的红色为主色调,象征优惠与实惠,界面简洁美观,交互流畅自然。
通过本应用,希望能够帮助用户及时发现周边优惠,节省购物开支,享受更实惠的本地生活。
本地商超优惠推送——让优惠触手可及
更多推荐

所有评论(0)