feat: 前台匿名浏览、登录引导、客服入口与返水增强
前台: - 未登录可浏览首页/赛事/赔率,下注等操作弹出登录引导(去登录/继续浏览) - 顶部新增客服入口与 iframe 弹窗 - 登录页支持暂不登录返回浏览 API: - 首页/赛事/冠军盘接口改为公开访问,支持 X-Locale 头 - JWT 守卫支持可选认证 返水: - 注单新增 is_cashbacked 字段,发放时自动标记 - 预览展示玩家余额,明确平台直发不从代理扣款 - 后台注单列表与玩家历史展示回水状态 其他: - 串关禁止同场重复选号(SAME_MATCH) - 补充结算资金流分析文档 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -229,6 +229,12 @@ async function openDetail(row: BetListRow) {
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('bet.col.cashbacked')" width="88" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.isCashbacked" type="success" size="small" effect="plain">✓</el-tag>
|
||||
<span v-else class="bet-content-empty">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('bet.col.placed_at')" min-width="168">
|
||||
<template #default="{ row }">{{ formatTime(row.placedAt) }}</template>
|
||||
</el-table-column>
|
||||
@@ -284,6 +290,9 @@ async function openDetail(row: BetListRow) {
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="t('bet.col.placed_at')">{{ formatTime(detail.placedAt) }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="t('bet.field.settled_at')">{{ formatTime(detail.settledAt) }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="t('bet.col.cashbacked')">
|
||||
{{ detail.isCashbacked ? t('common.yes') : t('common.no') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="t('bet.field.request_id')" :span="2">{{ detail.requestId }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ interface CashbackPreviewItem {
|
||||
userId: string;
|
||||
username: string;
|
||||
agentUsername: string | null;
|
||||
availableBalance: string;
|
||||
effectiveStake: string;
|
||||
betCount: number;
|
||||
rate: string;
|
||||
@@ -288,6 +289,7 @@ onMounted(loadHistory);
|
||||
<li>{{ t('cashback.rule_formula') }}</li>
|
||||
<li>{{ t('cashback.rule_rate') }}</li>
|
||||
<li>{{ t('cashback.rule_flow') }}</li>
|
||||
<li>{{ t('cashback.rule_platform') }}</li>
|
||||
<li class="rules-note">{{ t('cashback.rule_note_zero') }}</li>
|
||||
</ul>
|
||||
</el-dialog>
|
||||
@@ -374,6 +376,18 @@ onMounted(loadHistory);
|
||||
>
|
||||
<template #default="{ row }">{{ row.agentUsername || '—' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="availableBalance"
|
||||
:label="t('cashback.col.balance')"
|
||||
min-width="110"
|
||||
align="right"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tooltip :content="formatAmountFull(row.availableBalance)" placement="top">
|
||||
<span>{{ formatAmount(row.availableBalance) }}</span>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="betCount"
|
||||
:label="t('cashback.col.bet_count')"
|
||||
@@ -547,6 +561,9 @@ onMounted(loadHistory);
|
||||
<el-table-column prop="agentUsername" :label="t('cashback.col.agent')" min-width="100">
|
||||
<template #default="{ row }">{{ row.agentUsername || '—' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="availableBalance" :label="t('cashback.col.balance')" min-width="100" align="right">
|
||||
<template #default="{ row }">{{ formatAmount(row.availableBalance) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="betCount" :label="t('cashback.col.bet_count')" width="88" align="right" />
|
||||
<el-table-column prop="effectiveStake" :label="t('cashback.col.effective_stake')" min-width="110" align="right">
|
||||
<template #default="{ row }">{{ formatAmount(row.effectiveStake) }}</template>
|
||||
|
||||
@@ -25,6 +25,7 @@ export interface BetListRow {
|
||||
currency: string;
|
||||
placedAt: string;
|
||||
settledAt: string | null;
|
||||
isCashbacked: boolean;
|
||||
selectionCount: number;
|
||||
selectionSummary: string;
|
||||
selectionPreviews: BetSelectionPreview[];
|
||||
|
||||
Reference in New Issue
Block a user