修复时间字段

This commit is contained in:
zhx 2026-05-19 21:04:46 +08:00
parent 8d0836e7e8
commit aa0988af6b
5 changed files with 326 additions and 73 deletions

View File

@ -37,6 +37,12 @@ export async function pageBank(params: Record<string, any>) {
}); });
} }
export async function getBankStatistics(params: Record<string, any>) {
return requestClient.get<Record<string, any>>('/user-bank-balance/statistics', {
params,
});
}
export async function exprotBank(params: Record<string, any>) { export async function exprotBank(params: Record<string, any>) {
return downloadLegacyExcel( return downloadLegacyExcel(
'/user-bank-balance/export', '/user-bank-balance/export',

View File

@ -1,21 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue'; import { computed, reactive, ref, watch } from 'vue';
import {
addGift,
updateGift,
} from '#/api/legacy/gift';
import {
mapLuckyGiftStandard,
} from '#/api/legacy/game-lucky-gift';
import {
getAccessImgUrl,
simpleUploadFile,
} from '#/api/legacy/oss';
import {
regionConfigTable,
} from '#/api/legacy/system';
import { import {
Button, Button,
DatePicker, DatePicker,
@ -24,14 +9,29 @@ import {
FormItem, FormItem,
Image, Image,
Input, Input,
message,
Select, Select,
Space, Space,
Spin, Spin,
Switch, Switch,
TextArea, TextArea,
message,
} from 'antdv-next'; } from 'antdv-next';
import {
mapLuckyGiftStandard,
} from '#/api/legacy/game-lucky-gift';
import {
addGift,
updateGift,
} from '#/api/legacy/gift';
import {
getAccessImgUrl,
simpleUploadFile,
} from '#/api/legacy/oss';
import {
regionConfigTable,
} from '#/api/legacy/system';
import { import {
GIFT_CONFIG_TAB_OPTIONS, GIFT_CONFIG_TAB_OPTIONS,
GIFT_SPECIAL_OPTIONS, GIFT_SPECIAL_OPTIONS,
@ -39,6 +39,17 @@ import {
defineOptions({ name: 'OperateGiftFormModal' }); defineOptions({ name: 'OperateGiftFormModal' });
const props = defineProps<{
open: boolean;
row?: null | Record<string, any>;
sysOrigin: string;
}>();
const emit = defineEmits<{
close: [];
success: [];
}>();
function createForm(sysOrigin = '') { function createForm(sysOrigin = '') {
return { return {
account: '', account: '',
@ -61,17 +72,6 @@ function createForm(sysOrigin = '') {
}; };
} }
const props = defineProps<{
open: boolean;
row?: null | Record<string, any>;
sysOrigin: string;
}>();
const emit = defineEmits<{
close: [];
success: [];
}>();
const form = reactive(createForm()); const form = reactive(createForm());
const loading = ref(false); const loading = ref(false);
const saving = ref(false); const saving = ref(false);
@ -128,6 +128,13 @@ function normalizeMultiValue(value: any) {
.filter(Boolean); .filter(Boolean);
} }
function normalizeTimestampValue(value: any) {
if (value === '' || value === null || value === undefined) {
return '';
}
return String(value);
}
function resetForm() { function resetForm() {
Object.assign(form, createForm(props.sysOrigin)); Object.assign(form, createForm(props.sysOrigin));
previousStandardId.value = ''; previousStandardId.value = '';
@ -157,6 +164,7 @@ watch(
Object.assign(form, { Object.assign(form, {
...props.row, ...props.row,
explanationGift: Boolean(props.row.explanationGift), explanationGift: Boolean(props.row.explanationGift),
expiredTime: normalizeTimestampValue(props.row.expiredTime),
regionList: normalizeMultiValue(props.row.regions || props.row.regionList), regionList: normalizeMultiValue(props.row.regions || props.row.regionList),
specialList: normalizeMultiValue(props.row.special || props.row.specialList), specialList: normalizeMultiValue(props.row.special || props.row.specialList),
sysOrigin: props.row.sysOrigin || props.sysOrigin, sysOrigin: props.row.sysOrigin || props.sysOrigin,
@ -290,11 +298,7 @@ async function handleSubmit() {
giftCandy: form.type === 'FREE' ? '' : form.giftCandy, giftCandy: form.type === 'FREE' ? '' : form.giftCandy,
giftIntegral: form.type === 'FREE' ? '' : form.giftIntegral, giftIntegral: form.type === 'FREE' ? '' : form.giftIntegral,
}; };
if (payload.id) { await (payload.id ? updateGift(payload) : addGift(payload));
await updateGift(payload);
} else {
await addGift(payload);
}
message.success('保存成功'); message.success('保存成功');
emit('success'); emit('success');
emit('close'); emit('close');
@ -323,10 +327,11 @@ async function handleSubmit() {
<Button size="small" @click="toggleAllRegions"> <Button size="small" @click="toggleAllRegions">
{{ form.regionList.length === regions.length ? '取消全选' : '全选' }} {{ form.regionList.length === regions.length ? '取消全选' : '全选' }}
</Button> </Button>
<Select option-label-prop="label" <Select
v-model:value="form.regionList" v-model:value="form.regionList"
:options="regionOptions" :options="regionOptions"
mode="multiple" mode="multiple"
option-label-prop="label"
placeholder="请选择区域" placeholder="请选择区域"
show-search show-search
style="width: 100%" style="width: 100%"
@ -461,14 +466,14 @@ async function handleSubmit() {
hidden hidden
type="file" type="file"
@change="handleCoverUpload" @change="handleCoverUpload"
> />
<input <input
ref="sourceInputRef" ref="sourceInputRef"
accept=".svga,.pag,.mp4" accept=".svga,.pag,.mp4"
hidden hidden
type="file" type="file"
@change="handleSourceUpload" @change="handleSourceUpload"
> />
<template #footer> <template #footer>
<Space> <Space>

View File

@ -8,10 +8,21 @@ import {
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { useAccessStore } from '@vben/stores'; import { useAccessStore } from '@vben/stores';
import {
Button,
Card,
Input,
message,
Modal,
Space,
Table,
} from 'antdv-next';
import { import {
confirmImport, confirmImport,
deductMoney, deductMoney,
exprotBank, exprotBank,
getBankStatistics,
pageBank, pageBank,
sendMoney, sendMoney,
transferMoney, transferMoney,
@ -20,16 +31,6 @@ import AccountInput from '#/components/account-input.vue';
import { formatDate, import { formatDate,
getAllowedSysOrigins } from '#/views/system/shared'; getAllowedSysOrigins } from '#/views/system/shared';
import {
Button,
Card,
Input,
Modal,
Space,
Table,
message,
} from 'antdv-next';
import UserBankCreateModal from './components/user-bank-create-modal.vue'; import UserBankCreateModal from './components/user-bank-create-modal.vue';
import UserBankRunningWaterModal from './components/user-bank-running-water-modal.vue'; import UserBankRunningWaterModal from './components/user-bank-running-water-modal.vue';
import UserProfileLink from './components/user-profile-link.vue'; import UserProfileLink from './components/user-profile-link.vue';
@ -45,6 +46,7 @@ const sysOriginOptions = computed(() => {
const loading = ref(false); const loading = ref(false);
const loadMoreLoading = ref(false); const loadMoreLoading = ref(false);
const exportLoading = ref(false); const exportLoading = ref(false);
const statisticsLoading = ref(false);
const notData = ref(false); const notData = ref(false);
const list = ref<Array<Record<string, any>>>([]); const list = ref<Array<Record<string, any>>>([]);
const createOpen = ref(false); const createOpen = ref(false);
@ -54,16 +56,33 @@ const importLoading = ref(false);
const actionModalOpen = ref(false); const actionModalOpen = ref(false);
const transferOpen = ref(false); const transferOpen = ref(false);
const actionType = ref<'deduct' | 'send'>('send'); const actionType = ref<'deduct' | 'send'>('send');
const activeRow = ref<Record<string, any> | null>(null); const activeRow = ref<null | Record<string, any>>(null);
const importInput = ref<HTMLInputElement | null>(null); const importInput = ref<HTMLInputElement | null>(null);
const query = reactive({ const query = reactive({
lastId: '', lastId: '',
limit: 20, limit: 20,
pageNo: 1,
sortField: '',
sortOrder: '',
sysOrigin: '', sysOrigin: '',
userId: '', userId: '',
}); });
const statistics = reactive({
totalBalance: 0,
totalConsumptionPoints: 0,
totalEarnPoints: 0,
});
const sortableAmountKeys = new Set(['balance', 'consumptionPoints', 'earnPoints']);
type BankSortOrder = 'ascend' | 'descend';
const isSortActive = computed(() => {
return Boolean(query.sortField && query.sortOrder);
});
const actionForm = reactive({ const actionForm = reactive({
quantity: '', quantity: '',
remark: '', remark: '',
@ -79,17 +98,96 @@ const transferForm = reactive({
userId: '', userId: '',
}); });
const columns = [ const columns = computed(() => [
{ dataIndex: 'index', key: 'index', title: 'No', width: 70 }, { dataIndex: 'index', key: 'index', title: 'No', width: 70 },
{ dataIndex: 'sysOrigin', key: 'sysOrigin', title: '系统', width: 90 }, { dataIndex: 'sysOrigin', key: 'sysOrigin', title: '系统', width: 90 },
{ dataIndex: 'userProfile', key: 'userProfile', title: '用户', width: 300 }, { dataIndex: 'userProfile', key: 'userProfile', title: '用户', width: 300 },
{ dataIndex: 'earnPoints', key: 'earnPoints', title: '获得总额', width: 120 }, {
{ dataIndex: 'consumptionPoints', key: 'consumptionPoints', title: '消费总额', width: 120 }, align: 'right' as const,
{ dataIndex: 'balance', key: 'balance', title: '余额', width: 120 }, dataIndex: 'earnPoints',
key: 'earnPoints',
sorter: true,
sortOrder: getSortOrder('earnPoints'),
title: '获得总额',
width: 120,
},
{
align: 'right' as const,
dataIndex: 'consumptionPoints',
key: 'consumptionPoints',
sorter: true,
sortOrder: getSortOrder('consumptionPoints'),
title: '消费总额',
width: 120,
},
{
align: 'right' as const,
dataIndex: 'balance',
key: 'balance',
sorter: true,
sortOrder: getSortOrder('balance'),
title: '余额',
width: 120,
},
{ dataIndex: 'createTime', key: 'createTime', title: '创建时间', width: 180 }, { dataIndex: 'createTime', key: 'createTime', title: '创建时间', width: 180 },
{ dataIndex: 'updateTime', key: 'updateTime', title: '修改时间', width: 180 }, { dataIndex: 'updateTime', key: 'updateTime', title: '修改时间', width: 180 },
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 260, fixed: 'right' as const }, { dataIndex: 'actions', key: 'actions', title: '操作', width: 260, fixed: 'right' as const },
]; ]);
function isBankSortOrder(value: string): value is BankSortOrder {
return value === 'ascend' || value === 'descend';
}
function getSortOrder(field: string) {
return query.sortField === field && isBankSortOrder(query.sortOrder)
? query.sortOrder
: undefined;
}
function formatAmount(value: any) {
const rawValue = String(value ?? '0').replaceAll(',', '');
if (!rawValue || rawValue === 'null' || rawValue === 'undefined') {
return '0';
}
const [integerPart = '0', decimalPart = ''] = rawValue.split('.');
const isNegative = integerPart.startsWith('-');
const unsignedInteger = isNegative ? integerPart.slice(1) : integerPart;
const formattedInteger =
unsignedInteger.replaceAll(/\B(?=(\d{3})+(?!\d))/g, ',') || '0';
const trimmedDecimal = decimalPart.replaceAll(/0+$/g, '');
return `${isNegative ? '-' : ''}${formattedInteger}${trimmedDecimal ? `.${trimmedDecimal}` : ''}`;
}
function buildListParams() {
return {
...query,
lastId: isSortActive.value ? undefined : query.lastId,
pageNo: isSortActive.value ? query.pageNo : undefined,
sortField: isSortActive.value ? query.sortField : undefined,
sortOrder: isSortActive.value ? query.sortOrder : undefined,
};
}
function buildStatisticsParams() {
return {
sysOrigin: query.sysOrigin,
};
}
async function loadStatistics() {
if (!query.sysOrigin) {
return;
}
statisticsLoading.value = true;
try {
const result = await getBankStatistics(buildStatisticsParams());
statistics.totalEarnPoints = result?.totalEarnPoints ?? 0;
statistics.totalConsumptionPoints = result?.totalConsumptionPoints ?? 0;
statistics.totalBalance = result?.totalBalance ?? 0;
} finally {
statisticsLoading.value = false;
}
}
watch( watch(
sysOriginOptions, sysOriginOptions,
@ -107,6 +205,7 @@ async function loadData(reset = false) {
} }
if (reset) { if (reset) {
query.lastId = ''; query.lastId = '';
query.pageNo = 1;
list.value = []; list.value = [];
notData.value = false; notData.value = false;
} }
@ -116,12 +215,20 @@ async function loadData(reset = false) {
loadMoreLoading.value = true; loadMoreLoading.value = true;
} }
try { try {
const result = await pageBank({ ...query }); const result = reset
? await Promise.all([pageBank(buildListParams()), loadStatistics()]).then(
([rows]) => rows,
)
: await pageBank(buildListParams());
const current = result || []; const current = result || [];
notData.value = current.length <= 0; notData.value = current.length < Number(query.limit || 20);
if (!notData.value) { if (current.length > 0) {
list.value = [...list.value, ...current]; list.value = [...list.value, ...current];
query.lastId = String(list.value[list.value.length - 1]?.id || ''); if (isSortActive.value) {
query.pageNo += 1;
} else {
query.lastId = String(list.value[list.value.length - 1]?.id || '');
}
} }
} finally { } finally {
loading.value = false; loading.value = false;
@ -133,6 +240,20 @@ function handleSearch() {
void loadData(true); void loadData(true);
} }
function handleTableChange(_: any, __: any, sorter: any) {
const activeSorter = Array.isArray(sorter) ? sorter[0] : sorter;
const field = String(activeSorter?.columnKey || '');
const order = String(activeSorter?.order || '');
if (isBankSortOrder(order) && sortableAmountKeys.has(field)) {
query.sortField = field;
query.sortOrder = order;
} else {
query.sortField = '';
query.sortOrder = '';
}
void loadData(true);
}
function openAction(record: Record<string, any>, type: 'deduct' | 'send') { function openAction(record: Record<string, any>, type: 'deduct' | 'send') {
activeRow.value = record; activeRow.value = record;
actionType.value = type; actionType.value = type;
@ -165,11 +286,7 @@ async function submitAction() {
} }
loading.value = true; loading.value = true;
try { try {
if (actionType.value === 'send') { await (actionType.value === 'send' ? sendMoney : deductMoney)({ ...actionForm });
await sendMoney({ ...actionForm });
} else {
await deductMoney({ ...actionForm });
}
message.success('操作成功'); message.success('操作成功');
actionModalOpen.value = false; actionModalOpen.value = false;
await loadData(true); await loadData(true);
@ -252,11 +369,28 @@ watch(
<template> <template>
<Page title="用户银行账户"> <Page title="用户银行账户">
<Card> <Card>
<div class="statistics-card" :class="{ 'is-loading': statisticsLoading }">
<div class="statistics-item">
<span class="statistics-label">所有用户获得总额</span>
<strong>{{ formatAmount(statistics.totalEarnPoints) }}</strong>
</div>
<div class="statistics-item">
<span class="statistics-label">所有用户消费总额</span>
<strong>{{ formatAmount(statistics.totalConsumptionPoints) }}</strong>
</div>
<div class="statistics-item">
<span class="statistics-label">所有用户余额</span>
<strong>{{ formatAmount(statistics.totalBalance) }}</strong>
</div>
</div>
<div class="toolbar"> <div class="toolbar">
<Space wrap> <Space wrap>
<SysOriginSelect v-model:value="query.sysOrigin" style="width: 140px" <SysOriginSelect
v-model:value="query.sysOrigin"
:options="sysOriginOptions" :options="sysOriginOptions"
></SysOriginSelect> style="width: 140px"
/>
<AccountInput <AccountInput
v-model:value="query.userId" v-model:value="query.userId"
:sys-origin="query.sysOrigin" :sys-origin="query.sysOrigin"
@ -279,6 +413,7 @@ watch(
:pagination="false" :pagination="false"
row-key="id" row-key="id"
:scroll="{ x: 1500 }" :scroll="{ x: 1500 }"
@change="handleTableChange"
> >
<template #bodyCell="{ column, record, index }"> <template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'index'"> <template v-if="column.key === 'index'">
@ -287,6 +422,15 @@ watch(
<template v-else-if="column.key === 'userProfile'"> <template v-else-if="column.key === 'userProfile'">
<UserProfileLink :profile="record.userProfile" /> <UserProfileLink :profile="record.userProfile" />
</template> </template>
<template
v-else-if="
column.key === 'earnPoints' ||
column.key === 'consumptionPoints' ||
column.key === 'balance'
"
>
{{ formatAmount(record[column.key]) }}
</template>
<template v-else-if="column.key === 'createTime'"> <template v-else-if="column.key === 'createTime'">
{{ formatDate(record.createTime) }} {{ formatDate(record.createTime) }}
</template> </template>
@ -438,7 +582,7 @@ watch(
class="hidden-input" class="hidden-input"
type="file" type="file"
@change="handleImportChange" @change="handleImportChange"
> />
<Button :loading="importLoading" block @click="chooseImportFile"> <Button :loading="importLoading" block @click="chooseImportFile">
选择文件并导入 选择文件并导入
</Button> </Button>
@ -448,6 +592,39 @@ watch(
</template> </template>
<style scoped> <style scoped>
.statistics-card {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
padding: 14px 16px;
margin-bottom: 16px;
background: #f8fafc;
border: 1px solid #e5e7eb;
border-radius: 8px;
}
.statistics-card.is-loading {
opacity: 0.68;
}
.statistics-item {
display: flex;
flex-direction: column;
gap: 6px;
}
.statistics-label {
color: #64748b;
font-size: 13px;
}
.statistics-item strong {
color: #0f172a;
font-size: 20px;
font-weight: 600;
line-height: 1.25;
}
.toolbar { .toolbar {
margin-bottom: 16px; margin-bottom: 16px;
} }

View File

@ -17,10 +17,10 @@ import { listEmojiGroupsBySysOrigin } from '#/api/legacy/app-system';
import { listBadgePictureBySysOrigin } from '#/api/legacy/badge'; import { listBadgePictureBySysOrigin } from '#/api/legacy/badge';
import { listGiftBySysOrigin } from '#/api/legacy/gift'; import { listGiftBySysOrigin } from '#/api/legacy/gift';
import { import {
listNotFamilyBySysOriginType,
listSysOriginTypeList, listSysOriginTypeList,
saveOrUpdatePropsActivityRewardGroup, saveOrUpdatePropsActivityRewardGroup,
} from '#/api/legacy/props'; } from '#/api/legacy/props';
import { getResidentVipConfig } from '#/api/legacy/resident-activity';
import { getDisplaySysOriginText } from '#/views/system/shared'; import { getDisplaySysOriginText } from '#/views/system/shared';
import { import {
@ -53,8 +53,11 @@ const draftLoading = ref(false);
type DraftSourceOption = { type DraftSourceOption = {
badgeName?: string; badgeName?: string;
cover?: string; cover?: string;
durationDays?: number;
id: number | string; id: number | string;
level?: number;
name: string; name: string;
priceGold?: number;
remark?: string; remark?: string;
sourceUrl?: string; sourceUrl?: string;
}; };
@ -199,6 +202,35 @@ function needsRemoteOptions(type: string) {
); );
} }
function normalizeVipResource(value: null | Record<string, any> | undefined) {
return {
cover: String(value?.cover || value?.coverUrl || '').trim(),
sourceUrl: String(
value?.sourceUrl || value?.resourceUrl || value?.url || value?.cover || '',
).trim(),
};
}
function pickVipPreviewResource(item: Record<string, any>) {
const fields = [
'longBadge',
'shortBadge',
'avatarFrame',
'entryEffect',
'chatBubble',
'floatPicture',
'backgroundCard',
'effectImage',
];
for (const field of fields) {
const resource = normalizeVipResource(item[field]);
if (resource.cover || resource.sourceUrl) {
return resource;
}
}
return { cover: '', sourceUrl: '' };
}
async function loadOptions(type: string) { async function loadOptions(type: string) {
if (!type || !form.sysOrigin || !needsRemoteOptions(type)) { if (!type || !form.sysOrigin || !needsRemoteOptions(type)) {
return; return;
@ -243,13 +275,25 @@ async function loadOptions(type: string) {
break; break;
} }
case 'NOBLE_VIP': { case 'NOBLE_VIP': {
const list = await listNotFamilyBySysOriginType(form.sysOrigin, type); const config = await getResidentVipConfig(form.sysOrigin);
store.list = list.map((item) => ({ const levels = Array.isArray(config?.levels) ? config.levels : [];
cover: item.cover || '', store.list = levels
id: item.id ?? '', .filter((item: Record<string, any>) => item.enabled && item.id)
name: item.name || '', .map((item: Record<string, any>) => {
sourceUrl: item.sourceUrl || '', const preview = pickVipPreviewResource(item);
})); const durationDays = Number(item.durationDays || 30);
const level = Number(item.level || 0);
return {
cover: preview.cover,
durationDays,
id: item.id ?? '',
level,
name: String(item.displayName || item.levelCode || `VIP ${level}`),
priceGold: Number(item.priceGold || 0),
remark: `${durationDays}`,
sourceUrl: preview.sourceUrl,
};
});
break; break;
} }
default: { default: {
@ -296,6 +340,10 @@ function handleDraftContentChange(value: number | string) {
(item) => String(item.id) === String(value), (item) => String(item.id) === String(value),
); );
selectedDraftResource.value = option || null; selectedDraftResource.value = option || null;
if (draft.type === 'NOBLE_VIP' && option) {
draft.quantity = option.durationDays || 30;
draft.remark = option.name;
}
} }
function buildRewardItem(): null | RewardGroupItem { function buildRewardItem(): null | RewardGroupItem {
@ -311,7 +359,7 @@ function buildRewardItem(): null | RewardGroupItem {
cover: selectedDraftResource.value?.cover || '', cover: selectedDraftResource.value?.cover || '',
detailType: draft.type, detailType: draft.type,
quantity: draft.quantity, quantity: draft.quantity,
remark: draft.remark, remark: draft.remark || selectedDraftResource.value?.remark || selectedDraftResource.value?.name || '',
sourceUrl: selectedDraftResource.value?.sourceUrl || '', sourceUrl: selectedDraftResource.value?.sourceUrl || '',
type: mapping.value, type: mapping.value,
}; };
@ -370,6 +418,10 @@ function validateDraft() {
} }
return true; return true;
} }
if (draft.type === 'NOBLE_VIP') {
draft.quantity = draft.quantity || selectedDraftResource.value?.durationDays || 30;
return true;
}
if (draft.quantity === '' || Number.isNaN(Number(draft.quantity))) { if (draft.quantity === '' || Number.isNaN(Number(draft.quantity))) {
message.warning('请输入数量/天数'); message.warning('请输入数量/天数');
return false; return false;
@ -550,6 +602,13 @@ async function handleSubmit() {
<Input v-model:value="draft.remark" placeholder="请输入描述" /> <Input v-model:value="draft.remark" placeholder="请输入描述" />
</FormItem> </FormItem>
<FormItem v-else-if="draft.type === 'NOBLE_VIP'" label="有效期">
<Input
:value="`${draft.quantity || selectedDraftResource?.durationDays || 30} 天`"
disabled
/>
</FormItem>
<FormItem v-else label="数量/天数"> <FormItem v-else label="数量/天数">
<Input <Input
v-model:value="draft.quantity" v-model:value="draft.quantity"

View File

@ -116,7 +116,7 @@ export const PROPS_SOURCE_GROUP_TYPE_MAP: Record<
> = { > = {
AVATAR_FRAME: { value: 'PROPS', name: '头像框' }, AVATAR_FRAME: { value: 'PROPS', name: '头像框' },
RIDE: { value: 'PROPS', name: '座驾' }, RIDE: { value: 'PROPS', name: '座驾' },
NOBLE_VIP: { value: 'PROPS', name: '贵族' }, NOBLE_VIP: { value: 'PROPS', name: 'VIP' },
THEME: { value: 'PROPS', name: '房间背景主题' }, THEME: { value: 'PROPS', name: '房间背景主题' },
GIFT: { value: 'GIFT', name: '礼物' }, GIFT: { value: 'GIFT', name: '礼物' },
SPECIAL_ID: { value: 'SPECIAL_ID', name: '靓号' }, SPECIAL_ID: { value: 'SPECIAL_ID', name: '靓号' },
@ -318,6 +318,12 @@ export function formatRewardText(item: Record<string, any>) {
quantity <= 0 ? '永久' : `${quantity}` quantity <= 0 ? '永久' : `${quantity}`
}`; }`;
} }
if (detailType === 'NOBLE_VIP') {
const quantity = Number(item.quantity || 0);
return `${item.name || item.remark || item.content || '-'} ${
quantity <= 0 ? '' : `${quantity}`
}`.trim();
}
if (detailType === 'GIFT' || detailType === 'FRAGMENTS') { if (detailType === 'GIFT' || detailType === 'FRAGMENTS') {
return `数量:${item.quantity || 0}`; return `数量:${item.quantity || 0}`;
} }