11 Commits

Author SHA1 Message Date
1ab75f4701 Merge branch 'develop' into feature/member
修改
2024-11-27 16:18:26 +08:00
773c155d0c 修复警告 2024-11-27 16:08:34 +08:00
3ad8cf9184 Revert "修复警告"
This reverts commit 1147bc47d7.
2024-11-27 16:07:37 +08:00
1147bc47d7 修复警告 2024-11-27 16:07:10 +08:00
30e9345d81 优化: 主页统计功能改进
- 调整主页统计区域布局和样式
- 优化支出、收入、结余的显示顺序
- 改进结余区域的高亮显示逻辑
- 简化代码结构和格式
2024-11-27 14:27:26 +08:00
c75439d15a 修改README 2024-11-27 13:50:53 +08:00
95b3233d5e docs: update README.md with checkboxes and status icons 2024-11-27 13:46:15 +08:00
df80dadfea docs: update README.md with complete formatting 2024-11-27 13:43:07 +08:00
e03149377c docs: update README.md with new format and roadmap 2024-11-27 13:37:01 +08:00
49e83cea90 docs: update README.md with new email and roadmap 2024-11-27 13:29:29 +08:00
6d9c5a27f7 修改README 2024-11-27 13:09:28 +08:00
2 changed files with 165 additions and 83 deletions

148
README.md
View File

