feat: 开户备注、账单展示优化与后台代理管理增强

- 新增初始上分备注(日常上分/开户赠金/自定义)及前后台校验与展示

- 优化钱包流水类型与备注显示,区分管理员/代理/玩家上下分

- 修复登录后语言被后端覆盖的问题,登录时同步当前语言到服务端

- 后台代理/玩家表格操作栏重构,充值订单增加备注列

- 前台个人中心、充值、账单与验证码组件体验优化

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-11 17:23:58 +08:00
parent 10485ecfaf
commit 03e72ca9b2
46 changed files with 3721 additions and 1059 deletions

View File

@@ -4,13 +4,16 @@ import { useRoute, useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import api from '../api';
import { formatMoney } from '../utils/localeDisplay';
import { txTypeKey, isCashbackType } from '../utils/walletTx';
import { txTypeKey, isCashbackType, txDisplayType, txSummaryLabel } from '../utils/walletTx';
import GoldSpinner from '../components/GoldSpinner.vue';
import { usePullToRefresh } from '../composables/usePullToRefresh';
type TransactionDetail = {
transactionId: string;
transactionType: string;
displayType?: string;
summary?: string | null;
summaryKind?: 'opening_bonus' | null;
amount: string;
balanceBefore: string;
balanceAfter: string;
@@ -21,6 +24,7 @@ type TransactionDetail = {
remark: string | null;
createdAt: string;
betNo: string | null;
cashbackBatchNo?: string | null;
};
const route = useRoute();
@@ -67,6 +71,16 @@ function txLabel(type: string): string {
return type;
}
const displayTypeLabel = computed(() => {
if (!tx.value) return '';
return txLabel(txDisplayType(tx.value));
});
const summaryText = computed(() => {
if (!tx.value) return '';
return txSummaryLabel(tx.value, t);
});
const amountClass = computed(() => {
if (!tx.value) return '';
return parseFloat(tx.value.amount) >= 0 ? 'pos' : 'neg';
@@ -87,8 +101,8 @@ const isCashbackTx = computed(
);
const cashbackBatchNo = computed(() => {
if (!isCashbackTx.value || !tx.value?.referenceId) return null;
return tx.value.referenceId;
if (!isCashbackTx.value) return null;
return tx.value?.cashbackBatchNo ?? tx.value?.referenceId ?? null;
});
const referenceLabel = computed(() => {
@@ -132,7 +146,8 @@ function goCashbackDetail() {
<template v-else>
<div class="hero" :class="amountClass">
<span class="hero-type">{{ txLabel(tx.transactionType) }}</span>
<span class="hero-type">{{ displayTypeLabel }}</span>
<span v-if="summaryText" class="hero-summary">{{ summaryText }}</span>
<span class="hero-amount">{{ formatMoney(tx.amount, locale) }}</span>
<span class="hero-time">{{ formattedTime }}</span>
</div>
@@ -266,6 +281,14 @@ function goCashbackDetail() {
color: #888;
}
.hero-summary {
font-size: 13px;
font-weight: 600;
color: #bbb;
max-width: 100%;
word-break: break-all;
}
.hero-amount {
font-size: 34px;
font-weight: 900;