优化抽奖方式,以及记录相关信息

This commit is contained in:
2026-03-26 18:10:41 +08:00
parent 77ec0dcade
commit e32f3890f1
32 changed files with 304 additions and 244 deletions

View File

@@ -75,12 +75,5 @@ export default {
return request.get<{ id: number; name: string }[]>({
url: '/dice/play_record/DicePlayRecord/getLotteryConfigOptions'
})
},
/** 获取奖励配置选项id、ui_text、tier */
getRewardConfigOptions() {
return request.get<{ id: number; ui_text: string; tier: string }[]>({
url: '/dice/play_record/DicePlayRecord/getRewardConfigOptions'
})
}
}

View File

@@ -56,19 +56,37 @@
<!-- 抽奖类型 tag -->
<template #lottery_type="{ row }">
<ElTag size="small" :type="row.lottery_type === 0 ? 'warning' : 'success'">
{{ row.lottery_type === 0 ? t('page.search.paid') : row.lottery_type === 1 ? t('page.search.free') : '-' }}
{{
row.lottery_type === 0
? t('page.search.paid')
: row.lottery_type === 1
? t('page.search.free')
: '-'
}}
</ElTag>
</template>
<!-- 是否中大奖 tag -->
<template #is_win="{ row }">
<ElTag size="small" :type="row.is_win === 1 ? 'success' : 'info'">
{{ row.is_win === 0 ? t('page.search.noBigWin') : row.is_win === 1 ? t('page.search.bigWin') : '-' }}
{{
row.is_win === 0
? t('page.search.noBigWin')
: row.is_win === 1
? t('page.search.bigWin')
: '-'
}}
</ElTag>
</template>
<!-- 方向 tag -->
<template #direction="{ row }">
<ElTag size="small" :type="row.direction === 0 ? 'primary' : 'warning'">
{{ row.direction === 0 ? t('page.search.clockwise') : row.direction === 1 ? t('page.search.anticlockwise') : '-' }}
{{
row.direction === 0
? t('page.search.clockwise')
: row.direction === 1
? t('page.search.anticlockwise')
: '-'
}}
</ElTag>
</template>
<!-- 平台币相关统一整数显示 -->
@@ -158,8 +176,7 @@
row?.dicePlayer?.username ?? row?.player_id ?? '-'
const lotteryConfigNameFormatter = (row: Record<string, any>) =>
row?.diceLotteryPoolConfig?.name ?? row?.lottery_config_id ?? '-'
const rewardTierFormatter = (row: Record<string, any>) =>
row?.diceRewardConfig?.tier ?? row?.reward_config_id ?? '-'
const rewardTierFormatter = (row: Record<string, any>) => row?.reward_tier ?? '-'
/** 摇取点数格式化为 1,3,4,5,6,6 */
function formatRollArray(val: unknown): string {
@@ -216,25 +233,32 @@
useSlot: true
},
{ prop: 'lottery_type', label: 'page.table.drawType', width: 100, useSlot: true },
{ prop: 'direction', label: 'page.table.direction', width: 90, useSlot: true },
{ prop: 'ante', label: 'page.table.ante', width: 80, align: 'center' },
{ prop: 'paid_amount', label: 'page.table.paidAmount', width: 110, align: 'center' },
{ prop: 'is_win', label: 'page.table.isBigWin', width: 100, useSlot: true },
{ prop: 'win_coin', label: 'page.table.winCoin', width: 110, useSlot: true },
{ prop: 'super_win_coin', label: 'page.table.superWinCoin', width: 120, useSlot: true },
{ prop: 'reward_win_coin', label: 'page.table.rewardWinCoin', width: 140, useSlot: true },
{ prop: 'direction', label: 'page.table.direction', width: 90, useSlot: true },
{ prop: 'start_index', label: 'page.table.startIndex', width: 90 },
{ prop: 'target_index', label: 'page.table.targetIndex', width: 90 },
{ prop: 'roll_array', label: 'page.table.rollArray', width: 140, useSlot: true },
{ prop: 'roll_number', label: 'page.table.rollNumber', width: 110, sortable: true },
{
prop: 'reward_config_id',
label: 'page.table.rewardConfig',
prop: 'reward_tier',
label: 'page.table.rewardTier',
width: 100,
formatter: (row: Record<string, any>) => rewardTierFormatter(row)
},
{ prop: 'create_time', label: 'page.table.createTime', width: 170 },
{ prop: 'update_time', label: 'page.table.updateTime', width: 170 },
{ prop: 'operation', label: 'table.actions.operation', width: 100, fixed: 'right', useSlot: true }
{
prop: 'operation',
label: 'table.actions.operation',
width: 100,
fixed: 'right',
useSlot: true
}
]
}
})

