feat(affiliate): 完善邀请返利系统
- 修复返利不到账的根因:tryClaimAffiliateRebateAudit 中 PostgreSQL 参数类型推断冲突 - 补全 OAuth 注册路径(LinuxDo/OIDC/WeChat/Pending Flow)的邀请码绑定 - 前端 OAuth 注册页面传递 aff_code 参数 - 新增返利冻结期机制:可配置冻结时间,到期后自动解冻(懒解冻) - 新增返利有效期:绑定后 N 天内有效,过期不再产生返利 - 新增单人返利上限:超出上限部分精确截断 - 增强返利流程 slog 结构化日志,便于排查问题 - 已邀请用户列表增加返利明细列
This commit is contained in:
@@ -9,21 +9,17 @@
|
||||
|
||||
<template v-else-if="detail">
|
||||
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<!-- 返利比例:用主色突出,让用户一眼看到「能拿多少」 -->
|
||||
<div class="card relative overflow-hidden p-5">
|
||||
<div class="absolute -right-6 -top-6 h-24 w-24 rounded-full bg-primary-500/10"></div>
|
||||
<div class="relative">
|
||||
<p class="flex items-center gap-1.5 text-sm text-gray-500 dark:text-dark-400">
|
||||
<Icon name="dollar" size="sm" class="text-primary-500" />
|
||||
{{ t('affiliate.stats.rebateRate') }}
|
||||
</p>
|
||||
<p class="mt-2 text-2xl font-semibold text-primary-600 dark:text-primary-400">
|
||||
{{ formattedRebateRate }}<span class="ml-0.5 text-base font-medium">%</span>
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-gray-400 dark:text-dark-500">
|
||||
{{ t('affiliate.stats.rebateRateHint') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card p-5">
|
||||
<p class="flex items-center gap-1.5 text-sm text-gray-500 dark:text-dark-400">
|
||||
<Icon name="dollar" size="sm" class="text-primary-500" />
|
||||
{{ t('affiliate.stats.rebateRate') }}
|
||||
</p>
|
||||
<p class="mt-2 text-2xl font-semibold text-primary-600 dark:text-primary-400">
|
||||
{{ formattedRebateRate }}<span class="ml-0.5 text-base font-medium">%</span>
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-gray-400 dark:text-dark-500">
|
||||
{{ t('affiliate.stats.rebateRateHint') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card p-5">
|
||||
<p class="text-sm text-gray-500 dark:text-dark-400">{{ t('affiliate.stats.invitedUsers') }}</p>
|
||||
@@ -42,6 +38,9 @@
|
||||
<p class="mt-2 text-2xl font-semibold text-gray-900 dark:text-white">
|
||||
{{ formatCurrency(detail.aff_history_quota) }}
|
||||
</p>
|
||||
<p v-if="detail.aff_frozen_quota > 0" class="mt-1 text-xs text-amber-600 dark:text-amber-400">
|
||||
{{ t('affiliate.stats.frozenQuota') }}: {{ formatCurrency(detail.aff_frozen_quota) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -79,6 +78,7 @@
|
||||
<li>1. {{ t('affiliate.tips.line1') }}</li>
|
||||
<li>2. {{ t('affiliate.tips.line2', { rate: `${formattedRebateRate}%` }) }}</li>
|
||||
<li>3. {{ t('affiliate.tips.line3') }}</li>
|
||||
<li v-if="detail.aff_frozen_quota > 0">4. {{ t('affiliate.tips.line4') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -115,6 +115,7 @@
|
||||
<tr class="border-b border-gray-200 text-gray-500 dark:border-dark-700 dark:text-dark-400">
|
||||
<th class="px-3 py-2 font-medium">{{ t('affiliate.invitees.columns.email') }}</th>
|
||||
<th class="px-3 py-2 font-medium">{{ t('affiliate.invitees.columns.username') }}</th>
|
||||
<th class="px-3 py-2 font-medium text-right">{{ t('affiliate.invitees.columns.rebate') }}</th>
|
||||
<th class="px-3 py-2 font-medium">{{ t('affiliate.invitees.columns.joinedAt') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -126,6 +127,7 @@
|
||||
>
|
||||
<td class="px-3 py-3 text-gray-900 dark:text-white">{{ item.email || '-' }}</td>
|
||||
<td class="px-3 py-3 text-gray-700 dark:text-gray-300">{{ item.username || '-' }}</td>
|
||||
<td class="px-3 py-3 text-right font-medium text-emerald-600 dark:text-emerald-400">{{ formatCurrency(item.total_rebate) }}</td>
|
||||
<td class="px-3 py-3 text-gray-700 dark:text-gray-300">{{ formatDateTime(item.created_at) || '-' }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user