修改并发上传
This commit is contained in:
parent
d2a994cfa9
commit
ec97291d0e
@ -54,6 +54,13 @@ interface ParsedGiftFile {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface UploadTask {
|
||||||
|
file: File;
|
||||||
|
fileName: string;
|
||||||
|
kind: AssetKind;
|
||||||
|
row: BatchGiftRow;
|
||||||
|
}
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
initialSysOrigin?: number | string;
|
initialSysOrigin?: number | string;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -82,6 +89,9 @@ const sequence = ref(0);
|
|||||||
const showOnlyErrors = ref(false);
|
const showOnlyErrors = ref(false);
|
||||||
const submitting = ref(false);
|
const submitting = ref(false);
|
||||||
const droppedFilePathMap = new WeakMap<File, string>();
|
const droppedFilePathMap = new WeakMap<File, string>();
|
||||||
|
const uploadQueue: UploadTask[] = [];
|
||||||
|
const MAX_UPLOAD_CONCURRENCY = 2;
|
||||||
|
let activeUploadCount = 0;
|
||||||
|
|
||||||
const giftTabOptions = GIFT_CONFIG_TAB_OPTIONS.map((item) => ({
|
const giftTabOptions = GIFT_CONFIG_TAB_OPTIONS.map((item) => ({
|
||||||
label: item.name,
|
label: item.name,
|
||||||
@ -171,6 +181,7 @@ function resetBatch() {
|
|||||||
activeRowKey.value = '';
|
activeRowKey.value = '';
|
||||||
showOnlyErrors.value = false;
|
showOnlyErrors.value = false;
|
||||||
sequence.value = 0;
|
sequence.value = 0;
|
||||||
|
uploadQueue.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@ -342,7 +353,26 @@ function setRowAsset(row: BatchGiftRow, kind: AssetKind, file: File) {
|
|||||||
}
|
}
|
||||||
row.saved = false;
|
row.saved = false;
|
||||||
refreshAllRows();
|
refreshAllRows();
|
||||||
void uploadAsset(row, kind, file, fileName);
|
enqueueUpload({ file, fileName, kind, row });
|
||||||
|
}
|
||||||
|
|
||||||
|
function enqueueUpload(task: UploadTask) {
|
||||||
|
uploadQueue.push(task);
|
||||||
|
runUploadQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runUploadQueue() {
|
||||||
|
while (activeUploadCount < MAX_UPLOAD_CONCURRENCY && uploadQueue.length > 0) {
|
||||||
|
const task = uploadQueue.shift();
|
||||||
|
if (!task) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activeUploadCount += 1;
|
||||||
|
void uploadAsset(task.row, task.kind, task.file, task.fileName).finally(() => {
|
||||||
|
activeUploadCount -= 1;
|
||||||
|
runUploadQueue();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadAsset(
|
async function uploadAsset(
|
||||||
@ -1131,6 +1161,18 @@ async function submitBatch() {
|
|||||||
width: 52px;
|
width: 52px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.asset-cover {
|
||||||
|
border-radius: 6px;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.asset-cover :deep(.ant-image-img) {
|
||||||
|
height: 52px;
|
||||||
|
object-fit: contain;
|
||||||
|
width: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
.asset-empty {
|
.asset-empty {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: #f8fafc;
|
background: #f8fafc;
|
||||||
|
|||||||
@ -79,6 +79,13 @@ interface StructuredResourceFile {
|
|||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface UploadTask {
|
||||||
|
file: File;
|
||||||
|
fileName: string;
|
||||||
|
kind: AssetKind;
|
||||||
|
row: BatchRow;
|
||||||
|
}
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
initialSysOrigin?: number | string;
|
initialSysOrigin?: number | string;
|
||||||
initialType?: number | string;
|
initialType?: number | string;
|
||||||
@ -109,6 +116,9 @@ const sequence = ref(0);
|
|||||||
const showOnlyErrors = ref(false);
|
const showOnlyErrors = ref(false);
|
||||||
const submitting = ref(false);
|
const submitting = ref(false);
|
||||||
const droppedFilePathMap = new WeakMap<File, string>();
|
const droppedFilePathMap = new WeakMap<File, string>();
|
||||||
|
const uploadQueue: UploadTask[] = [];
|
||||||
|
const MAX_UPLOAD_CONCURRENCY = 2;
|
||||||
|
let activeUploadCount = 0;
|
||||||
|
|
||||||
const propsTypeOptions = PROPS_RESOURCE_CONFIG_TYPES.map((item) => ({
|
const propsTypeOptions = PROPS_RESOURCE_CONFIG_TYPES.map((item) => ({
|
||||||
label: item.name,
|
label: item.name,
|
||||||
@ -243,6 +253,7 @@ function resetBatch() {
|
|||||||
activeRowKey.value = '';
|
activeRowKey.value = '';
|
||||||
showOnlyErrors.value = false;
|
showOnlyErrors.value = false;
|
||||||
sequence.value = 0;
|
sequence.value = 0;
|
||||||
|
uploadQueue.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@ -456,7 +467,26 @@ function setRowAsset(row: BatchRow, kind: AssetKind, file: File) {
|
|||||||
}
|
}
|
||||||
row.saved = false;
|
row.saved = false;
|
||||||
refreshAllRows();
|
refreshAllRows();
|
||||||
void uploadAsset(row, kind, file, fileName);
|
enqueueUpload({ file, fileName, kind, row });
|
||||||
|
}
|
||||||
|
|
||||||
|
function enqueueUpload(task: UploadTask) {
|
||||||
|
uploadQueue.push(task);
|
||||||
|
runUploadQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runUploadQueue() {
|
||||||
|
while (activeUploadCount < MAX_UPLOAD_CONCURRENCY && uploadQueue.length > 0) {
|
||||||
|
const task = uploadQueue.shift();
|
||||||
|
if (!task) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activeUploadCount += 1;
|
||||||
|
void uploadAsset(task.row, task.kind, task.file, task.fileName).finally(() => {
|
||||||
|
activeUploadCount -= 1;
|
||||||
|
runUploadQueue();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadAsset(
|
async function uploadAsset(
|
||||||
@ -1410,6 +1440,18 @@ function customRow(record: Record<string, any>) {
|
|||||||
width: 52px;
|
width: 52px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.asset-cover {
|
||||||
|
border-radius: 6px;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.asset-cover :deep(.ant-image-img) {
|
||||||
|
height: 52px;
|
||||||
|
object-fit: contain;
|
||||||
|
width: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
.asset-empty {
|
.asset-empty {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: #f8fafc;
|
background: #f8fafc;
|
||||||
|
|||||||
@ -13,12 +13,12 @@ import {
|
|||||||
InputNumber,
|
InputNumber,
|
||||||
message,
|
message,
|
||||||
Pagination,
|
Pagination,
|
||||||
Select,
|
|
||||||
Spin,
|
Spin,
|
||||||
Tag,
|
Tag,
|
||||||
} from 'antdv-next';
|
} from 'antdv-next';
|
||||||
|
|
||||||
import { listBadgePictureBySysOrigin } from '#/api/legacy/badge';
|
import { listBadgePictureBySysOrigin } from '#/api/legacy/badge';
|
||||||
|
import { listGiftBySysOrigin } from '#/api/legacy/gift';
|
||||||
import {
|
import {
|
||||||
listNotFamilyBySysOriginType,
|
listNotFamilyBySysOriginType,
|
||||||
sendPropsGiveUser,
|
sendPropsGiveUser,
|
||||||
@ -31,7 +31,7 @@ import { BADGE_TYPE_OPTIONS, PROPS_TYPES } from './shared';
|
|||||||
|
|
||||||
defineOptions({ name: 'PropsSendTool' });
|
defineOptions({ name: 'PropsSendTool' });
|
||||||
|
|
||||||
type ResourceKind = 'badge' | 'props';
|
type ResourceKind = 'badge' | 'gift' | 'props';
|
||||||
|
|
||||||
type TypeOption = {
|
type TypeOption = {
|
||||||
icon: string;
|
icon: string;
|
||||||
@ -50,6 +50,7 @@ type DisplayResource = {
|
|||||||
name: string;
|
name: string;
|
||||||
raw: Record<string, any>;
|
raw: Record<string, any>;
|
||||||
secondaryType: string;
|
secondaryType: string;
|
||||||
|
type: string;
|
||||||
typeLabel: string;
|
typeLabel: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,9 +63,11 @@ type RecipientProfile = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const BADGE_TYPE_VALUE = '__BADGE__';
|
const BADGE_TYPE_VALUE = '__BADGE__';
|
||||||
|
const GIFT_TYPE_VALUE = '__GIFT__';
|
||||||
const MAX_BATCH_ACCOUNTS = 15;
|
const MAX_BATCH_ACCOUNTS = 15;
|
||||||
const RESOURCE_PAGE_SIZE = 72;
|
const RESOURCE_PAGE_SIZE = 72;
|
||||||
const QUICK_DAYS = [1, 7, 15, 30, -1, -7];
|
const QUICK_DAYS = [1, 7, 15, 30, -1, -7];
|
||||||
|
const QUICK_GIFT_QUANTITIES = [1, 5, 10, 50, 100];
|
||||||
const USER_AVATAR_FALLBACK =
|
const USER_AVATAR_FALLBACK =
|
||||||
'https://dummyimage.com/40x40/e2e8f0/64748b&text=U';
|
'https://dummyimage.com/40x40/e2e8f0/64748b&text=U';
|
||||||
|
|
||||||
@ -76,14 +79,7 @@ const sysOriginOptions = computed(() => {
|
|||||||
return options.length > 0 ? options : getAllowedSysOrigins([]);
|
return options.length > 0 ? options : getAllowedSysOrigins([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
const propsTypeOptions = PROPS_TYPES.filter(
|
const propsTypeOptions = PROPS_TYPES.filter((item) => item.value !== 'CUSTOMIZE');
|
||||||
(item) => item.value !== 'CUSTOMIZE' && item.value !== 'FRAGMENTS',
|
|
||||||
);
|
|
||||||
const vipOriginOptions = [
|
|
||||||
{ label: '系统赠送', value: 'SYSTEM_GIVE' as any },
|
|
||||||
{ label: '购买或朋友赠送', value: 'BUY_OR_GIVE' as any },
|
|
||||||
{ label: '活动奖励', value: 'ACTIVITY_AWARD' as any },
|
|
||||||
];
|
|
||||||
|
|
||||||
const propsFormLoading = ref(false);
|
const propsFormLoading = ref(false);
|
||||||
const sourceLoading = ref(false);
|
const sourceLoading = ref(false);
|
||||||
@ -98,10 +94,10 @@ let recipientSearchTimer: number | undefined;
|
|||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
exchangeDays: '',
|
exchangeDays: '',
|
||||||
|
giftQuantity: 1,
|
||||||
receiverAccounts: '',
|
receiverAccounts: '',
|
||||||
secondaryType: '',
|
secondaryType: '',
|
||||||
sysOrigin: sysOriginOptions.value[0]?.value ?? '',
|
sysOrigin: sysOriginOptions.value[0]?.value ?? '',
|
||||||
vipOrigin: '',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function hasPermission(code: string) {
|
function hasPermission(code: string) {
|
||||||
@ -113,7 +109,12 @@ const canSendProps = computed(() => hasPermission('send:props'));
|
|||||||
const canSendBadge = computed(
|
const canSendBadge = computed(
|
||||||
() => canSendProps.value || hasPermission('send:props:badge'),
|
() => canSendProps.value || hasPermission('send:props:badge'),
|
||||||
);
|
);
|
||||||
const canUsePage = computed(() => canSendProps.value || canSendBadge.value);
|
const canSendGift = computed(
|
||||||
|
() => canSendProps.value || hasPermission('send:props:GIFT'),
|
||||||
|
);
|
||||||
|
const canUsePage = computed(
|
||||||
|
() => canSendProps.value || canSendBadge.value || canSendGift.value,
|
||||||
|
);
|
||||||
|
|
||||||
const typeOptions = computed<TypeOption[]>(() => {
|
const typeOptions = computed<TypeOption[]>(() => {
|
||||||
const options: TypeOption[] = [];
|
const options: TypeOption[] = [];
|
||||||
@ -135,6 +136,14 @@ const typeOptions = computed<TypeOption[]>(() => {
|
|||||||
value: BADGE_TYPE_VALUE,
|
value: BADGE_TYPE_VALUE,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (canSendGift.value) {
|
||||||
|
options.push({
|
||||||
|
icon: 'lucide:gift',
|
||||||
|
kind: 'gift',
|
||||||
|
label: '礼物',
|
||||||
|
value: GIFT_TYPE_VALUE,
|
||||||
|
});
|
||||||
|
}
|
||||||
return options;
|
return options;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -156,14 +165,27 @@ const displayedRecipients = computed(() =>
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
const sendActionText = computed(() => (Number(form.exchangeDays) < 0 ? '回收' : '赠送'));
|
|
||||||
const selectedCount = computed(() => selectedResources.value.length);
|
const selectedCount = computed(() => selectedResources.value.length);
|
||||||
const needsVipOrigin = computed(
|
const selectedHasGift = computed(() =>
|
||||||
() =>
|
selectedResources.value.some((item) => item.kind === 'gift'),
|
||||||
selectedResources.value.some(
|
|
||||||
(item) => item.kind === 'props' && item.secondaryType === 'NOBLE_VIP',
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
const selectedHasNonGift = computed(() =>
|
||||||
|
selectedResources.value.some((item) => item.kind !== 'gift'),
|
||||||
|
);
|
||||||
|
const currentTypeIsGift = computed(() => currentTypeOption.value?.kind === 'gift');
|
||||||
|
const showGiftQuantity = computed(() => selectedHasGift.value || currentTypeIsGift.value);
|
||||||
|
const showExchangeDays = computed(
|
||||||
|
() => selectedHasNonGift.value || (!selectedHasGift.value && !currentTypeIsGift.value),
|
||||||
|
);
|
||||||
|
const sendActionText = computed(() => {
|
||||||
|
if (selectedHasGift.value && selectedHasNonGift.value) {
|
||||||
|
return Number(form.exchangeDays) < 0 ? '礼物赠送 / 道具回收' : '赠送';
|
||||||
|
}
|
||||||
|
if (selectedHasGift.value) {
|
||||||
|
return '赠送';
|
||||||
|
}
|
||||||
|
return Number(form.exchangeDays) < 0 ? '回收' : '赠送';
|
||||||
|
});
|
||||||
const selectedTypeSummary = computed(() => {
|
const selectedTypeSummary = computed(() => {
|
||||||
const labels = [
|
const labels = [
|
||||||
...new Set(selectedResources.value.map((item) => item.typeLabel).filter(Boolean)),
|
...new Set(selectedResources.value.map((item) => item.typeLabel).filter(Boolean)),
|
||||||
@ -331,17 +353,19 @@ function normalizeDisplayResource(
|
|||||||
secondaryType: string,
|
secondaryType: string,
|
||||||
typeLabel: string,
|
typeLabel: string,
|
||||||
): DisplayResource {
|
): DisplayResource {
|
||||||
const id =
|
let id = firstPresent(item, ['id', 'resourceId', 'propsSourceId', 'propsId']);
|
||||||
kind === 'badge'
|
let name = firstPresent(item, ['name', 'resourceName', 'sourceName']);
|
||||||
? firstPresent(item, ['badgeConfigId', 'id', 'badgeId'])
|
if (kind === 'badge') {
|
||||||
: firstPresent(item, ['id', 'resourceId', 'propsSourceId', 'propsId']);
|
id = firstPresent(item, ['badgeConfigId', 'id', 'badgeId']);
|
||||||
const name =
|
name = firstPresent(item, ['badgeName', 'name']);
|
||||||
kind === 'badge'
|
} else if (kind === 'gift') {
|
||||||
? firstPresent(item, ['badgeName', 'name'])
|
id = firstPresent(item, ['id', 'giftId']);
|
||||||
: firstPresent(item, ['name', 'resourceName', 'sourceName']);
|
name = firstPresent(item, ['giftName', 'name']);
|
||||||
|
}
|
||||||
const cover = firstPresent(item, [
|
const cover = firstPresent(item, [
|
||||||
'cover',
|
'cover',
|
||||||
'coverUrl',
|
'coverUrl',
|
||||||
|
'giftPhoto',
|
||||||
'resourceCover',
|
'resourceCover',
|
||||||
'resourceCoverUrl',
|
'resourceCoverUrl',
|
||||||
'selectUrl',
|
'selectUrl',
|
||||||
@ -349,7 +373,7 @@ function normalizeDisplayResource(
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
amount: firstPresent(item, ['amount', 'price', 'goldAmount']),
|
amount: firstPresent(item, ['amount', 'giftCandy', 'price', 'goldAmount']),
|
||||||
badgeTypeLabel: kind === 'badge' ? typeLabel : '',
|
badgeTypeLabel: kind === 'badge' ? typeLabel : '',
|
||||||
cover: String(cover || ''),
|
cover: String(cover || ''),
|
||||||
id: id as number | string,
|
id: id as number | string,
|
||||||
@ -358,6 +382,7 @@ function normalizeDisplayResource(
|
|||||||
name: String(name || (id ? `资源 ${id}` : '-')),
|
name: String(name || (id ? `资源 ${id}` : '-')),
|
||||||
raw: item,
|
raw: item,
|
||||||
secondaryType,
|
secondaryType,
|
||||||
|
type: secondaryType,
|
||||||
typeLabel,
|
typeLabel,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -387,12 +412,15 @@ function setQuickDays(value: number) {
|
|||||||
form.exchangeDays = String(value);
|
form.exchangeDays = String(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setQuickGiftQuantity(value: number) {
|
||||||
|
form.giftQuantity = value;
|
||||||
|
}
|
||||||
|
|
||||||
function selectType(option: TypeOption) {
|
function selectType(option: TypeOption) {
|
||||||
if (form.secondaryType === option.value) {
|
if (form.secondaryType === option.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
form.secondaryType = option.value;
|
form.secondaryType = option.value;
|
||||||
form.vipOrigin = option.value === 'NOBLE_VIP' ? form.vipOrigin : '';
|
|
||||||
resourceKeyword.value = '';
|
resourceKeyword.value = '';
|
||||||
resourcePage.value = 1;
|
resourcePage.value = 1;
|
||||||
sourceOptions.value = [];
|
sourceOptions.value = [];
|
||||||
@ -429,6 +457,14 @@ async function loadSources() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type.kind === 'gift') {
|
||||||
|
const rows = await listGiftBySysOrigin(form.sysOrigin);
|
||||||
|
sourceOptions.value = (rows || []).map((item) =>
|
||||||
|
normalizeDisplayResource(item, 'gift', 'GIFT', '礼物'),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const rows = await listNotFamilyBySysOriginType(form.sysOrigin, type.value);
|
const rows = await listNotFamilyBySysOriginType(form.sysOrigin, type.value);
|
||||||
sourceOptions.value = (rows || []).map((item) =>
|
sourceOptions.value = (rows || []).map((item) =>
|
||||||
normalizeDisplayResource(item, 'props', type.value, type.label),
|
normalizeDisplayResource(item, 'props', type.value, type.label),
|
||||||
@ -483,18 +519,37 @@ function validateBeforeSend() {
|
|||||||
message.warning('请选择资源');
|
message.warning('请选择资源');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (form.exchangeDays === '' || Number.isNaN(Number(form.exchangeDays))) {
|
if (
|
||||||
|
selectedHasNonGift.value &&
|
||||||
|
(form.exchangeDays === '' || Number.isNaN(Number(form.exchangeDays)))
|
||||||
|
) {
|
||||||
message.warning('请输入有效天数');
|
message.warning('请输入有效天数');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (needsVipOrigin.value && !form.vipOrigin) {
|
if (
|
||||||
message.warning('请选择贵族来源');
|
selectedHasGift.value &&
|
||||||
|
(!Number.isFinite(Number(form.giftQuantity)) || Number(form.giftQuantity) <= 0)
|
||||||
|
) {
|
||||||
|
message.warning('请输入礼物数量');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return accounts;
|
return accounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildSendPayload(resource: DisplayResource, accounts: string[]) {
|
function buildSendPayload(resource: DisplayResource, accounts: string[]) {
|
||||||
|
if (resource.kind === 'gift') {
|
||||||
|
const quantity = Number(form.giftQuantity);
|
||||||
|
return {
|
||||||
|
content: resource.id,
|
||||||
|
exchangeDays: quantity,
|
||||||
|
quantity,
|
||||||
|
receiverAccounts: accounts.join(','),
|
||||||
|
secondaryType: 'GIFT',
|
||||||
|
sysOrigin: form.sysOrigin,
|
||||||
|
type: 'GIFT',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const payload: Record<string, any> = {
|
const payload: Record<string, any> = {
|
||||||
content: resource.id,
|
content: resource.id,
|
||||||
exchangeDays: Number(form.exchangeDays),
|
exchangeDays: Number(form.exchangeDays),
|
||||||
@ -504,11 +559,6 @@ function buildSendPayload(resource: DisplayResource, accounts: string[]) {
|
|||||||
type: resource.kind === 'badge' ? 'BADGE' : 'PROPS',
|
type: resource.kind === 'badge' ? 'BADGE' : 'PROPS',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (resource.kind === 'props') {
|
|
||||||
payload.vipOrigin =
|
|
||||||
resource.secondaryType === 'NOBLE_VIP' ? form.vipOrigin : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,7 +592,7 @@ function resetCurrentForm() {
|
|||||||
form.receiverAccounts = '';
|
form.receiverAccounts = '';
|
||||||
form.secondaryType = '';
|
form.secondaryType = '';
|
||||||
form.exchangeDays = '';
|
form.exchangeDays = '';
|
||||||
form.vipOrigin = '';
|
form.giftQuantity = 1;
|
||||||
resourceKeyword.value = '';
|
resourceKeyword.value = '';
|
||||||
resourcePage.value = 1;
|
resourcePage.value = 1;
|
||||||
sourceOptions.value = [];
|
sourceOptions.value = [];
|
||||||
@ -551,7 +601,7 @@ function resetCurrentForm() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page title="道具赠送">
|
<Page title="资源赠送">
|
||||||
<div v-if="canUsePage" class="send-tool">
|
<div v-if="canUsePage" class="send-tool">
|
||||||
<div class="send-layout">
|
<div class="send-layout">
|
||||||
<section class="send-main">
|
<section class="send-main">
|
||||||
@ -687,7 +737,7 @@ function resetCurrentForm() {
|
|||||||
<aside class="send-summary">
|
<aside class="send-summary">
|
||||||
<div class="summary-title">
|
<div class="summary-title">
|
||||||
<IconifyIcon icon="lucide:package-check" />
|
<IconifyIcon icon="lucide:package-check" />
|
||||||
<span>赠送道具</span>
|
<span>赠送资源</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="selected-panel">
|
<div class="selected-panel">
|
||||||
@ -732,7 +782,7 @@ function resetCurrentForm() {
|
|||||||
<div v-else class="summary-empty">未选择资源</div>
|
<div v-else class="summary-empty">未选择资源</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="summary-control summary-control--days">
|
<div v-if="showExchangeDays" class="summary-control summary-control--days">
|
||||||
<div class="summary-control__row">
|
<div class="summary-control__row">
|
||||||
<label class="summary-control__label" for="props-send-days">
|
<label class="summary-control__label" for="props-send-days">
|
||||||
有效天数
|
有效天数
|
||||||
@ -760,15 +810,33 @@ function resetCurrentForm() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="needsVipOrigin" class="summary-control">
|
<div v-if="showGiftQuantity" class="summary-control summary-control--days">
|
||||||
<label class="summary-control__label">贵族来源</label>
|
<div class="summary-control__row">
|
||||||
<Select
|
<label class="summary-control__label" for="gift-send-quantity">
|
||||||
v-model:value="form.vipOrigin"
|
礼物数量
|
||||||
:options="vipOriginOptions"
|
</label>
|
||||||
class="summary-vip-origin"
|
<InputNumber
|
||||||
option-label-prop="label"
|
id="gift-send-quantity"
|
||||||
placeholder="请选择贵族来源"
|
v-model:value="form.giftQuantity"
|
||||||
/>
|
:controls="false"
|
||||||
|
:min="1"
|
||||||
|
:precision="0"
|
||||||
|
class="summary-days-input"
|
||||||
|
placeholder="请输入数量"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="quick-days summary-quick-days">
|
||||||
|
<button
|
||||||
|
v-for="quantity in QUICK_GIFT_QUANTITIES"
|
||||||
|
:key="quantity"
|
||||||
|
:class="{ 'quick-day--active': Number(form.giftQuantity) === quantity }"
|
||||||
|
class="quick-day"
|
||||||
|
type="button"
|
||||||
|
@click="setQuickGiftQuantity(quantity)"
|
||||||
|
>
|
||||||
|
{{ quantity }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<dl class="summary-list">
|
<dl class="summary-list">
|
||||||
@ -1256,8 +1324,7 @@ function resetCurrentForm() {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-days-input,
|
.summary-days-input {
|
||||||
.summary-vip-origin {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,12 +8,8 @@ export interface OptionItem {
|
|||||||
export const PROPS_TYPES: OptionItem[] = [
|
export const PROPS_TYPES: OptionItem[] = [
|
||||||
{ value: 'AVATAR_FRAME', name: '头像框' },
|
{ value: 'AVATAR_FRAME', name: '头像框' },
|
||||||
{ value: 'RIDE', name: '座驾' },
|
{ value: 'RIDE', name: '座驾' },
|
||||||
{ value: 'NOBLE_VIP', name: '贵族' },
|
|
||||||
{ value: 'THEME', name: '主题' },
|
|
||||||
{ value: 'LAYOUT', name: '装扮' },
|
|
||||||
{ value: 'CHAT_BUBBLE', name: '聊天气泡' },
|
{ value: 'CHAT_BUBBLE', name: '聊天气泡' },
|
||||||
{ value: 'FLOAT_PICTURE', name: '飘窗' },
|
{ value: 'FLOAT_PICTURE', name: '飘窗' },
|
||||||
{ value: 'FRAGMENTS', name: '碎片' },
|
|
||||||
{ value: 'DATA_CARD', name: '资料卡' },
|
{ value: 'DATA_CARD', name: '资料卡' },
|
||||||
{ value: 'SPECIAL_ID', name: '靓号' },
|
{ value: 'SPECIAL_ID', name: '靓号' },
|
||||||
{ value: 'CUSTOMIZE', name: '自定义(只读)' },
|
{ value: 'CUSTOMIZE', name: '自定义(只读)' },
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user