feat: 增强财务管理系统功能与分析能力
主要更新: - 🎯 新增综合分析仪表板,包含关键指标卡片、预算对比、智能洞察等组件 - 📊 增强数据可视化能力,新增标签云分析、时间维度分析等图表 - 📱 优化移动端响应式设计,改进触控交互体验 - 🔧 新增多个API模块(base、budget、tag),完善数据管理 - 🗂️ 重构路由结构,新增贷款、快速添加、设置、统计等独立模块 - 🔄 优化数据导入导出功能,增强数据迁移能力 - 🐛 修复多个已知问题,提升系统稳定性 技术改进: - 使用IndexedDB提升本地存储性能 - 实现模拟API服务,支持离线开发 - 增加自动化测试脚本,确保功能稳定 - 优化打包配置,提升构建效率 文件变更: - 新增42个文件 - 修改55个文件 - 包含测试脚本、配置文件、组件和API模块 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,22 +1,17 @@
|
||||
<template>
|
||||
<div class="trend-chart">
|
||||
<div ref="chartRef" class="chart-container"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { EChartsOption } from '#/components/charts/useChart';
|
||||
import type { Transaction } from '#/types/finance';
|
||||
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { useChart } from '#/components/charts/useChart';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import { useChart } from '#/components/charts/useChart';
|
||||
|
||||
interface Props {
|
||||
transactions: Transaction[];
|
||||
dateRange: [string, string];
|
||||
groupBy?: 'day' | 'week' | 'month';
|
||||
groupBy?: 'day' | 'month' | 'week';
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@@ -30,19 +25,19 @@ const chartData = computed(() => {
|
||||
const [startDate, endDate] = props.dateRange;
|
||||
const start = dayjs(startDate);
|
||||
const end = dayjs(endDate);
|
||||
|
||||
|
||||
// 生成日期序列
|
||||
const dates: string[] = [];
|
||||
const incomeMap = new Map<string, number>();
|
||||
const expenseMap = new Map<string, number>();
|
||||
|
||||
|
||||
let current = start;
|
||||
while (current.isBefore(end) || current.isSame(end)) {
|
||||
const dateKey = getDateKey(current);
|
||||
dates.push(dateKey);
|
||||
incomeMap.set(dateKey, 0);
|
||||
expenseMap.set(dateKey, 0);
|
||||
|
||||
|
||||
// 根据分组方式调整日期增量
|
||||
if (props.groupBy === 'day') {
|
||||
current = current.add(1, 'day');
|
||||
@@ -52,25 +47,34 @@ const chartData = computed(() => {
|
||||
current = current.add(1, 'month');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 统计交易数据
|
||||
props.transactions.forEach((transaction) => {
|
||||
const date = dayjs(transaction.date);
|
||||
if (date.isAfter(start.subtract(1, 'day')) && date.isBefore(end.add(1, 'day'))) {
|
||||
if (
|
||||
date.isAfter(start.subtract(1, 'day')) &&
|
||||
date.isBefore(end.add(1, 'day'))
|
||||
) {
|
||||
const dateKey = getDateKey(date);
|
||||
|
||||
|
||||
if (transaction.type === 'income') {
|
||||
incomeMap.set(dateKey, (incomeMap.get(dateKey) || 0) + transaction.amount);
|
||||
incomeMap.set(
|
||||
dateKey,
|
||||
(incomeMap.get(dateKey) || 0) + transaction.amount,
|
||||
);
|
||||
} else {
|
||||
expenseMap.set(dateKey, (expenseMap.get(dateKey) || 0) + transaction.amount);
|
||||
expenseMap.set(
|
||||
dateKey,
|
||||
(expenseMap.get(dateKey) || 0) + transaction.amount,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
dates: dates,
|
||||
income: dates.map(date => incomeMap.get(date) || 0),
|
||||
expense: dates.map(date => expenseMap.get(date) || 0),
|
||||
dates,
|
||||
income: dates.map((date) => incomeMap.get(date) || 0),
|
||||
expense: dates.map((date) => expenseMap.get(date) || 0),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -151,6 +155,12 @@ onMounted(() => {
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="trend-chart">
|
||||
<div ref="chartRef" class="chart-container"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.trend-chart {
|
||||
width: 100%;
|
||||
@@ -161,4 +171,4 @@ onMounted(() => {
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user