积分与余额账务系统硬切重构

This commit is contained in:
kate522 committed 2026-08-24 15:59:11 +08:00
1 parent ca12226b39
commit 5cae5b5c93
159 files changed
+7275 -4718

No files matched your search

@@ -49,7 +49,7 @@
</div>
<n-empty v-else size="small" description="暂无数据" />
<div class="aksrt-revenue__chart-summary">
<span>期间总计: <strong>{{ formatAmount(group.total, group.key) }}</strong></span>
<span>期间总计: <strong>{{ formatAmount(group.total, group.key) }}</strong></span>
<span>共 {{ group.count }} 笔</span>
</div>
</div>
@@ -91,7 +91,7 @@
</n-grid-item>
<n-grid-item>
<div class="aksrt-revenue__stat">
<strong>{{ withdrawalStats.total_paid.toFixed(2) }}</strong>
<strong>{{ formatAmount(withdrawalStats.total_paid, 'cash') }}</strong>
<p>已提现 (元)</p>
</div>
</n-grid-item>
@@ -106,16 +106,21 @@ import { ref, computed, onMounted } from 'vue'
import PaymentSectionPage from '@/pages/payment/PaymentSectionPage.vue'
import api from '@/api'
const emptyCurrencyStats = () => ({ total: 0, pending: 0, settled: 0, count: 0 })
const revenueStats = ref({ cash: emptyCurrencyStats(), points: emptyCurrencyStats() })
const withdrawalStats = ref({ total: 0, pending: 0, processing: 0, completed: 0, rejected: 0, total_paid: 0 })
const emptyCurrencyStats = (currency) => ({
total: currency === 'cash' ? '0.00' : 0,
pending: currency === 'cash' ? '0.00' : 0,
settled: currency === 'cash' ? '0.00' : 0,
count: 0,
})
const revenueStats = ref({ cash: emptyCurrencyStats('cash'), points: emptyCurrencyStats('points') })
const withdrawalStats = ref({ total: 0, pending: 0, processing: 0, completed: 0, rejected: 0, total_paid: '0.00' })
const timeSeries = ref({ cash: [], points: [] })
const granularity = ref('day')
const revenueSummary = computed(() => [
{ key: 'cash-total', value: `${revenueStats.value.cash.total.toFixed(2)} 元`, label: '现金总收益' },
{ key: 'cash-pending', value: `${revenueStats.value.cash.pending.toFixed(2)} 元`, label: '现金待结算' },
{ key: 'cash-settled', value: `${revenueStats.value.cash.settled.toFixed(2)} 元`, label: '现金已结算' },
{ key: 'cash-total', value: `${formatAmount(revenueStats.value.cash.total, 'cash')} 元`, label: '现金总收益' },
{ key: 'cash-pending', value: `${formatAmount(revenueStats.value.cash.pending, 'cash')} 元`, label: '现金待结算' },
{ key: 'cash-settled', value: `${formatAmount(revenueStats.value.cash.settled, 'cash')} 元`, label: '现金已结算' },
{ key: 'cash-count', value: revenueStats.value.cash.count, label: '现金收益笔数' },
{ key: 'points-total', value: `${formatAmount(revenueStats.value.points.total, 'points')}`, label: '积分总收益' },
{ key: 'points-pending', value: `${formatAmount(revenueStats.value.points.pending, 'points')}`, label: '积分待结算' },
@@ -134,21 +139,44 @@ const timeSeriesGroups = computed(() => [
label: '积分收益',
items: Array.isArray(timeSeries.value.points) ? timeSeries.value.points : [],
},
].map((group) => ({
...group,
total: group.items.reduce((sum, item) => sum + Number(item.amount || 0), 0),
count: group.items.reduce((sum, item) => sum + Number(item.count || 0), 0),
})))
].map((group) => {
const totalMinor = group.items.reduce((sum, item) => sum + amountMinor(item.amount, group.key), 0n)
return {
...group,
total: formatMinor(totalMinor, group.key),
count: group.items.reduce((sum, item) => sum + Number(item.count || 0), 0),
}
}))
const hasTimeSeries = computed(() => timeSeriesGroups.value.some((group) => group.items.length > 0))
function formatAmount(amount, currency) {
return currency === 'points' ? `${Number(amount || 0).toFixed(0)} 积分` : `¥${Number(amount || 0).toFixed(2)}`
return currency === 'points'
? `${formatMinor(amountMinor(amount, currency), currency)} 积分`
: `¥${formatMinor(amountMinor(amount, currency), currency)}`
}
function amountMinor(amount, currency) {
const raw = String(amount ?? '').trim()
if (currency === 'points') return /^\d+$/.test(raw) ? BigInt(raw) : 0n
const match = /^(0|[1-9]\d*)(?:\.(\d{1,2}))?$/.exec(raw)
return match ? (BigInt(match[1]) * 100n) + BigInt((match[2] || '').padEnd(2, '0') || '0') : 0n
}
function formatMinor(minor, currency) {
if (currency === 'points') return String(minor)
return `${minor / 100n}.${String(minor % 100n).padStart(2, '0')}`
}
function getBarHeight(amount, items) {
const maxAmount = Math.max(1, ...items.map((item) => Number(item.amount || 0)))
return Math.max(2, (Number(amount || 0) / maxAmount) * 100)
const currency = items === timeSeries.value.points ? 'points' : 'cash'
const maxAmount = items.reduce((max, item) => {
const current = amountMinor(item.amount, currency)
return current > max ? current : max
}, 0n)
if (maxAmount <= 0n) return 2
const scaled = Number((amountMinor(amount, currency) * 10000n) / maxAmount) / 100
return Math.max(2, scaled)
}
function formatLabel(date) {
@@ -170,8 +198,8 @@ async function loadRevenue() {
if (res?.data) {
if (res.data.revenue) {
revenueStats.value = {
cash: { ...emptyCurrencyStats(), ...(res.data.revenue.cash || {}) },
points: { ...emptyCurrencyStats(), ...(res.data.revenue.points || {}) },
cash: { ...emptyCurrencyStats('cash'), ...(res.data.revenue.cash || {}) },
points: { ...emptyCurrencyStats('points'), ...(res.data.revenue.points || {}) },
}
}
if (res.data.withdrawal) {
@@ -181,7 +209,7 @@ async function loadRevenue() {
processing: Number(res.data.withdrawal.processing || 0),
completed: Number(res.data.withdrawal.completed || 0),
rejected: Number(res.data.withdrawal.rejected || 0),
total_paid: Number(res.data.withdrawal.total_paid || 0),
total_paid: String(res.data.withdrawal.total_paid || '0.00'),
}
}
timeSeries.value = {