上传限制
This commit is contained in:
parent
9d3880a8aa
commit
3a96357b2a
@ -125,6 +125,12 @@ export async function pageResidentWheelDrawRecords(params: Record<string, any>)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function retryResidentWheelDrawRecord(id: number | string) {
|
||||||
|
return requestClient.post<Record<string, any>>(`${WHEEL_BASE}/record/retry`, {
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export async function getResidentSmashGoldenEggConfig(sysOrigin: string) {
|
export async function getResidentSmashGoldenEggConfig(sysOrigin: string) {
|
||||||
return requestClient.get<Record<string, any>>(`${SMASH_GOLDEN_EGG_BASE}/config`, {
|
return requestClient.get<Record<string, any>>(`${SMASH_GOLDEN_EGG_BASE}/config`, {
|
||||||
params: { sysOrigin },
|
params: { sysOrigin },
|
||||||
|
|||||||
@ -90,7 +90,7 @@ 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 uploadQueue: UploadTask[] = [];
|
||||||
const MAX_UPLOAD_CONCURRENCY = 2;
|
const MAX_UPLOAD_CONCURRENCY = 1;
|
||||||
let activeUploadCount = 0;
|
let activeUploadCount = 0;
|
||||||
|
|
||||||
const giftTabOptions = GIFT_CONFIG_TAB_OPTIONS.map((item) => ({
|
const giftTabOptions = GIFT_CONFIG_TAB_OPTIONS.map((item) => ({
|
||||||
|
|||||||
@ -117,7 +117,7 @@ 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 uploadQueue: UploadTask[] = [];
|
||||||
const MAX_UPLOAD_CONCURRENCY = 2;
|
const MAX_UPLOAD_CONCURRENCY = 1;
|
||||||
let activeUploadCount = 0;
|
let activeUploadCount = 0;
|
||||||
|
|
||||||
const propsTypeOptions = PROPS_RESOURCE_CONFIG_TYPES.map((item) => ({
|
const propsTypeOptions = PROPS_RESOURCE_CONFIG_TYPES.map((item) => ({
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
getResidentWheelConfig,
|
getResidentWheelConfig,
|
||||||
pageResidentWheelDrawRecords,
|
pageResidentWheelDrawRecords,
|
||||||
|
retryResidentWheelDrawRecord,
|
||||||
saveResidentWheelCategoryConfig,
|
saveResidentWheelCategoryConfig,
|
||||||
} from '#/api/legacy/resident-activity';
|
} from '#/api/legacy/resident-activity';
|
||||||
import PropsSourceSelectDrawer from '#/views/operate/components/props-source-select-drawer.vue';
|
import PropsSourceSelectDrawer from '#/views/operate/components/props-source-select-drawer.vue';
|
||||||
@ -30,7 +31,7 @@ import { getAllowedSysOrigins } from '#/views/system/shared';
|
|||||||
|
|
||||||
defineOptions({ name: 'ResidentWheelConfigPage' });
|
defineOptions({ name: 'ResidentWheelConfigPage' });
|
||||||
|
|
||||||
const PROBABILITY_TOTAL = 10_000;
|
const PROBABILITY_TOTAL = 1_000_000;
|
||||||
const WHEEL_CATEGORIES = [
|
const WHEEL_CATEGORIES = [
|
||||||
{
|
{
|
||||||
category: 'CLASSIC',
|
category: 'CLASSIC',
|
||||||
@ -95,6 +96,7 @@ function createReward(type = 'RESOURCE', sort = 1) {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
goldAmount: type === 'GOLD' ? 100 : 0,
|
goldAmount: type === 'GOLD' ? 100 : 0,
|
||||||
id: 0,
|
id: 0,
|
||||||
|
issuedCount: 0,
|
||||||
probability: 0,
|
probability: 0,
|
||||||
rewardType: type,
|
rewardType: type,
|
||||||
resourceId: null as null | number | string,
|
resourceId: null as null | number | string,
|
||||||
@ -103,6 +105,8 @@ function createReward(type = 'RESOURCE', sort = 1) {
|
|||||||
resourceUrl: '',
|
resourceUrl: '',
|
||||||
rowKey: createRowKey(sort),
|
rowKey: createRowKey(sort),
|
||||||
sort,
|
sort,
|
||||||
|
totalLimit: 0,
|
||||||
|
userLimit: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +150,7 @@ const loading = ref(false);
|
|||||||
const savingCategory = ref('');
|
const savingCategory = ref('');
|
||||||
const recordLoading = ref(false);
|
const recordLoading = ref(false);
|
||||||
const resourcePickerOpen = ref(false);
|
const resourcePickerOpen = ref(false);
|
||||||
|
const retryingRecordId = ref<null | number | string>(null);
|
||||||
const pickerCategory = ref('CLASSIC');
|
const pickerCategory = ref('CLASSIC');
|
||||||
const pickerRewardIndex = ref(-1);
|
const pickerRewardIndex = ref(-1);
|
||||||
const pickerRewardRecord = ref<null | Record<string, any>>(null);
|
const pickerRewardRecord = ref<null | Record<string, any>>(null);
|
||||||
@ -169,8 +174,9 @@ const rewardColumns = [
|
|||||||
{ dataIndex: 'enabled', key: 'enabled', title: '启用', width: 80 },
|
{ dataIndex: 'enabled', key: 'enabled', title: '启用', width: 80 },
|
||||||
{ dataIndex: 'sort', key: 'sort', title: '位置', width: 90 },
|
{ dataIndex: 'sort', key: 'sort', title: '位置', width: 90 },
|
||||||
{ dataIndex: 'rewardType', key: 'rewardType', title: '类型', width: 130 },
|
{ dataIndex: 'rewardType', key: 'rewardType', title: '类型', width: 130 },
|
||||||
{ dataIndex: 'reward', key: 'reward', title: '奖励', width: 620 },
|
{ dataIndex: 'reward', key: 'reward', title: '奖励', width: 560 },
|
||||||
{ dataIndex: 'probability', key: 'probability', title: '概率', width: 180 },
|
{ dataIndex: 'probability', key: 'probability', title: '概率', width: 180 },
|
||||||
|
{ dataIndex: 'limit', key: 'limit', title: '止损线', width: 280 },
|
||||||
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 90 },
|
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 90 },
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -185,6 +191,7 @@ const recordColumns = [
|
|||||||
{ dataIndex: 'status', key: 'status', title: '状态', width: 110 },
|
{ dataIndex: 'status', key: 'status', title: '状态', width: 110 },
|
||||||
{ dataIndex: 'createTime', key: 'createTime', title: '时间', width: 180 },
|
{ dataIndex: 'createTime', key: 'createTime', title: '时间', width: 180 },
|
||||||
{ dataIndex: 'errorMessage', key: 'errorMessage', title: '失败原因', width: 260 },
|
{ dataIndex: 'errorMessage', key: 'errorMessage', title: '失败原因', width: 260 },
|
||||||
|
{ dataIndex: 'actions', key: 'actions', title: '操作', width: 110 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const statusMeta = computed(() => {
|
const statusMeta = computed(() => {
|
||||||
@ -222,6 +229,10 @@ function categoryProbabilityColor(category: Record<string, any>) {
|
|||||||
return categoryProbability(category) === PROBABILITY_TOTAL ? 'success' : 'error';
|
return categoryProbability(category) === PROBABILITY_TOTAL ? 'success' : 'error';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function probabilityPercent(value: any) {
|
||||||
|
return ((Number(value || 0) * 100) / PROBABILITY_TOTAL).toFixed(4);
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeReward(item: Record<string, any> | undefined, index: number) {
|
function normalizeReward(item: Record<string, any> | undefined, index: number) {
|
||||||
const value = item || {};
|
const value = item || {};
|
||||||
const rewardType = normalizeRewardTypeValue(value.rewardType);
|
const rewardType = normalizeRewardTypeValue(value.rewardType);
|
||||||
@ -243,6 +254,7 @@ function normalizeReward(item: Record<string, any> | undefined, index: number) {
|
|||||||
enabled: value.enabled !== false,
|
enabled: value.enabled !== false,
|
||||||
goldAmount: Number(value.goldAmount || 0),
|
goldAmount: Number(value.goldAmount || 0),
|
||||||
id: Number(value.id || 0),
|
id: Number(value.id || 0),
|
||||||
|
issuedCount: Number(value.issuedCount || 0),
|
||||||
probability: Number(value.probability || 0),
|
probability: Number(value.probability || 0),
|
||||||
rewardType,
|
rewardType,
|
||||||
resourceId: resourceId || null,
|
resourceId: resourceId || null,
|
||||||
@ -251,6 +263,8 @@ function normalizeReward(item: Record<string, any> | undefined, index: number) {
|
|||||||
resourceUrl: String(value.resourceUrl || ''),
|
resourceUrl: String(value.resourceUrl || ''),
|
||||||
rowKey: createRowKey(value.id || index + 1),
|
rowKey: createRowKey(value.id || index + 1),
|
||||||
sort: Number(value.sort || index + 1),
|
sort: Number(value.sort || index + 1),
|
||||||
|
totalLimit: Number(value.totalLimit || 0),
|
||||||
|
userLimit: Number(value.userLimit || 0),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,6 +600,14 @@ function validateReward(category: Record<string, any>, item: Record<string, any>
|
|||||||
message.warning(`${label} 概率不能小于 0`);
|
message.warning(`${label} 概率不能小于 0`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (Number(item.totalLimit || 0) < 0) {
|
||||||
|
message.warning(`${label} 总量上限不能小于 0`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Number(item.userLimit || 0) < 0) {
|
||||||
|
message.warning(`${label} 单用户上限不能小于 0`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
category.enabled !== false &&
|
category.enabled !== false &&
|
||||||
item.enabled !== false &&
|
item.enabled !== false &&
|
||||||
@ -669,6 +691,8 @@ function categoryPayload(category: Record<string, any>) {
|
|||||||
resourceType: rewardType === 'RESOURCE' ? String(item.resourceType || '') : '',
|
resourceType: rewardType === 'RESOURCE' ? String(item.resourceType || '') : '',
|
||||||
resourceUrl: rewardType === 'RESOURCE' ? String(item.resourceUrl || '') : '',
|
resourceUrl: rewardType === 'RESOURCE' ? String(item.resourceUrl || '') : '',
|
||||||
sort: Number(item.sort || 0),
|
sort: Number(item.sort || 0),
|
||||||
|
totalLimit: Number(item.totalLimit || 0),
|
||||||
|
userLimit: Number(item.userLimit || 0),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
@ -715,6 +739,21 @@ function handleRecordTableChange(pagination: Record<string, any>) {
|
|||||||
void loadRecords();
|
void loadRecords();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function retryRecord(record: Record<string, any>) {
|
||||||
|
const id = record?.id;
|
||||||
|
if (!id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
retryingRecordId.value = id;
|
||||||
|
try {
|
||||||
|
await retryResidentWheelDrawRecord(id);
|
||||||
|
message.success('补发成功');
|
||||||
|
await loadRecords();
|
||||||
|
} finally {
|
||||||
|
retryingRecordId.value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function rewardRecordName(record: Record<string, any>) {
|
function rewardRecordName(record: Record<string, any>) {
|
||||||
if (record.resourceName) {
|
if (record.resourceName) {
|
||||||
return record.resourceName;
|
return record.resourceName;
|
||||||
@ -740,6 +779,9 @@ function statusColor(status: string) {
|
|||||||
case 'FAILED': {
|
case 'FAILED': {
|
||||||
return 'error';
|
return 'error';
|
||||||
}
|
}
|
||||||
|
case 'PAY_FAILED': {
|
||||||
|
return 'warning';
|
||||||
|
}
|
||||||
case 'SUCCESS': {
|
case 'SUCCESS': {
|
||||||
return 'success';
|
return 'success';
|
||||||
}
|
}
|
||||||
@ -875,7 +917,7 @@ watch(activePageTab, (value) => {
|
|||||||
:loading="loading"
|
:loading="loading"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
row-key="rowKey"
|
row-key="rowKey"
|
||||||
:scroll="{ x: 1180 }"
|
:scroll="{ x: 1460 }"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, index, record }">
|
<template #bodyCell="{ column, index, record }">
|
||||||
<template v-if="column.key === 'enabled'">
|
<template v-if="column.key === 'enabled'">
|
||||||
@ -980,12 +1022,35 @@ watch(activePageTab, (value) => {
|
|||||||
style="width: 120px"
|
style="width: 120px"
|
||||||
/>
|
/>
|
||||||
<span class="sub-text">
|
<span class="sub-text">
|
||||||
{{
|
{{ probabilityPercent(record.probability) }}%
|
||||||
(Number(record.probability || 0) / 100).toFixed(2)
|
|
||||||
}}%
|
|
||||||
</span>
|
</span>
|
||||||
</Space>
|
</Space>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="column.key === 'limit'">
|
||||||
|
<Space direction="vertical" size="small">
|
||||||
|
<Space align="center">
|
||||||
|
<span class="sub-text">总量</span>
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="record.totalLimit"
|
||||||
|
:min="0"
|
||||||
|
:precision="0"
|
||||||
|
placeholder="不限"
|
||||||
|
style="width: 110px"
|
||||||
|
/>
|
||||||
|
<span class="sub-text">已占 {{ Number(record.issuedCount || 0) }}</span>
|
||||||
|
</Space>
|
||||||
|
<Space align="center">
|
||||||
|
<span class="sub-text">单用户</span>
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="record.userLimit"
|
||||||
|
:min="0"
|
||||||
|
:precision="0"
|
||||||
|
placeholder="不限"
|
||||||
|
style="width: 110px"
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
</Space>
|
||||||
|
</template>
|
||||||
<template v-else-if="column.key === 'actions'">
|
<template v-else-if="column.key === 'actions'">
|
||||||
<Button danger type="link" @click="clearResource(record)">
|
<Button danger type="link" @click="clearResource(record)">
|
||||||
清空
|
清空
|
||||||
@ -1018,7 +1083,9 @@ watch(activePageTab, (value) => {
|
|||||||
allow-clear
|
allow-clear
|
||||||
:options="[
|
:options="[
|
||||||
{ label: '成功', value: 'SUCCESS' },
|
{ label: '成功', value: 'SUCCESS' },
|
||||||
{ label: '失败', value: 'FAILED' },
|
{ label: '发奖失败', value: 'FAILED' },
|
||||||
|
{ label: '扣款失败', value: 'PAY_FAILED' },
|
||||||
|
{ label: '发奖中', value: 'GRANTING' },
|
||||||
{ label: '处理中', value: 'PENDING' },
|
{ label: '处理中', value: 'PENDING' },
|
||||||
]"
|
]"
|
||||||
placeholder="状态"
|
placeholder="状态"
|
||||||
@ -1041,7 +1108,7 @@ watch(activePageTab, (value) => {
|
|||||||
total: recordPage.total,
|
total: recordPage.total,
|
||||||
}"
|
}"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
:scroll="{ x: 1680 }"
|
:scroll="{ x: 1790 }"
|
||||||
@change="handleRecordTableChange"
|
@change="handleRecordTableChange"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
@ -1065,7 +1132,7 @@ watch(activePageTab, (value) => {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'probability'">
|
<template v-else-if="column.key === 'probability'">
|
||||||
{{ (Number(record.probability || 0) / 100).toFixed(2) }}%
|
{{ probabilityPercent(record.probability) }}%
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'status'">
|
<template v-else-if="column.key === 'status'">
|
||||||
<Tag :color="statusColor(record.status)">{{ record.status || '-' }}</Tag>
|
<Tag :color="statusColor(record.status)">{{ record.status || '-' }}</Tag>
|
||||||
@ -1073,7 +1140,19 @@ watch(activePageTab, (value) => {
|
|||||||
<template v-else-if="column.key === 'errorMessage'">
|
<template v-else-if="column.key === 'errorMessage'">
|
||||||
{{ record.errorMessage || '-' }}
|
{{ record.errorMessage || '-' }}
|
||||||
</template>
|
</template>
|
||||||
</template>
|
<template v-else-if="column.key === 'actions'">
|
||||||
|
<Button
|
||||||
|
v-if="String(record.status || '').toUpperCase() === 'FAILED'"
|
||||||
|
:loading="retryingRecordId === record.id"
|
||||||
|
size="small"
|
||||||
|
type="link"
|
||||||
|
@click="retryRecord(record)"
|
||||||
|
>
|
||||||
|
补发
|
||||||
|
</Button>
|
||||||
|
<span v-else class="sub-text">-</span>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
</Table>
|
</Table>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user