View File

@@ -153,25 +153,21 @@
:disabled="dialogType === 'edit'"
/>
</el-form-item>
<el-form-item :label="$t('page.form.rewardConfig')" prop="reward_config_id">
<el-form-item :label="$t('page.form.rewardTier')" prop="reward_tier">
<el-select
v-model="formData.reward_config_id"
:placeholder="$t('page.form.placeholderRewardConfig')"
v-model="formData.reward_tier"
:placeholder="$t('page.form.placeholderRewardTier')"
clearable
filterable
style="width: 100%"
:disabled="dialogType === 'edit'"
:disabled="true"
>
<el-option
v-for="item in rewardConfigOptions"
:key="item.id"
:label="
item.ui_text
? `${item.ui_text}${item.tier ? ' (' + item.tier + ')' : ''}`
: String(item.id)
"
:value="item.id"
/>
<el-option label="T1" value="T1" />
<el-option label="T2" value="T2" />
<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>
@@ -239,12 +235,11 @@
trigger: 'change'
}
],
reward_config_id: [{ required: true, message: '请选择奖励配置', trigger: 'change' }]
reward_tier: [{ required: true, message: '请选择中奖档位', trigger: 'change' }]
})
const playerOptions = ref<Array<{ id: number; username: string }>>([])
const lotteryConfigOptions = ref<Array<{ id: number; name: string }>>([])
const rewardConfigOptions = ref<Array<{ id: number; ui_text: string; tier: string }>>([])
const initialFormData = {
id: null as number | null,
@@ -260,7 +255,7 @@
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
reward_tier: '' as string
}
/** 摇取点数固定 5 位 [n0..n4],每项 16 */
@@ -277,22 +272,17 @@
if (open) {
initPage()
try {
const [players, lotteryConfigs, rewardConfigs] = await Promise.all([
const [players, lotteryConfigs] = await Promise.all([
api.getPlayerOptions(),
api.getLotteryConfigOptions(),
api.getRewardConfigOptions()
api.getLotteryConfigOptions()
])
playerOptions.value = Array.isArray(players) ? players : ((players as any)?.data ?? [])
lotteryConfigOptions.value = Array.isArray(lotteryConfigs)
? lotteryConfigs
: ((lotteryConfigs as any)?.data ?? [])
rewardConfigOptions.value = Array.isArray(rewardConfigs)
? rewardConfigs
: ((rewardConfigs as any)?.data ?? [])
} catch {
playerOptions.value = []
lotteryConfigOptions.value = []
rewardConfigOptions.value = []
}
}
}
@@ -322,7 +312,7 @@
'target_index',
'roll_array',
'roll_number',
'reward_config_id'
'reward_tier'
]
keys.forEach((key) => {
const val = props.data![key]

View File

@@ -101,6 +101,7 @@
<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-col>

View File

@@ -8,7 +8,9 @@
<ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData">
<template #left>
<span v-if="totalWinCoin !== null" class="table-summary-inline">
{{ $t('page.toolbar.platformTotalProfit') }}<strong>{{ formatPlatformCoin(totalWinCoin) }}</strong>
{{ $t('page.toolbar.platformTotalProfit') }}<strong>{{
formatPlatformCoin(totalWinCoin)
}}</strong>
</span>
<ElSpace wrap class="table-toolbar-buttons">
<ElButton
@@ -97,8 +99,8 @@
{{ formatRollArray(row.roll_array) }}
</ElTag>
</template>
<!-- 奖励档位显示 DiceRewardConfig.tier -->
<template #reward_config_id="{ row }">
<!-- 奖励档位优先显示记录自带 reward_tier -->
<template #reward_tier="{ row }">
<ElTag size="small">{{ rewardTierFormatter(row) }}</ElTag>
</template>
<!-- 平台币相关统一整数显示 -->
@@ -180,8 +182,7 @@
const lotteryConfigNameFormatter = (row: Record<string, any>) =>
row?.diceLotteryPoolConfig?.name ?? row?.lottery_config_id ?? '-'
const rewardTierFormatter = (row: Record<string, any>) =>
row?.diceRewardConfig?.tier ?? row?.reward_config_id ?? '-'
const rewardTierFormatter = (row: Record<string, any>) => row?.reward_tier ?? '-'
/** 摇取点数格式化为 1,3,4,5,6 */
function formatRollArray(val: unknown): string {
@@ -258,18 +259,18 @@
useSlot: true
},
{ prop: 'lottery_type', label: 'page.table.drawType', width: 100, useSlot: true },
{ prop: 'direction', label: 'page.table.direction', width: 90, useSlot: true },
{ prop: 'ante', label: 'page.table.ante', width: 90 },
{ prop: 'is_win', label: 'page.table.isBigWin', width: 100, useSlot: true },
{ prop: 'paid_amount', label: 'page.table.paidAmount', width: 130 },
{ prop: 'ante', label: 'page.table.ante', width: 90 },
{ prop: 'win_coin', label: 'page.table.winCoin', width: 110, useSlot: true },
{ prop: 'super_win_coin', label: 'page.table.superWinCoin', width: 120, useSlot: true },
{ prop: 'reward_win_coin', label: 'page.table.rewardWinCoin', width: 140, useSlot: true },
{ prop: 'direction', label: 'page.table.direction', width: 90, useSlot: true },
{ prop: 'start_index', label: 'page.table.startIndex', width: 90 },
{ prop: 'target_index', label: 'page.table.targetIndex', width: 90 },
{ prop: 'roll_array', label: 'page.table.rollArray', width: 140, useSlot: true },
{ prop: 'roll_number', label: 'page.table.rollNumber', width: 110, sortable: true },
{ prop: 'reward_config_id', label: 'page.table.rewardConfig', width: 100, useSlot: true },
{ prop: 'reward_tier', label: 'page.table.rewardTier', width: 100, useSlot: true },
{ prop: 'status', label: 'page.table.status', width: 80, useSlot: true },
{ prop: 'create_time', label: 'page.table.createTime', width: 170 },
{

View File

@@ -67,21 +67,15 @@
:placeholder="$t('page.form.placeholderRewardTier')"
clearable
style="width: 100%"
@change="onRewardTierChange"
>
<el-option label="T1" value="T1" />
<el-option label="T2" value="T2" />
<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 :label="$t('page.form.rewardConfigId')" prop="reward_config_id">
<el-input
v-model="formData.reward_config_id"
:placeholder="$t('page.form.placeholderRewardConfigId')"
/>
</el-form-item>
<el-form-item :label="$t('page.table.startIndex')" prop="start_index">
<el-input v-model="formData.start_index" :placeholder="$t('page.form.placeholderStartIndex')" />
</el-form-item>
@@ -128,7 +122,6 @@
<script setup lang="ts">
import api from '../../../api/play_record_test/index'
import rewardConfigApi from '../../../api/reward_config/index'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { useI18n } from 'vue-i18n'
@@ -171,7 +164,7 @@
lottery_type: [{ required: true, message: t('page.form.ruleDrawTypeRequired'), trigger: 'blur' }],
is_win: [{ required: true, message: t('page.form.ruleIsBigWinRequired'), trigger: 'blur' }],
direction: [{ required: true, message: t('page.form.ruleDirectionRequired'), trigger: 'blur' }],
reward_config_id: [{ required: true, message: t('page.form.ruleRewardConfigIdRequired'), trigger: 'blur' }],
reward_tier: [{ required: true, message: t('page.form.ruleRewardTierRequired'), trigger: 'blur' }],
status: [{ required: true, message: t('page.form.ruleStatusRequired'), trigger: 'blur' }]
}))
@@ -188,7 +181,6 @@
win_coin: 0,
direction: null,
reward_tier: undefined as string | undefined,
reward_config_id: null,
start_index: null,
target_index: null,
roll_number: null,
@@ -242,7 +234,6 @@
const initForm = () => {
if (props.data) {
for (const key in formData) {
if (key === 'reward_tier') continue
if (props.data[key] != null && props.data[key] !== undefined) {
;(formData as Record<string, unknown>)[key] = props.data[key]
}
@@ -253,30 +244,6 @@
}
}
/**
* 中奖档位变更:按档位拉取奖励配置并取第一条的 id 填入 reward_config_id
*/
async function onRewardTierChange(tier: string) {
if (!tier) {
formData.reward_config_id = null
return
}
try {
const res = await rewardConfigApi.list({
saiType: 'all',
tier: tier
})
const list = res?.data
const first = Array.isArray(list) && list.length > 0 ? list[0] : undefined
if (first && first.id != null) {
formData.reward_config_id = first.id
} else {
formData.reward_config_id = null
}
} catch {
formData.reward_config_id = null
}
}
/**
* 关闭弹窗并重置表单
@@ -294,7 +261,6 @@
try {
await formRef.value.validate()
const payload = { ...formData }
delete (payload as Record<string, unknown>).reward_tier
if (props.dialogType === 'add') {
await api.save(payload)
ElMessage.success(t('page.form.addSuccess'))

View File

@@ -95,6 +95,7 @@
<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-col>

View File

@@ -98,6 +98,7 @@
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { useTable } from '@/hooks/core/useTable'
import { useSaiAdmin } from '@/composables/useSaiAdmin'
import api from '../../api/player/index'
@@ -105,6 +106,8 @@
import EditDialog from './modules/edit-dialog.vue'
import WalletOperateDialog from './modules/WalletOperateDialog.vue'
const { t } = useI18n()
// 搜索表单
const searchForm = ref({
username: undefined,
@@ -129,7 +132,8 @@
// 根据 lottery_config_id 显示彩金池配置名称
const lotteryConfigNameFormatter = (row: any) =>
row?.diceLotteryPoolConfig?.name ?? (row?.lottery_config_id ? `#${row.lottery_config_id}` : '未知')
row?.diceLotteryPoolConfig?.name ??
(row?.lottery_config_id ? `#${row.lottery_config_id}` : t('page.table.customConfig'))
// 表格
const {

View File

@@ -271,9 +271,9 @@ export function generateTiers(input: GenerateTierInput): GenerateTierResult {
return { ok: false, message: '在当前盘面与约束下未找到可行解,请调整 T1/T4/T5 固定条数或放宽 T2 下限后重试' }
}
/** 展示文案:100 + 真实结算(中英文相同)T5 不使用 */
function uiTextFromRealEvPlus100(realEv: number): { ui_text: string; ui_text_en: string } {
const s = String(100 + realEv)
/** 展示文案:直接使用真实结算(中英文相同) */
function uiTextFromRealEv(realEv: number): { ui_text: string; ui_text_en: string } {
const s = String(realEv)
return { ui_text: s, ui_text_en: s }
}
@@ -315,32 +315,33 @@ export function buildRowsFromTiers(
if (standards !== undefined) {
if (tier === 'T1') {
real_ev = standards.T1
const f = uiTextFromRealEvPlus100(real_ev)
const f = uiTextFromRealEv(real_ev)
ui_text = f.ui_text
ui_text_en = f.ui_text_en
remark = '大奖格'
} else if (tier === 'T2') {
real_ev = standards.T2
const f = uiTextFromRealEvPlus100(real_ev)
const f = uiTextFromRealEv(real_ev)
ui_text = f.ui_text
ui_text_en = f.ui_text_en
remark = standards.T2 <= 1 ? '完美回本' : '小赚'
} else if (tier === 'T3') {
real_ev = standards.T3
const f = uiTextFromRealEvPlus100(real_ev)
const f = uiTextFromRealEv(real_ev)
ui_text = f.ui_text
ui_text_en = f.ui_text_en
remark = '抽水'
} else if (tier === 'T4') {
real_ev = standards.T4
const f = uiTextFromRealEvPlus100(real_ev)
const f = uiTextFromRealEv(real_ev)
ui_text = f.ui_text
ui_text_en = f.ui_text_en
remark = '惩罚'
} else {
real_ev = standards.T5
ui_text = '再来一次'
ui_text_en = 'Once again'
const f = uiTextFromRealEv(real_ev)
ui_text = f.ui_text
ui_text_en = f.ui_text_en
remark = '前端需要在播放一次动画(特殊)'
}
} else if (tier === 'T1') {
@@ -348,7 +349,7 @@ export function buildRowsFromTiers(
if (real_ev >= 500) {
real_ev = 498
}
const f = uiTextFromRealEvPlus100(real_ev)
const f = uiTextFromRealEv(real_ev)
ui_text = f.ui_text
ui_text_en = f.ui_text_en
remark = '大奖格'
@@ -363,26 +364,27 @@ export function buildRowsFromTiers(
}
remark = '小赚'
}
const f = uiTextFromRealEvPlus100(real_ev)
const f = uiTextFromRealEv(real_ev)
ui_text = f.ui_text
ui_text_en = f.ui_text_en
} else if (tier === 'T3') {
real_ev = -72 - (id % 15)
const f = uiTextFromRealEvPlus100(real_ev)
const f = uiTextFromRealEv(real_ev)
ui_text = f.ui_text
ui_text_en = f.ui_text_en
remark = '抽水'
} else if (tier === 'T4') {
t4Seq++
real_ev = -101 - t4Seq * 15
const f = uiTextFromRealEvPlus100(real_ev)
const f = uiTextFromRealEv(real_ev)
ui_text = f.ui_text
ui_text_en = f.ui_text_en
remark = '惩罚'
} else {
real_ev = 0
ui_text = '再来一次'
ui_text_en = 'Once again'
const f = uiTextFromRealEv(real_ev)
ui_text = f.ui_text
ui_text_en = f.ui_text_en
remark = '前端需要在播放一次动画(特殊)'
}
rows.push({