优化玩家DicePlayer权重输入方式

This commit is contained in:
2026-03-07 11:51:34 +08:00
parent 4b6bbab9d1
commit 282d73a203
6 changed files with 241 additions and 35 deletions

View File

@@ -44,39 +44,98 @@
style="width: 100%"
/>
</el-form-item>
<!-- lottery_config_id = 自定义权重否则 = DiceLotteryConfig.id选择后该配置的五个 weight 会写入下方 player.*_weight -->
<el-form-item label="彩金池配置" prop="lottery_config_id">
<el-select
v-model="formData.lottery_config_id"
placeholder="不选则使用下方自定义权重"
placeholder="留空则使用下方自定义权重,或选择彩金池"
clearable
filterable
style="width: 100%"
:loading="lotteryConfigLoading"
@change="onLotteryConfigChange"
>
<el-option label="自定义权重" :value="0" />
<el-option
v-for="item in lotteryConfigOptions"
:key="item.id"
:label="item.name"
:label="(item.name && String(item.name).trim()) || `#${item.id}`"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item v-if="!formData.lottery_config_id" label="T1池权重(%)" prop="t1_weight">
<el-slider v-model="formData.t1_weight" :min="0" :max="100" :step="0.01" show-input />
<!-- 当前选中的 DiceLotteryConfig 数据展示 -->
<el-form-item v-if="currentLotteryConfig" label="当前配置" class="current-config-block">
<div class="current-lottery-config">
<div class="config-row">
<span class="config-label">名称</span>
<span>{{ currentLotteryConfig.name ?? '-' }}</span>
</div>
<div class="config-row">
<span class="config-label">类型</span>
<span>{{ lotteryConfigTypeText(currentLotteryConfig.type) }}</span>
</div>
<div class="config-row">
<span class="config-label">T1T5 权重</span>
<span>{{ currentLotteryConfigWeightsText }}</span>
</div>
<div v-if="currentLotteryConfig.remark" class="config-row">
<span class="config-label">备注</span>
<span>{{ currentLotteryConfig.remark }}</span>
</div>
</div>
</el-form-item>
<el-form-item v-if="!formData.lottery_config_id" label="T2池权重(%)" prop="t2_weight">
<el-slider v-model="formData.t2_weight" :min="0" :max="100" :step="0.01" show-input />
<!-- lottery_config_id 为空时自定义权重可编辑有值时来自所选 DiceLotteryConfig仅展示不可编辑 -->
<el-form-item label="T1池权重(%)" prop="t1_weight">
<el-slider
v-model="formData.t1_weight"
:min="0"
:max="100"
:step="0.01"
show-input
:disabled="!isLotteryConfigEmpty()"
/>
</el-form-item>
<el-form-item v-if="!formData.lottery_config_id" label="T3池权重(%)" prop="t3_weight">
<el-slider v-model="formData.t3_weight" :min="0" :max="100" :step="0.01" show-input />
<el-form-item label="T2池权重(%)" prop="t2_weight">
<el-slider
v-model="formData.t2_weight"
:min="0"
:max="100"
:step="0.01"
show-input
:disabled="!isLotteryConfigEmpty()"
/>
</el-form-item>
<el-form-item v-if="!formData.lottery_config_id" label="T4池权重(%)" prop="t4_weight">
<el-slider v-model="formData.t4_weight" :min="0" :max="100" :step="0.01" show-input />
<el-form-item label="T3池权重(%)" prop="t3_weight">
<el-slider
v-model="formData.t3_weight"
:min="0"
:max="100"
:step="0.01"
show-input
:disabled="!isLotteryConfigEmpty()"
/>
</el-form-item>
<el-form-item v-if="!formData.lottery_config_id" label="T5池权重(%)" prop="t5_weight">
<el-slider v-model="formData.t5_weight" :min="0" :max="100" :step="0.01" show-input />
<el-form-item label="T4池权重(%)" prop="t4_weight">
<el-slider
v-model="formData.t4_weight"
:min="0"
:max="100"
:step="0.01"
show-input
:disabled="!isLotteryConfigEmpty()"
/>
</el-form-item>
<el-form-item v-if="!formData.lottery_config_id">
<el-form-item label="T5池权重(%)" prop="t5_weight">
<el-slider
v-model="formData.t5_weight"
:min="0"
:max="100"
:step="0.01"
show-input
:disabled="!isLotteryConfigEmpty()"
/>
</el-form-item>
<el-form-item v-if="isLotteryConfigEmpty()">
<div class="text-gray-500 text-sm">
五个池权重总和<span :class="Math.abs(weightsSum - 100) > 0.01 ? 'text-red-500' : ''">{{
weightsSum
@@ -130,6 +189,18 @@
return WEIGHT_FIELDS.reduce((sum, key) => sum + Number(formData[key] ?? 0), 0)
})
/** 当前彩金池配置的 T1T5 权重展示文案 */
const currentLotteryConfigWeightsText = computed(() => {
const c = currentLotteryConfig.value
if (!c) return '-'
const t1 = c.t1_weight ?? 0
const t2 = c.t2_weight ?? 0
const t3 = c.t3_weight ?? 0
const t4 = c.t4_weight ?? 0
const t5 = c.t5_weight ?? 0
return `${t1}% / ${t2}% / ${t3}% / ${t4}% / ${t5}%`
})
/** 新增时密码必填,编辑时选填 */
const passwordRules = computed(() =>
props.dialogType === 'add' ? [{ required: true, message: '密码必需填写', trigger: 'blur' }] : []
@@ -151,6 +222,7 @@
password: '',
status: 1 as number,
coin: 0 as number,
/** 彩金池配置 ID空 = 自定义权重,否则 = DiceLotteryConfig.id */
lottery_config_id: null as number | null,
t1_weight: 0 as number,
t2_weight: 0 as number,
@@ -161,8 +233,48 @@
const formData = reactive({ ...initialFormData })
/** 彩金池配置下拉选项 */
/** 彩金池配置下拉选项DiceLotteryConfig id、name */
const lotteryConfigOptions = ref<Array<{ id: number; name: string }>>([])
/** 彩金池选项加载中 */
const lotteryConfigLoading = ref(false)
/** 当前选中的 DiceLotteryConfig 完整数据(用于展示) */
const currentLotteryConfig = ref<Record<string, any> | null>(null)
function lotteryConfigTypeText(type: unknown): string {
const t = Number(type)
if (t === 0) return '付费'
if (t === 1) return '赠送'
return t ? `类型${t}` : '-'
}
/** 是否为空/自定义权重(未选彩金池或选 0 */
function isLotteryConfigEmpty(): boolean {
const v = formData.lottery_config_id
return v == null || v === 0
}
/** 根据当前 lottery_config_id 加载 DiceLotteryConfig并将五个权重写入当前 player.*_weight */
async function loadCurrentLotteryConfig() {
const id = formData.lottery_config_id
if (id == null || id === 0) {
currentLotteryConfig.value = null
return
}
try {
const res = await lotteryConfigApi.read(id)
const row = (res as any)?.data ?? (res as any)
if (row && typeof row === 'object') {
currentLotteryConfig.value = row
WEIGHT_FIELDS.forEach((key) => {
;(formData as any)[key] = Number(row[key] ?? 0)
})
} else {
currentLotteryConfig.value = null
}
} catch {
currentLotteryConfig.value = null
}
}
watch(
() => props.modelValue,
@@ -171,37 +283,51 @@
}
)
/** 选择彩金池配置时,拉取该配置的权重填入表单(仅展示/备份lottery_config_id 非空时后端以配置为准) */
async function onLotteryConfigChange(lotteryConfigId: number | null) {
if (!lotteryConfigId) return
/** 选择彩金池,拉取该配置的五个权重并写入当前 player.*_weight并更新当前配置展示 */
async function onLotteryConfigChange(lotteryConfigId: number | null | undefined) {
if (lotteryConfigId == null || lotteryConfigId === 0) {
currentLotteryConfig.value = null
return
}
try {
const res = await lotteryConfigApi.read(lotteryConfigId)
const row = (res as any)?.data
if (row) {
const row = (res as any)?.data ?? (res as any)
if (row && typeof row === 'object') {
WEIGHT_FIELDS.forEach((key) => {
;(formData as any)[key] = Number(row[key] ?? 0)
})
currentLotteryConfig.value = row
} else {
currentLotteryConfig.value = null
}
} catch (err) {
console.warn('拉取彩金池配置权重失败', err)
console.warn('拉取彩金池配置失败', err)
currentLotteryConfig.value = null
}
}
const initPage = async () => {
currentLotteryConfig.value = null
Object.assign(formData, initialFormData)
await loadLotteryConfigOptions()
if (props.data) {
await nextTick()
initForm()
if (!isLotteryConfigEmpty()) {
await loadCurrentLotteryConfig()
}
}
}
/** 从 DiceLotteryConfig 拉取彩金池配置下拉选项 */
/** 从玩家控制器获取 DiceLotteryConfig id/name 列表,供 lottery_config_id 下拉使用 */
async function loadLotteryConfigOptions() {
lotteryConfigLoading.value = true
try {
lotteryConfigOptions.value = await lotteryConfigApi.getOptions()
lotteryConfigOptions.value = await api.getLotteryConfigOptions()
} catch {
lotteryConfigOptions.value = []
} finally {
lotteryConfigLoading.value = false
}
}
@@ -227,8 +353,14 @@
}
const val = props.data[key]
if (numKeys.includes(key)) {
;(formData as any)[key] =
key === 'id' ? (val != null ? Number(val) || null : null) : Number(val) || 0
if (key === 'id') {
;(formData as any)[key] = val != null ? Number(val) || null : null
} else if (key === 'lottery_config_id') {
const num = Number(val)
;(formData as any)[key] = val != null && !Number.isNaN(num) && num !== 0 ? num : null
} else {
;(formData as any)[key] = Number(val) || 0
}
} else {
;(formData as any)[key] = val ?? ''
}
@@ -244,12 +376,15 @@
if (!formRef.value) return
try {
await formRef.value.validate()
const useCustomWeights = !formData.lottery_config_id
const useCustomWeights = isLotteryConfigEmpty()
if (useCustomWeights && Math.abs(weightsSum.value - 100) > 0.01) {
ElMessage.warning('五个池权重总和必须为100%')
return
}
const payload = { ...formData }
if (isLotteryConfigEmpty()) {
;(payload as any).lottery_config_id = null
}
if (props.dialogType === 'edit' && !payload.password) {
delete (payload as any).password
}
@@ -267,3 +402,31 @@
}
}
</script>
<style lang="scss" scoped>
.current-config-block {
margin-bottom: 12px;
}
.current-lottery-config {
padding: 10px 12px;
background: var(--el-fill-color-light);
border-radius: 6px;
font-size: 13px;
color: var(--el-text-color-regular);
.config-row {
margin-bottom: 6px;
line-height: 1.5;
&:last-child {
margin-bottom: 0;
}
}
.config-label {
color: var(--el-text-color-secondary);
margin-right: 4px;
}
}
</style>

View File

@@ -64,7 +64,7 @@
</template>
<script setup lang="ts">
import lotteryConfigApi from '../../../api/lottery_config/index'
import api from '../../../api/player/index'
interface Props {
modelValue: Record<string, any>
@@ -79,10 +79,10 @@
const isExpanded = ref<boolean>(false)
const lotteryConfigOptions = ref<Array<{ id: number; name: string }>>([])
/** 从 DiceLotteryConfig 拉取彩金池配置下拉选项,用于 lottery_config_id 筛选 */
/** 从玩家控制器获取 DiceLotteryConfig id/name 列表,用于 lottery_config_id 筛选 */
onMounted(async () => {
try {
lotteryConfigOptions.value = await lotteryConfigApi.getOptions()
lotteryConfigOptions.value = await api.getLotteryConfigOptions()
} catch {
lotteryConfigOptions.value = []
}