Compare commits
3 Commits
4b6bbab9d1
...
6632923213
| Author | SHA1 | Date | |
|---|---|---|---|
| 6632923213 | |||
| 316506b597 | |||
| 282d73a203 |
@@ -17,17 +17,16 @@ export default {
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取彩金池配置下拉选项(来自 DiceLotteryConfig,用于 lottery_config_id 选择)
|
||||
* @returns { id, name }[]
|
||||
* 获取 DiceLotteryConfig 列表数据,仅含 id、name,用于 lottery_config_id 下拉
|
||||
* @returns DiceLotteryConfig['id','name'] 列表
|
||||
*/
|
||||
async getOptions(): Promise<Array<{ id: number; name: string }>> {
|
||||
const res = await request.get<any>({
|
||||
url: '/dice/lottery_config/DiceLotteryConfig/index',
|
||||
params: { limit: 500, page: 1 }
|
||||
url: '/dice/lottery_config/DiceLotteryConfig/getOptions'
|
||||
})
|
||||
const rows = (res?.data?.data ?? res?.data?.rows ?? []) as Array<{ id: number; name: string }>
|
||||
const rows = (res?.data ?? []) as Array<{ id: number; name: string }>
|
||||
return Array.isArray(rows)
|
||||
? rows.map((r) => ({ id: Number(r.id), name: String(r.name ?? r.id) }))
|
||||
? rows.map((r) => ({ id: Number(r.id), name: String(r.name ?? r.id ?? '') }))
|
||||
: []
|
||||
},
|
||||
|
||||
|
||||
@@ -71,5 +71,17 @@ export default {
|
||||
url: '/dice/player/DicePlayer/updateStatus',
|
||||
data: params
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取彩金池配置选项(DiceLotteryConfig.id、name),供 lottery_config_id 下拉使用
|
||||
* @returns [ { id, name } ]
|
||||
*/
|
||||
async getLotteryConfigOptions(): Promise<Array<{ id: number; name: string }>> {
|
||||
const res = await request.get<any>({
|
||||
url: '/dice/player/DicePlayer/getLotteryConfigOptions'
|
||||
})
|
||||
const rows = (Array.isArray(res) ? res : (res?.data ?? [])) as Array<{ id: number; name: string }>
|
||||
return rows.map((r) => ({ id: Number(r.id), name: String(r.name ?? r.id ?? '') }))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
is_win: undefined,
|
||||
win_coin_min: undefined,
|
||||
win_coin_max: undefined,
|
||||
roll_number_min: undefined,
|
||||
roll_number_max: undefined,
|
||||
reward_ui_text: undefined,
|
||||
reward_tier: undefined,
|
||||
direction: undefined
|
||||
@@ -190,6 +192,7 @@
|
||||
{ prop: 'start_index', label: '起始索引', width: 90 },
|
||||
{ prop: 'target_index', label: '终点索引', width: 90 },
|
||||
{ prop: 'roll_array', label: '摇取点数', width: 140, useSlot: true },
|
||||
{ prop: 'roll_number', label: '摇取点数和', width: 110, sortable: true },
|
||||
{
|
||||
prop: 'reward_config_id',
|
||||
label: '奖励配置',
|
||||
|
||||
@@ -142,6 +142,17 @@
|
||||
</div>
|
||||
<div class="roll-array-hint">固定 5 个数,每个 1~6</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="摇取点数和" prop="roll_number">
|
||||
<el-input-number
|
||||
v-model="formData.roll_number"
|
||||
placeholder="5 个色子点数之和(5~30)"
|
||||
:min="5"
|
||||
:max="30"
|
||||
:precision="0"
|
||||
style="width: 100%"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="奖励配置" prop="reward_config_id">
|
||||
<el-select
|
||||
v-model="formData.reward_config_id"
|
||||
@@ -245,6 +256,7 @@
|
||||
start_index: null as number | null,
|
||||
target_index: null as number | null,
|
||||
roll_array: null as string | number[] | null,
|
||||
roll_number: null as number | null,
|
||||
reward_config_id: null as number | null
|
||||
}
|
||||
|
||||
@@ -306,6 +318,7 @@
|
||||
'start_index',
|
||||
'target_index',
|
||||
'roll_array',
|
||||
'roll_number',
|
||||
'reward_config_id'
|
||||
]
|
||||
keys.forEach((key) => {
|
||||
@@ -319,6 +332,10 @@
|
||||
}
|
||||
}
|
||||
})
|
||||
// 若后端未返回 roll_number,根据摇取点数计算
|
||||
if (formData.roll_number == null && formData.rollArrayItems.length === 5) {
|
||||
formData.roll_number = formData.rollArrayItems.reduce((s, n) => s + (n ?? 0), 0) || null
|
||||
}
|
||||
}
|
||||
|
||||
/** 将接口的 roll_array 转为固定 5 项数组,不足补 null */
|
||||
@@ -355,10 +372,12 @@
|
||||
const payload = { ...formData } as Record<string, unknown>
|
||||
// 将 5 个输入值拼成 [1,2,3,4,5] 格式,确保每项为 1~6 的整数
|
||||
const items = formData.rollArrayItems
|
||||
payload.roll_array = items.map((n) => {
|
||||
const rollArray = items.map((n) => {
|
||||
const v = n != null ? Number(n) : 1
|
||||
return Math.min(6, Math.max(1, Number.isNaN(v) ? 1 : Math.floor(v)))
|
||||
})
|
||||
payload.roll_array = rollArray
|
||||
payload.roll_number = formData.roll_number ?? rollArray.reduce((s, n) => s + n, 0)
|
||||
delete payload.rollArrayItems
|
||||
if (props.dialogType === 'add') {
|
||||
delete payload.id
|
||||
|
||||
@@ -63,6 +63,31 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="setSpan(6)">
|
||||
<el-form-item label="摇取点数和" prop="roll_number_min">
|
||||
<div class="range-wrap">
|
||||
<el-input-number
|
||||
v-model="formData.roll_number_min"
|
||||
placeholder="最小"
|
||||
:min="5"
|
||||
:max="30"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
class="range-input"
|
||||
/>
|
||||
<span class="range-sep">至</span>
|
||||
<el-input-number
|
||||
v-model="formData.roll_number_max"
|
||||
placeholder="最大"
|
||||
:min="5"
|
||||
:max="30"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
class="range-input"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="setSpan(6)">
|
||||
<el-form-item label="奖励配置" prop="reward_ui_text">
|
||||
<el-input v-model="formData.reward_ui_text" placeholder="前端显示文本模糊" clearable />
|
||||
|
||||
@@ -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">T1~T5 权重:</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)
|
||||
})
|
||||
|
||||
/** 当前彩金池配置的 T1~T5 权重展示文案 */
|
||||
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>
|
||||
|
||||
@@ -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 = []
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
{ prop: 'ui_text', label: '前端显示文本', align: 'center' },
|
||||
{ prop: 'real_ev', label: '真实资金结算', align: 'center' },
|
||||
{ prop: 'tier', label: '所属档位', sortable: true, align: 'center' },
|
||||
{ prop: 'weight', label: '权重(%)', width: 100, align: 'center' },
|
||||
// { prop: 'create_time', label: '创建时间', sortable: true, align: 'center' },
|
||||
{
|
||||
prop: 'operation',
|
||||
|
||||
@@ -34,8 +34,12 @@
|
||||
<el-option label="T3" value="T3" />
|
||||
<el-option label="T4" value="T4" />
|
||||
<el-option label="T5" value="T5" />
|
||||
<el-option label="BIGWIN(超级大奖)" value="BIGWIN" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formData.tier === 'BIGWIN'" label="权重(%)" prop="weight">
|
||||
<el-slider v-model="formData.weight" :min="0" :max="100" :step="0.01" show-input />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
@@ -95,7 +99,24 @@
|
||||
grid_number: [{ required: true, message: '色子点数必需填写', trigger: 'blur' }],
|
||||
ui_text: [{ required: true, message: '前端显示文本必需填写', trigger: 'blur' }],
|
||||
real_ev: [{ required: true, message: '真实资金结算必需填写', trigger: 'blur' }],
|
||||
tier: [{ required: true, message: '所属档位必需填写', trigger: 'blur' }]
|
||||
tier: [{ required: true, message: '所属档位必需填写', trigger: 'blur' }],
|
||||
weight: [
|
||||
{
|
||||
validator: (_rule: unknown, value: number | null, callback: (e?: Error) => void) => {
|
||||
if (formData.tier !== 'BIGWIN') {
|
||||
callback()
|
||||
return
|
||||
}
|
||||
const n = value != null ? Number(value) : NaN
|
||||
if (Number.isNaN(n) || n < 0 || n > 100) {
|
||||
callback(new Error('权重仅 BIGWIN 可设定,且必须为 0-100%'))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -107,6 +128,7 @@
|
||||
ui_text: '',
|
||||
real_ev: '',
|
||||
tier: '',
|
||||
weight: 0 as number,
|
||||
remark: ''
|
||||
}
|
||||
|
||||
@@ -141,14 +163,21 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化表单数据
|
||||
* 初始化表单数据(数值字段转为 number,便于滑块/输入框正确回显)
|
||||
*/
|
||||
const initForm = () => {
|
||||
if (props.data) {
|
||||
for (const key in formData) {
|
||||
if (props.data[key] != null && props.data[key] != undefined) {
|
||||
;(formData as any)[key] = props.data[key]
|
||||
}
|
||||
if (!props.data) return
|
||||
const numKeys = ['id', 'grid_number', 'real_ev', 'weight']
|
||||
for (const key of Object.keys(formData)) {
|
||||
if (!(key in props.data)) continue
|
||||
const val = props.data[key]
|
||||
if (val == null || val === undefined) continue
|
||||
if (numKeys.includes(key)) {
|
||||
const numVal = Number(val)
|
||||
;(formData as Record<string, unknown>)[key] =
|
||||
key === 'id' ? numVal || null : Number.isNaN(numVal) ? 0 : numVal
|
||||
} else {
|
||||
;(formData as Record<string, unknown>)[key] = val ?? ''
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,11 +197,18 @@
|
||||
if (!formRef.value) return
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
const payload = { ...formData }
|
||||
if (payload.tier !== 'BIGWIN') {
|
||||
payload.weight = 0
|
||||
} else {
|
||||
const w = Number(payload.weight)
|
||||
payload.weight = Number.isNaN(w) ? 0 : Math.max(0, Math.min(100, w))
|
||||
}
|
||||
if (props.dialogType === 'add') {
|
||||
await api.save(formData)
|
||||
await api.save(payload)
|
||||
ElMessage.success('新增成功')
|
||||
} else {
|
||||
await api.update(formData)
|
||||
await api.update(payload)
|
||||
ElMessage.success('修改成功')
|
||||
}
|
||||
emit('success')
|
||||
|
||||
@@ -150,6 +150,7 @@ class GameController extends OpenController
|
||||
'start_index' => 0,
|
||||
'target_index' => 0,
|
||||
'roll_array' => '[]',
|
||||
'roll_number' => 0,
|
||||
'status' => PlayStartLogic::RECORD_STATUS_TIMEOUT,
|
||||
]);
|
||||
} catch (\Exception $inner) {
|
||||
|
||||
@@ -34,8 +34,10 @@ class PlayStartLogic
|
||||
|
||||
/** 开启对局最低余额 = |DiceRewardConfig 最小 real_ev + 100| */
|
||||
private const MIN_COIN_EXTRA = 100;
|
||||
/** 豹子号中大奖额外平台币(可从 dice_config 等配置读取) */
|
||||
/** 豹子号中大奖额外平台币(无 BIGWIN 配置时兜底) */
|
||||
private const SUPER_WIN_BONUS = 500;
|
||||
/** 可触发超级大奖的 grid_number(5=全1 10=全2 15=全3 20=全4 25=全5) */
|
||||
private const SUPER_WIN_GRID_NUMBERS = [5, 10, 15, 20, 25];
|
||||
|
||||
/**
|
||||
* 执行一局游戏
|
||||
@@ -112,7 +114,30 @@ class PlayStartLogic
|
||||
? (int) ($startRecord['s_end_index'] ?? 0)
|
||||
: (int) ($startRecord['n_end_index'] ?? 0);
|
||||
$rollNumber = (int) ($startRecord['grid_number'] ?? 0);
|
||||
$rollArray = $this->generateRollArrayFromSum($rollNumber);
|
||||
$realEv = (float) ($chosen['real_ev'] ?? 0);
|
||||
$rewardWinCoin = 100 + $realEv; // 摇色子中奖平台币 = 100 + DiceRewardConfig.real_ev
|
||||
|
||||
// 当抽到的 grid_number 为 5/10/15/20/25 时,从缓存查 tier=BIGWIN 同 grid_number 的配置,按 weight 决定是否生成豹子组合
|
||||
$superWinCoin = 0;
|
||||
$isWin = 0;
|
||||
if (in_array($rollNumber, self::SUPER_WIN_GRID_NUMBERS, true)) {
|
||||
$bigWinConfig = DiceRewardConfig::getCachedByTierAndGridNumber('BIGWIN', $rollNumber);
|
||||
$weight = $bigWinConfig !== null
|
||||
? max(0.0, min(100.0, (float) ($bigWinConfig['weight'] ?? 0)))
|
||||
: 100.0;
|
||||
$roll = mt_rand(1, 10000) / 10000;
|
||||
if ($roll <= $weight / 100) {
|
||||
$rollArray = $this->getSuperWinRollArray($rollNumber);
|
||||
$isWin = 1;
|
||||
$superWinCoin = $bigWinConfig !== null
|
||||
? 100 + (float) ($bigWinConfig['real_ev'] ?? 0)
|
||||
: self::SUPER_WIN_BONUS;
|
||||
} else {
|
||||
$rollArray = $this->generateNonSuperWinRollArrayWithSum($rollNumber);
|
||||
}
|
||||
} else {
|
||||
$rollArray = $this->generateRollArrayFromSum($rollNumber);
|
||||
}
|
||||
|
||||
Log::info(sprintf(
|
||||
'摇取点数 roll_number=%d, 方向=%d, start_index=%d, target_index=%d',
|
||||
@@ -121,17 +146,6 @@ class PlayStartLogic
|
||||
$startIndex,
|
||||
$targetIndex
|
||||
));
|
||||
$realEv = (float) ($chosen['real_ev'] ?? 0);
|
||||
$rewardWinCoin = 100 + $realEv; // 摇色子中奖平台币 = 100 + DiceRewardConfig.real_ev
|
||||
$isSuperWin = DicePlayRecord::isSuperWin($rollArray);
|
||||
// 豹子中大奖时从缓存查 tier=BIGWIN 且 grid_number=roll_number 的奖励配置,取 real_ev 计算中大奖平台币
|
||||
$superWinCoin = 0;
|
||||
if ($isSuperWin) {
|
||||
$bigWinConfig = DiceRewardConfig::getCachedByTierAndGridNumber('BIGWIN', $rollNumber);
|
||||
$superWinCoin = $bigWinConfig !== null
|
||||
? 100 + (float) ($bigWinConfig['real_ev'] ?? 0)
|
||||
: self::SUPER_WIN_BONUS;
|
||||
}
|
||||
$winCoin = $superWinCoin + $rewardWinCoin; // 赢取平台币 = 中大奖 + 摇色子中奖
|
||||
|
||||
$record = null;
|
||||
@@ -139,7 +153,6 @@ class PlayStartLogic
|
||||
$rewardId = $chosenId;
|
||||
$configName = (string) ($config->name ?? '');
|
||||
$isTierT5 = (string) ($chosen['tier'] ?? '') === 'T5';
|
||||
$isWin = $isSuperWin ? 1 : 0;
|
||||
try {
|
||||
Db::transaction(function () use (
|
||||
$playerId,
|
||||
@@ -173,6 +186,7 @@ class PlayStartLogic
|
||||
'start_index' => $startIndex,
|
||||
'target_index' => $targetIndex,
|
||||
'roll_array' => is_array($rollArray) ? json_encode($rollArray) : $rollArray,
|
||||
'roll_number' => is_array($rollArray) ? array_sum($rollArray) : 0,
|
||||
'lottery_name' => $configName,
|
||||
'status' => self::RECORD_STATUS_SUCCESS,
|
||||
]);
|
||||
@@ -239,6 +253,7 @@ class PlayStartLogic
|
||||
'start_index' => $startIndex,
|
||||
'target_index' => 0,
|
||||
'roll_array' => '[]',
|
||||
'roll_number' => 0,
|
||||
'status' => self::RECORD_STATUS_TIMEOUT,
|
||||
]);
|
||||
} catch (\Throwable $_) {
|
||||
@@ -290,4 +305,51 @@ class PlayStartLogic
|
||||
shuffle($arr);
|
||||
return array_values($arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 豹子组合:grid_number 5->[1,1,1,1,1],10->[2,2,2,2,2],15->[3,3,3,3,3],20->[4,4,4,4,4],25->[5,5,5,5,5]
|
||||
* @return int[]
|
||||
*/
|
||||
private function getSuperWinRollArray(int $gridNumber): array
|
||||
{
|
||||
$n = (int) ($gridNumber / 5);
|
||||
$n = max(1, min(5, $n));
|
||||
return array_fill(0, 5, $n);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成总和为 $sum 且非豹子的 5 个色子(1-6);sum=5 时仅 [1,1,1,1,1] 可能,仍返回该组合
|
||||
* @return int[]
|
||||
*/
|
||||
private function generateNonSuperWinRollArrayWithSum(int $sum): array
|
||||
{
|
||||
$sum = max(5, min(30, $sum));
|
||||
$super = $this->getSuperWinRollArray($sum);
|
||||
if ($sum === 5) {
|
||||
return $super;
|
||||
}
|
||||
$arr = $super;
|
||||
$maxAttempts = 20;
|
||||
for ($a = 0; $a < $maxAttempts; $a++) {
|
||||
$idx = array_rand($arr);
|
||||
$j = array_rand($arr);
|
||||
if ($idx === $j) {
|
||||
$j = ($j + 1) % 5;
|
||||
}
|
||||
$i = $idx;
|
||||
if ($arr[$i] >= 2 && $arr[$j] <= 5) {
|
||||
$arr[$i]--;
|
||||
$arr[$j]++;
|
||||
shuffle($arr);
|
||||
return array_values($arr);
|
||||
}
|
||||
if ($arr[$i] <= 5 && $arr[$j] >= 2) {
|
||||
$arr[$i]++;
|
||||
$arr[$j]--;
|
||||
shuffle($arr);
|
||||
return array_values($arr);
|
||||
}
|
||||
}
|
||||
return $this->generateRollArrayFromSum($sum);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,9 @@ class UserLogic
|
||||
|
||||
$player = DicePlayer::where('username', $username)->find();
|
||||
if ($player) {
|
||||
if ((int) ($player->status ?? 1) === 0) {
|
||||
throw new ApiException('账号已被禁用,无法登录');
|
||||
}
|
||||
$hashed = $this->hashPassword($password);
|
||||
if ($player->password !== $hashed) {
|
||||
throw new ApiException('密码错误');
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\controller\lottery_config;
|
||||
|
||||
use app\dice\model\lottery_config\DiceLotteryConfig;
|
||||
use plugin\saiadmin\basic\BaseController;
|
||||
use app\dice\logic\lottery_config\DiceLotteryConfigLogic;
|
||||
use app\dice\validate\lottery_config\DiceLotteryConfigValidate;
|
||||
@@ -28,6 +29,21 @@ class DiceLotteryConfigController extends BaseController
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 DiceLotteryConfig 列表数据,仅含 id、name,用于 lottery_config_id 下拉(值为 id,显示为 name)
|
||||
* @param Request $request
|
||||
* @return Response 返回 [ ['id' => int, 'name' => string], ... ]
|
||||
*/
|
||||
#[Permission('色子奖池配置列表', 'dice:lottery_config:index:index')]
|
||||
public function getOptions(Request $request): Response
|
||||
{
|
||||
$list = DiceLotteryConfig::field('id,name')->order('id', 'asc')->select();
|
||||
$data = $list->map(function ($item) {
|
||||
return ['id' => (int) $item['id'], 'name' => (string) ($item['name'] ?? '')];
|
||||
})->toArray();
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据列表
|
||||
* @param Request $request
|
||||
|
||||
@@ -46,6 +46,8 @@ class DicePlayRecordController extends BaseController
|
||||
['is_win', ''],
|
||||
['win_coin_min', ''],
|
||||
['win_coin_max', ''],
|
||||
['roll_number_min', ''],
|
||||
['roll_number_max', ''],
|
||||
['reward_ui_text', ''],
|
||||
['reward_tier', ''],
|
||||
['direction', ''],
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\controller\player;
|
||||
|
||||
use app\dice\model\lottery_config\DiceLotteryConfig;
|
||||
use plugin\saiadmin\basic\BaseController;
|
||||
use app\dice\logic\player\DicePlayerLogic;
|
||||
use app\dice\validate\player\DicePlayerValidate;
|
||||
@@ -28,6 +29,21 @@ class DicePlayerController extends BaseController
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取彩金池配置选项(DiceLotteryConfig.id、name),供前端 lottery_config_id 下拉使用
|
||||
* @param Request $request
|
||||
* @return Response 返回 [ ['id' => int, 'name' => string], ... ]
|
||||
*/
|
||||
#[Permission('大富翁-玩家列表', 'dice:player:index:index')]
|
||||
public function getLotteryConfigOptions(Request $request): Response
|
||||
{
|
||||
$list = DiceLotteryConfig::field('id,name')->order('id', 'asc')->select();
|
||||
$data = $list->map(function ($item) {
|
||||
return ['id' => (int) $item['id'], 'name' => (string) ($item['name'] ?? '')];
|
||||
})->toArray();
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据列表
|
||||
* @param Request $request
|
||||
|
||||
@@ -43,16 +43,18 @@ class DicePlayRecordLogic extends BaseLogic
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 roll_array 从数组转为 JSON 字符串
|
||||
* 将 roll_array 转为 JSON 字符串,并确保 roll_number 与摇取点数一致
|
||||
*/
|
||||
private function normalizeRollArray(array $data): array
|
||||
{
|
||||
if (!array_key_exists('roll_array', $data)) {
|
||||
return $data;
|
||||
}
|
||||
$val = $data['roll_array'];
|
||||
if (is_array($val)) {
|
||||
$data['roll_array'] = json_encode($val, JSON_UNESCAPED_UNICODE);
|
||||
if (array_key_exists('roll_array', $data)) {
|
||||
$val = $data['roll_array'];
|
||||
if (is_array($val)) {
|
||||
$data['roll_array'] = json_encode($val, JSON_UNESCAPED_UNICODE);
|
||||
if (!isset($data['roll_number'])) {
|
||||
$data['roll_number'] = array_sum($val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ use app\dice\model\reward_config\DiceRewardConfig;
|
||||
|
||||
/**
|
||||
* 奖励配置逻辑层
|
||||
* weight 仅 tier=BIGWIN 时可设定,保存时非 BIGWIN 强制 weight=0
|
||||
*/
|
||||
class DiceRewardConfigLogic extends BaseLogic
|
||||
{
|
||||
@@ -24,4 +25,36 @@ class DiceRewardConfigLogic extends BaseLogic
|
||||
$this->model = new DiceRewardConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增前:非 BIGWIN 时强制 weight=0
|
||||
*/
|
||||
public function add(array $data): mixed
|
||||
{
|
||||
$data = $this->normalizeWeightByTier($data);
|
||||
return parent::add($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改前:非 BIGWIN 时强制 weight=0
|
||||
*/
|
||||
public function edit($id, array $data): mixed
|
||||
{
|
||||
$data = $this->normalizeWeightByTier($data);
|
||||
return parent::edit($id, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅 tier=BIGWIN 时保留 weight(且限制 0-100),否则强制为 0
|
||||
*/
|
||||
private function normalizeWeightByTier(array $data): array
|
||||
{
|
||||
$tier = isset($data['tier']) ? (string) $data['tier'] : '';
|
||||
if ($tier !== 'BIGWIN') {
|
||||
$data['weight'] = 0;
|
||||
return $data;
|
||||
}
|
||||
$w = isset($data['weight']) ? (float) $data['weight'] : 0;
|
||||
$data['weight'] = max(0, min(100, $w));
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ use think\model\relation\BelongsTo;
|
||||
* @property $start_index 起始索引
|
||||
* @property $target_index 结束索引
|
||||
* @property $roll_array 摇取点数,格式:[1,2,3,4,5](5个点数)
|
||||
* @property $roll_number 摇取点数和(5个色子点数之和,5-30)
|
||||
* @property $lottery_name 奖池名
|
||||
* @property $status 状态:0=超时/失败 1=成功
|
||||
* @property $create_time 创建时间
|
||||
@@ -222,4 +223,20 @@ class DicePlayRecord extends BaseModel
|
||||
$query->where('direction', '=', $value);
|
||||
}
|
||||
}
|
||||
|
||||
/** 摇取点数和下限 */
|
||||
public function searchRollNumberMinAttr($query, $value)
|
||||
{
|
||||
if ($value !== '' && $value !== null) {
|
||||
$query->where('roll_number', '>=', $value);
|
||||
}
|
||||
}
|
||||
|
||||
/** 摇取点数和上限 */
|
||||
public function searchRollNumberMaxAttr($query, $value)
|
||||
{
|
||||
if ($value !== '' && $value !== null) {
|
||||
$query->where('roll_number', '<=', $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,16 @@ class DicePlayer extends BaseModel
|
||||
if ($name === null || $name === '') {
|
||||
$model->setAttr('name', $uid);
|
||||
}
|
||||
// 创建玩家时:未指定则自动保存 lottery_config_id 为 DiceLotteryConfig type=0 的 id,没有则为 0
|
||||
try {
|
||||
$lotteryConfigId = $model->getAttr('lottery_config_id');
|
||||
} catch (\Throwable $e) {
|
||||
$lotteryConfigId = null;
|
||||
}
|
||||
if ($lotteryConfigId === null || $lotteryConfigId === '' || (int) $lotteryConfigId === 0) {
|
||||
$config = DiceLotteryConfig::where('type', 0)->find();
|
||||
$model->setAttr('lottery_config_id', $config ? (int) $config->id : 0);
|
||||
}
|
||||
// 彩金池权重默认取 type=0 的奖池配置
|
||||
self::setDefaultWeightsFromLotteryConfig($model);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ use support\think\Cache;
|
||||
* @property $ui_text 前端显示文本
|
||||
* @property $real_ev 真实资金结算
|
||||
* @property $tier 所属档位
|
||||
* @property $weight 权重%(仅 tier=BIGWIN 时可设定,0-100)
|
||||
* @property $s_end_index 顺时针结束索引
|
||||
* @property $n_end_index 逆时针结束索引
|
||||
* @property $remark 备注
|
||||
@@ -80,7 +81,8 @@ class DiceRewardConfig extends BaseModel
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新从数据库加载并写入缓存(保存时调用),构建列表与索引
|
||||
* 重新从数据库加载并写入缓存(DiceRewardConfig 新增/修改/删除后调用),构建列表与索引
|
||||
* 实例化结果含完整行(含 weight),供 playStart 从缓存中查找 BIGWIN 的 weight 按概率抽奖
|
||||
*/
|
||||
public static function refreshCache(): void
|
||||
{
|
||||
@@ -148,10 +150,11 @@ class DiceRewardConfig extends BaseModel
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存按档位 + 色子点数取一条奖励配置(用于超级大奖 tier=BIGWIN + grid_number=roll_number)
|
||||
* 从缓存实例按档位 + 色子点数取一条奖励配置(用于超级大奖 tier=BIGWIN + grid_number=roll_number)
|
||||
* 返回行含 weight(0-100):playStart 据此概率抽奖,weight=100 表示摇到该 roll_number 时 100% 中超级大奖
|
||||
* @param string $tier 档位,如 BIGWIN
|
||||
* @param int $gridNumber 色子点数(如摇出总和)
|
||||
* @return array|null 配置行或 null
|
||||
* @param int $gridNumber 色子点数(摇出总和 roll_number)
|
||||
* @return array|null 配置行(含 weight、real_ev 等)或 null
|
||||
*/
|
||||
public static function getCachedByTierAndGridNumber(string $tier, int $gridNumber): ?array
|
||||
{
|
||||
@@ -277,4 +280,20 @@ class DiceRewardConfig extends BaseModel
|
||||
$query->where('tier', '=', $value);
|
||||
}
|
||||
}
|
||||
|
||||
/** 权重下限(仅 tier=BIGWIN 时有意义) */
|
||||
public function searchWeightMinAttr($query, $value)
|
||||
{
|
||||
if ($value !== '' && $value !== null) {
|
||||
$query->where('weight', '>=', $value);
|
||||
}
|
||||
}
|
||||
|
||||
/** 权重上限 */
|
||||
public function searchWeightMaxAttr($query, $value)
|
||||
{
|
||||
if ($value !== '' && $value !== null) {
|
||||
$query->where('weight', '<=', $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,45 +10,56 @@ use plugin\saiadmin\basic\BaseValidate;
|
||||
|
||||
/**
|
||||
* 奖励配置验证器
|
||||
* weight 仅当 tier=BIGWIN 时可设定,且严格限制 0-100(%)
|
||||
*/
|
||||
class DiceRewardConfigValidate extends BaseValidate
|
||||
{
|
||||
/**
|
||||
* 定义验证规则
|
||||
*/
|
||||
protected $rule = [
|
||||
protected $rule = [
|
||||
'grid_number' => 'require',
|
||||
'ui_text' => 'require',
|
||||
'real_ev' => 'require',
|
||||
'tier' => 'require',
|
||||
'ui_text' => 'require',
|
||||
'real_ev' => 'require',
|
||||
'tier' => 'require',
|
||||
'weight' => 'checkWeight',
|
||||
];
|
||||
|
||||
/**
|
||||
* 定义错误信息
|
||||
*/
|
||||
protected $message = [
|
||||
protected $message = [
|
||||
'grid_number' => '色子点数必须填写',
|
||||
'ui_text' => '前端显示文本必须填写',
|
||||
'real_ev' => '真实资金结算必须填写',
|
||||
'tier' => '所属档位必须填写',
|
||||
'ui_text' => '前端显示文本必须填写',
|
||||
'real_ev' => '真实资金结算必须填写',
|
||||
'tier' => '所属档位必须填写',
|
||||
'weight' => '权重仅 tier=BIGWIN 时可设定,且必须为 0-100',
|
||||
];
|
||||
|
||||
/**
|
||||
* 定义场景
|
||||
*/
|
||||
protected $scene = [
|
||||
'save' => [
|
||||
'grid_number',
|
||||
'ui_text',
|
||||
'real_ev',
|
||||
'tier',
|
||||
],
|
||||
'update' => [
|
||||
'grid_number',
|
||||
'ui_text',
|
||||
'real_ev',
|
||||
'tier',
|
||||
],
|
||||
'save' => ['grid_number', 'ui_text', 'real_ev', 'tier', 'weight'],
|
||||
'update' => ['grid_number', 'ui_text', 'real_ev', 'tier', 'weight'],
|
||||
];
|
||||
|
||||
/**
|
||||
* weight:仅 tier=BIGWIN 时可设定,严格限制 0-100(%)
|
||||
*/
|
||||
protected function checkWeight($value, $rule = '', $data = []): bool
|
||||
{
|
||||
$tier = isset($data['tier']) ? (string) $data['tier'] : '';
|
||||
if ($tier !== 'BIGWIN') {
|
||||
return true;
|
||||
}
|
||||
$num = is_numeric($value) ? (float) $value : null;
|
||||
if ($num === null) {
|
||||
return false;
|
||||
}
|
||||
if ($num < 0 || $num > 100) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user