优化一键测试权重
This commit is contained in:
@@ -2,42 +2,131 @@
|
||||
<ElDialog
|
||||
v-model="visible"
|
||||
title="一键测试权重"
|
||||
width="520px"
|
||||
width="560px"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
@close="onClose"
|
||||
>
|
||||
<ElForm ref="formRef" :model="form" label-width="140px" :disabled="running">
|
||||
<ElFormItem label="测试数据档位类型" prop="lottery_config_id" required>
|
||||
<ElSelect
|
||||
v-model="form.lottery_config_id"
|
||||
placeholder="请选择奖池配置"
|
||||
filterable
|
||||
style="width: 100%"
|
||||
>
|
||||
<ElOption
|
||||
v-for="item in lotteryOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="顺时针方向次数" prop="s_count" required>
|
||||
<ElSelect v-model="form.s_count" placeholder="请选择" style="width: 100%">
|
||||
<ElOption v-for="c in countOptions" :key="c" :label="String(c)" :value="c" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="逆时针方向次数" prop="n_count" required>
|
||||
<ElSelect v-model="form.n_count" placeholder="请选择" style="width: 100%">
|
||||
<ElOption v-for="c in countOptions" :key="c" :label="String(c)" :value="c" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElForm ref="formRef" :model="form" label-width="140px">
|
||||
<ElSteps :active="currentStep" finish-status="success" simple class="steps-wrap">
|
||||
<ElStep title="付费抽奖券" />
|
||||
<ElStep title="免费抽奖券" />
|
||||
</ElSteps>
|
||||
|
||||
<!-- 第一页:付费抽奖券 -->
|
||||
<div v-show="currentStep === 0" class="step-panel">
|
||||
<ElFormItem label="测试数据档位类型" prop="paid_lottery_config_id">
|
||||
<ElSelect
|
||||
v-model="form.paid_lottery_config_id"
|
||||
placeholder="不选则下方自定义档位概率(默认 type=0)"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
>
|
||||
<ElOption
|
||||
v-for="item in paidLotteryOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<template v-if="form.paid_lottery_config_id == null || form.paid_lottery_config_id === ''">
|
||||
<div class="tier-label">自定义档位概率(T1~T5),每档 0-100%,五档之和不能超过 100%</div>
|
||||
<ElRow :gutter="12" class="tier-row">
|
||||
<ElCol v-for="t in tierKeys" :key="'paid-' + t" :span="8">
|
||||
<div class="tier-field">
|
||||
<label class="tier-field-label">档位 {{ t }}(%)</label>
|
||||
<input
|
||||
type="number"
|
||||
:value="getPaidTier(t)"
|
||||
min="0"
|
||||
max="100"
|
||||
placeholder="0"
|
||||
class="tier-input"
|
||||
@input="setPaidTier(t, $event)"
|
||||
/>
|
||||
</div>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
<div v-if="paidTierSum > 100" class="tier-error"
|
||||
>当前五档之和为 {{ paidTierSum }}%,不能超过 100%</div
|
||||
>
|
||||
</template>
|
||||
<ElFormItem label="顺时针次数" prop="paid_s_count" required>
|
||||
<ElSelect v-model="form.paid_s_count" placeholder="请选择" style="width: 100%">
|
||||
<ElOption v-for="c in countOptions" :key="c" :label="String(c)" :value="c" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="逆时针次数" prop="paid_n_count" required>
|
||||
<ElSelect v-model="form.paid_n_count" placeholder="请选择" style="width: 100%">
|
||||
<ElOption v-for="c in countOptions" :key="c" :label="String(c)" :value="c" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</div>
|
||||
|
||||
<!-- 第二页:免费抽奖券 -->
|
||||
<div v-show="currentStep === 1" class="step-panel">
|
||||
<ElFormItem label="测试数据档位类型" prop="free_lottery_config_id">
|
||||
<ElSelect
|
||||
v-model="form.free_lottery_config_id"
|
||||
placeholder="不选则下方自定义档位概率(默认 type=1)"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
>
|
||||
<ElOption
|
||||
v-for="item in freeLotteryOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<template v-if="form.free_lottery_config_id == null || form.free_lottery_config_id === ''">
|
||||
<div class="tier-label">自定义档位概率(T1~T5),每档 0-100%,五档之和不能超过 100%</div>
|
||||
<ElRow :gutter="12" class="tier-row">
|
||||
<ElCol v-for="t in tierKeys" :key="'free-' + t" :span="8">
|
||||
<div class="tier-field">
|
||||
<label class="tier-field-label">档位 {{ t }}(%)</label>
|
||||
<input
|
||||
type="number"
|
||||
:value="getFreeTier(t)"
|
||||
min="0"
|
||||
max="100"
|
||||
placeholder="0"
|
||||
class="tier-input"
|
||||
@input="setFreeTier(t, $event)"
|
||||
/>
|
||||
</div>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
<div v-if="freeTierSum > 100" class="tier-error"
|
||||
>当前五档之和为 {{ freeTierSum }}%,不能超过 100%</div
|
||||
>
|
||||
</template>
|
||||
<ElFormItem label="顺时针次数" prop="free_s_count" required>
|
||||
<ElSelect v-model="form.free_s_count" placeholder="请选择" style="width: 100%">
|
||||
<ElOption v-for="c in countOptions" :key="c" :label="String(c)" :value="c" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="逆时针次数" prop="free_n_count" required>
|
||||
<ElSelect v-model="form.free_n_count" placeholder="请选择" style="width: 100%">
|
||||
<ElOption v-for="c in countOptions" :key="c" :label="String(c)" :value="c" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</div>
|
||||
</ElForm>
|
||||
|
||||
<template #footer>
|
||||
<ElButton @click="visible = false">取消</ElButton>
|
||||
<ElButton type="primary" :loading="running" @click="handleStart">开始测试</ElButton>
|
||||
<ElButton v-if="currentStep > 0" :disabled="running" @click="currentStep--">上一步</ElButton>
|
||||
<ElButton v-if="currentStep < 1" type="primary" :disabled="running" @click="currentStep++"
|
||||
>下一步</ElButton
|
||||
>
|
||||
<ElButton v-if="currentStep === 1" type="primary" :loading="running" @click="handleStart"
|
||||
>开始测试</ElButton
|
||||
>
|
||||
<ElButton :disabled="running" @click="visible = false">取消</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</template>
|
||||
@@ -46,49 +135,166 @@
|
||||
import api from '../../../api/reward/index'
|
||||
import lotteryPoolApi from '../../../api/lottery_pool_config/index'
|
||||
|
||||
const countOptions = [100, 500, 1000, 5000]
|
||||
const countOptions = [0, 100, 500, 1000, 5000]
|
||||
const tierKeys = ['T1', 'T2', 'T3', 'T4', 'T5'] as const
|
||||
|
||||
const visible = defineModel<boolean>({ default: false })
|
||||
const emit = defineEmits<{ (e: 'success'): void }>()
|
||||
|
||||
const formRef = ref()
|
||||
const currentStep = ref(0)
|
||||
const form = reactive({
|
||||
lottery_config_id: undefined as number | undefined,
|
||||
s_count: 100,
|
||||
n_count: 100
|
||||
paid_lottery_config_id: undefined as number | undefined,
|
||||
free_lottery_config_id: undefined as number | undefined,
|
||||
paid_tier_weights: { T1: 20, T2: 20, T3: 20, T4: 20, T5: 20 } as Record<string, number>,
|
||||
free_tier_weights: { T1: 20, T2: 20, T3: 20, T4: 20, T5: 20 } as Record<string, number>,
|
||||
paid_s_count: 100,
|
||||
paid_n_count: 100,
|
||||
free_s_count: 100,
|
||||
free_n_count: 100
|
||||
})
|
||||
const lotteryOptions = ref<Array<{ id: number; name: string; type: number }>>([])
|
||||
/** 将 type 转为数字(接口可能返回字符串 "0"/"1") */
|
||||
function tierTypeNum(r: { type?: number | string }): number {
|
||||
const t = r.type ?? 0
|
||||
return typeof t === 'number' ? t : Number(t) || 0
|
||||
}
|
||||
/** 付费抽奖券可选档位:type=0 */
|
||||
const paidLotteryOptions = computed(() =>
|
||||
lotteryOptions.value.filter((r) => tierTypeNum(r) === 0)
|
||||
)
|
||||
/**
|
||||
* 免费抽奖券可选档位:优先 type=1(DiceLotteryPoolConfig.type=1),若无则显示全部以便下拉有选项
|
||||
*/
|
||||
const freeLotteryOptions = computed(() => {
|
||||
const type1List = lotteryOptions.value.filter((r) => tierTypeNum(r) === 1)
|
||||
return type1List.length > 0 ? type1List : lotteryOptions.value
|
||||
})
|
||||
const lotteryOptions = ref<Array<{ id: number; name: string }>>([])
|
||||
const running = ref(false)
|
||||
|
||||
function onClose() {
|
||||
running.value = false
|
||||
currentStep.value = 0
|
||||
}
|
||||
|
||||
function getPaidTier(t: string): string {
|
||||
const v = form.paid_tier_weights[t]
|
||||
return v !== undefined && v !== null ? String(v) : ''
|
||||
}
|
||||
function setPaidTier(t: string, val: string | Event) {
|
||||
const raw =
|
||||
typeof val === 'string'
|
||||
? val
|
||||
: ((val as Event & { target: HTMLInputElement }).target?.value ?? '')
|
||||
const num = raw === '' ? 0 : Math.max(0, Math.min(100, Number(raw) || 0))
|
||||
form.paid_tier_weights[t] = num
|
||||
}
|
||||
const paidTierSum = computed(() =>
|
||||
tierKeys.reduce((s, t) => s + (form.paid_tier_weights[t] ?? 0), 0)
|
||||
)
|
||||
function getFreeTier(t: string): string {
|
||||
const v = form.free_tier_weights[t]
|
||||
return v !== undefined && v !== null ? String(v) : ''
|
||||
}
|
||||
function setFreeTier(t: string, val: string | Event) {
|
||||
const raw =
|
||||
typeof val === 'string'
|
||||
? val
|
||||
: ((val as Event & { target: HTMLInputElement }).target?.value ?? '')
|
||||
const num = raw === '' ? 0 : Math.max(0, Math.min(100, Number(raw) || 0))
|
||||
form.free_tier_weights[t] = num
|
||||
}
|
||||
const freeTierSum = computed(() =>
|
||||
tierKeys.reduce((s, t) => s + (form.free_tier_weights[t] ?? 0), 0)
|
||||
)
|
||||
|
||||
async function loadLotteryOptions() {
|
||||
try {
|
||||
const list = await lotteryPoolApi.getOptions()
|
||||
lotteryOptions.value = list.map((r: { id: number; name: string }) => ({ id: r.id, name: r.name }))
|
||||
if (list.length && !form.lottery_config_id) {
|
||||
form.lottery_config_id = list[0].id
|
||||
lotteryOptions.value = list.map(
|
||||
(r: { id: number; name: string; type?: number | string }) => ({
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
type: tierTypeNum(r)
|
||||
})
|
||||
)
|
||||
// 付费抽奖券默认使用 type=0 的档位类型
|
||||
const type0 = list.find((r: { type?: number | string }) => tierTypeNum(r) === 0)
|
||||
if (type0) {
|
||||
form.paid_lottery_config_id = type0.id
|
||||
}
|
||||
// 免费抽奖券默认使用 type=1 的档位类型(DiceLotteryPoolConfig.type=1);若无 type=1 则默认选第一项
|
||||
const type1 = list.find((r: { type?: number | string }) => tierTypeNum(r) === 1)
|
||||
if (type1) {
|
||||
form.free_lottery_config_id = type1.id
|
||||
} else if (list.length > 0) {
|
||||
form.free_lottery_config_id = list[0].id
|
||||
}
|
||||
} catch (_) {
|
||||
lotteryOptions.value = []
|
||||
}
|
||||
}
|
||||
|
||||
async function handleStart() {
|
||||
if (!form.lottery_config_id) {
|
||||
ElMessage.warning('请选择测试数据档位类型')
|
||||
return
|
||||
function buildPayload() {
|
||||
const payload: Record<string, unknown> = {
|
||||
paid_s_count: form.paid_s_count,
|
||||
paid_n_count: form.paid_n_count,
|
||||
free_s_count: form.free_s_count,
|
||||
free_n_count: form.free_n_count
|
||||
}
|
||||
if (form.paid_lottery_config_id != null && form.paid_lottery_config_id !== '') {
|
||||
payload.paid_lottery_config_id = form.paid_lottery_config_id
|
||||
} else {
|
||||
payload.paid_tier_weights = { ...form.paid_tier_weights }
|
||||
}
|
||||
if (form.free_lottery_config_id != null && form.free_lottery_config_id !== '') {
|
||||
payload.free_lottery_config_id = form.free_lottery_config_id
|
||||
} else {
|
||||
payload.free_tier_weights = { ...form.free_tier_weights }
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
function validateForm(): boolean {
|
||||
if (form.paid_s_count + form.paid_n_count + form.free_s_count + form.free_n_count <= 0) {
|
||||
ElMessage.warning('付费或免费至少一种方向次数之和大于 0')
|
||||
return false
|
||||
}
|
||||
const needPaidTier = form.paid_lottery_config_id == null || form.paid_lottery_config_id === ''
|
||||
const needFreeTier = form.free_lottery_config_id == null || form.free_lottery_config_id === ''
|
||||
if (needPaidTier) {
|
||||
const sum = paidTierSum.value
|
||||
if (sum <= 0) {
|
||||
ElMessage.warning('付费未选奖池时,T1~T5 档位概率之和需大于 0')
|
||||
return false
|
||||
}
|
||||
if (sum > 100) {
|
||||
ElMessage.warning('付费档位概率 T1~T5 之和不能超过 100%')
|
||||
return false
|
||||
}
|
||||
}
|
||||
if (needFreeTier) {
|
||||
const sum = freeTierSum.value
|
||||
if (sum <= 0) {
|
||||
ElMessage.warning('免费未选奖池时,T1~T5 档位概率之和需大于 0')
|
||||
return false
|
||||
}
|
||||
if (sum > 100) {
|
||||
ElMessage.warning('免费档位概率 T1~T5 之和不能超过 100%')
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
async function handleStart() {
|
||||
if (!validateForm()) return
|
||||
running.value = true
|
||||
try {
|
||||
await api.startWeightTest({
|
||||
lottery_config_id: form.lottery_config_id,
|
||||
s_count: form.s_count,
|
||||
n_count: form.n_count
|
||||
})
|
||||
ElMessage.success('测试任务已创建,后台将自动执行。请在【玩家抽奖记录(测试数据)】中查看生成的测试数据')
|
||||
await api.startWeightTest(buildPayload())
|
||||
ElMessage.success(
|
||||
'测试任务已创建,后台将自动执行。请在【玩家抽奖记录(测试数据)】中查看生成的测试数据'
|
||||
)
|
||||
visible.value = false
|
||||
emit('success')
|
||||
} catch (e: any) {
|
||||
@@ -105,4 +311,71 @@
|
||||
onClose()
|
||||
}
|
||||
})
|
||||
|
||||
// 切换到免费步骤时,若当前选中 id 不在免费档位列表中,则重置为第一个 type=1 的选项,避免显示错误
|
||||
watch(currentStep, (step) => {
|
||||
if (step === 1) {
|
||||
const freeOpts = freeLotteryOptions.value
|
||||
const id = form.free_lottery_config_id
|
||||
if (freeOpts.length && (id == null || !freeOpts.some((o) => o.id === id))) {
|
||||
form.free_lottery_config_id = freeOpts[0].id
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.steps-wrap {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.step-panel {
|
||||
min-height: 200px;
|
||||
}
|
||||
.tier-label {
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.tier-row {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.tier-field {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.tier-field-label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-regular);
|
||||
margin-bottom: 4px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.tier-input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: var(--el-text-color-regular);
|
||||
background-color: var(--el-fill-color-blank);
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: var(--el-border-radius-base);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.tier-input:hover {
|
||||
border-color: var(--el-border-color-hover);
|
||||
}
|
||||
.tier-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--el-color-primary);
|
||||
box-shadow: 0 0 0 2px var(--el-color-primary-light-7);
|
||||
}
|
||||
.tier-input::placeholder {
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
.tier-error {
|
||||
font-size: 12px;
|
||||
color: var(--el-color-danger);
|
||||
margin-top: 4px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user