fix(admin,api,player): 返水注单去重、操作日志 i18n 与钱包紧凑金额

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-08 16:07:11 +08:00
parent 22535d4c27
commit 0d761db70b
8 changed files with 216 additions and 26 deletions

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { formatMoney, parseAmount } from '../utils/localeDisplay';
import { formatMoneyCompact, parseAmount } from '../utils/localeDisplay';
interface Transaction {
transactionType: string;
@@ -50,24 +50,24 @@ const stats = computed(() => {
<div class="wallet-stats-panel">
<div class="stats-row">
<div class="stat-item">
<span class="stat-val income">{{ formatMoney(stats.income, locale) }}</span>
<span class="stat-val income">{{ formatMoneyCompact(stats.income, locale) }}</span>
<span class="stat-label">{{ t('wallet.stats_income') }}</span>
</div>
<div class="stat-divider" />
<div class="stat-item">
<span class="stat-val expense">{{ formatMoney(stats.expense, locale) }}</span>
<span class="stat-val expense">{{ formatMoneyCompact(stats.expense, locale) }}</span>
<span class="stat-label">{{ t('wallet.stats_expense') }}</span>
</div>
<div class="stat-divider" />
<div class="stat-item">
<span class="stat-val" :class="stats.net >= 0 ? 'income' : 'expense'">
{{ formatMoney(stats.net, locale) }}
{{ formatMoneyCompact(stats.net, locale) }}
</span>
<span class="stat-label">{{ t('wallet.stats_net') }}</span>
</div>
<div class="stat-divider" />
<div class="stat-item">
<span class="stat-val cashback">{{ formatMoney(stats.cashback, locale) }}</span>
<span class="stat-val cashback">{{ formatMoneyCompact(stats.cashback, locale) }}</span>
<span class="stat-label">{{ t('wallet.stats_cashback') }}</span>
</div>
</div>

View File

@@ -55,3 +55,35 @@ export function formatMoney(amount: unknown, locale: string): string {
return `${getLocaleDisplay(locale).currency} ${value.toFixed(2)}`;
}
}
export function formatMoneyCompact(amount: unknown, locale: string): string {
const value = parseAmount(amount);
const abs = Math.abs(value);
const sign = value < 0 ? '-' : '';
const { currency } = getLocaleDisplay(locale);
const sym = currency === 'CNY' ? '¥' : currency === 'MYR' ? 'RM' : '$';
if (abs >= 10000 && locale === 'zh-CN') {
const v = abs / 10000;
return `${sign}${sym}${v % 1 === 0 ? v.toFixed(0) : v.toFixed(1)}`;
}
if (abs >= 1000000) {
const v = abs / 1000000;
return `${sign}${sym}${v % 1 === 0 ? v.toFixed(0) : v.toFixed(1)}M`;
}
if (abs >= 10000) {
const v = abs / 1000;
return `${sign}${sym}${v % 1 === 0 ? v.toFixed(0) : v.toFixed(1)}K`;
}
try {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(value);
} catch {
return `${sym}${value.toFixed(2)}`;
}
}