fix: 修复微信账单金额解析问题(半角¥符号支持)
- 修复 parse_amount 函数同时支持全角¥和半角¥ - 新增 MonthRangePicker 日期选择组件 - 新增 /api/monthly-stats 接口获取月度统计 - 分析页面月度趋势使用全量数据 - 新增健康检查路由
This commit is contained in:
@@ -303,6 +303,86 @@ func (r *Repository) GetBillsNeedReview() ([]model.CleanedBill, error) {
|
||||
return r.GetCleanedBills(filter)
|
||||
}
|
||||
|
||||
// GetMonthlyStats 获取月度统计(全部数据,不受筛选条件影响)
|
||||
func (r *Repository) GetMonthlyStats() ([]model.MonthlyStat, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// 使用聚合管道按月份分组统计
|
||||
// 先按月份和收支类型分组,再汇总
|
||||
pipeline := mongo.Pipeline{
|
||||
// 添加月份字段
|
||||
{{Key: "$addFields", Value: bson.D{
|
||||
{Key: "month", Value: bson.D{
|
||||
{Key: "$dateToString", Value: bson.D{
|
||||
{Key: "format", Value: "%Y-%m"},
|
||||
{Key: "date", Value: "$time"},
|
||||
}},
|
||||
}},
|
||||
}}},
|
||||
// 按月份和收支类型分组
|
||||
{{Key: "$group", Value: bson.D{
|
||||
{Key: "_id", Value: bson.D{
|
||||
{Key: "month", Value: "$month"},
|
||||
{Key: "income_expense", Value: "$income_expense"},
|
||||
}},
|
||||
{Key: "total", Value: bson.D{{Key: "$sum", Value: "$amount"}}},
|
||||
}}},
|
||||
// 按月份重新分组,汇总收入和支出
|
||||
{{Key: "$group", Value: bson.D{
|
||||
{Key: "_id", Value: "$_id.month"},
|
||||
{Key: "expense", Value: bson.D{
|
||||
{Key: "$sum", Value: bson.D{
|
||||
{Key: "$cond", Value: bson.A{
|
||||
bson.D{{Key: "$eq", Value: bson.A{"$_id.income_expense", "支出"}}},
|
||||
"$total",
|
||||
0,
|
||||
}},
|
||||
}},
|
||||
}},
|
||||
{Key: "income", Value: bson.D{
|
||||
{Key: "$sum", Value: bson.D{
|
||||
{Key: "$cond", Value: bson.A{
|
||||
bson.D{{Key: "$eq", Value: bson.A{"$_id.income_expense", "收入"}}},
|
||||
"$total",
|
||||
0,
|
||||
}},
|
||||
}},
|
||||
}},
|
||||
}}},
|
||||
// 按月份排序
|
||||
{{Key: "$sort", Value: bson.D{{Key: "_id", Value: 1}}}},
|
||||
}
|
||||
|
||||
cursor, err := r.cleanedCollection.Aggregate(ctx, pipeline)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("月度统计聚合失败: %w", err)
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
// 解析结果
|
||||
var results []struct {
|
||||
Month string `bson:"_id"`
|
||||
Expense float64 `bson:"expense"`
|
||||
Income float64 `bson:"income"`
|
||||
}
|
||||
if err := cursor.All(ctx, &results); err != nil {
|
||||
return nil, fmt.Errorf("解析月度统计结果失败: %w", err)
|
||||
}
|
||||
|
||||
// 转换为 MonthlyStat
|
||||
stats := make([]model.MonthlyStat, len(results))
|
||||
for i, r := range results {
|
||||
stats[i] = model.MonthlyStat{
|
||||
Month: r.Month,
|
||||
Expense: r.Expense,
|
||||
Income: r.Income,
|
||||
}
|
||||
}
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
// GetClient 获取 MongoDB 客户端(用于兼容旧代码)
|
||||
func (r *Repository) GetClient() *mongo.Client {
|
||||
return r.client
|
||||
|
||||
@@ -36,6 +36,10 @@ type BillRepository interface {
|
||||
// 返回: 总支出、总收入、错误
|
||||
GetBillsAggregate(filter map[string]interface{}) (totalExpense float64, totalIncome float64, err error)
|
||||
|
||||
// GetMonthlyStats 获取月度统计(全部数据,不受筛选条件影响)
|
||||
// 返回: 月度统计列表、错误
|
||||
GetMonthlyStats() ([]model.MonthlyStat, error)
|
||||
|
||||
// GetBillsNeedReview 获取需要复核的账单
|
||||
GetBillsNeedReview() ([]model.CleanedBill, error)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user