fix
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 3m13s
Docker Build & Deploy / Deploy to Production (push) Successful in 8s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 3m13s
Docker Build & Deploy / Deploy to Production (push) Successful in 8s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
This commit is contained in:
@@ -134,6 +134,8 @@ const chartData = computed(() => {
|
||||
label: '支出',
|
||||
data: expenseData,
|
||||
borderColor: '#ff6b6b',
|
||||
yAxisID: 'yExpense',
|
||||
order: 2,
|
||||
backgroundColor: (context) => {
|
||||
const chart = context.chart
|
||||
const { ctx, chartArea } = chart
|
||||
@@ -150,13 +152,15 @@ const chartData = computed(() => {
|
||||
label: '收入',
|
||||
data: incomeData,
|
||||
borderColor: '#4ade80',
|
||||
yAxisID: 'yIncome',
|
||||
order: 1,
|
||||
backgroundColor: (context) => {
|
||||
const chart = context.chart
|
||||
const { ctx, chartArea } = chart
|
||||
if (!chartArea) {return 'rgba(74, 222, 128, 0.1)'}
|
||||
return createGradient(ctx, chartArea, '#4ade80')
|
||||
},
|
||||
fill: true,
|
||||
fill: false,
|
||||
tension: 0.4,
|
||||
pointRadius: 0,
|
||||
pointHoverRadius: 4,
|
||||
@@ -168,12 +172,40 @@ const chartData = computed(() => {
|
||||
|
||||
// Chart.js 配置
|
||||
const chartOptions = computed(() => {
|
||||
const { chartData: rawData } = prepareChartData()
|
||||
const { chartData: rawData, expenseData, incomeData } = prepareChartData()
|
||||
const maxExpense = Math.max(...expenseData, 0)
|
||||
const maxIncome = Math.max(...incomeData, 0)
|
||||
|
||||
return getChartOptions({
|
||||
scales: {
|
||||
x: { display: false },
|
||||
y: { display: false }
|
||||
x: {
|
||||
display: false,
|
||||
grid: { display: false, drawBorder: false },
|
||||
ticks: { display: false },
|
||||
border: { display: false }
|
||||
},
|
||||
y: {
|
||||
display: false,
|
||||
grid: { display: false, drawBorder: false },
|
||||
ticks: { display: false },
|
||||
border: { display: false }
|
||||
},
|
||||
yIncome: {
|
||||
display: false,
|
||||
beginAtZero: true,
|
||||
suggestedMax: maxIncome ? maxIncome * 1.1 : undefined,
|
||||
grid: { display: false, drawBorder: false },
|
||||
ticks: { display: false },
|
||||
border: { display: false }
|
||||
},
|
||||
yExpense: {
|
||||
display: false,
|
||||
beginAtZero: true,
|
||||
suggestedMax: maxExpense ? maxExpense * 1.1 : undefined,
|
||||
grid: { display: false, drawBorder: false },
|
||||
ticks: { display: false },
|
||||
border: { display: false }
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
@@ -202,7 +234,7 @@ const chartOptions = computed(() => {
|
||||
},
|
||||
label: (context) => {
|
||||
if (context.parsed.y === 0) {return null}
|
||||
return `${context.dataset.label}: ¥${context.parsed.y.toFixed(2)}`
|
||||
return `${context.dataset.label}: ¥${context.parsed.y.toFixed(1)}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,13 +210,14 @@ const pieLabelLinePlugin = {
|
||||
}
|
||||
|
||||
// 格式化金额
|
||||
const formatMoney = (value) => {
|
||||
const formatMoney = (value, decimals = 1) => {
|
||||
if (!value && value !== 0) {
|
||||
return '0'
|
||||
return Number(0).toFixed(decimals)
|
||||
}
|
||||
return Number(value)
|
||||
.toFixed(0)
|
||||
.toFixed(decimals)
|
||||
.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
.replace(/\.0$/, '')
|
||||
}
|
||||
|
||||
// 计算属性
|
||||
@@ -317,6 +318,11 @@ const chartOptions = computed(() => {
|
||||
right: 2
|
||||
}
|
||||
},
|
||||
// 显式禁用笛卡尔坐标系(Doughnut 图表不需要)
|
||||
scales: {
|
||||
x: { display: false },
|
||||
y: { display: false }
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
@@ -335,12 +341,12 @@ const chartOptions = computed(() => {
|
||||
const value = context.parsed || 0
|
||||
const total = context.dataset.data.reduce((a, b) => a + b, 0)
|
||||
const percentage = total > 0 ? ((value / total) * 100).toFixed(1) : 0
|
||||
return `${label}: ¥${formatMoney(value)} (${percentage}%)`
|
||||
return `${label}: ¥${formatMoney(value, 0)} (${percentage}%)`
|
||||
}
|
||||
}
|
||||
},
|
||||
pieCenterText: {
|
||||
text: `¥${formatMoney(totalAmount.value)}`,
|
||||
text: `¥${formatMoney(totalAmount.value, 0)}`,
|
||||
subtext: '总支出',
|
||||
textColor: isDarkMode ? '#ffffff' : '#323233',
|
||||
subtextColor: isDarkMode ? '#969799' : '#969799',
|
||||
@@ -403,7 +409,7 @@ const onChartRender = (chart) => {
|
||||
.ring-chart {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 170px;
|
||||
height: 190px;
|
||||
margin: 0px auto 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
class="income-text"
|
||||
style="font-size: 13px; margin-left: 4px"
|
||||
>
|
||||
¥{{ formatMoney(totalIncome) }}
|
||||
¥{{ formatMoney(totalIncome, 0) }}
|
||||
</span>
|
||||
</h3>
|
||||
<van-tag
|
||||
@@ -36,7 +36,7 @@
|
||||
<span class="category-name text-ellipsis">{{ category.classify || '未分类' }}</span>
|
||||
</div>
|
||||
<div class="category-amount income-text">
|
||||
¥{{ formatMoney(category.amount) }}
|
||||
¥{{ formatMoney(category.amount, 0) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -80,7 +80,7 @@
|
||||
<span class="category-name text-ellipsis">{{ category.classify || '未分类' }}</span>
|
||||
</div>
|
||||
<div class="category-amount none-text">
|
||||
¥{{ formatMoney(category.amount) }}
|
||||
¥{{ formatMoney(category.amount, 0) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
支出
|
||||
</div>
|
||||
<div class="stat-amount">
|
||||
¥{{ formatMoney(amount) }}
|
||||
¥{{ formatMoney(amount, 0) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item income">
|
||||
@@ -15,7 +15,7 @@
|
||||
收入
|
||||
</div>
|
||||
<div class="stat-amount">
|
||||
¥{{ formatMoney(income) }}
|
||||
¥{{ formatMoney(income, 0) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item balance">
|
||||
@@ -26,7 +26,7 @@
|
||||
class="stat-amount"
|
||||
:class="balanceClass"
|
||||
>
|
||||
¥{{ formatMoney(balance) }}
|
||||
¥{{ formatMoney(balance, 0) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -203,10 +203,12 @@ const prepareChartData = () => {
|
||||
let expense = 0
|
||||
let income = 0
|
||||
|
||||
if (item.expense !== undefined || item.income !== undefined) {
|
||||
// 优先使用 expense 和 income 字段
|
||||
if ('expense' in item && 'income' in item) {
|
||||
expense = item.expense || 0
|
||||
income = item.income || 0
|
||||
} else {
|
||||
} else if ('amount' in item) {
|
||||
// 如果只有 amount 字段,根据正负值判断
|
||||
const amount = item.amount || 0
|
||||
if (amount < 0) {
|
||||
expense = Math.abs(amount)
|
||||
@@ -239,6 +241,8 @@ const chartData = computed(() => {
|
||||
label: '支出',
|
||||
data: expenseData,
|
||||
borderColor: expenseColor.value,
|
||||
yAxisID: 'yExpense',
|
||||
order: 2,
|
||||
backgroundColor: (context) => {
|
||||
const chart = context.chart
|
||||
const { ctx, chartArea } = chart
|
||||
@@ -258,6 +262,8 @@ const chartData = computed(() => {
|
||||
label: '收入',
|
||||
data: incomeData,
|
||||
borderColor: incomeColor.value,
|
||||
yAxisID: 'yIncome',
|
||||
order: 1,
|
||||
backgroundColor: (context) => {
|
||||
const chart = context.chart
|
||||
const { ctx, chartArea } = chart
|
||||
@@ -266,7 +272,7 @@ const chartData = computed(() => {
|
||||
}
|
||||
return createGradient(ctx, chartArea, incomeColor.value)
|
||||
},
|
||||
fill: true,
|
||||
fill: false,
|
||||
tension: 0.4,
|
||||
pointRadius: 0,
|
||||
pointHoverRadius: 6,
|
||||
@@ -279,12 +285,40 @@ const chartData = computed(() => {
|
||||
|
||||
// Chart.js 配置
|
||||
const chartOptions = computed(() => {
|
||||
const { chartData: rawData } = prepareChartData()
|
||||
const { chartData: rawData, expenseData, incomeData } = prepareChartData()
|
||||
const maxExpense = Math.max(...expenseData, 0)
|
||||
const maxIncome = Math.max(...incomeData, 0)
|
||||
|
||||
return getChartOptions({
|
||||
scales: {
|
||||
x: { display: false },
|
||||
y: { display: false }
|
||||
x: {
|
||||
display: false,
|
||||
grid: { display: false, drawBorder: false },
|
||||
ticks: { display: false },
|
||||
border: { display: false }
|
||||
},
|
||||
y: {
|
||||
display: false,
|
||||
grid: { display: false, drawBorder: false },
|
||||
ticks: { display: false },
|
||||
border: { display: false }
|
||||
},
|
||||
yIncome: {
|
||||
display: false,
|
||||
beginAtZero: true,
|
||||
suggestedMax: maxIncome ? maxIncome * 1.1 : undefined,
|
||||
grid: { display: false, drawBorder: false },
|
||||
ticks: { display: false },
|
||||
border: { display: false }
|
||||
},
|
||||
yExpense: {
|
||||
display: false,
|
||||
beginAtZero: true,
|
||||
suggestedMax: maxExpense ? maxExpense * 1.1 : undefined,
|
||||
grid: { display: false, drawBorder: false },
|
||||
ticks: { display: false },
|
||||
border: { display: false }
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
@@ -326,10 +360,12 @@ const chartOptions = computed(() => {
|
||||
let dailyExpense = 0
|
||||
let dailyIncome = 0
|
||||
|
||||
if (item.expense !== undefined || item.income !== undefined) {
|
||||
// 优先使用 expense 和 income 字段
|
||||
if ('expense' in item && 'income' in item) {
|
||||
dailyExpense = item.expense || 0
|
||||
dailyIncome = item.income || 0
|
||||
} else {
|
||||
} else if ('amount' in item) {
|
||||
// 如果只有 amount 字段,根据正负值判断
|
||||
const amount = item.amount || 0
|
||||
if (amount < 0) {
|
||||
dailyExpense = Math.abs(amount)
|
||||
@@ -343,7 +379,7 @@ const chartOptions = computed(() => {
|
||||
return null
|
||||
}
|
||||
|
||||
return `${context.dataset.label}: ¥${value.toFixed(2)}`
|
||||
return `${context.dataset.label}: ¥${value.toFixed(1)}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user