From 474caa56e06c6b3db695ef8f79ef7e802d1d59fe Mon Sep 17 00:00:00 2001 From: hy Date: Mon, 20 Apr 2026 13:45:50 +0800 Subject: [PATCH] feat: add register reward daily records --- apps/src/api/legacy/resident-activity.ts | 9 + .../register-reward-config.vue | 250 +++++++++++++++++- apps/vite.config.ts | 8 + 3 files changed, 263 insertions(+), 4 deletions(-) diff --git a/apps/src/api/legacy/resident-activity.ts b/apps/src/api/legacy/resident-activity.ts index 6ca74b4..1acf9f7 100644 --- a/apps/src/api/legacy/resident-activity.ts +++ b/apps/src/api/legacy/resident-activity.ts @@ -45,6 +45,15 @@ export async function resetResidentRegisterRewardConfig(sysOrigin: string) { }); } +export async function pageResidentRegisterRewardDailyRecords( + params: Record, +) { + return requestClient.get>( + '/go/resident-activity/register-reward/daily-record/page', + { params }, + ); +} + export async function pageSpecifiedGiftWeeklyRankConfigs(params: Record) { return requestClient.get>>( `${SPECIFIED_GIFT_WEEKLY_RANK_BASE}/config/page`, diff --git a/apps/src/views/resident-activity/register-reward-config.vue b/apps/src/views/resident-activity/register-reward-config.vue index 7349217..ac3062b 100644 --- a/apps/src/views/resident-activity/register-reward-config.vue +++ b/apps/src/views/resident-activity/register-reward-config.vue @@ -6,21 +6,26 @@ import { useAccessStore } from '@vben/stores'; import { getResidentRegisterRewardConfig, + pageResidentRegisterRewardDailyRecords, resetResidentRegisterRewardConfig, saveResidentRegisterRewardConfig, } from '#/api/legacy/resident-activity'; import ActivityResourceGroupSelectDrawer from '#/views/props/components/activity-resource-group-select-drawer.vue'; +import UserProfileLink from '#/views/operate/components/user-profile-link.vue'; import { getAllowedSysOrigins } from '#/views/system/shared'; import { Button, Card, + DatePicker, InputNumber, Modal, + Pagination, Select, Space, Spin, Switch, + Table, Tag, message, } from 'antdv-next'; @@ -35,10 +40,14 @@ const sysOriginOptions = computed(() => { const loading = ref(false); const saving = ref(false); +const recordLoading = ref(false); +const recordTotal = ref(0); const groupPickerOpen = ref(false); +const recordList = ref>>([]); const form = reactive>({ configured: false, + dailyLimit: 0, enabled: false, goldAmount: 0, rewardGroupId: null, @@ -46,6 +55,22 @@ const form = reactive>({ sysOrigin: '', }); +const recordQuery = reactive>({ + claimDate: '', + cursor: 1, + limit: 20, +}); + +const recordSummary = reactive>({ + dailyLimit: 0, + date: '', + issuedCount: 0, + limitEnabled: false, + occupiedCount: 0, + remainingCount: 0, + successCount: 0, +}); + const statusMeta = computed(() => { if (!form.configured) { return { @@ -57,7 +82,10 @@ const statusMeta = computed(() => { if (form.enabled) { return { color: 'success', - description: '当前已启用,注册后会按下面配置发金币和/或奖励组。', + description: + form.dailyLimit > 0 + ? `当前已启用,每日最多发放 ${form.dailyLimit} 份注册奖励。` + : '当前已启用,注册后会按下面配置发金币和/或奖励组。', text: '已启用', }; } @@ -68,9 +96,20 @@ const statusMeta = computed(() => { }; }); +const recordColumns = [ + { dataIndex: 'user', key: 'user', title: '领取用户', width: 280 }, + { dataIndex: 'claimResult', key: 'claimResult', title: '领取结果', width: 220 }, + { dataIndex: 'status', key: 'status', title: '处理状态', width: 120 }, + { dataIndex: 'rewardPayload', key: 'rewardPayload', title: '奖励内容', width: 220 }, + { dataIndex: 'claimDate', key: 'claimDate', title: '领取日期', width: 120 }, + { dataIndex: 'createTime', key: 'createTime', title: '触发时间', width: 180 }, + { dataIndex: 'errorMessage', key: 'errorMessage', title: '备注 / 失败原因', width: 260 }, +]; + function normalizeConfig(result: Record | null | undefined) { const value = result ?? {}; form.configured = Boolean(value.configured); + form.dailyLimit = Number(value.dailyLimit || 0); form.enabled = Boolean(value.enabled); form.goldAmount = Number(value.goldAmount || 0); form.rewardGroupId = value.rewardGroupId ?? null; @@ -78,7 +117,46 @@ function normalizeConfig(result: Record | null | undefined) { form.sysOrigin = String(value.sysOrigin || form.sysOrigin || sysOriginOptions.value[0]?.value || ''); } -async function loadData() { +function syncRecordSummary(result: Record | null | undefined) { + const value = result ?? {}; + recordSummary.date = String(value.date || recordSummary.date || ''); + recordSummary.dailyLimit = Number(value.dailyLimit || 0); + recordSummary.limitEnabled = Boolean(value.limitEnabled); + recordSummary.occupiedCount = Number(value.occupiedCount || 0); + recordSummary.issuedCount = Number(value.issuedCount || 0); + recordSummary.successCount = Number(value.successCount || 0); + recordSummary.remainingCount = Number(value.remainingCount || 0); +} + +function claimResultColor(result: string) { + switch (String(result || '').toUpperCase()) { + case 'REWARDED': + return 'success'; + case 'QUOTA_EXHAUSTED': + return 'warning'; + case 'FAILED': + return 'error'; + case 'SKIPPED': + return 'default'; + default: + return 'processing'; + } +} + +function processStatusColor(status: string) { + switch (String(status || '').toUpperCase()) { + case 'SUCCESS': + return 'success'; + case 'FAILED': + return 'error'; + case 'SKIPPED': + return 'default'; + default: + return 'processing'; + } +} + +async function loadConfig() { if (!form.sysOrigin) { return; } @@ -91,6 +169,36 @@ async function loadData() { } } +async function loadDailyRecords(reset = false) { + if (!form.sysOrigin) { + recordList.value = []; + recordTotal.value = 0; + return; + } + if (reset) { + recordQuery.cursor = 1; + } + recordLoading.value = true; + try { + const result = await pageResidentRegisterRewardDailyRecords({ + ...recordQuery, + sysOrigin: form.sysOrigin, + }); + recordList.value = Array.isArray(result.records) ? result.records : []; + recordTotal.value = Number(result.total || 0); + syncRecordSummary(result); + if (!recordQuery.claimDate && result.date) { + recordQuery.claimDate = String(result.date); + } + } finally { + recordLoading.value = false; + } +} + +async function loadData() { + await Promise.all([loadConfig(), loadDailyRecords(true)]); +} + watch( sysOriginOptions, (options) => { @@ -130,6 +238,7 @@ async function submitForm() { saving.value = true; try { await saveResidentRegisterRewardConfig({ + dailyLimit: Number(form.dailyLimit || 0), enabled: Boolean(form.enabled), goldAmount: Number(form.goldAmount || 0), rewardGroupId: form.rewardGroupId ?? null, @@ -167,6 +276,16 @@ function handleReset() { content: '清空后会删除当前系统的后台配置,普通注册成功后不再发放注册奖励。', }); } + +function handleRecordSearch() { + void loadDailyRecords(true); +} + +function handleRecordPageChange(page: number, pageSize: number) { + recordQuery.cursor = page; + recordQuery.limit = pageSize; + void loadDailyRecords(); +}