@@ -2,58 +2,136 @@
一个轻量级的个人记账应用,专注于隐私和离线使用。 一个轻量级的个人记账应用,专注于隐私和离线使用。
## 🌟 特点 ## 📖 项目概述
本项目是一个使用 Kotlin 和 Jetpack Compose 开发的 Android 记账应用,采用 MVVM 架构,提供简洁直观的用户界面和丰富的记账功能。
## ⭐️ 主要特性
- 🔒 完全离线运行,无需网络连接 - 🔒 完全离线运行,无需网络连接
- 📱 极简权限要求,仅使用必要的系统权限 - 📱 极简权限要求,仅使用必要的系统权限
- 💰 支持收入和支出记录 - 💰 支持收入和支出记录
- 👥 支持多人记账 - 👥 支持多人记账
- 📊 按日期和类别统计 - 📊 按日期和类别统计
- 🎨 Material You 设计风格
## 🛠 技术栈 ## 🛠 技术栈
- 语言Kotlin - 💻 开发语言Kotlin
- UI框架Jetpack Compose - 🎨 UI 框架Jetpack Compose
- 数据库Room - 🏗️ 架构模式MVVM
- 架构MVVM - 💾 数据存储Room Database
- 💉 依赖注入Hilt
- ⚡️ 异步处理Kotlin Coroutines
## 📱 功能 ## 🗺 开发路线图
### 记账管理 ### 1. 基础记账 (已完成 ✨)
- 收入支出记录 - [x] 收入/支出记录管理
- 自定义分类管理 - [x] 分类管理系统
- 日期和时间选择 - [x] 自定义日期选择
- 备注说明 - [x] Material 3 设计界面
- [x] 深色/浅色主题切换
- [x] 主题色自定义
### 成员管理 ### 2. 成员系统 (已完成 🎉)
- 多人记账支持 - [x] 成员添加/编辑/删除
- 成员关联记录 - [x] 记账时选择相关成员
- 按成员筛选统计 - [x] 主页账单修改相关成员
- [x] 成员消费统计
### 数据统计 ### 3. 数据分析 (进行中 🚀)
- 月度收支统计 - [ ] 支出/收入趋势图表
- 分类统计 - [ ] 分类占比饼图
- 每日收支明细 - [ ] 月度/年度报表
- [ ] 成员消费分析
- [ ] 自定义统计周期
## 🔒 隐私保护 ### 4. 数据管理 (计划中 📝)
- [ ] 导出 CSV/Excel 功能
- [ ] 云端备份支持
- [ ] 数据迁移工具
- [ ] 定期自动备份
- [ ] 备份加密功能
- 完全离线运行,数据存储在本地 ### 5. 预算管理 (计划中 💡)
- 无需任何网络权限 - [ ] 月度预算设置
- 最小化系统权限要求 - [ ] 预算超支提醒
- [ ] 分类预算管理
- [ ] 成员预算管理
- [ ] 预算分析报告
## 📝 系统要求 ### 6. 体验优化 (持续进行 🔄)
- [x] 深色模式支持
- Android 5.0 (API 21) 或更高版本 - [ ] 手势操作优化
- 存储权限(用于数据备份,可选) - [ ] 快速记账小组件
- [ ] 多语言支持
## 🔜 未来计划
- [ ] 数据导出和备份
- [ ] 预算管理
- [ ] 更多统计图表
- [ ] 自定义主题 - [ ] 自定义主题
### 7. 性能提升 (持续进行 ⚡️)
- [ ] 大数据量处理优化
- [ ] 启动速度优化
- [ ] 内存使用优化
- [ ] 缓存策略优化
- [ ] 数据库查询优化
## 🌲 分支管理
- `master`: 稳定主分支
- `develop`: 主开发分支
- `feature/*`: 功能开发分支
- `release/*`: 版本发布分支
- `hotfix/*`: 紧急修复分支
## 📝 版本历史
### v1.1.0 (2024-01-10)
- 成员管理功能
- 成员添加/编辑/删除
- 记账时选择相关成员
- 成员消费统计
- UI/UX 优化
- 记录展示优化
- 月度统计界面
- 分组展示优化
- 数据管理
- 记录筛选增强
- 数据库性能优化
- 状态管理重构
### v1.0.0 (2024-01-05)
- 基础记账功能
- 收入/支出记录
- 金额、日期、分类、备注管理
- Material 3 设计界面
- 深色/浅色主题切换
- 主题色自定义
- 分类管理
- 默认分类预设
- 自定义分类支持
- 分类编辑与删除
- 月度统计
- 月度收支总览
- 月份快速切换
- 自定义日期选择器
## 🤝 贡献指南
1. Fork 项目
2. 创建功能分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'feat: Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 提交 Pull Request
## 📄 许可证 ## 📄 许可证
[MIT License](LICENSE) 本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详细信息
## 📮 联系方式
- 作者YovinChen
- 邮箱gzh298255@gmail.com
- 博客:[blog.hhdxw.top](https://blog.hhdxw.top)
## 🙏 致谢
感谢所有为这个项目做出贡献的开发者!

View File

@@ -1,5 +1,6 @@
package com.yovinchen.bookkeeping.ui.components package com.yovinchen.bookkeeping.ui.components
import android.annotation.SuppressLint
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@@ -22,9 +23,7 @@ import java.time.YearMonth
@Composable @Composable
fun MonthYearPickerDialog( fun MonthYearPickerDialog(
selectedMonth: YearMonth, selectedMonth: YearMonth, onMonthSelected: (YearMonth) -> Unit, onDismiss: () -> Unit
onMonthSelected: (YearMonth) -> Unit,
onDismiss: () -> Unit
) { ) {
var currentYearMonth by remember { mutableStateOf(selectedMonth) } var currentYearMonth by remember { mutableStateOf(selectedMonth) }
@@ -71,8 +70,7 @@ fun MonthYearPickerDialog(
// 月份网格 // 月份网格
LazyVerticalGrid( LazyVerticalGrid(
columns = GridCells.Fixed(3), columns = GridCells.Fixed(3), modifier = Modifier.height(200.dp)
modifier = Modifier.height(200.dp)
) { ) {
items(12) { index -> items(12) { index ->
val month = index + 1 val month = index + 1
@@ -126,6 +124,7 @@ fun MonthYearPickerDialog(
} }
} }
@SuppressLint("DefaultLocale")
@Composable @Composable
fun MonthlyStatistics( fun MonthlyStatistics(
totalIncome: Double, totalIncome: Double,
@@ -163,11 +162,9 @@ fun MonthlyStatistics(
Icon(Icons.AutoMirrored.Filled.KeyboardArrowLeft, "上个月") Icon(Icons.AutoMirrored.Filled.KeyboardArrowLeft, "上个月")
} }
Text( Text(text = "${selectedMonth.year}${selectedMonth.monthValue}",
text = "${selectedMonth.year}${selectedMonth.monthValue}",
style = MaterialTheme.typography.titleLarge, style = MaterialTheme.typography.titleLarge,
modifier = Modifier.clickable { showMonthPicker = true } modifier = Modifier.clickable { showMonthPicker = true })
)
IconButton(onClick = onNextMonth) { IconButton(onClick = onNextMonth) {
Icon(Icons.AutoMirrored.Filled.KeyboardArrowRight, "下个月") Icon(Icons.AutoMirrored.Filled.KeyboardArrowRight, "下个月")
@@ -177,24 +174,38 @@ fun MonthlyStatistics(
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween
horizontalArrangement = Arrangement.SpaceBetween
) { ) {
// 收入统计 // 支出统计
Column( Column(modifier = Modifier
modifier = Modifier .weight(1f)
.weight(1f) .clickable { onExpenseClick() }
.clickable { onIncomeClick() } .background(
.background( if (selectedType == TransactionType.EXPENSE) MaterialTheme.colorScheme.primaryContainer
if (selectedType == TransactionType.INCOME) MaterialTheme.colorScheme.primaryContainer else Color.Transparent, RoundedCornerShape(8.dp)
else Color.Transparent, )
RoundedCornerShape(8.dp) .padding(8.dp)) {
)
.padding(8.dp)
) {
Text( Text(
text = "收入", text = "支出", style = MaterialTheme.typography.titleMedium
style = MaterialTheme.typography.titleMedium )
Text(
text = "¥${String.format("%.2f", totalExpense)}",
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.error
)
}
Spacer(modifier = Modifier.width(16.dp))
// 收入统计
Column(modifier = Modifier
.weight(1f)
.clickable { onIncomeClick() }
.background(
if (selectedType == TransactionType.INCOME) MaterialTheme.colorScheme.primaryContainer
else Color.Transparent, RoundedCornerShape(8.dp)
)
.padding(8.dp)) {
Text(
text = "收入", style = MaterialTheme.typography.titleMedium
) )
Text( Text(
text = "¥${String.format("%.2f", totalIncome)}", text = "¥${String.format("%.2f", totalIncome)}",
@@ -204,35 +215,30 @@ fun MonthlyStatistics(
} }
Spacer(modifier = Modifier.width(16.dp)) Spacer(modifier = Modifier.width(16.dp))
// 结余统计
// 支出统计 Column(modifier = Modifier
Column( .weight(1f)
modifier = Modifier .clickable { onClearFilter() }
.weight(1f) .background(
.clickable { onExpenseClick() } if (selectedType == TransactionType.INCOME) MaterialTheme.colorScheme.primaryContainer
.background( else Color.Transparent, RoundedCornerShape(8.dp)
if (selectedType == TransactionType.EXPENSE) MaterialTheme.colorScheme.primaryContainer )
else Color.Transparent, .padding(8.dp)) {
RoundedCornerShape(8.dp)
)
.padding(8.dp)
) {
Text( Text(
text = "支出", text = "结余", style = MaterialTheme.typography.titleMedium
style = MaterialTheme.typography.titleMedium
) )
Text( Text(
text = "¥${String.format("%.2f", totalExpense)}", text = "¥${String.format("%.2f", totalIncome - totalExpense)}",
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.error color = if (totalIncome >= totalExpense) MaterialTheme.colorScheme.tertiary
else MaterialTheme.colorScheme.error
) )
} }
} }
if (selectedType != null) { if (selectedType != null) {
TextButton( TextButton(
onClick = onClearFilter, onClick = onClearFilter, modifier = Modifier.align(Alignment.End)
modifier = Modifier.align(Alignment.End)
) { ) {
Text("清除筛选") Text("清除筛选")
} }
@@ -241,10 +247,8 @@ fun MonthlyStatistics(
} }
if (showMonthPicker) { if (showMonthPicker) {
MonthYearPickerDialog( MonthYearPickerDialog(selectedMonth = selectedMonth,
selectedMonth = selectedMonth,
onMonthSelected = onMonthSelected, onMonthSelected = onMonthSelected,
onDismiss = { showMonthPicker = false } onDismiss = { showMonthPicker = false })
)
} }
} }