重新优化中奖权重计算方式
This commit is contained in:
@@ -336,6 +336,13 @@
|
||||
if (formData.roll_number == null && formData.rollArrayItems.length === 5) {
|
||||
formData.roll_number = formData.rollArrayItems.reduce((s, n) => (s ?? 0) + (n ?? 0), 0) || null
|
||||
}
|
||||
// 点数和有值但五个点数为空或无效时,根据 roll_number 补全显示(兼容历史错误数据)
|
||||
const sum = formData.roll_number != null ? Number(formData.roll_number) : 0
|
||||
const hasNull = formData.rollArrayItems.some((n) => n == null)
|
||||
const itemsSum = formData.rollArrayItems.reduce((s, n) => (s ?? 0) + (n ?? 0), 0) ?? 0
|
||||
if (sum >= 5 && sum <= 30 && (hasNull || itemsSum !== sum)) {
|
||||
formData.rollArrayItems = defaultRollArrayItems(sum)
|
||||
}
|
||||
}
|
||||
|
||||
/** 将接口的 roll_array 转为固定 5 项数组,不足补 null */
|
||||
@@ -360,6 +367,16 @@
|
||||
return items.slice(0, 5)
|
||||
}
|
||||
|
||||
/** 点数和有值但五个点数缺失时,根据点数和生成默认 5 个数(与后端 defaultRollArrayForSum 一致) */
|
||||
function defaultRollArrayItems(sum: number): (number | null)[] {
|
||||
const s = Math.max(5, Math.min(30, Math.floor(Number(sum))))
|
||||
const base = Math.floor(s / 5)
|
||||
const rem = s - 5 * base
|
||||
const arr: number[] = Array(5).fill(base)
|
||||
for (let i = 0; i < rem; i++) arr[i]++
|
||||
return arr.map((v) => Math.max(1, Math.min(6, v)))
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
visible.value = false
|
||||
formRef.value?.resetFields()
|
||||
|
||||
@@ -114,7 +114,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: 'weight', label: '权重(1-10000)', width: 110, align: 'center' },
|
||||
// { prop: 'create_time', label: '创建时间', sortable: true, align: 'center' },
|
||||
{
|
||||
prop: 'operation',
|
||||
|
||||
@@ -37,19 +37,25 @@
|
||||
<el-option label="BIGWIN(超级大奖)" value="BIGWIN" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formData.tier === 'BIGWIN'" label="权重(%)" prop="weight">
|
||||
<el-slider
|
||||
<el-form-item label="权重(1-10000)" prop="weight">
|
||||
<el-input-number
|
||||
v-model="formData.weight"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:step="0.01"
|
||||
:disabled="isWeightFixed100"
|
||||
show-input
|
||||
:min="1"
|
||||
:max="10000"
|
||||
:step="1"
|
||||
:disabled="isWeightFixed10000"
|
||||
placeholder="1-10000"
|
||||
/>
|
||||
<div v-if="isWeightFixed100" class="weight-fixed-hint">
|
||||
色子点数 5、30 固定 100% 豹子,不可修改权重
|
||||
<div v-if="isWeightFixed10000" class="weight-fixed-hint">
|
||||
色子点数 5、30 固定 10000,不可修改权重
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="顺时针起始索引" prop="s_start_index">
|
||||
<el-input-number v-model="formData.s_start_index" :min="0" :step="1" placeholder="s_start_index" />
|
||||
</el-form-item>
|
||||
<el-form-item label="逆时针起始索引" prop="n_start_index">
|
||||
<el-input-number v-model="formData.n_start_index" :min="0" :step="1" placeholder="n_start_index" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
@@ -102,8 +108,8 @@
|
||||
set: (value) => emit('update:modelValue', value)
|
||||
})
|
||||
|
||||
/** BIGWIN 且 grid_number 为 5 或 30 时豹子概率固定为 100%(禁止手动调整) */
|
||||
const isWeightFixed100 = computed(
|
||||
/** BIGWIN 且 grid_number 为 5 或 30 时权重固定为 10000(禁止手动调整) */
|
||||
const isWeightFixed10000 = computed(
|
||||
() =>
|
||||
formData.tier === 'BIGWIN' &&
|
||||
(formData.grid_number === 5 || formData.grid_number === 30)
|
||||
@@ -120,20 +126,18 @@
|
||||
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%'))
|
||||
if (Number.isNaN(n) || n < 1 || n > 10000) {
|
||||
callback(new Error('权重必须为 1-10000'))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
],
|
||||
n_start_index: [],
|
||||
s_start_index: []
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -145,7 +149,9 @@
|
||||
ui_text: '',
|
||||
real_ev: '',
|
||||
tier: '',
|
||||
weight: 0 as number,
|
||||
weight: 1 as number,
|
||||
n_start_index: 0 as number,
|
||||
s_start_index: 0 as number,
|
||||
remark: ''
|
||||
}
|
||||
|
||||
@@ -166,7 +172,7 @@
|
||||
}
|
||||
)
|
||||
|
||||
/** 当 BIGWIN 且 grid_number 为 5 或 30 时,权重固定为 100 便于展示 */
|
||||
/** 当 BIGWIN 且 grid_number 为 5 或 30 时,权重固定为 10000 便于展示 */
|
||||
watch(
|
||||
() => [formData.tier, formData.grid_number],
|
||||
() => {
|
||||
@@ -174,7 +180,7 @@
|
||||
formData.tier === 'BIGWIN' &&
|
||||
(formData.grid_number === 5 || formData.grid_number === 30)
|
||||
) {
|
||||
formData.weight = 100
|
||||
formData.weight = 10000
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -197,7 +203,7 @@
|
||||
*/
|
||||
const initForm = () => {
|
||||
if (!props.data) return
|
||||
const numKeys = ['id', 'grid_number', 'real_ev', 'weight']
|
||||
const numKeys = ['id', 'grid_number', 'real_ev', 'weight', 'n_start_index', 's_start_index']
|
||||
for (const key of Object.keys(formData)) {
|
||||
if (!(key in props.data)) continue
|
||||
const val = props.data[key]
|
||||
@@ -228,18 +234,13 @@
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
const payload = { ...formData }
|
||||
if (payload.tier !== 'BIGWIN') {
|
||||
payload.weight = 0
|
||||
} else if (payload.grid_number === 5 || payload.grid_number === 30) {
|
||||
payload.weight = 100
|
||||
} else {
|
||||
if (payload.grid_number === 5 || payload.grid_number === 30) {
|
||||
payload.weight = 100
|
||||
} else {
|
||||
const w = Number(payload.weight)
|
||||
payload.weight = Number.isNaN(w) ? 0 : Math.max(0, Math.min(100, w))
|
||||
}
|
||||
const w = Number(payload.weight)
|
||||
payload.weight = Number.isNaN(w) ? 1 : Math.max(1, Math.min(10000, w))
|
||||
if (payload.tier === 'BIGWIN' && (payload.grid_number === 5 || payload.grid_number === 30)) {
|
||||
payload.weight = 10000
|
||||
}
|
||||
payload.n_start_index = Number(payload.n_start_index) || 0
|
||||
payload.s_start_index = Number(payload.s_start_index) || 0
|
||||
if (props.dialogType === 'add') {
|
||||
await api.save(payload)
|
||||
ElMessage.success('新增成功')
|
||||
|
||||
@@ -13,19 +13,18 @@
|
||||
<template v-else>
|
||||
<div class="chart-wrap">
|
||||
<ArtBarChart
|
||||
x-axis-name="色子点数"
|
||||
:x-axis-data="getTierChartLabels(t)"
|
||||
:data="getTierChartData(t)"
|
||||
height="220px"
|
||||
/>
|
||||
</div>
|
||||
<div class="weight-sum" v-if="t !== 'BIGWIN'">
|
||||
当前档位权重合计:<strong :class="{ over: getTierSumForValidation(t) !== 100 }">{{
|
||||
getTierSumForValidation(t).toFixed(1)
|
||||
}}</strong>
|
||||
/ 100(须等于 100%)
|
||||
当前档位权重合计:<strong>{{ getTierSumForValidation(t) }}</strong>
|
||||
(各条权重 1-10000,档位内按权重比抽取 grid_number,和不限制)
|
||||
</div>
|
||||
<div class="weight-sum weight-sum-bigwin" v-else>
|
||||
BIGWIN 为豹子权重,单独设定每条 0–100%,无合计要求
|
||||
BIGWIN 为豹子权重,每条权重 1-10000
|
||||
</div>
|
||||
<el-table :data="getTierItems(t)" border size="small" class="weight-table">
|
||||
<el-table-column label="色子点数" prop="grid_number" width="50" align="center" />
|
||||
@@ -50,20 +49,20 @@
|
||||
align="center"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="权重(%)" min-width="200" align="center">
|
||||
<el-table-column label="权重(1-10000)" min-width="200" align="center">
|
||||
<template #default="{ row }">
|
||||
<div class="weight-cell-vertical">
|
||||
<div class="weight-slider-wrap">
|
||||
<el-slider
|
||||
:model-value="getItemWeight(row)"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:min="1"
|
||||
:max="10000"
|
||||
:step="1"
|
||||
size="small"
|
||||
:disabled="isWeightDisabled(row, t)"
|
||||
class="weight-slider"
|
||||
@update:model-value="
|
||||
(v: number | number[]) => setItemWeight(row, normalizeSliderValue(v))
|
||||
(v: number | number[]) => setItemWeightByRow(t, row, normalizeSliderValue(v))
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
@@ -71,28 +70,29 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
:disabled="isWeightDisabled(row, t) || getItemWeight(row) <= 0"
|
||||
@click="adjustWeight(row, -1)"
|
||||
native-type="button"
|
||||
:disabled="isWeightDisabled(row, t) || getItemWeight(row) <= 1"
|
||||
@click.prevent="adjustWeightByRow(t, row, -1)"
|
||||
>
|
||||
-
|
||||
</el-button>
|
||||
<el-input-number
|
||||
:model-value="getItemWeight(row)"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:min="1"
|
||||
:max="10000"
|
||||
:step="1"
|
||||
:precision="1"
|
||||
:disabled="isWeightDisabled(row, t)"
|
||||
controls-position="right"
|
||||
size="small"
|
||||
class="weight-input"
|
||||
@update:model-value="(v: number | undefined) => setItemWeight(row, v ?? 0)"
|
||||
@update:model-value="(v: number | string | undefined) => setItemWeightByRow(t, row, typeof v === 'number' && !Number.isNaN(v) ? v : Number(v) || 1)"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
:disabled="isWeightDisabled(row, t) || getItemWeight(row) >= 100"
|
||||
@click="adjustWeight(row, 1)"
|
||||
native-type="button"
|
||||
:disabled="isWeightDisabled(row, t) || getItemWeight(row) >= 10000"
|
||||
@click.prevent="adjustWeightByRow(t, row, 1)"
|
||||
>
|
||||
+
|
||||
</el-button>
|
||||
@@ -156,30 +156,59 @@
|
||||
return grouped.value[tier] ?? []
|
||||
}
|
||||
|
||||
/** 图表横坐标为色子点数(grid_number) */
|
||||
function getTierChartLabels(tier: string): string[] {
|
||||
const items = getTierItems(tier)
|
||||
return items.map((r) => (r.ui_text ? String(r.ui_text) : `点数 ${r.grid_number ?? ''}`))
|
||||
return items.map((r) => String(r.grid_number ?? ''))
|
||||
}
|
||||
|
||||
function getTierChartData(tier: string): number[] {
|
||||
const items = getTierItems(tier)
|
||||
return items.map((r) => getItemWeight(r))
|
||||
return items.map((r) => getItemWeight(r)).map((n) => Number(n))
|
||||
}
|
||||
|
||||
/** 用于 T1–T5 校验与展示的档位权重和(仅 T1–T5 使用;BIGWIN 不要求合计) */
|
||||
/** 档位权重和(仅展示用,不限制) */
|
||||
function getTierSumForValidation(tier: string): number {
|
||||
const items = getTierItems(tier)
|
||||
return items.reduce((s, r) => s + getItemWeight(r), 0)
|
||||
}
|
||||
|
||||
function getItemWeight(row: Record<string, unknown> & { weight?: number }): number {
|
||||
/** 读取权重,1-10000 整数(兼容后端 int 返回为 number 或 string) */
|
||||
function getItemWeight(row: Record<string, unknown> & { weight?: number | string }): number {
|
||||
const w = row.weight
|
||||
if (typeof w === 'number' && !Number.isNaN(w)) return Math.max(0, Math.min(100, w))
|
||||
return 0
|
||||
const num = typeof w === 'number' && !Number.isNaN(w) ? w : Number(w)
|
||||
if (Number.isNaN(num)) return 1
|
||||
const n = Math.max(1, Math.min(10000, Math.floor(num)))
|
||||
return n
|
||||
}
|
||||
|
||||
function setItemWeight(row: Record<string, unknown> & { weight: number }, value: number) {
|
||||
row.weight = Math.max(0, Math.min(100, value))
|
||||
const v = toWeightPrecision(value)
|
||||
row.weight = v
|
||||
}
|
||||
|
||||
/** 权重 1-10000 整数 */
|
||||
function toWeightPrecision(value: number): number {
|
||||
const n = Math.max(1, Math.min(10000, Math.floor(value)))
|
||||
return n
|
||||
}
|
||||
|
||||
/** 按档位与行更新权重:原地修改 list 中对应项 */
|
||||
function setItemWeightByRow(tier: string, row: Record<string, unknown> & { weight: number }, value: number) {
|
||||
const v = toWeightPrecision(value)
|
||||
const list = grouped.value[tier]
|
||||
if (!list) return
|
||||
const idx = list.findIndex((r) => r === row || (r.id != null && row.id != null && r.id === row.id))
|
||||
if (idx >= 0) {
|
||||
list[idx].weight = v
|
||||
} else {
|
||||
row.weight = v
|
||||
}
|
||||
}
|
||||
|
||||
function adjustWeightByRow(tier: string, row: Record<string, unknown> & { weight: number }, delta: number) {
|
||||
const cur = getItemWeight(row)
|
||||
setItemWeightByRow(tier, row, cur + delta)
|
||||
}
|
||||
|
||||
function adjustWeight(row: Record<string, unknown> & { weight: number }, delta: number) {
|
||||
@@ -187,9 +216,8 @@
|
||||
setItemWeight(row, cur + delta)
|
||||
}
|
||||
|
||||
/** T4、T5 及 BIGWIN 的 grid_number=5、30 不可修改权重(固定 100%) */
|
||||
/** BIGWIN 的 grid_number=5、30 不可修改权重(固定 10000) */
|
||||
function isWeightDisabled(row: Record<string, unknown>, tier: string): boolean {
|
||||
if (tier === 'T4' || tier === 'T5') return true
|
||||
if (tier === 'BIGWIN' && (row.grid_number === 5 || row.grid_number === 30)) return true
|
||||
return false
|
||||
}
|
||||
@@ -242,13 +270,11 @@
|
||||
}
|
||||
for (const t of TIER_KEYS) {
|
||||
const list = Array.isArray(data[t]) ? data[t] : []
|
||||
next[t] = list.map((r) => ({
|
||||
...r,
|
||||
weight:
|
||||
typeof r.weight === 'number' && !Number.isNaN(r.weight)
|
||||
? r.weight
|
||||
: Number(r.weight) || 0
|
||||
}))
|
||||
next[t] = list.map((r) => {
|
||||
const raw =
|
||||
typeof r.weight === 'number' && !Number.isNaN(r.weight) ? r.weight : Number(r.weight) || 1
|
||||
return { ...r, weight: Math.max(1, Math.min(10000, Math.floor(raw))) }
|
||||
})
|
||||
}
|
||||
grouped.value = next
|
||||
})
|
||||
@@ -258,23 +284,11 @@
|
||||
}
|
||||
|
||||
function validateAll(): boolean {
|
||||
for (const t of TIER_KEYS) {
|
||||
if (t === 'BIGWIN') continue
|
||||
const items = getTierItems(t)
|
||||
if (items.length === 0) continue
|
||||
const sum = getTierSumForValidation(t)
|
||||
if (Math.abs(sum - 100) > 0.01) {
|
||||
ElMessage.warning(`档位 ${t} 的权重之和必须等于 100%,当前为 ${sum.toFixed(1)}%`)
|
||||
activeTier.value = t
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 收集所有档位的 id + weight,同一 id 出现多次时合并权重(避免后端只保留最后一次导致档位合计不足 100%)。
|
||||
* T4、T5、BIGWIN 的 5/30 不可修改,提交时固定为 100。
|
||||
* 收集所有档位的 id + weight(1-10000),BIGWIN 的 5/30 提交时固定为 10000。
|
||||
*/
|
||||
function collectItems(): Array<{ id: number; weight: number }> {
|
||||
const byId = new Map<number, number>()
|
||||
@@ -282,8 +296,8 @@
|
||||
for (const row of getTierItems(t)) {
|
||||
const id = row.id != null ? Number(row.id) : 0
|
||||
if (id >= 0 && !Number.isNaN(id)) {
|
||||
const w = isWeightDisabled(row, t) ? 100 : getItemWeight(row)
|
||||
byId.set(id, Math.min(100, (byId.get(id) ?? 0) + w))
|
||||
const w = isWeightDisabled(row, t) ? 10000 : getItemWeight(row)
|
||||
byId.set(id, w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user