修复时间字段
This commit is contained in:
parent
8d0836e7e8
commit
aa0988af6b
@ -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>) {
|
||||
return downloadLegacyExcel(
|
||||
'/user-bank-balance/export',
|
||||
|
||||
@ -1,21 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
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 {
|
||||
Button,
|
||||
DatePicker,
|
||||
@ -24,14 +9,29 @@ import {
|
||||
FormItem,
|
||||
Image,
|
||||
Input,
|
||||
message,
|
||||
Select,
|
||||
Space,
|
||||
Spin,
|
||||
Switch,
|
||||
TextArea,
|
||||
message,
|
||||
} 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 {
|
||||
GIFT_CONFIG_TAB_OPTIONS,
|
||||
GIFT_SPECIAL_OPTIONS,
|
||||
@ -39,6 +39,17 @@ import {
|
||||
|
||||
defineOptions({ name: 'OperateGiftFormModal' });
|
||||
|
||||
const props = defineProps<{
|
||||
open: boolean;
|
||||
row?: null | Record<string, any>;
|
||||
sysOrigin: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
close: [];
|
||||
success: [];
|
||||
}>();
|
||||
|
||||
function createForm(sysOrigin = '') {
|
||||
return {
|
||||
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 loading = ref(false);
|
||||
const saving = ref(false);
|
||||
@ -128,6 +128,13 @@ function normalizeMultiValue(value: any) {
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function normalizeTimestampValue(value: any) {
|
||||
if (value === '' || value === null || value === undefined) {
|
||||
return '';
|
||||
}
|
||||
return String(value);
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
Object.assign(form, createForm(props.sysOrigin));
|
||||
previousStandardId.value = '';
|
||||
@ -157,6 +164,7 @@ watch(
|
||||
Object.assign(form, {
|
||||
...props.row,
|
||||
explanationGift: Boolean(props.row.explanationGift),
|
||||
expiredTime: normalizeTimestampValue(props.row.expiredTime),
|
||||
regionList: normalizeMultiValue(props.row.regions || props.row.regionList),
|
||||
specialList: normalizeMultiValue(props.row.special || props.row.specialList),
|
||||
sysOrigin: props.row.sysOrigin || props.sysOrigin,
|
||||
@ -290,11 +298,7 @@ async function handleSubmit() {
|
||||
giftCandy: form.type === 'FREE' ? '' : form.giftCandy,
|
||||
giftIntegral: form.type === 'FREE' ? '' : form.giftIntegral,
|
||||
};
|
||||
if (payload.id) {
|
||||
await updateGift(payload);
|
||||
} else {
|
||||
await addGift(payload);
|
||||
}
|
||||
await (payload.id ? updateGift(payload) : addGift(payload));
|
||||
message.success('保存成功');
|
||||
emit('success');
|
||||
emit('close');
|
||||
@ -323,10 +327,11 @@ async function handleSubmit() {
|
||||
<Button size="small" @click="toggleAllRegions">
|
||||
{{ form.regionList.length === regions.length ? '取消全选' : '全选' }}
|
||||
</Button>
|
||||
<Select option-label-prop="label"
|
||||
<Select
|
||||
v-model:value="form.regionList"
|
||||
:options="regionOptions"
|
||||
mode="multiple"
|
||||
option-label-prop="label"
|
||||
placeholder="请选择区域"
|
||||
show-search
|
||||
style="width: 100%"
|
||||
@ -461,14 +466,14 @@ async function handleSubmit() {
|
||||
hidden
|
||||
type="file"
|
||||
@change="handleCoverUpload"
|
||||
>
|
||||
/>
|
||||
<input
|
||||
ref="sourceInputRef"
|
||||
accept=".svga,.pag,.mp4"
|
||||
hidden
|
||||
type="file"
|
||||
@change="handleSourceUpload"
|
||||
>
|
||||
/>
|
||||
|
||||
<template #footer>
|
||||
<Space>
|
||||
|
||||
@ -8,10 +8,21 @@ import {
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Input,
|
||||
message,
|
||||
Modal,
|
||||
Space,
|
||||
Table,
|
||||
} from 'antdv-next';
|
||||
|
||||
import {
|
||||
confirmImport,
|
||||
deductMoney,
|
||||
exprotBank,
|
||||
getBankStatistics,
|
||||
pageBank,
|
||||
sendMoney,
|
||||
transferMoney,
|
||||
@ -20,16 +31,6 @@ import AccountInput from '#/components/account-input.vue';
|
||||
import { formatDate,
|
||||
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 UserBankRunningWaterModal from './components/user-bank-running-water-modal.vue';
|
||||
import UserProfileLink from './components/user-profile-link.vue';
|
||||
@ -45,6 +46,7 @@ const sysOriginOptions = computed(() => {
|
||||
const loading = ref(false);
|
||||
const loadMoreLoading = ref(false);
|
||||
const exportLoading = ref(false);
|
||||
const statisticsLoading = ref(false);
|
||||
const notData = ref(false);
|
||||
const list = ref<Array<Record<string, any>>>([]);
|
||||
const createOpen = ref(false);
|
||||
@ -54,16 +56,33 @@ const importLoading = ref(false);
|
||||
const actionModalOpen = ref(false);
|
||||
const transferOpen = ref(false);
|
||||
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 query = reactive({
|
||||
lastId: '',
|
||||
limit: 20,
|
||||
pageNo: 1,
|
||||
sortField: '',
|
||||
sortOrder: '',
|
||||
sysOrigin: '',
|
||||
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({
|
||||
quantity: '',
|
||||
remark: '',
|
||||
@ -79,17 +98,96 @@ const transferForm = reactive({
|
||||
userId: '',
|
||||
});
|
||||
|
||||
const columns = [
|
||||
const columns = computed(() => [
|
||||
{ dataIndex: 'index', key: 'index', title: 'No', width: 70 },
|
||||
{ dataIndex: 'sysOrigin', key: 'sysOrigin', title: '系统', width: 90 },
|
||||
{ dataIndex: 'userProfile', key: 'userProfile', title: '用户', width: 300 },
|
||||
{ dataIndex: 'earnPoints', key: 'earnPoints', title: '获得总额', width: 120 },
|
||||
{ dataIndex: 'consumptionPoints', key: 'consumptionPoints', title: '消费总额', width: 120 },
|
||||
{ dataIndex: 'balance', key: 'balance', title: '余额', width: 120 },
|
||||
{
|
||||
align: 'right' as const,
|
||||
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: 'updateTime', key: 'updateTime', title: '修改时间', width: 180 },
|
||||
{ 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(
|
||||
sysOriginOptions,
|
||||
@ -107,6 +205,7 @@ async function loadData(reset = false) {
|
||||
}
|
||||
if (reset) {
|
||||
query.lastId = '';
|
||||
query.pageNo = 1;
|
||||
list.value = [];
|
||||
notData.value = false;
|
||||
}
|
||||
@ -116,12 +215,20 @@ async function loadData(reset = false) {
|
||||
loadMoreLoading.value = true;
|
||||
}
|
||||
try {
|
||||
const result = await pageBank({ ...query });
|
||||
const result = reset
|
||||
? await Promise.all([pageBank(buildListParams()), loadStatistics()]).then(
|
||||
([rows]) => rows,
|
||||
)
|
||||
: await pageBank(buildListParams());
|
||||
const current = result || [];
|
||||
notData.value = current.length <= 0;
|
||||
if (!notData.value) {
|
||||
notData.value = current.length < Number(query.limit || 20);
|
||||
if (current.length > 0) {
|
||||
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 {
|
||||
loading.value = false;
|
||||
@ -133,6 +240,20 @@ function handleSearch() {
|
||||
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') {
|
||||
activeRow.value = record;
|
||||
actionType.value = type;
|
||||
@ -165,11 +286,7 @@ async function submitAction() {
|
||||
}
|
||||
loading.value = true;
|
||||
try {
|
||||
if (actionType.value === 'send') {
|
||||
await sendMoney({ ...actionForm });
|
||||
} else {
|
||||
await deductMoney({ ...actionForm });
|
||||
}
|
||||
await (actionType.value === 'send' ? sendMoney : deductMoney)({ ...actionForm });
|
||||
message.success('操作成功');
|
||||
actionModalOpen.value = false;
|
||||
await loadData(true);
|
||||
@ -252,11 +369,28 @@ watch(
|
||||
<template>
|
||||
<Page title="用户银行账户">
|
||||
<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">
|
||||
<Space wrap>
|
||||
<SysOriginSelect v-model:value="query.sysOrigin" style="width: 140px"
|
||||
<SysOriginSelect
|
||||
v-model:value="query.sysOrigin"
|
||||
:options="sysOriginOptions"
|
||||
></SysOriginSelect>
|
||||
style="width: 140px"
|
||||
/>
|
||||
<AccountInput
|
||||
v-model:value="query.userId"
|
||||
:sys-origin="query.sysOrigin"
|
||||
@ -279,6 +413,7 @@ watch(
|
||||
:pagination="false"
|
||||
row-key="id"
|
||||
:scroll="{ x: 1500 }"
|
||||
@change="handleTableChange"
|
||||
>
|
||||
<template #bodyCell="{ column, record, index }">
|
||||
<template v-if="column.key === 'index'">
|
||||
@ -287,6 +422,15 @@ watch(
|
||||
<template v-else-if="column.key === 'userProfile'">
|
||||
<UserProfileLink :profile="record.userProfile" />
|
||||
</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'">
|
||||
{{ formatDate(record.createTime) }}
|
||||
</template>
|
||||
@ -438,7 +582,7 @@ watch(
|
||||
class="hidden-input"
|
||||
type="file"
|
||||
@change="handleImportChange"
|
||||
>
|
||||
/>
|
||||
<Button :loading="importLoading" block @click="chooseImportFile">
|
||||
选择文件并导入
|
||||
</Button>
|
||||
@ -448,6 +592,39 @@ watch(
|
||||
</template>
|
||||
|
||||
<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 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@ -17,10 +17,10 @@ import { listEmojiGroupsBySysOrigin } from '#/api/legacy/app-system';
|
||||
import { listBadgePictureBySysOrigin } from '#/api/legacy/badge';
|
||||
import { listGiftBySysOrigin } from '#/api/legacy/gift';
|
||||
import {
|
||||
listNotFamilyBySysOriginType,
|
||||
listSysOriginTypeList,
|
||||
saveOrUpdatePropsActivityRewardGroup,
|
||||
} from '#/api/legacy/props';
|
||||
import { getResidentVipConfig } from '#/api/legacy/resident-activity';
|
||||
import { getDisplaySysOriginText } from '#/views/system/shared';
|
||||
|
||||
import {
|
||||
@ -53,8 +53,11 @@ const draftLoading = ref(false);
|
||||
type DraftSourceOption = {
|
||||
badgeName?: string;
|
||||
cover?: string;
|
||||
durationDays?: number;
|
||||
id: number | string;
|
||||
level?: number;
|
||||
name: string;
|
||||
priceGold?: number;
|
||||
remark?: 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) {
|
||||
if (!type || !form.sysOrigin || !needsRemoteOptions(type)) {
|
||||
return;
|
||||
@ -243,13 +275,25 @@ async function loadOptions(type: string) {
|
||||
break;
|
||||
}
|
||||
case 'NOBLE_VIP': {
|
||||
const list = await listNotFamilyBySysOriginType(form.sysOrigin, type);
|
||||
store.list = list.map((item) => ({
|
||||
cover: item.cover || '',
|
||||
id: item.id ?? '',
|
||||
name: item.name || '',
|
||||
sourceUrl: item.sourceUrl || '',
|
||||
}));
|
||||
const config = await getResidentVipConfig(form.sysOrigin);
|
||||
const levels = Array.isArray(config?.levels) ? config.levels : [];
|
||||
store.list = levels
|
||||
.filter((item: Record<string, any>) => item.enabled && item.id)
|
||||
.map((item: Record<string, any>) => {
|
||||
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;
|
||||
}
|
||||
default: {
|
||||
@ -296,6 +340,10 @@ function handleDraftContentChange(value: number | string) {
|
||||
(item) => String(item.id) === String(value),
|
||||
);
|
||||
selectedDraftResource.value = option || null;
|
||||
if (draft.type === 'NOBLE_VIP' && option) {
|
||||
draft.quantity = option.durationDays || 30;
|
||||
draft.remark = option.name;
|
||||
}
|
||||
}
|
||||
|
||||
function buildRewardItem(): null | RewardGroupItem {
|
||||
@ -311,7 +359,7 @@ function buildRewardItem(): null | RewardGroupItem {
|
||||
cover: selectedDraftResource.value?.cover || '',
|
||||
detailType: draft.type,
|
||||
quantity: draft.quantity,
|
||||
remark: draft.remark,
|
||||
remark: draft.remark || selectedDraftResource.value?.remark || selectedDraftResource.value?.name || '',
|
||||
sourceUrl: selectedDraftResource.value?.sourceUrl || '',
|
||||
type: mapping.value,
|
||||
};
|
||||
@ -370,6 +418,10 @@ function validateDraft() {
|
||||
}
|
||||
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))) {
|
||||
message.warning('请输入数量/天数');
|
||||
return false;
|
||||
@ -550,6 +602,13 @@ async function handleSubmit() {
|
||||
<Input v-model:value="draft.remark" placeholder="请输入描述" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem v-else-if="draft.type === 'NOBLE_VIP'" label="有效期">
|
||||
<Input
|
||||
:value="`${draft.quantity || selectedDraftResource?.durationDays || 30} 天`"
|
||||
disabled
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem v-else label="数量/天数">
|
||||
<Input
|
||||
v-model:value="draft.quantity"
|
||||
|
||||
@ -116,7 +116,7 @@ export const PROPS_SOURCE_GROUP_TYPE_MAP: Record<
|
||||
> = {
|
||||
AVATAR_FRAME: { value: 'PROPS', name: '头像框' },
|
||||
RIDE: { value: 'PROPS', name: '座驾' },
|
||||
NOBLE_VIP: { value: 'PROPS', name: '贵族' },
|
||||
NOBLE_VIP: { value: 'PROPS', name: 'VIP' },
|
||||
THEME: { value: 'PROPS', name: '房间背景主题' },
|
||||
GIFT: { value: 'GIFT', name: '礼物' },
|
||||
SPECIAL_ID: { value: 'SPECIAL_ID', name: '靓号' },
|
||||
@ -318,6 +318,12 @@ export function formatRewardText(item: Record<string, any>) {
|
||||
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') {
|
||||
return `数量:${item.quantity || 0}`;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user