This commit is contained in:
zhx 2026-05-22 13:27:17 +08:00
parent bc04695ac8
commit e4147ec2fa
6 changed files with 372 additions and 0 deletions

View File

@ -7,6 +7,7 @@ const SPECIFIED_GIFT_WEEKLY_RANK_BASE =
const SIGN_IN_REWARD_BASE = '/go/resident-activity/sign-in-reward';
const ROOM_TURNOVER_REWARD_BASE =
'/go/resident-activity/room-turnover-reward';
const CP_BASE = '/resident-activity/cp';
const VIP_BASE = '/go/resident-activity/vip';
const RECHARGE_REWARD_BASE = '/go/resident-activity/recharge-reward';
const FIRST_RECHARGE_REWARD_BASE =
@ -57,6 +58,16 @@ export async function resetResidentRegisterRewardConfig(sysOrigin: string) {
});
}
export async function getResidentCpConfig(sysOrigin: string) {
return requestClient.get<Record<string, any>>(`${CP_BASE}/config`, {
params: { sysOrigin },
});
}
export async function saveResidentCpConfig(data: Record<string, any>) {
return requestClient.post<Record<string, any>>(`${CP_BASE}/config/save`, data);
}
export async function pageResidentRegisterRewardDailyRecords(
params: Record<string, any>,
) {

View File

@ -62,6 +62,7 @@ const ROUTE_MENU_OVERRIDES: Record<
};
const LOCAL_RESIDENT_ACTIVITY_FALLBACK_ROUTES = new Set([
'ResidentCpConfig',
'ResidentSmashGoldenEggConfig',
'ResidentVoiceRoomRocket',
'ResidentWheelConfig',

View File

@ -23,6 +23,12 @@ const routes: RouteRecordRaw[] = [
component: () => import('#/views/resident-activity/vip-config.vue'),
meta: { title: 'VIP' },
},
{
name: 'ResidentCpConfig',
path: 'cp/config',
component: () => import('#/views/resident-activity/cp-config.vue'),
meta: { title: 'CP' },
},
{
name: 'ResidentWheelConfig',
path: 'wheel/config',

View File

@ -0,0 +1,247 @@
<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue';
import { Page } from '@vben/common-ui';
import { useAccessStore } from '@vben/stores';
import {
getResidentCpConfig,
saveResidentCpConfig,
} from '#/api/legacy/resident-activity';
import { getAllowedSysOrigins } from '#/views/system/shared';
import {
Button,
Card,
Input,
InputNumber,
Modal,
Select,
Space,
Spin,
Table,
Tag,
message,
} from 'antdv-next';
defineOptions({ name: 'ResidentCpConfigPage' });
interface CpLevelConfig {
cabinConfigId?: null | string;
level: number;
levelName: string;
requiredIntimacyValue: number;
}
function defaultLevel(level: number): CpLevelConfig {
return {
cabinConfigId: null,
level,
levelName: `CP ${level}`,
requiredIntimacyValue: 0,
};
}
function defaultLevels() {
return Array.from({ length: 5 }, (_, index) => defaultLevel(index + 1));
}
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 columns = [
{ dataIndex: 'level', key: 'level', title: '等级', width: 100 },
{ dataIndex: 'levelName', key: 'levelName', title: '等级文案', width: 260 },
{
dataIndex: 'requiredIntimacyValue',
key: 'requiredIntimacyValue',
title: '所需亲密值',
width: 220,
},
];
const form = reactive({
configured: false,
sysOrigin: '',
levels: defaultLevels(),
});
function normalizeLevels(levels: Array<Record<string, any>> | undefined) {
const levelMap = new Map<number, Record<string, any>>();
for (const item of levels || []) {
const level = Number(item.level || 0);
if (level >= 1 && level <= 5) {
levelMap.set(level, item);
}
}
return defaultLevels().map((fallback) => {
const item = levelMap.get(fallback.level);
if (!item) {
return fallback;
}
return {
cabinConfigId: item.cabinConfigId ? String(item.cabinConfigId) : null,
level: fallback.level,
levelName: String(item.levelName || fallback.levelName),
requiredIntimacyValue: Number(item.requiredIntimacyValue || 0),
};
});
}
function applyConfig(result: Record<string, any> | null | undefined) {
const value = result ?? {};
form.configured = Boolean(value.configured);
form.sysOrigin = String(
value.sysOrigin || form.sysOrigin || sysOriginOptions.value[0]?.value || '',
);
form.levels = normalizeLevels(value.levels);
}
async function loadConfig() {
if (!form.sysOrigin) {
return;
}
loading.value = true;
try {
const result = await getResidentCpConfig(form.sysOrigin);
applyConfig(result);
} finally {
loading.value = false;
}
}
function validateLevels() {
let previous = -1;
for (const item of form.levels) {
const requiredValue = Number(item.requiredIntimacyValue || 0);
if (requiredValue < 0) {
message.error('所需亲密值不能小于 0');
return false;
}
if (requiredValue < previous) {
message.error('所需亲密值需要按等级递增');
return false;
}
previous = requiredValue;
}
return true;
}
async function submitForm() {
if (!validateLevels()) {
return;
}
saving.value = true;
try {
await saveResidentCpConfig({
sysOrigin: form.sysOrigin,
levels: form.levels.map((item) => ({
cabinConfigId: item.cabinConfigId || null,
level: item.level,
levelName: String(item.levelName || `CP ${item.level}`).trim(),
requiredIntimacyValue: Number(item.requiredIntimacyValue || 0),
})),
});
message.success('保存成功');
await loadConfig();
} finally {
saving.value = false;
}
}
function handleSave() {
Modal.confirm({
async onOk() {
await submitForm();
},
title: '确认保存 CP 等级积分配置?',
content: '保存后 Flutter 端 CP 权益配置接口会读取新的 5 级亲密值。',
});
}
watch(
sysOriginOptions,
(options) => {
if (!form.sysOrigin) {
form.sysOrigin = String(options[0]?.value || '');
}
},
{ immediate: true },
);
watch(
() => form.sysOrigin,
(value) => {
if (value) {
void loadConfig();
}
},
{ immediate: true },
);
</script>
<template>
<Page auto-content-height>
<Spin :spinning="loading">
<Card :bordered="false" title="CP 等级积分配置">
<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="form.configured ? 'success' : 'processing'">
{{ form.configured ? '已配置' : '未配置' }}
</Tag>
<Button :loading="saving" type="primary" @click="handleSave">
保存
</Button>
</Space>
<Table
:columns="columns"
:data-source="form.levels"
:pagination="false"
row-key="level"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'level'">
{{ record.level }}
</template>
<template v-else-if="column.key === 'levelName'">
<Input
v-model:value="record.levelName"
:maxlength="30"
placeholder="请输入等级文案"
/>
</template>
<template v-else-if="column.key === 'requiredIntimacyValue'">
<InputNumber
v-model:value="record.requiredIntimacyValue"
:min="0"
:precision="0"
style="width: 180px"
/>
</template>
</template>
</Table>
</Card>
</Spin>
</Page>
</template>
<style scoped>
.toolbar {
margin-bottom: 16px;
}
</style>

View File

@ -52,3 +52,18 @@ SET
status = 0,
router = 'first-recharge-reward/config'
WHERE alias = 'ResidentFirstRechargeRewardConfig';
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT DISTINCT
parent_role.role_id,
target_menu.id
FROM sys_role_menu AS parent_role
JOIN sys_menu AS parent_menu
ON parent_menu.id = parent_role.menu_id
AND parent_menu.alias = 'ResidentActivityManager'
JOIN sys_menu AS target_menu
ON target_menu.alias = 'ResidentFirstRechargeRewardConfig'
LEFT JOIN sys_role_menu AS existing_role_menu
ON existing_role_menu.role_id = parent_role.role_id
AND existing_role_menu.menu_id = target_menu.id
WHERE existing_role_menu.id IS NULL;

View File

@ -665,6 +665,7 @@ JOIN sys_menu AS target_menu
'ResidentSpecifiedGiftWeeklyRank',
'ResidentVipConfig',
'ResidentRechargeRewardConfig',
'ResidentFirstRechargeRewardConfig',
'ResidentDailyTaskConfig',
'OperateGameManager',
'GameConfig',
@ -691,6 +692,93 @@ LEFT JOIN sys_role_menu AS existing_role_menu
AND existing_role_menu.menu_id = target_menu.id
WHERE existing_role_menu.id IS NULL;
INSERT INTO sys_menu (
id,
parent_id,
menu_name,
path,
menu_type,
icon,
create_user,
update_user,
sort,
status,
router,
alias
)
SELECT
next_id,
(SELECT id FROM sys_menu WHERE alias = 'ResidentActivityManager' LIMIT 1),
'CP',
'resident-activity/cp-config/index',
2,
'form',
'0',
'0',
6,
0,
'cp/config',
'ResidentCpConfig'
FROM (
SELECT COALESCE(MAX(id), 1700000000) + 1 AS next_id
FROM sys_menu
) AS menu_id
WHERE NOT EXISTS (
SELECT 1 FROM sys_menu WHERE alias = 'ResidentCpConfig'
);
UPDATE sys_menu
SET
parent_id = (
SELECT resident_menu.id
FROM (
SELECT id
FROM sys_menu
WHERE alias = 'ResidentActivityManager'
LIMIT 1
) AS resident_menu
),
menu_name = 'CP',
path = 'resident-activity/cp-config/index',
menu_type = 2,
icon = 'form',
create_user = '0',
update_user = '0',
sort = 6,
status = 0,
router = 'cp/config'
WHERE alias = 'ResidentCpConfig';
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT DISTINCT
parent_role.role_id,
target_menu.id
FROM sys_role_menu AS parent_role
JOIN sys_menu AS parent_menu
ON parent_menu.id = parent_role.menu_id
AND parent_menu.alias = 'ResidentActivityManager'
JOIN sys_menu AS target_menu
ON target_menu.alias = 'ResidentCpConfig'
LEFT JOIN sys_role_menu AS existing_role_menu
ON existing_role_menu.role_id = parent_role.role_id
AND existing_role_menu.menu_id = target_menu.id
WHERE existing_role_menu.id IS NULL;
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT DISTINCT
parent_role.role_id,
target_menu.id
FROM sys_role_menu AS parent_role
JOIN sys_menu AS parent_menu
ON parent_menu.id = parent_role.menu_id
AND parent_menu.alias = 'ResidentActivityManager'
JOIN sys_menu AS target_menu
ON target_menu.alias = 'ResidentFirstRechargeRewardConfig'
LEFT JOIN sys_role_menu AS existing_role_menu
ON existing_role_menu.role_id = parent_role.role_id
AND existing_role_menu.menu_id = target_menu.id
WHERE existing_role_menu.id IS NULL;
UPDATE sys_menu
SET menu_name = CONVERT(0xE5B8B8E9A9BBE6B4BBE58AA8 USING utf8mb4)
WHERE alias = 'ResidentActivityManager';
@ -723,6 +811,10 @@ UPDATE sys_menu
SET menu_name = CONVERT(0xE58585E580BCE5A596E58AB1E9858DE7BDAE USING utf8mb4)
WHERE alias = 'ResidentRechargeRewardConfig';
UPDATE sys_menu
SET menu_name = CONVERT(0xE9A696E586B2E5A596E58AB1 USING utf8mb4)
WHERE alias = 'ResidentFirstRechargeRewardConfig';
UPDATE sys_menu
SET menu_name = CONVERT(0xE6AF8FE697A5E4BBBBE58AA1 USING utf8mb4)
WHERE alias = 'ResidentDailyTaskConfig';