旅行预算管家应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图




1.1 应用简介
旅行预算管家是一款旅行探索类应用,为旅行者提供全程预算管理服务。支持预算规划、实时记账、多币种换算、支出分析四大核心功能,帮助用户在旅途中合理控制开支,避免超支尴尬。无论是短途周末游还是长途跨国旅行,都能轻松掌握财务状况。
应用以清新的青色为主色调,象征旅途的轻松与自由。涵盖预算概览、支出记录、支出分析、我的旅行四大模块。用户可以创建旅行计划、设定预算、记录每笔支出、查看分析报告,实现旅行财务的全方位管理。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 预算规划 | 创建旅行并设定预算 | 表单输入 |
| 实时记账 | 快速记录每笔支出 | 分类记账 |
| 多币种 | 支持10种货币换算 | 汇率转换 |
| 支出分析 | 分类统计与可视化 | 饼图展示 |
| 进度追踪 | 预算使用进度监控 | 进度条 |
| 旅行管理 | 多次旅行统一管理 | 列表展示 |
1.3 货币类型定义
| 序号 | 货币名称 | 符号 | 代码 | 汇率(参考) |
|---|---|---|---|---|
| 1 | 人民币 | ¥ | CNY | 1.0 |
| 2 | 美元 | $ | USD | 0.14 |
| 3 | 欧元 | € | EUR | 0.13 |
| 4 | 日元 | ¥ | JPY | 21.0 |
| 5 | 韩元 | ₩ | KRW | 188.0 |
| 6 | 泰铢 | ฿ | THB | 4.9 |
| 7 | 港币 | HK$ | HKD | 1.09 |
| 8 | 新币 | S$ | SGD | 0.19 |
| 9 | 马币 | RM | MYR | 0.66 |
| 10 | 澳元 | A$ | AUD | 0.21 |
1.4 支出分类定义
| 序号 | 分类名称 | Emoji | 颜色代码 | 描述 |
|---|---|---|---|---|
| 1 | 交通 | 🚗 | #2196F3 | 机票、车票等 |
| 2 | 住宿 | 🏨 | #9C27B0 | 酒店、民宿 |
| 3 | 餐饮 | 🍜 | #FF9800 | 餐厅、小吃 |
| 4 | 购物 | 🛍️ | #E91E63 | 纪念品、特产 |
| 5 | 娱乐 | 🎢 | #4CAF50 | 游乐、表演 |
| 6 | 门票 | 🎫 | #00BCD4 | 景点门票 |
| 7 | 通讯 | 📱 | #795548 | 电话卡、WiFi |
| 8 | 医疗 | 💊 | #F44336 | 药品、就医 |
| 9 | 其他 | 📦 | #607D8B | 其他支出 |
1.5 旅行状态定义
| 序号 | 状态名称 | Emoji | 颜色代码 | 描述 |
|---|---|---|---|---|
| 1 | 计划中 | 📋 | #9E9E9E | 尚未出发 |
| 2 | 进行中 | ✈️ | #4CAF50 | 正在旅行 |
| 3 | 已完成 | ✅ | #2196F3 | 旅行结束 |
| 4 | 已取消 | ❌ | #F44336 | 取消计划 |
1.6 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 自定义绘制 | CustomPainter | - |
| 图表展示 | 饼图绘制 | - |
| 目标平台 | 鸿蒙OS / Web | API 21+ |
1.7 项目结构
lib/
└── main_travel_budget.dart
├── TravelBudgetApp # 应用入口
├── Currency # 货币类型枚举
├── ExpenseCategory # 支出分类枚举
├── TripStatus # 旅行状态枚举
├── Trip # 旅行模型
├── Expense # 支出模型
├── BudgetAllocation # 预算分配模型
├── TravelBudgetHomePage # 主页面(底部导航)
├── _buildOverviewPage # 预算概览页
├── _buildExpensesPage # 支出记录页
├── _buildAnalysisPage # 支出分析页
├── _buildTripsPage # 我的旅行页
└── PieChartPainter # 饼图绘制器
二、系统架构
2.1 整体架构图
Data Layer
Business Layer
Presentation Layer
主页面
TravelBudgetHomePage
预算概览
支出记录
支出分析
我的旅行
预算进度
今日支出
统计卡片
日期分组
支出列表
添加支出
饼图展示
分类明细
旅行列表
创建旅行
货币转换器
CurrencyConverter
支出计算器
ExpenseCalculator
图表绘制器
ChartPainter
Trip
旅行模型
Expense
支出模型
Currency
货币枚举
ExpenseCategory
支出分类
2.2 类图设计
uses
has
uses
has
belongs to
TravelBudgetApp
+Widget build()
<<enumeration>>
Currency
+String label
+String symbol
+String code
+double rate
+toCny(amount)
+fromCny(amount)
+cny()
+usd()
+eur()
+jpy()
+krw()
+thb()
<<enumeration>>
ExpenseCategory
+String label
+String icon
+Color color
+transport()
+accommodation()
+food()
+shopping()
+entertainment()
+tickets()
<<enumeration>>
TripStatus
+String label
+String icon
+Color color
+planning()
+ongoing()
+completed()
+cancelled()
Trip
+String id
+String name
+String destination
+DateTime startDate
+DateTime endDate
+double budget
+Currency currency
+TripStatus status
+int days
+int daysRemaining
Expense
+String id
+String tripId
+String title
+double amount
+Currency currency
+ExpenseCategory category
+DateTime date
+double amountInCny
2.3 页面导航流程
概览
记录
分析
旅行
应用启动
预算概览
底部导航
查看预算进度
支出列表
饼图分析
旅行列表
添加支出
填写支出信息
保存支出
创建旅行
填写旅行信息
保存旅行
查看分类明细
2.4 记账流程
概览页 支出管理 记账弹窗 用户 概览页 支出管理 记账弹窗 用户 点击记一笔 显示表单 输入支出名称 输入金额 选择货币 选择分类 创建支出记录 计算人民币金额 更新统计数据 显示更新后的进度
三、核心模块设计
3.1 数据模型设计
3.1.1 货币类型枚举 (Currency)
dart
enum Currency {
cny('人民币', '¥', 'CNY', 1.0),
usd('美元', '\$', 'USD', 0.14),
eur('欧元', '€', 'EUR', 0.13),
jpy('日元', '¥', 'JPY', 21.0),
krw('韩元', '₩', 'KRW', 188.0),
thb('泰铢', '฿', 'THB', 4.9),
hkd('港币', 'HK\$', 'HKD', 1.09),
sgd('新币', 'S\$', 'SGD', 0.19),
myr('马币', 'RM', 'MYR', 0.66),
aud('澳元', 'A\$', 'AUD', 0.21);
final String label;
final String symbol;
final String code;
final double rate;
double toCny(double amount) => amount / rate;
double fromCny(double amount) => amount * rate;
}
3.1.2 支出分类枚举 (ExpenseCategory)
dart
enum ExpenseCategory {
transport('交通', '🚗', Color(0xFF2196F3)),
accommodation('住宿', '🏨', Color(0xFF9C27B0)),
food('餐饮', '🍜', Color(0xFFFF9800)),
shopping('购物', '🛍️', Color(0xFFE91E63)),
entertainment('娱乐', '🎢', Color(0xFF4CAF50)),
tickets('门票', '🎫', Color(0xFF00BCD4)),
communication('通讯', '📱', Color(0xFF795548)),
medical('医疗', '💊', Color(0xFFF44336)),
other('其他', '📦', Color(0xFF607D8B));
final String label;
final String icon;
final Color color;
}
3.1.3 旅行模型 (Trip)
dart
class Trip {
final String id; // 旅行ID
final String name; // 旅行名称
final String destination; // 目的地
final DateTime startDate; // 开始日期
final DateTime endDate; // 结束日期
final double budget; // 预算金额
final Currency currency; // 预算货币
final TripStatus status; // 旅行状态
final String? coverImage; // 封面图片
final DateTime createdAt; // 创建时间
int get days => endDate.difference(startDate).inDays + 1;
int get daysRemaining => endDate.difference(DateTime.now()).inDays;
}
3.1.4 支出模型 (Expense)
dart
class Expense {
final String id; // 支出ID
final String tripId; // 所属旅行ID
final String title; // 支出名称
final double amount; // 金额
final Currency currency; // 货币类型
final ExpenseCategory category; // 支出分类
final DateTime date; // 支出日期
final String? notes; // 备注
final String? receipt; // 小票图片
double get amountInCny => currency.toCny(amount);
}
3.1.5 支出分类分布
30% 25% 20% 15% 5% 5% 支出分类分布示例 交通 住宿 餐饮 购物 门票 其他
3.2 页面结构设计
3.2.1 主页面布局
TravelBudgetHomePage
IndexedStack
预算概览页
支出记录页
支出分析页
我的旅行页
NavigationBar
概览 Tab
记录 Tab
分析 Tab
旅行 Tab
3.2.2 预算概览页结构
预算概览页
预算进度卡
统计卡片组
今日支出
总预算显示
进度条
已支出/剩余
行程天数
目的地
日均预算
预计支出
今日支出列表
空状态提示
3.2.3 支出记录页结构
支出记录页
统计头部
日期分组列表
日期组
日期标题
当日合计
支出项列表
支出项
分类图标
支出名称
金额显示
3.2.4 支出分析页结构
支出分析页
统计头部
饼图区域
分类明细列表
饼图绘制
中心总金额
分类项
分类图标
进度条
金额/百分比
3.3 货币换算逻辑
CNY
其他
获取支出金额
货币类型
直接使用
获取汇率
计算人民币金额
amount / rate
累加统计
更新预算进度
更新分类统计
3.4 预算进度计算
是
否
获取旅行预算
转换为人民币
获取总支出
计算进度百分比
percentage = spent / budget
是否超支
显示红色警告
显示正常进度
计算剩余金额
更新UI显示
四、UI设计规范
4.1 配色方案
应用以清新的青色为主色调,象征旅途的轻松与自由:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #00ACC1 (Cyan) | 导航、主题元素 |
| 辅助色 | #00838F | 支出记录页 |
| 第三色 | #006064 | 分析页面 |
| 强调色 | #00BCD4 | 进度条 |
| 背景色 | #006064 | 页面背景 |
| 卡片背景 | #00838F | 统计卡片 |
4.2 分类颜色规范
| 分类 | 色值 | 视觉效果 |
|---|---|---|
| 交通 | #2196F3 | 蓝色 |
| 住宿 | #9C27B0 | 紫色 |
| 餐饮 | #FF9800 | 橙色 |
| 购物 | #E91E63 | 粉色 |
| 娱乐 | #4CAF50 | 绿色 |
| 门票 | #00BCD4 | 青色 |
| 通讯 | #795548 | 棕色 |
| 医疗 | #F44336 | 红色 |
| 其他 | #607D8B | 灰蓝 |
4.3 字体规范
| 元素 | 字号 | 字重 | 颜色 |
|---|---|---|---|
| 页面标题 | 24px | Bold | 白色 |
| 预算金额 | 28px | Bold | 白色 |
| 支出名称 | 16px | Bold | #000000 |
| 分类标签 | 12px | Regular | 灰色 |
| 统计数字 | 20px | Bold | 白色 |
4.4 组件规范
4.4.1 预算进度卡片
┌─────────────────────────────────────┐
│ 总预算 进行中 │
│ ¥15000 │
│ ████████████░░░░░░░░ 65% │
│ 已支出 ¥9750 剩余 ¥5250 │
└─────────────────────────────────────┘
4.4.2 统计卡片组
┌─────────────────────────────────────┐
│ 📅 行程天数 📍 目的地 │
│ 7天 东京 │
├─────────────────────────────────────┤
│ 💰 日均预算 📊 预计支出 │
│ ¥2143 ¥6429 │
└─────────────────────────────────────┘
4.4.3 支出项卡片
┌─────────────────────────────────────┐
│ 🍜 餐饮 │
│ 拉面 ¥1200 │
│ ≈¥57 │
└─────────────────────────────────────┘
4.4.4 分类明细项
┌─────────────────────────────────────┐
│ 🏨 住宿 │
│ ████████████░░░░░░░░ │
│ ¥4500 30.0% │
└─────────────────────────────────────┘
4.4.5 旅行卡片
┌─────────────────────────────────────┐
│ 日本东京之旅 进行中 │
│ 📍 日本东京 │
│ 📅 3/15 - 3/21 ⏱️ 7天 │
│ 预算: ¥15000 已用: 65% │
│ ████████████░░░░░░░░ │
└─────────────────────────────────────┘
五、核心功能实现
5.1 货币换算实现
dart
enum Currency {
cny('人民币', '¥', 'CNY', 1.0),
jpy('日元', '¥', 'JPY', 21.0),
// ...
final double rate;
// 换算为人民币
double toCny(double amount) => amount / rate;
// 从人民币换算
double fromCny(double amount) => amount * rate;
}
汇率换算公式:
AmountCNY=AmountforeignRateforeign Amount_{CNY} = \frac{Amount_{foreign}}{Rate_{foreign}} AmountCNY=RateforeignAmountforeign
5.2 支出统计实现
dart
double _getTotalExpenses(String tripId) {
return _expenses
.where((e) => e.tripId == tripId)
.fold(0.0, (sum, e) => sum + e.amountInCny);
}
Map<ExpenseCategory, double> _getExpensesByCategory(String tripId) {
Map<ExpenseCategory, double> result = {};
for (var expense in _expenses.where((e) => e.tripId == tripId)) {
result[expense.category] =
(result[expense.category] ?? 0) + expense.amountInCny;
}
return result;
}
5.3 饼图绘制实现
dart
class PieChartPainter extends CustomPainter {
final Map<ExpenseCategory, double> data;
final double total;
@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
final radius = size.width < size.height
? size.width / 2 - 20
: size.height / 2 - 20;
double startAngle = -pi / 2;
for (var entry in data.entries) {
final sweepAngle = (entry.value / total) * 2 * pi;
final paint = Paint()
..color = entry.key.color
..style = PaintingStyle.fill;
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
startAngle,
sweepAngle,
true,
paint,
);
startAngle += sweepAngle;
}
// 绘制中心圆
canvas.drawCircle(center, radius * 0.5, innerPaint);
}
}
5.4 预算进度计算
预算使用百分比计算:
Percentage=TotalSpentTotalBudget×100% Percentage = \frac{TotalSpent}{TotalBudget} \times 100\% Percentage=TotalBudgetTotalSpent×100%
日均预算计算:
DailyBudget=TotalBudgetTripDays DailyBudget = \frac{TotalBudget}{TripDays} DailyBudget=TripDaysTotalBudget
预计支出计算:
ExpectedSpent=DailyBudget×DaysPassed ExpectedSpent = DailyBudget \times DaysPassed ExpectedSpent=DailyBudget×DaysPassed
5.5 添加支出实现
dart
void _addExpense() {
if (_selectedTrip == null) return;
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Row(
children: [
Icon(Icons.add_circle, color: Colors.cyanAccent),
SizedBox(width: 8),
Text('添加支出'),
],
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(decoration: InputDecoration(hintText: '支出名称')),
Row(
children: [
Expanded(child: TextField(keyboardType: TextInputType.number)),
DropdownButtonFormField<Currency>(...),
],
),
DropdownButtonFormField<ExpenseCategory>(...),
],
),
),
);
}
六、交互设计
6.1 记账流程
数据层 记账弹窗 主页 用户 数据层 记账弹窗 主页 用户 点击记一笔 显示表单 填写支出信息 保存支出 更新统计 显示更新
6.2 旅行切换流程
点击旅行
创建旅行
打开我的旅行
显示旅行列表
用户操作
选中旅行
跳转概览页
显示该旅行数据
显示创建表单
填写信息
保存旅行
6.3 分析查看流程
自动加载
滚动查看
按金额排序
分析页
饼图展示
分类明细
排序显示
七、扩展功能规划
7.1 后续版本规划
2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 2024-03-24 2024-03-31 2024-04-07 基础UI框架 预算管理 多币种支持 实时汇率 预算提醒 导出报表 多人分账 云端同步 AI智能建议 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 旅行预算管家应用开发计划
7.2 功能扩展建议
7.2.1 实时汇率
汇率功能:
- 接入汇率API
- 自动更新汇率
- 离线汇率缓存
- 汇率趋势图
7.2.2 预算提醒
提醒功能:
- 超支预警
- 日预算提醒
- 分类预算限制
- 自定义提醒规则
7.2.3 多人分账
分账功能:
- 创建旅行群组
- 成员费用记录
- 自动分账计算
- 结算报表导出
八、注意事项
8.1 开发注意事项
-
汇率精度:货币换算需注意精度问题
-
数据持久化:支出数据需本地持久化存储
-
状态管理:旅行切换时需正确更新状态
-
图表绘制:CustomPainter需正确实现shouldRepaint
-
日期计算:跨日期计算需注意时区问题
8.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 汇率不准 | 使用固定汇率 | 接入实时API |
| 金额显示异常 | 精度丢失 | 使用Decimal |
| 饼图不显示 | 数据为空 | 添加空判断 |
| 进度超100% | 超支未处理 | 添加clamp |
| 日期计算错误 | 时区问题 | 统一时区 |
8.3 使用技巧
💰 旅行预算管理技巧 💰
预算规划建议
- 交通费用:预留20%弹性空间
- 住宿费用:提前预订享优惠
- 餐饮费用:按人均×天数计算
- 购物费用:设定上限避免冲动
记账习惯培养
- 每日睡前整理当日支出
- 大额支出及时记录
- 保留小票便于核对
- 分类准确便于分析
超支应对策略
- 调整后续行程预算
- 减少非必要支出
- 寻找免费替代活动
- 合理使用优惠券
九、运行说明
9.1 环境要求
| 环境 | 版本要求 |
|---|---|
| Flutter SDK | >= 3.0.0 |
| Dart SDK | >= 2.17.0 |
| 鸿蒙OS | API 21+ |
| Web浏览器 | Chrome 90+ |
9.2 运行命令
bash
# 查看可用设备
flutter devices
# 运行到Web服务器
flutter run -d web-server -t lib/main_travel_budget.dart --web-port 8140
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_travel_budget.dart
# 代码分析
flutter analyze lib/main_travel_budget.dart
十、总结
旅行预算管家应用通过预算概览、支出记录、支出分析、我的旅行四大模块,为旅行者提供了一个便捷的预算管理平台。应用支持10种货币换算、9种支出分类、4种旅行状态,帮助用户在旅途中合理控制开支,避免超支尴尬。
核心功能涵盖预算规划、实时记账、多币种换算、支出分析四大模块。预算规划支持创建旅行并设定预算上限;实时记账支持快速记录每笔支出并自动换算;多币种换算支持10种常用货币;支出分析通过饼图直观展示消费分布。
应用采用 Material Design 3 设计规范,以清新的青色为主色调,象征旅途的轻松与自由。通过本应用,希望能够帮助旅行者轻松掌握财务状况,享受无忧旅程。
旅行预算管家------不超支的旅行