Files
dafuweng-saiadmin6.x/saiadmin-artd/src/views/plugin/dice/reward/index/modules/weight-test-dialog.vue

406 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<ElDialog
v-model="visible"
:title="$t('page.weightTest.title')"
width="560px"
:close-on-click-modal="false"
destroy-on-close
@close="onClose"
>
<ElAlert type="info" :closable="false" show-icon class="weight-test-tip">
<template #title>{{ $t('page.weightTest.alertTitle') }}</template>
{{ $t('page.weightTest.alertBody') }}
</ElAlert>
<ElAlert type="warning" :closable="false" show-icon class="weight-test-tip chain-tip">
{{ $t('page.weightTest.chainModeHint') }}
</ElAlert>
<ElAlert type="info" :closable="false" show-icon class="weight-test-tip chain-tip">
{{ $t('page.weightTest.killModeHint') }}
</ElAlert>
<ElForm :model="form" label-width="140px">
<ElFormItem :label="$t('page.weightTest.labelAnte')" prop="ante" required>
<ElInputNumber v-model="form.ante" :min="1" :step="1" style="width: 100%" />
</ElFormItem>
<ElFormItem :label="$t('page.weightTest.labelKillModeEnabled')" prop="kill_mode_enabled">
<ElSwitch v-model="form.kill_mode_enabled" />
</ElFormItem>
<ElFormItem :label="$t('page.weightTest.labelTestSafetyLine')" prop="test_safety_line">
<ElInputNumber
v-model="form.test_safety_line"
:min="0"
:step="100"
:disabled="!form.kill_mode_enabled"
style="width: 100%"
/>
</ElFormItem>
<div class="section-title">{{ $t('page.weightTest.sectionPaid') }}</div>
<ElFormItem
:label="$t('page.weightTest.labelLotteryTypePaid')"
prop="paid_lottery_config_id"
>
<ElSelect
v-model="form.paid_lottery_config_id"
:placeholder="$t('page.weightTest.placeholderPaidPool')"
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">
<div class="tier-label">{{ $t('page.weightTest.tierProbHint') }}</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('page.weightTest.tierFieldLabel', { tier: 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">{{
$t('page.weightTest.tierSumError', { sum: paidTierSum })
}}</div>
</template>
<ElFormItem :label="$t('page.weightTest.labelCwCount')" prop="paid_s_count" required>
<ElSelect
v-model="form.paid_s_count"
:placeholder="$t('page.weightTest.placeholderSelect')"
style="width: 100%"
>
<ElOption v-for="c in countOptions" :key="c" :label="String(c)" :value="c" />
</ElSelect>
</ElFormItem>
<ElFormItem :label="$t('page.weightTest.labelCcwCount')" prop="paid_n_count" required>
<ElSelect
v-model="form.paid_n_count"
:placeholder="$t('page.weightTest.placeholderSelect')"
style="width: 100%"
>
<ElOption v-for="c in countOptions" :key="c" :label="String(c)" :value="c" />
</ElSelect>
</ElFormItem>
<div class="section-title">{{ $t('page.weightTest.sectionFreeAfterPlayAgain') }}</div>
<ElFormItem
:label="$t('page.weightTest.labelLotteryTypeFree')"
prop="free_lottery_config_id"
>
<ElSelect
v-model="form.free_lottery_config_id"
:placeholder="$t('page.weightTest.placeholderFreePool')"
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">
<div class="tier-label">{{ $t('page.weightTest.tierProbHintFreeChain') }}</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('page.weightTest.tierFieldLabel', { tier: 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">{{
$t('page.weightTest.tierSumError', { sum: freeTierSum })
}}</div>
</template>
</ElForm>
<template #footer>
<ElButton
v-permission="'dice:reward:index:startWeightTest'"
type="primary"
:loading="running"
@click="handleStart"
>{{ $t('page.weightTest.btnStart') }}</ElButton
>
<ElButton :disabled="running" @click="visible = false">{{
$t('page.weightTest.btnCancel')
}}</ElButton>
</template>
</ElDialog>
</template>
<script setup lang="ts">
import api from '../../../api/reward/index'
import lotteryPoolApi from '../../../api/lottery_pool_config/index'
import { ElMessage } from 'element-plus'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
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 form = reactive({
ante: 1,
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,
kill_mode_enabled: false,
test_safety_line: 5000
})
const lotteryOptions = ref<Array<{ id: number; name: string }>>([])
/** 付费抽奖券可选档位name=default */
const paidLotteryOptions = computed(() =>
lotteryOptions.value.filter((r) => r.name === 'default')
)
/** 免费抽奖券可选档位:优先 name=killScore若无则显示全部以便下拉有选项 */
const freeLotteryOptions = computed(() => {
const list = lotteryOptions.value.filter((r) => r.name === 'killScore')
return list.length > 0 ? list : lotteryOptions.value
})
const running = ref(false)
function onClose() {
running.value = false
}
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
}))
const normal = list.find((r: { name?: string }) => r.name === 'default')
if (normal) {
form.paid_lottery_config_id = normal.id
}
const kill = list.find((r: { name?: string }) => r.name === 'killScore')
if (kill) {
form.free_lottery_config_id = kill.id
} else if (list.length > 0) {
form.free_lottery_config_id = list[0].id
}
} catch {
lotteryOptions.value = []
}
}
function buildPayload() {
const payload: Record<string, unknown> = {
ante: form.ante,
paid_s_count: form.paid_s_count,
paid_n_count: form.paid_n_count,
free_s_count: 0,
free_n_count: 0,
chain_free_mode: true,
kill_mode_enabled: form.kill_mode_enabled,
test_safety_line: form.test_safety_line
}
if (form.paid_lottery_config_id != null) {
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) {
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.ante == null || form.ante <= 0) {
ElMessage.warning(t('page.weightTest.warnAnte'))
return false
}
if (form.paid_s_count + form.paid_n_count <= 0) {
ElMessage.warning(t('page.weightTest.warnPaidSpins'))
return false
}
if (form.kill_mode_enabled && (form.test_safety_line == null || form.test_safety_line < 0)) {
ElMessage.warning(t('page.weightTest.warnTestSafetyLine'))
return false
}
const needPaidTier = form.paid_lottery_config_id == null
const needFreeTier = form.free_lottery_config_id == null
if (needPaidTier) {
const sum = paidTierSum.value
if (sum <= 0) {
ElMessage.warning(t('page.weightTest.warnPaidTierSumPositive'))
return false
}
if (sum > 100) {
ElMessage.warning(t('page.weightTest.warnPaidTierSumMax'))
return false
}
}
if (needFreeTier) {
const sum = freeTierSum.value
if (sum <= 0) {
ElMessage.warning(t('page.weightTest.warnFreeTierSumPositive'))
return false
}
if (sum > 100) {
ElMessage.warning(t('page.weightTest.warnFreeTierSumMax'))
return false
}
}
return true
}
async function handleStart() {
if (!validateForm()) return
running.value = true
try {
await api.startWeightTest(buildPayload())
ElMessage.success(t('page.weightTest.successCreated'))
visible.value = false
emit('success')
} catch (e: any) {
ElMessage.error(e?.message || t('page.weightTest.failCreate'))
} finally {
running.value = false
}
}
watch(visible, (v) => {
if (v) {
loadLotteryOptions()
} else {
onClose()
}
})
</script>
<style lang="scss" scoped>
.weight-test-tip {
margin-bottom: 16px;
}
.chain-tip {
margin-top: -8px;
}
.section-title {
font-size: 14px;
font-weight: 600;
color: var(--el-text-color-primary);
margin: 8px 0 12px;
padding-bottom: 6px;
border-bottom: 1px solid var(--el-border-color-lighter);
}
.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>