feat: add register reward config page

This commit is contained in:
hy 2026-04-16 20:07:14 +08:00
parent a5725f23d4
commit 719fe76bba
3 changed files with 323 additions and 0 deletions

View File

@ -25,3 +25,19 @@ export async function pageResidentInviteInvitee(params: Record<string, any>) {
{ params },
);
}
export async function getResidentRegisterRewardConfig(sysOrigin: string) {
return requestClient.get<Record<string, any>>('/resident-activity/register-reward/config', {
params: { sysOrigin },
});
}
export async function saveResidentRegisterRewardConfig(data: Record<string, any>) {
return requestClient.post('/resident-activity/register-reward/config/save', data);
}
export async function resetResidentRegisterRewardConfig(sysOrigin: string) {
return requestClient.post('/resident-activity/register-reward/config/reset', {}, {
params: { sysOrigin },
});
}

View File

@ -11,6 +11,12 @@ const routes: RouteRecordRaw[] = [
path: '/resident-activity/manager',
redirect: '/resident-activity/manager/invite/config',
children: [
{
name: 'ResidentRegisterRewardConfig',
path: 'register-reward/config',
component: () => import('#/views/resident-activity/register-reward-config.vue'),
meta: { title: '注册奖励配置' },
},
{
name: 'ResidentInviteConfig',
path: 'invite/config',

View File

@ -0,0 +1,301 @@
<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue';
import { Page } from '@vben/common-ui';
import { useAccessStore } from '@vben/stores';
import {
getResidentRegisterRewardConfig,
resetResidentRegisterRewardConfig,
saveResidentRegisterRewardConfig,
} from '#/api/legacy/resident-activity';
import ActivityResourceGroupSelectDrawer from '#/views/props/components/activity-resource-group-select-drawer.vue';
import { getAllowedSysOrigins } from '#/views/system/shared';
import {
Button,
Card,
InputNumber,
Modal,
Select,
Space,
Spin,
Switch,
Tag,
message,
} from 'antdv-next';
defineOptions({ name: 'ResidentRegisterRewardConfigPage' });
const accessStore = useAccessStore();
const sysOriginOptions = computed(() => {
const options = getAllowedSysOrigins(accessStore.accessCodes || []);
return options.length > 0 ? options : getAllowedSysOrigins([]);
});
const loading = ref(false);
const saving = ref(false);
const groupPickerOpen = ref(false);
const form = reactive<Record<string, any>>({
configured: false,
enabled: false,
goldAmount: 0,
rewardGroupId: null,
rewardGroupName: '',
sysOrigin: '',
});
const statusMeta = computed(() => {
if (!form.configured) {
return {
color: 'processing',
description: '当前未配置,普通注册成功后不会发放注册奖励。',
text: '未配置',
};
}
if (form.enabled) {
return {
color: 'success',
description: '当前已启用,注册后会按下面配置发金币和/或奖励组。',
text: '已启用',
};
}
return {
color: 'default',
description: '当前已明确关闭,普通注册成功后不发任何注册奖励。',
text: '已关闭',
};
});
function normalizeConfig(result: Record<string, any> | null | undefined) {
const value = result ?? {};
form.configured = Boolean(value.configured);
form.enabled = Boolean(value.enabled);
form.goldAmount = Number(value.goldAmount || 0);
form.rewardGroupId = value.rewardGroupId ?? null;
form.rewardGroupName = String(value.rewardGroupName || '');
form.sysOrigin = String(value.sysOrigin || form.sysOrigin || sysOriginOptions.value[0]?.value || '');
}
async function loadData() {
if (!form.sysOrigin) {
return;
}
loading.value = true;
try {
const result = await getResidentRegisterRewardConfig(form.sysOrigin);
normalizeConfig(result);
} finally {
loading.value = false;
}
}
watch(
sysOriginOptions,
(options) => {
if (!form.sysOrigin) {
form.sysOrigin = String(options[0]?.value || '');
}
},
{ immediate: true },
);
watch(
() => form.sysOrigin,
(value) => {
if (value) {
void loadData();
}
},
{ immediate: true },
);
function openRewardPicker() {
groupPickerOpen.value = true;
}
function clearRewardGroup() {
form.rewardGroupId = null;
form.rewardGroupName = '';
}
function handleRewardGroupSelect(row: Record<string, any>) {
form.rewardGroupId = row.id;
form.rewardGroupName = row.name;
groupPickerOpen.value = false;
}
async function submitForm() {
saving.value = true;
try {
await saveResidentRegisterRewardConfig({
enabled: Boolean(form.enabled),
goldAmount: Number(form.goldAmount || 0),
rewardGroupId: form.rewardGroupId ?? null,
sysOrigin: form.sysOrigin,
});
message.success('保存成功');
await loadData();
} finally {
saving.value = false;
}
}
function handleSave() {
Modal.confirm({
async onOk() {
await submitForm();
},
title: '确认保存当前系统的注册奖励配置?',
});
}
function handleReset() {
Modal.confirm({
async onOk() {
saving.value = true;
try {
await resetResidentRegisterRewardConfig(form.sysOrigin);
message.success('已清空当前系统的注册奖励配置');
await loadData();
} finally {
saving.value = false;
}
},
title: '确认清空当前系统的注册奖励配置?',
content: '清空后会删除当前系统的后台配置,普通注册成功后不再发放注册奖励。',
});
}
</script>
<template>
<Page auto-content-height>
<Spin :spinning="loading">
<Card :bordered="false" title="注册奖励配置">
<Space class="toolbar" wrap>
<Select
v-model:value="form.sysOrigin"
:options="sysOriginOptions"
option-filter-prop="label"
option-label-prop="label"
placeholder="请选择系统"
show-search
style="width: 180px"
/>
<Tag :color="statusMeta.color">
{{ statusMeta.text }}
</Tag>
<span class="status-desc">{{ statusMeta.description }}</span>
</Space>
<div class="section">
<div class="field-label">启用后台注册奖励</div>
<Switch v-model:checked="form.enabled" />
</div>
<div class="section">
<div class="field-label">赠送金币</div>
<InputNumber
v-model:value="form.goldAmount"
:disabled="!form.enabled"
:min="0"
:precision="0"
placeholder="请输入金币数量"
style="width: 240px"
/>
</div>
<div class="section">
<div class="field-label">赠送奖励组</div>
<Space wrap>
<Button :disabled="!form.enabled" @click="openRewardPicker">
{{ form.rewardGroupId ? '更换奖励组' : '选择奖励组' }}
</Button>
<Button
v-if="form.rewardGroupId"
:disabled="!form.enabled"
danger
type="link"
@click="clearRewardGroup"
>
清空
</Button>
<span v-if="form.rewardGroupId" class="reward-group">
{{ form.rewardGroupName }} (ID: {{ form.rewardGroupId }})
</span>
<span v-else class="reward-group empty">
未选择奖励组
</span>
</Space>
</div>
<div class="tips">
<div>未配置注册成功后不发奖励</div>
<div>已启用可以同时送金币和奖励组两者至少配置一个</div>
<div>已关闭注册成功后不发奖励</div>
</div>
<Space class="actions" wrap>
<Button :loading="saving" type="primary" @click="handleSave">
保存配置
</Button>
<Button :loading="saving" @click="handleReset">
清空配置
</Button>
</Space>
</Card>
<ActivityResourceGroupSelectDrawer
:open="groupPickerOpen"
:sys-origin="form.sysOrigin"
@close="groupPickerOpen = false"
@select="handleRewardGroupSelect"
/>
</Spin>
</Page>
</template>
<style scoped>
.toolbar {
margin-bottom: 24px;
}
.status-desc {
color: rgb(100 116 139);
}
.section {
align-items: center;
display: flex;
gap: 16px;
margin-bottom: 20px;
}
.field-label {
color: rgb(15 23 42);
flex: 0 0 120px;
font-weight: 600;
}
.reward-group {
color: rgb(15 23 42);
}
.reward-group.empty {
color: rgb(148 163 184);
}
.tips {
background: rgb(248 250 252);
border-radius: 12px;
color: rgb(71 85 105);
line-height: 1.8;
margin-top: 12px;
padding: 16px;
}
.actions {
margin-top: 24px;
}
</style>