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

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

@@ -361,6 +361,7 @@
"dice": { "dice": {
"title": "Dice Game", "title": "Dice Game",
"lotteryPoolConfig": "Lottery Tier Weight Config", "lotteryPoolConfig": "Lottery Tier Weight Config",
"anteConfig": "Ante Config",
"player": "Player Management", "player": "Player Management",
"playerWalletRecord": "Player Wallet Records", "playerWalletRecord": "Player Wallet Records",
"playRecord": "Player Draw Records", "playRecord": "Player Draw Records",

View File

@@ -30,8 +30,8 @@
"rollArrayHint": "5 numbers, each 16", "rollArrayHint": "5 numbers, each 16",
"rollNumber": "Roll Sum", "rollNumber": "Roll Sum",
"placeholderRollNumber": "Sum of 5 dice (530)", "placeholderRollNumber": "Sum of 5 dice (530)",
"rewardConfig": "Reward Config", "rewardTier": "Reward Tier",
"placeholderRewardConfig": "Select reward config (by UI text)", "placeholderRewardTier": "Select reward tier",
"addSuccess": "Added successfully", "addSuccess": "Added successfully",
"editSuccess": "Updated successfully", "editSuccess": "Updated successfully",
"validateFailed": "Validation failed, please check required fields and format" "validateFailed": "Validation failed, please check required fields and format"
@@ -47,8 +47,8 @@
"direction": "Direction", "direction": "Direction",
"winCoin": "Win Coin", "winCoin": "Win Coin",
"rollNumber": "Roll Number", "rollNumber": "Roll Number",
"rewardConfig": "Reward Config",
"rewardTier": "Reward Tier", "rewardTier": "Reward Tier",
"rewardConfig": "Reward Config",
"usernameFuzzy": "Username (fuzzy)", "usernameFuzzy": "Username (fuzzy)",
"nameFuzzy": "Name (fuzzy)", "nameFuzzy": "Name (fuzzy)",
"uiTextFuzzy": "UI Text (fuzzy)", "uiTextFuzzy": "UI Text (fuzzy)",
@@ -75,7 +75,7 @@
"targetIndex": "Target Index", "targetIndex": "Target Index",
"rollArray": "Roll Array", "rollArray": "Roll Array",
"rollNumber": "Roll Number", "rollNumber": "Roll Number",
"rewardConfig": "Reward Config", "rewardTier": "Reward Tier",
"createTime": "Create Time", "createTime": "Create Time",
"updateTime": "Update Time" "updateTime": "Update Time"
} }

View File

@@ -37,7 +37,8 @@
"targetIndex": "Target Index", "targetIndex": "Target Index",
"rollArray": "Roll Array", "rollArray": "Roll Array",
"rollNumber": "Roll Number", "rollNumber": "Roll Number",
"rewardConfig": "Reward Config", "rewardTier": "Reward Tier",
"status": "Status",
"createTime": "Create Time" "createTime": "Create Time"
}, },
"form": { "form": {
@@ -46,9 +47,7 @@
"labelLotteryConfigId": "Lottery Config ID", "labelLotteryConfigId": "Lottery Config ID",
"placeholderLotteryConfigId": "Please enter lottery config id", "placeholderLotteryConfigId": "Please enter lottery config id",
"placeholderWinCoin": "Win coin", "placeholderWinCoin": "Win coin",
"placeholderRewardTier": "Please select tier (will auto fill reward config id)", "placeholderRewardTier": "Please select reward tier",
"rewardConfigId": "Reward Config ID",
"placeholderRewardConfigId": "Auto fill by tier or enter manually",
"placeholderStartIndex": "Please enter start index", "placeholderStartIndex": "Please enter start index",
"labelTargetIndex": "Target Index", "labelTargetIndex": "Target Index",
"placeholderTargetIndex": "Please enter target index", "placeholderTargetIndex": "Please enter target index",
@@ -64,7 +63,7 @@
"ruleDrawTypeRequired": "Draw type is required", "ruleDrawTypeRequired": "Draw type is required",
"ruleIsBigWinRequired": "Is big win is required", "ruleIsBigWinRequired": "Is big win is required",
"ruleDirectionRequired": "Direction is required", "ruleDirectionRequired": "Direction is required",
"ruleRewardConfigIdRequired": "Reward config id is required", "ruleRewardTierRequired": "Reward tier is required",
"ruleStatusRequired": "Status is required", "ruleStatusRequired": "Status is required",
"addSuccess": "Added successfully", "addSuccess": "Added successfully",
"editSuccess": "Updated successfully" "editSuccess": "Updated successfully"

View File

@@ -66,6 +66,7 @@
"status": "Status", "status": "Status",
"coin": "Coin", "coin": "Coin",
"lotteryPoolConfig": "Lottery Pool Config", "lotteryPoolConfig": "Lottery Pool Config",
"customConfig": "Custom",
"t1Weight": "T1 Weight", "t1Weight": "T1 Weight",
"t2Weight": "T2 Weight", "t2Weight": "T2 Weight",
"t3Weight": "T3 Weight", "t3Weight": "T3 Weight",

View File

@@ -357,6 +357,7 @@
"dice": { "dice": {
"title": "大富翁-色子游戏", "title": "大富翁-色子游戏",
"lotteryPoolConfig": "彩金池配置", "lotteryPoolConfig": "彩金池配置",
"anteConfig": "底注配置",
"player": "玩家管理", "player": "玩家管理",
"playerWalletRecord": "玩家钱包记录", "playerWalletRecord": "玩家钱包记录",
"playRecord": "玩家抽奖记录", "playRecord": "玩家抽奖记录",

View File

@@ -30,8 +30,8 @@
"rollArrayHint": "固定 5 个数,每个 16", "rollArrayHint": "固定 5 个数,每个 16",
"rollNumber": "摇取点数和", "rollNumber": "摇取点数和",
"placeholderRollNumber": "5 个色子点数之和530", "placeholderRollNumber": "5 个色子点数之和530",
"rewardConfig": "奖励配置", "rewardTier": "中奖档位",
"placeholderRewardConfig": "请选择奖励配置(显示前端文本)", "placeholderRewardTier": "请选择中奖档位",
"addSuccess": "新增成功", "addSuccess": "新增成功",
"editSuccess": "修改成功", "editSuccess": "修改成功",
"validateFailed": "表单验证失败,请检查必填项与格式" "validateFailed": "表单验证失败,请检查必填项与格式"
@@ -47,8 +47,8 @@
"direction": "方向", "direction": "方向",
"winCoin": "赢取平台币", "winCoin": "赢取平台币",
"rollNumber": "摇取点数和", "rollNumber": "摇取点数和",
"rewardTier": "中奖档位",
"rewardConfig": "奖励配置", "rewardConfig": "奖励配置",
"rewardTier": "奖励档位",
"usernameFuzzy": "用户名模糊", "usernameFuzzy": "用户名模糊",
"nameFuzzy": "名称模糊", "nameFuzzy": "名称模糊",
"uiTextFuzzy": "前端显示文本模糊", "uiTextFuzzy": "前端显示文本模糊",
@@ -75,7 +75,7 @@
"targetIndex": "终点索引", "targetIndex": "终点索引",
"rollArray": "摇取点数", "rollArray": "摇取点数",
"rollNumber": "摇取点数和", "rollNumber": "摇取点数和",
"rewardConfig": "奖励配置", "rewardTier": "中奖档位",
"createTime": "创建时间", "createTime": "创建时间",
"updateTime": "更新时间" "updateTime": "更新时间"
} }

View File

@@ -11,7 +11,7 @@
"winCoin": "赢取平台币", "winCoin": "赢取平台币",
"paidAmount": "付费金额", "paidAmount": "付费金额",
"ante": "底注", "ante": "底注",
"rewardTier": "奖档位", "rewardTier": "奖档位",
"rollNumber": "摇取点数和", "rollNumber": "摇取点数和",
"paid": "付费", "paid": "付费",
"free": "免费", "free": "免费",
@@ -37,7 +37,8 @@
"targetIndex": "终点索引", "targetIndex": "终点索引",
"rollArray": "摇取点数", "rollArray": "摇取点数",
"rollNumber": "摇取点数和", "rollNumber": "摇取点数和",
"rewardConfig": "奖励配置", "rewardTier": "中奖档位",
"status": "状态",
"createTime": "创建时间" "createTime": "创建时间"
}, },
"form": { "form": {
@@ -46,9 +47,7 @@
"labelLotteryConfigId": "彩金池配置id", "labelLotteryConfigId": "彩金池配置id",
"placeholderLotteryConfigId": "请输入彩金池配置id", "placeholderLotteryConfigId": "请输入彩金池配置id",
"placeholderWinCoin": "赢取平台币", "placeholderWinCoin": "赢取平台币",
"placeholderRewardTier": "请选择档位(选后自动带出奖励配置ID)", "placeholderRewardTier": "请选择中奖档位",
"rewardConfigId": "奖励配置id",
"placeholderRewardConfigId": "可选中奖档位自动带出或手动输入",
"placeholderStartIndex": "请输入起始索引", "placeholderStartIndex": "请输入起始索引",
"labelTargetIndex": "结束索引", "labelTargetIndex": "结束索引",
"placeholderTargetIndex": "请输入结束索引", "placeholderTargetIndex": "请输入结束索引",
@@ -64,7 +63,7 @@
"ruleDrawTypeRequired": "抽奖类型必需填写", "ruleDrawTypeRequired": "抽奖类型必需填写",
"ruleIsBigWinRequired": "是否中大奖必需填写", "ruleIsBigWinRequired": "是否中大奖必需填写",
"ruleDirectionRequired": "方向必需填写", "ruleDirectionRequired": "方向必需填写",
"ruleRewardConfigIdRequired": "奖励配置id必需填写", "ruleRewardTierRequired": "中奖档位必需填写",
"ruleStatusRequired": "状态必需填写", "ruleStatusRequired": "状态必需填写",
"addSuccess": "新增成功", "addSuccess": "新增成功",
"editSuccess": "修改成功" "editSuccess": "修改成功"

View File

@@ -66,6 +66,7 @@
"status": "状态", "status": "状态",
"coin": "平台币", "coin": "平台币",
"lotteryPoolConfig": "彩金池配置", "lotteryPoolConfig": "彩金池配置",
"customConfig": "自定义",
"t1Weight": "T1权重", "t1Weight": "T1权重",
"t2Weight": "T2权重", "t2Weight": "T2权重",
"t3Weight": "T3权重", "t3Weight": "T3权重",

View File

@@ -42,6 +42,8 @@ export const MAP_PATH_TO_MENU_I18N_KEY: Record<string, string> = {
'/dice': 'menus.dice.title', '/dice': 'menus.dice.title',
'/dice/lottery_pool_config': 'menus.dice.lotteryPoolConfig', '/dice/lottery_pool_config': 'menus.dice.lotteryPoolConfig',
'/dice/lottery_pool_config/index': 'menus.dice.lotteryPoolConfig', '/dice/lottery_pool_config/index': 'menus.dice.lotteryPoolConfig',
'/dice/ante_config': 'menus.dice.anteConfig',
'/dice/ante_config/index': 'menus.dice.anteConfig',
'/dice/player': 'menus.dice.player', '/dice/player': 'menus.dice.player',
'/dice/player/index': 'menus.dice.player', '/dice/player/index': 'menus.dice.player',
'/dice/player_wallet_record': 'menus.dice.playerWalletRecord', '/dice/player_wallet_record': 'menus.dice.playerWalletRecord',

View File

@@ -75,12 +75,5 @@ export default {
return request.get<{ id: number; name: string }[]>({ return request.get<{ id: number; name: string }[]>({
url: '/dice/play_record/DicePlayRecord/getLotteryConfigOptions' 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 --> <!-- 抽奖类型 tag -->
<template #lottery_type="{ row }"> <template #lottery_type="{ row }">
<ElTag size="small" :type="row.lottery_type === 0 ? 'warning' : 'success'"> <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> </ElTag>
</template> </template>
<!-- 是否中大奖 tag --> <!-- 是否中大奖 tag -->
<template #is_win="{ row }"> <template #is_win="{ row }">
<ElTag size="small" :type="row.is_win === 1 ? 'success' : 'info'"> <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> </ElTag>
</template> </template>
<!-- 方向 tag --> <!-- 方向 tag -->
<template #direction="{ row }"> <template #direction="{ row }">
<ElTag size="small" :type="row.direction === 0 ? 'primary' : 'warning'"> <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> </ElTag>
</template> </template>
<!-- 平台币相关统一整数显示 --> <!-- 平台币相关统一整数显示 -->
@@ -158,8 +176,7 @@
row?.dicePlayer?.username ?? row?.player_id ?? '-' row?.dicePlayer?.username ?? row?.player_id ?? '-'
const lotteryConfigNameFormatter = (row: Record<string, any>) => const lotteryConfigNameFormatter = (row: Record<string, any>) =>
row?.diceLotteryPoolConfig?.name ?? row?.lottery_config_id ?? '-' row?.diceLotteryPoolConfig?.name ?? row?.lottery_config_id ?? '-'
const rewardTierFormatter = (row: Record<string, any>) => const rewardTierFormatter = (row: Record<string, any>) => row?.reward_tier ?? '-'
row?.diceRewardConfig?.tier ?? row?.reward_config_id ?? '-'
/** 摇取点数格式化为 1,3,4,5,6,6 */ /** 摇取点数格式化为 1,3,4,5,6,6 */
function formatRollArray(val: unknown): string { function formatRollArray(val: unknown): string {
@@ -216,25 +233,32 @@
useSlot: true useSlot: true
}, },
{ prop: 'lottery_type', label: 'page.table.drawType', width: 100, 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: 'ante', label: 'page.table.ante', width: 80, align: 'center' },
{ prop: 'paid_amount', label: 'page.table.paidAmount', width: 110, 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: 'is_win', label: 'page.table.isBigWin', width: 100, useSlot: true },
{ prop: 'win_coin', label: 'page.table.winCoin', width: 110, 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: 'super_win_coin', label: 'page.table.superWinCoin', width: 120, useSlot: true },
{ prop: 'reward_win_coin', label: 'page.table.rewardWinCoin', width: 140, 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: 'start_index', label: 'page.table.startIndex', width: 90 },
{ prop: 'target_index', label: 'page.table.targetIndex', width: 90 }, { prop: 'target_index', label: 'page.table.targetIndex', width: 90 },
{ prop: 'roll_array', label: 'page.table.rollArray', width: 140, useSlot: true }, { prop: 'roll_array', label: 'page.table.rollArray', width: 140, useSlot: true },
{ prop: 'roll_number', label: 'page.table.rollNumber', width: 110, sortable: true }, { prop: 'roll_number', label: 'page.table.rollNumber', width: 110, sortable: true },
{ {
prop: 'reward_config_id', prop: 'reward_tier',
label: 'page.table.rewardConfig', label: 'page.table.rewardTier',
width: 100,
formatter: (row: Record<string, any>) => rewardTierFormatter(row) formatter: (row: Record<string, any>) => rewardTierFormatter(row)
}, },
{ prop: 'create_time', label: 'page.table.createTime', width: 170 }, { prop: 'create_time', label: 'page.table.createTime', width: 170 },
{ prop: 'update_time', label: 'page.table.updateTime', 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'" :disabled="dialogType === 'edit'"
/> />
</el-form-item> </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 <el-select
v-model="formData.reward_config_id" v-model="formData.reward_tier"
:placeholder="$t('page.form.placeholderRewardConfig')" :placeholder="$t('page.form.placeholderRewardTier')"
clearable clearable
filterable filterable
style="width: 100%" style="width: 100%"
:disabled="dialogType === 'edit'" :disabled="true"
> >
<el-option <el-option label="T1" value="T1" />
v-for="item in rewardConfigOptions" <el-option label="T2" value="T2" />
:key="item.id" <el-option label="T3" value="T3" />
:label=" <el-option label="T4" value="T4" />
item.ui_text <el-option label="T5" value="T5" />
? `${item.ui_text}${item.tier ? ' (' + item.tier + ')' : ''}` <el-option label="BIGWIN" value="BIGWIN" />
: String(item.id)
"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -239,12 +235,11 @@
trigger: 'change' 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 playerOptions = ref<Array<{ id: number; username: string }>>([])
const lotteryConfigOptions = ref<Array<{ id: number; name: string }>>([]) const lotteryConfigOptions = ref<Array<{ id: number; name: string }>>([])
const rewardConfigOptions = ref<Array<{ id: number; ui_text: string; tier: string }>>([])
const initialFormData = { const initialFormData = {
id: null as number | null, id: null as number | null,
@@ -260,7 +255,7 @@
target_index: null as number | null, target_index: null as number | null,
roll_array: null as string | number[] | null, roll_array: null as string | number[] | null,
roll_number: null as number | null, roll_number: null as number | null,
reward_config_id: null as number | null reward_tier: '' as string
} }
/** 摇取点数固定 5 位 [n0..n4],每项 16 */ /** 摇取点数固定 5 位 [n0..n4],每项 16 */
@@ -277,22 +272,17 @@
if (open) { if (open) {
initPage() initPage()
try { try {
const [players, lotteryConfigs, rewardConfigs] = await Promise.all([ const [players, lotteryConfigs] = await Promise.all([
api.getPlayerOptions(), api.getPlayerOptions(),
api.getLotteryConfigOptions(), api.getLotteryConfigOptions()
api.getRewardConfigOptions()
]) ])
playerOptions.value = Array.isArray(players) ? players : ((players as any)?.data ?? []) playerOptions.value = Array.isArray(players) ? players : ((players as any)?.data ?? [])
lotteryConfigOptions.value = Array.isArray(lotteryConfigs) lotteryConfigOptions.value = Array.isArray(lotteryConfigs)
? lotteryConfigs ? lotteryConfigs
: ((lotteryConfigs as any)?.data ?? []) : ((lotteryConfigs as any)?.data ?? [])
rewardConfigOptions.value = Array.isArray(rewardConfigs)
? rewardConfigs
: ((rewardConfigs as any)?.data ?? [])
} catch { } catch {
playerOptions.value = [] playerOptions.value = []
lotteryConfigOptions.value = [] lotteryConfigOptions.value = []
rewardConfigOptions.value = []
} }
} }
} }
@@ -322,7 +312,7 @@
'target_index', 'target_index',
'roll_array', 'roll_array',
'roll_number', 'roll_number',
'reward_config_id' 'reward_tier'
] ]
keys.forEach((key) => { keys.forEach((key) => {
const val = props.data![key] const val = props.data![key]

View File

@@ -101,6 +101,7 @@
<el-option label="T3" value="T3" /> <el-option label="T3" value="T3" />
<el-option label="T4" value="T4" /> <el-option label="T4" value="T4" />
<el-option label="T5" value="T5" /> <el-option label="T5" value="T5" />
<el-option label="BIGWIN" value="BIGWIN" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>

View File

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

View File

@@ -67,21 +67,15 @@
:placeholder="$t('page.form.placeholderRewardTier')" :placeholder="$t('page.form.placeholderRewardTier')"
clearable clearable
style="width: 100%" style="width: 100%"
@change="onRewardTierChange"
> >
<el-option label="T1" value="T1" /> <el-option label="T1" value="T1" />
<el-option label="T2" value="T2" /> <el-option label="T2" value="T2" />
<el-option label="T3" value="T3" /> <el-option label="T3" value="T3" />
<el-option label="T4" value="T4" /> <el-option label="T4" value="T4" />
<el-option label="T5" value="T5" /> <el-option label="T5" value="T5" />
<el-option label="BIGWIN" value="BIGWIN" />
</el-select> </el-select>
</el-form-item> </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-form-item :label="$t('page.table.startIndex')" prop="start_index">
<el-input v-model="formData.start_index" :placeholder="$t('page.form.placeholderStartIndex')" /> <el-input v-model="formData.start_index" :placeholder="$t('page.form.placeholderStartIndex')" />
</el-form-item> </el-form-item>
@@ -128,7 +122,6 @@
<script setup lang="ts"> <script setup lang="ts">
import api from '../../../api/play_record_test/index' import api from '../../../api/play_record_test/index'
import rewardConfigApi from '../../../api/reward_config/index'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
@@ -171,7 +164,7 @@
lottery_type: [{ required: true, message: t('page.form.ruleDrawTypeRequired'), trigger: 'blur' }], lottery_type: [{ required: true, message: t('page.form.ruleDrawTypeRequired'), trigger: 'blur' }],
is_win: [{ required: true, message: t('page.form.ruleIsBigWinRequired'), trigger: 'blur' }], is_win: [{ required: true, message: t('page.form.ruleIsBigWinRequired'), trigger: 'blur' }],
direction: [{ required: true, message: t('page.form.ruleDirectionRequired'), 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' }] status: [{ required: true, message: t('page.form.ruleStatusRequired'), trigger: 'blur' }]
})) }))
@@ -188,7 +181,6 @@
win_coin: 0, win_coin: 0,
direction: null, direction: null,
reward_tier: undefined as string | undefined, reward_tier: undefined as string | undefined,
reward_config_id: null,
start_index: null, start_index: null,
target_index: null, target_index: null,
roll_number: null, roll_number: null,
@@ -242,7 +234,6 @@
const initForm = () => { const initForm = () => {
if (props.data) { if (props.data) {
for (const key in formData) { for (const key in formData) {
if (key === 'reward_tier') continue
if (props.data[key] != null && props.data[key] !== undefined) { if (props.data[key] != null && props.data[key] !== undefined) {
;(formData as Record<string, unknown>)[key] = props.data[key] ;(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 { try {
await formRef.value.validate() await formRef.value.validate()
const payload = { ...formData } const payload = { ...formData }
delete (payload as Record<string, unknown>).reward_tier
if (props.dialogType === 'add') { if (props.dialogType === 'add') {
await api.save(payload) await api.save(payload)
ElMessage.success(t('page.form.addSuccess')) ElMessage.success(t('page.form.addSuccess'))

View File

@@ -95,6 +95,7 @@
<el-option label="T3" value="T3" /> <el-option label="T3" value="T3" />
<el-option label="T4" value="T4" /> <el-option label="T4" value="T4" />
<el-option label="T5" value="T5" /> <el-option label="T5" value="T5" />
<el-option label="BIGWIN" value="BIGWIN" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>

View File

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

View File

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

View File

@@ -76,28 +76,28 @@ class GameController extends BaseController
* header: token由 TokenMiddleware 注入 request->player_id * header: token由 TokenMiddleware 注入 request->player_id
* body: count = 1 | 5 | 101次/100coin, 5次/500coin, 10次/1000coin * body: count = 1 | 5 | 101次/100coin, 5次/500coin, 10次/1000coin
*/ */
public function buyLotteryTickets(Request $request): Response // public function buyLotteryTickets(Request $request): Response
{ // {
$userId = (int) ($request->player_id ?? 0); // $userId = (int) ($request->player_id ?? 0);
$count = (int) $request->post('count', 0); // $count = (int) $request->post('count', 0);
if (!in_array($count, [1, 5, 10], true)) { // if (!in_array($count, [1, 5, 10], true)) {
return $this->fail('Invalid lottery ticket purchase', ReturnCode::PARAMS_ERROR); // return $this->fail('Invalid lottery ticket purchase', ReturnCode::PARAMS_ERROR);
} // }
//
try { // try {
$logic = new GameLogic(); // $logic = new GameLogic();
$data = $logic->buyLotteryTickets($userId, $count); // $data = $logic->buyLotteryTickets($userId, $count);
return $this->success($data); // return $this->success($data);
} catch (ApiException $e) { // } catch (ApiException $e) {
$msg = $e->getMessage(); // $msg = $e->getMessage();
if ($msg === '平台币不足') { // if ($msg === '平台币不足') {
$player = DicePlayer::find($userId); // $player = DicePlayer::find($userId);
$coin = $player ? (float) $player->coin : 0; // $coin = $player ? (float) $player->coin : 0;
return $this->success(['coin' => $coin], $msg); // return $this->success(['coin' => $coin], $msg);
} // }
return $this->fail($msg, ReturnCode::BUSINESS_ERROR); // return $this->fail($msg, ReturnCode::BUSINESS_ERROR);
} // }
} // }
/** /**
* 获取彩金池(中奖配置表) * 获取彩金池(中奖配置表)
@@ -194,10 +194,11 @@ class GameController extends BaseController
$langLower = strtolower($lang); $langLower = strtolower($lang);
$isEn = $langLower === 'en' || str_starts_with($langLower, 'en-'); $isEn = $langLower === 'en' || str_starts_with($langLower, 'en-');
if (is_array($data) && array_key_exists('reward_config_id', $data)) { if (is_array($data)) {
$rewardConfigId = (int) $data['reward_config_id']; $rewardTier = array_key_exists('reward_tier', $data) ? (string) ($data['reward_tier'] ?? '') : '';
if ($rewardConfigId > 0) { $targetIndex = array_key_exists('target_index', $data) ? (int) ($data['target_index'] ?? 0) : 0;
$configRow = DiceRewardConfig::getCachedById($rewardConfigId); if ($rewardTier !== 'BIGWIN' && $targetIndex > 0) {
$configRow = DiceRewardConfig::getCachedById($targetIndex);
if ($configRow !== null) { if ($configRow !== null) {
$uiText = ''; $uiText = '';
$uiTextEn = ''; $uiTextEn = '';
@@ -247,9 +248,8 @@ class GameController extends BaseController
'win_coin' => 0, 'win_coin' => 0,
'super_win_coin' => 0, 'super_win_coin' => 0,
'reward_win_coin' => 0, 'reward_win_coin' => 0,
'use_coins' => 0,
'direction' => $direction, 'direction' => $direction,
'reward_config_id' => 0, 'reward_tier' => '',
'start_index' => 0, 'start_index' => 0,
'target_index' => 0, 'target_index' => 0,
'roll_array' => '[]', 'roll_array' => '[]',

View File

@@ -91,7 +91,7 @@ class UserController extends BaseController
if (empty($user)) { if (empty($user)) {
return $this->fail('User not found', ReturnCode::NOT_FOUND); return $this->fail('User not found', ReturnCode::NOT_FOUND);
} }
$fields = ['id', 'username', 'phone', 'uid', 'name', 'coin', 'total_ticket_count']; $fields = ['id', 'username', 'phone', 'uid', 'name', 'coin', 'total_ticket_count', 'free_ticket'];
$info = []; $info = [];
foreach ($fields as $field) { foreach ($fields as $field) {
if (array_key_exists($field, $user)) { if (array_key_exists($field, $user)) {

View File

@@ -24,6 +24,8 @@ use support\think\Db;
*/ */
class PlayStartLogic class PlayStartLogic
{ {
/** 钱包流水类型:购买抽奖次数 */
public const WALLET_TYPE_BUY_DRAW = 2;
/** 抽奖类型:付费 */ /** 抽奖类型:付费 */
public const LOTTERY_TYPE_PAID = 0; public const LOTTERY_TYPE_PAID = 0;
/** 抽奖类型:免费 */ /** 抽奖类型:免费 */
@@ -74,12 +76,32 @@ class PlayStartLogic
throw new ApiException('当前注数不合规,请选择正确的注数'); throw new ApiException('当前注数不合规,请选择正确的注数');
} }
// 免费抽奖:不再使用抽奖券作为开始条件,仅用 free_ticket_count 表示“免费抽奖次数” // 免费抽奖:优先使用 free_ticket带 ante 与 count兼容旧字段 free_ticket_count
$freeCount = (int) ($player->free_ticket_count ?? 0); $freeTicket = $player->free_ticket ?? null;
$isFree = $freeCount > 0; $freeTicketAnte = null;
$freeTicketCount = 0;
if (is_array($freeTicket)) {
$a = $freeTicket['ante'] ?? null;
$c = $freeTicket['count'] ?? null;
if ($a !== null && $a !== '' && is_numeric($a)) {
$freeTicketAnte = (int) $a;
}
if ($c !== null && $c !== '' && is_numeric($c)) {
$freeTicketCount = (int) $c;
}
}
$legacyFreeCount = (int) ($player->free_ticket_count ?? 0);
$isFree = ($freeTicketAnte !== null && $freeTicketCount > 0) || $legacyFreeCount > 0;
$ticketType = $isFree ? self::LOTTERY_TYPE_FREE : self::LOTTERY_TYPE_PAID; $ticketType = $isFree ? self::LOTTERY_TYPE_FREE : self::LOTTERY_TYPE_PAID;
// 若为免费抽奖:注数必须与上一次触发免费抽奖时的注数一致 // 若为 free_ticket 免费抽奖:注数必须与券的 ante 一致
if ($ticketType === self::LOTTERY_TYPE_FREE && $freeTicketAnte !== null && $freeTicketCount > 0) {
if ($ante !== $freeTicketAnte) {
throw new ApiException('您有一张底注为' . $freeTicketAnte . '的免费抽奖券');
}
}
// 若为免费抽奖(旧逻辑):注数必须与上一次触发免费抽奖时的注数一致
if ($isFree) { if ($isFree) {
$requiredAnte = Cache::get(self::FREE_ANTE_KEY_PREFIX . $playerId); $requiredAnte = Cache::get(self::FREE_ANTE_KEY_PREFIX . $playerId);
if ($requiredAnte !== null && $requiredAnte !== '' && (int) $requiredAnte !== $ante) { if ($requiredAnte !== null && $requiredAnte !== '' && (int) $requiredAnte !== $ante) {
@@ -231,7 +253,6 @@ class PlayStartLogic
$adminId, $adminId,
$configId, $configId,
$type0ConfigId, $type0ConfigId,
$rewardId,
$configName, $configName,
$ticketType, $ticketType,
$ante, $ante,
@@ -247,8 +268,10 @@ class PlayStartLogic
$targetIndex, $targetIndex,
$rollArray, $rollArray,
$isTierT5, $isTierT5,
$tier,
&$record &$record
) { ) {
$rewardTier = ($isWin === 1 && $superWinCoin > 0) ? 'BIGWIN' : (string) ($tier ?? '');
$record = DicePlayRecord::create([ $record = DicePlayRecord::create([
'player_id' => $playerId, 'player_id' => $playerId,
'admin_id' => $adminId, 'admin_id' => $adminId,
@@ -260,14 +283,12 @@ class PlayStartLogic
'win_coin' => $winCoin, 'win_coin' => $winCoin,
'super_win_coin' => $superWinCoin, 'super_win_coin' => $superWinCoin,
'reward_win_coin' => $rewardWinCoin, 'reward_win_coin' => $rewardWinCoin,
'use_coins' => $paidAmount,
'direction' => $direction, 'direction' => $direction,
'reward_config_id' => $rewardId, 'reward_tier' => $rewardTier,
'start_index' => $startIndex, 'start_index' => $startIndex,
'target_index' => $targetIndex, 'target_index' => $targetIndex,
'roll_array' => is_array($rollArray) ? json_encode($rollArray) : $rollArray, 'roll_array' => is_array($rollArray) ? json_encode($rollArray) : $rollArray,
'roll_number' => is_array($rollArray) ? array_sum($rollArray) : 0, 'roll_number' => is_array($rollArray) ? array_sum($rollArray) : 0,
'lottery_name' => $configName,
'status' => self::RECORD_STATUS_SUCCESS, 'status' => self::RECORD_STATUS_SUCCESS,
]); ]);
@@ -279,10 +300,32 @@ class PlayStartLogic
// 开始前先扣付费金额,再加中奖金额(免费抽奖 paid_amount=0 // 开始前先扣付费金额,再加中奖金额(免费抽奖 paid_amount=0
$coinAfter = $coinBefore - $paidAmount + $winCoin; $coinAfter = $coinBefore - $paidAmount + $winCoin;
$p->coin = $coinAfter; $p->coin = $coinAfter;
// 不再使用抽奖券作为抽奖条件:付费不扣抽奖次数;免费抽奖消耗 free_ticket_count // 免费抽奖消耗:优先消耗 free_ticket.count耗尽则清空 free_ticket否则兼容旧 free_ticket_count
if ($ticketType === self::LOTTERY_TYPE_FREE) { if ($ticketType === self::LOTTERY_TYPE_FREE) {
$ft = $p->free_ticket ?? null;
$ftAnte = null;
$ftCount = 0;
if (is_array($ft)) {
$a = $ft['ante'] ?? null;
$c = $ft['count'] ?? null;
if ($a !== null && $a !== '' && is_numeric($a)) {
$ftAnte = (int) $a;
}
if ($c !== null && $c !== '' && is_numeric($c)) {
$ftCount = (int) $c;
}
}
if ($ftAnte !== null && $ftCount > 0) {
$next = $ftCount - 1;
if ($next <= 0) {
$p->free_ticket = null;
} else {
$p->free_ticket = ['ante' => $ftAnte, 'count' => $next];
}
} else {
$p->free_ticket_count = max(0, (int) $p->free_ticket_count - 1); $p->free_ticket_count = max(0, (int) $p->free_ticket_count - 1);
} }
}
// 记录每次游玩:写入抽奖券记录(用于后台“抽奖券记录”追踪付费/免费游玩与消耗) // 记录每次游玩:写入抽奖券记录(用于后台“抽奖券记录”追踪付费/免费游玩与消耗)
$isPaidPlay = $ticketType === self::LOTTERY_TYPE_PAID; $isPaidPlay = $ticketType === self::LOTTERY_TYPE_PAID;
@@ -299,9 +342,32 @@ class PlayStartLogic
'remark' => ($isPaidPlay ? '付费游玩' : '免费游玩') . '|play_record_id=' . $record->id, 'remark' => ($isPaidPlay ? '付费游玩' : '免费游玩') . '|play_record_id=' . $record->id,
]); ]);
// 若本局中奖档位为 T5则额外赠送 1 次免费抽奖次数(总次数也 +1并记录抽奖券获取记录 // 若本局中奖档位为 T5则额外赠送 1 次免费抽奖次数
// - 新结构:写入 free_ticketante=本局注数count+1
// - 兼容旧结构free_ticket_count +1
if ($isTierT5) { if ($isTierT5) {
$ft = $p->free_ticket ?? null;
$ftAnte = null;
$ftCount = 0;
if (is_array($ft)) {
$a = $ft['ante'] ?? null;
$c = $ft['count'] ?? null;
if ($a !== null && $a !== '' && is_numeric($a)) {
$ftAnte = (int) $a;
}
if ($c !== null && $c !== '' && is_numeric($c)) {
$ftCount = (int) $c;
}
}
if ($ftAnte === null) {
$ftAnte = $ante;
}
if ($ftAnte === $ante) {
$p->free_ticket = ['ante' => $ante, 'count' => $ftCount + 1];
} else {
// 若已有不同注数的免费券,则仍保留旧字段累加,避免覆盖玩家已有券
$p->free_ticket_count = (int) $p->free_ticket_count + 1; $p->free_ticket_count = (int) $p->free_ticket_count + 1;
}
DicePlayerTicketRecord::create([ DicePlayerTicketRecord::create([
'player_id' => $playerId, 'player_id' => $playerId,
@@ -314,7 +380,15 @@ class PlayStartLogic
Cache::set(self::FREE_ANTE_KEY_PREFIX . $playerId, $ante, self::FREE_ANTE_TTL); Cache::set(self::FREE_ANTE_KEY_PREFIX . $playerId, $ante, self::FREE_ANTE_TTL);
} else { } else {
// 若本次消耗了最后一次免费抽奖,则清理注数锁 // 若本次消耗了最后一次免费抽奖,则清理注数锁
if ($ticketType === self::LOTTERY_TYPE_FREE && (int) $p->free_ticket_count <= 0) { $ft = $p->free_ticket ?? null;
$ftCount = 0;
if (is_array($ft)) {
$c = $ft['count'] ?? null;
if ($c !== null && $c !== '' && is_numeric($c)) {
$ftCount = (int) $c;
}
}
if ($ticketType === self::LOTTERY_TYPE_FREE && $ftCount <= 0 && (int) $p->free_ticket_count <= 0) {
Cache::delete(self::FREE_ANTE_KEY_PREFIX . $playerId); Cache::delete(self::FREE_ANTE_KEY_PREFIX . $playerId);
} }
} }
@@ -338,15 +412,30 @@ class PlayStartLogic
]); ]);
} }
// 钱包流水拆分:先记录购券扣费,再记录抽奖结果(中奖/惩罚)
if ($paidAmount > 0) {
$walletAfterBuy = $coinBefore - $paidAmount;
DicePlayerWalletRecord::create([ DicePlayerWalletRecord::create([
'player_id' => $playerId, 'player_id' => $playerId,
'admin_id' => $adminId, 'admin_id' => $adminId,
// 钱包流水记录本局净变化:-付费金额 + 中奖金额(免费抽奖付费金额为 0 'coin' => -$paidAmount,
'coin' => $winCoin - (float) $paidAmount, 'type' => self::WALLET_TYPE_BUY_DRAW,
'type' => self::WALLET_TYPE_DRAW,
'wallet_before' => $coinBefore, 'wallet_before' => $coinBefore,
'wallet_after' => $walletAfterBuy,
'remark' => '抽奖购券扣费|play_record_id=' . $record->id,
]);
}
$walletBeforeDraw = $coinBefore - $paidAmount;
$drawRemark = ($winCoin >= 0 ? '抽奖中奖' : '抽奖惩罚') . '|play_record_id=' . $record->id;
DicePlayerWalletRecord::create([
'player_id' => $playerId,
'admin_id' => $adminId,
'coin' => $winCoin,
'type' => self::WALLET_TYPE_DRAW,
'wallet_before' => $walletBeforeDraw,
'wallet_after' => $coinAfter, 'wallet_after' => $coinAfter,
'remark' => '抽奖|play_record_id=' . $record->id, 'remark' => $drawRemark,
]); ]);
}); });
} catch (\Throwable $e) { } catch (\Throwable $e) {
@@ -361,9 +450,8 @@ class PlayStartLogic
'win_coin' => 0, 'win_coin' => 0,
'super_win_coin' => 0, 'super_win_coin' => 0,
'reward_win_coin' => 0, 'reward_win_coin' => 0,
'use_coins' => 0,
'direction' => $direction, 'direction' => $direction,
'reward_config_id' => 0, 'reward_tier' => '',
'start_index' => $startIndex, 'start_index' => $startIndex,
'target_index' => 0, 'target_index' => 0,
'roll_array' => '[]', 'roll_array' => '[]',
@@ -390,7 +478,7 @@ class PlayStartLogic
$arr['roll_array'] = json_decode($arr['roll_array'], true) ?? []; $arr['roll_array'] = json_decode($arr['roll_array'], true) ?? [];
} }
$arr['roll_number'] = is_array($arr['roll_array'] ?? null) ? array_sum($arr['roll_array']) : 0; $arr['roll_number'] = is_array($arr['roll_array'] ?? null) ? array_sum($arr['roll_array']) : 0;
$arr['tier'] = $tier ?? ''; $arr['reward_tier'] = ($isWin === 1 && $superWinCoin > 0) ? 'BIGWIN' : (string) ($tier ?? '');
// 记录完数据后返回当前玩家余额与抽奖次数 // 记录完数据后返回当前玩家余额与抽奖次数
$arr['coin'] = $updated ? (float) $updated->coin : 0; $arr['coin'] = $updated ? (float) $updated->coin : 0;
return $arr; return $arr;
@@ -619,10 +707,10 @@ class PlayStartLogic
$winCoin = $superWinCoin + $rewardWinCoin; $winCoin = $superWinCoin + $rewardWinCoin;
$configId = $config !== null ? (int) $config->id : 0; $configId = $config !== null ? (int) $config->id : 0;
$rewardId = ($isWin === 1 && $superWinCoin > 0) ? 0 : $targetIndex;
$configName = $config !== null ? (string) ($config->name ?? '') : '自定义'; $configName = $config !== null ? (string) ($config->name ?? '') : '自定义';
$costRealEv = $realEv + ($isWin === 1 ? $bigWinRealEv : 0.0); $costRealEv = $realEv + ($isWin === 1 ? $bigWinRealEv : 0.0);
$paidAmount = $lotteryType === 0 ? ($ante * self::UNIT_COST) : 0; $paidAmount = $lotteryType === 0 ? ($ante * self::UNIT_COST) : 0;
$rewardTier = ($isWin === 1 && $superWinCoin > 0) ? 'BIGWIN' : (string) ($tier ?? '');
return [ return [
'player_id' => 0, 'player_id' => 0,
@@ -635,14 +723,12 @@ class PlayStartLogic
'paid_amount' => $paidAmount, 'paid_amount' => $paidAmount,
'super_win_coin' => $superWinCoin, 'super_win_coin' => $superWinCoin,
'reward_win_coin' => $rewardWinCoin, 'reward_win_coin' => $rewardWinCoin,
'use_coins' => $paidAmount,
'direction' => $direction, 'direction' => $direction,
'reward_config_id' => $rewardId, 'reward_tier' => $rewardTier,
'start_index' => $startIndex, 'start_index' => $startIndex,
'target_index' => $targetIndex, 'target_index' => $targetIndex,
'roll_array' => json_encode($rollArray), 'roll_array' => json_encode($rollArray),
'roll_number' => array_sum($rollArray), 'roll_number' => array_sum($rollArray),
'lottery_name' => $configName,
'status' => self::RECORD_STATUS_SUCCESS, 'status' => self::RECORD_STATUS_SUCCESS,
'tier' => $tier, 'tier' => $tier,
'roll_number_for_count' => $rollNumber, 'roll_number_for_count' => $rollNumber,

View File

@@ -12,7 +12,6 @@ use app\dice\logic\play_record\DicePlayRecordLogic;
use app\dice\validate\play_record\DicePlayRecordValidate; use app\dice\validate\play_record\DicePlayRecordValidate;
use app\dice\model\player\DicePlayer; use app\dice\model\player\DicePlayer;
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig; use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
use app\dice\model\reward\DiceRewardConfig;
use plugin\saiadmin\service\Permission; use plugin\saiadmin\service\Permission;
use support\Request; use support\Request;
use support\Response; use support\Response;
@@ -57,7 +56,6 @@ class DicePlayRecordController extends BaseController
AdminScopeHelper::applyAdminScope($query, $this->adminInfo ?? null); AdminScopeHelper::applyAdminScope($query, $this->adminInfo ?? null);
$query->with([ $query->with([
'dicePlayer', 'dicePlayer',
'diceRewardConfig',
'diceLotteryPoolConfig', 'diceLotteryPoolConfig',
]); ]);
@@ -101,23 +99,6 @@ class DicePlayRecordController extends BaseController
return $this->success($data); return $this->success($data);
} }
/**
* 获取奖励配置选项id、ui_text、tier
*/
#[Permission('玩家抽奖记录列表', 'dice:play_record:index:index')]
public function getRewardConfigOptions(Request $request): Response
{
$list = DiceRewardConfig::field('id,ui_text,tier')->select();
$data = $list->map(function ($item) {
return [
'id' => $item['id'],
'ui_text' => $item['ui_text'] ?? '',
'tier' => $item['tier'] ?? ''
];
})->toArray();
return $this->success($data);
}
/** /**
* 读取数据 * 读取数据
* @param Request $request * @param Request $request

View File

@@ -50,7 +50,7 @@ class DicePlayRecordTestController extends BaseController
['roll_number', ''], ['roll_number', ''],
]); ]);
$query = $this->logic->search($where); $query = $this->logic->search($where);
$query->with(['diceLotteryPoolConfig', 'diceRewardConfig']); $query->with(['diceLotteryPoolConfig']);
// 按当前筛选条件统计:平台总盈利 = 付费金额(paid_amount 求和) - 玩家总收益(win_coin 求和) // 按当前筛选条件统计:平台总盈利 = 付费金额(paid_amount 求和) - 玩家总收益(win_coin 求和)
$sumQuery = clone $query; $sumQuery = clone $query;

View File

@@ -19,6 +19,26 @@ use support\think\Db;
class WeightTestRunner class WeightTestRunner
{ {
private const BATCH_SIZE = 10; private const BATCH_SIZE = 10;
/** 测试记录写库白名单字段 */
private const PLAY_RECORD_TEST_COLUMNS = [
'reward_config_record_id',
'admin_id',
'lottery_config_id',
'lottery_type',
'is_win',
'win_coin',
'super_win_coin',
'reward_win_coin',
'direction',
'reward_tier',
'ante',
'paid_amount',
'start_index',
'target_index',
'roll_array',
'roll_number',
'status',
];
/** /**
* 执行指定测试记录:按付费/免费、顺/逆方向交替模拟(付费顺→付费逆→免费顺→免费逆),每 10 条写入一次测试表并更新进度 * 执行指定测试记录:按付费/免费、顺/逆方向交替模拟(付费顺→付费逆→免费顺→免费逆),每 10 条写入一次测试表并更新进度
@@ -194,10 +214,10 @@ class WeightTestRunner
'reward_config_record_id' => $rewardConfigRecordId, 'reward_config_record_id' => $rewardConfigRecordId,
]; ];
$keys = [ $keys = [
'player_id', 'admin_id', 'lottery_config_id', 'lottery_type', 'is_win', 'win_coin', 'admin_id', 'lottery_config_id', 'lottery_type', 'is_win', 'win_coin',
'super_win_coin', 'reward_win_coin', 'use_coins', 'direction', 'reward_config_id', 'super_win_coin', 'reward_win_coin', 'direction', 'reward_tier',
'ante', 'paid_amount', 'ante', 'paid_amount',
'start_index', 'target_index', 'roll_array', 'roll_number', 'lottery_name', 'status', 'start_index', 'target_index', 'roll_array', 'roll_number', 'status',
]; ];
foreach ($keys as $k) { foreach ($keys as $k) {
if (array_key_exists($k, $row)) { if (array_key_exists($k, $row)) {
@@ -223,7 +243,19 @@ class WeightTestRunner
return; return;
} }
foreach ($rows as $row) { foreach ($rows as $row) {
DicePlayRecordTest::create($row); if (!is_array($row)) {
continue;
}
$payload = [];
foreach (self::PLAY_RECORD_TEST_COLUMNS as $column) {
if (array_key_exists($column, $row)) {
$payload[$column] = $row[$column];
}
}
if ($payload === []) {
continue;
}
Db::name((new DicePlayRecordTest())->getTable())->insert($payload);
} }
} }

View File

@@ -30,7 +30,7 @@ use think\model\relation\BelongsTo;
* @property $reward_win_coin 摇色子中奖平台币 * @property $reward_win_coin 摇色子中奖平台币
* @property $use_coins 消耗平台币(兼容字段:付费局=paid_amount免费局=0 * @property $use_coins 消耗平台币(兼容字段:付费局=paid_amount免费局=0
* @property $direction 方向:0=顺时针,1=逆时针 * @property $direction 方向:0=顺时针,1=逆时针
* @property $reward_config_id 奖励配置id * @property $reward_tier 中奖档位T1,T2,T3,T4,T5,BIGWIN
* @property $lottery_id 奖池 * @property $lottery_id 奖池
* @property $start_index 起始索引 * @property $start_index 起始索引
* @property $target_index 结束索引 * @property $target_index 结束索引
@@ -64,15 +64,6 @@ class DicePlayRecord extends BaseModel
return $this->belongsTo(DicePlayer::class, 'player_id', 'id'); return $this->belongsTo(DicePlayer::class, 'player_id', 'id');
} }
/**
* 中奖配置
* 关联模型 diceRewardConfig
*/
public function diceRewardConfig(): BelongsTo
{
return $this->belongsTo(DiceRewardConfig::class, 'reward_config_id', 'id');
}
/** /**
* 彩金池配置 * 彩金池配置
* 关联模型 diceLotteryPoolConfig * 关联模型 diceLotteryPoolConfig
@@ -252,24 +243,19 @@ class DicePlayRecord extends BaseModel
} }
$ids = DiceRewardConfig::where('ui_text', 'like', '%' . $value . '%')->column('id'); $ids = DiceRewardConfig::where('ui_text', 'like', '%' . $value . '%')->column('id');
if (!empty($ids)) { if (!empty($ids)) {
$query->whereIn('reward_config_id', $ids); $query->whereIn('target_index', $ids);
} else { } else {
$query->whereRaw('1=0'); $query->whereRaw('1=0');
} }
} }
/** 按奖励档位(diceRewardConfig.tier中奖名 T1-T5 */ /** 按奖励档位(表字段 reward_tier中奖名 T1-T5/BIGWIN */
public function searchRewardTierAttr($query, $value) public function searchRewardTierAttr($query, $value)
{ {
if ($value === '' || $value === null) { if ($value === '' || $value === null) {
return; return;
} }
$ids = DiceRewardConfig::where('tier', '=', $value)->column('id'); $query->where('reward_tier', '=', $value);
if (!empty($ids)) {
$query->whereIn('reward_config_id', $ids);
} else {
$query->whereRaw('1=0');
}
} }
/** 方向 0=顺时针 1=逆时针 */ /** 方向 0=顺时针 1=逆时针 */

View File

@@ -7,7 +7,6 @@
namespace app\dice\model\play_record_test; namespace app\dice\model\play_record_test;
use plugin\saiadmin\basic\think\BaseModel; use plugin\saiadmin\basic\think\BaseModel;
use app\dice\model\reward_config\DiceRewardConfig;
use app\dice\model\reward_config_record\DiceRewardConfigRecord; use app\dice\model\reward_config_record\DiceRewardConfigRecord;
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig; use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
use think\model\relation\BelongsTo; use think\model\relation\BelongsTo;
@@ -25,7 +24,7 @@ use think\model\relation\BelongsTo;
* @property int|null $ante 底注/注数dice_ante_config.mult * @property int|null $ante 底注/注数dice_ante_config.mult
* @property int|null $paid_amount 付费金额(付费局=ante*100免费局=0 * @property int|null $paid_amount 付费金额(付费局=ante*100免费局=0
* @property $direction 方向:0=顺时针,1=逆时针 * @property $direction 方向:0=顺时针,1=逆时针
* @property $reward_config_id 奖励配置id * @property $reward_tier 中奖档位T1,T2,T3,T4,T5,BIGWIN
* @property $create_time 创建时间 * @property $create_time 创建时间
* @property $update_time 修改时间 * @property $update_time 修改时间
* @property $start_index 起始索引 * @property $start_index 起始索引
@@ -61,15 +60,6 @@ class DicePlayRecordTest extends BaseModel
return $this->belongsTo(DiceLotteryPoolConfig::class, 'lottery_config_id', 'id'); return $this->belongsTo(DiceLotteryPoolConfig::class, 'lottery_config_id', 'id');
} }
/**
* 奖励配置(终点格 = target_index 对应 DiceRewardConfig.id表中为 reward_config_id
* 关联 reward_config_id -> DiceRewardConfig.id
*/
public function diceRewardConfig(): BelongsTo
{
return $this->belongsTo(DiceRewardConfig::class, 'reward_config_id', 'id');
}
/** /**
* 关联的权重测试记录 * 关联的权重测试记录
* reward_config_record_id -> DiceRewardConfigRecord.id * reward_config_record_id -> DiceRewardConfigRecord.id
@@ -135,18 +125,13 @@ class DicePlayRecordTest extends BaseModel
} }
} }
/** 中奖档位(按 reward_config_id 对应 DiceRewardConfig.tier */ /** 中奖档位(按表字段 reward_tier */
public function searchRewardTierAttr($query, $value) public function searchRewardTierAttr($query, $value)
{ {
if ($value === '' || $value === null) { if ($value === '' || $value === null) {
return; return;
} }
$ids = DiceRewardConfig::where('tier', '=', $value)->column('id'); $query->where('reward_tier', '=', $value);
if (!empty($ids)) {
$query->whereIn('reward_config_id', $ids);
} else {
$query->whereRaw('1=0');
}
} }
/** 点数和 roll_number摇取点数和 5-30 */ /** 点数和 roll_number摇取点数和 5-30 */

View File

@@ -32,6 +32,7 @@ use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
* @property $total_ticket_count 总抽奖次数 * @property $total_ticket_count 总抽奖次数
* @property $paid_ticket_count 购买抽奖次数 * @property $paid_ticket_count 购买抽奖次数
* @property $free_ticket_count 赠送抽奖次数 * @property $free_ticket_count 赠送抽奖次数
* @property array|null $free_ticket 免费抽奖券:{"ante":1,"count":1}
* @property $create_time 创建时间 * @property $create_time 创建时间
* @property $update_time 更新时间 * @property $update_time 更新时间
* @property $delete_time 删除时间 * @property $delete_time 删除时间
@@ -54,6 +55,10 @@ class DicePlayer extends BaseModel
protected $updateTime = 'update_time'; protected $updateTime = 'update_time';
protected $json = ['free_ticket'];
protected $jsonAssoc = true;
/** /**
* 新增前:生成唯一 uid昵称 name 默认使用 uid * 新增前:生成唯一 uid昵称 name 默认使用 uid
* 用 try-catch 避免表尚未含 uid 时 getAttr/getData 抛 InvalidArgumentException * 用 try-catch 避免表尚未含 uid 时 getAttr/getData 抛 InvalidArgumentException

View File

@@ -22,7 +22,7 @@ class DicePlayRecordValidate extends BaseValidate
'lottery_type' => 'require', 'lottery_type' => 'require',
'is_win' => 'require', 'is_win' => 'require',
'win_coin' => 'require', 'win_coin' => 'require',
'reward_config_id' => 'require', 'reward_tier' => 'require',
'roll_array' => 'require|checkRollArray', 'roll_array' => 'require|checkRollArray',
]; ];
@@ -35,7 +35,7 @@ class DicePlayRecordValidate extends BaseValidate
'lottery_type' => '抽奖类型必须填写', 'lottery_type' => '抽奖类型必须填写',
'is_win' => '中奖必须填写', 'is_win' => '中奖必须填写',
'win_coin' => '赢取平台币必须填写', 'win_coin' => '赢取平台币必须填写',
'reward_config_id' => '奖励配置必须填写', 'reward_tier' => '中奖档位必须填写',
'roll_array.require' => '摇取点数必须填写', 'roll_array.require' => '摇取点数必须填写',
]; ];
@@ -49,7 +49,7 @@ class DicePlayRecordValidate extends BaseValidate
'lottery_type', 'lottery_type',
'is_win', 'is_win',
'win_coin', 'win_coin',
'reward_config_id', 'reward_tier',
'roll_array', 'roll_array',
], ],
'update' => [ 'update' => [
@@ -58,7 +58,7 @@ class DicePlayRecordValidate extends BaseValidate
'lottery_type', 'lottery_type',
'is_win', 'is_win',
'win_coin', 'win_coin',
'reward_config_id', 'reward_tier',
'roll_array', 'roll_array',
], ],
]; ];

View File

@@ -21,7 +21,7 @@ class DicePlayRecordTestValidate extends BaseValidate
'lottery_type' => 'require', 'lottery_type' => 'require',
'is_win' => 'require', 'is_win' => 'require',
'direction' => 'require', 'direction' => 'require',
'reward_config_id' => 'require', 'reward_tier' => 'require',
'status' => 'require', 'status' => 'require',
]; ];
@@ -33,7 +33,7 @@ class DicePlayRecordTestValidate extends BaseValidate
'lottery_type' => '抽奖类型:0=付费,1=免费必须填写', 'lottery_type' => '抽奖类型:0=付费,1=免费必须填写',
'is_win' => '中大奖:0=无,1=中奖必须填写', 'is_win' => '中大奖:0=无,1=中奖必须填写',
'direction' => '方向:0=顺时针,1=逆时针必须填写', 'direction' => '方向:0=顺时针,1=逆时针必须填写',
'reward_config_id' => '奖励配置id必须填写', 'reward_tier' => '中奖档位必须填写',
'status' => '状态:0=失败,1=成功必须填写', 'status' => '状态:0=失败,1=成功必须填写',
]; ];
@@ -46,7 +46,7 @@ class DicePlayRecordTestValidate extends BaseValidate
'lottery_type', 'lottery_type',
'is_win', 'is_win',
'direction', 'direction',
'reward_config_id', 'reward_tier',
'status', 'status',
], ],
'update' => [ 'update' => [
@@ -54,7 +54,7 @@ class DicePlayRecordTestValidate extends BaseValidate
'lottery_type', 'lottery_type',
'is_win', 'is_win',
'direction', 'direction',
'reward_config_id', 'reward_tier',
'status', 'status',
], ],
]; ];

View File

@@ -46,7 +46,7 @@ Route::group('/api', function () {
Route::any('/user/walletRecord', [app\api\controller\UserController::class, 'walletRecord']); Route::any('/user/walletRecord', [app\api\controller\UserController::class, 'walletRecord']);
Route::any('/user/playGameRecord', [app\api\controller\UserController::class, 'playGameRecord']); Route::any('/user/playGameRecord', [app\api\controller\UserController::class, 'playGameRecord']);
Route::any('/game/config', [app\api\controller\GameController::class, 'config']); Route::any('/game/config', [app\api\controller\GameController::class, 'config']);
Route::any('/game/buyLotteryTickets', [app\api\controller\GameController::class, 'buyLotteryTickets']); // Route::any('/game/buyLotteryTickets', [app\api\controller\GameController::class, 'buyLotteryTickets']);
Route::any('/game/lotteryPool', [app\api\controller\GameController::class, 'lotteryPool']); Route::any('/game/lotteryPool', [app\api\controller\GameController::class, 'lotteryPool']);
Route::any('/game/anteConfig', [app\api\controller\GameController::class, 'anteConfig']); Route::any('/game/anteConfig', [app\api\controller\GameController::class, 'anteConfig']);
Route::any('/game/playStart', [app\api\controller\GameController::class, 'playStart']); Route::any('/game/playStart', [app\api\controller\GameController::class, 'playStart']);

View File

@@ -97,7 +97,6 @@ Route::group('/core', function () {
fastRoute('dice/play_record/DicePlayRecord', \app\dice\controller\play_record\DicePlayRecordController::class); fastRoute('dice/play_record/DicePlayRecord', \app\dice\controller\play_record\DicePlayRecordController::class);
Route::get('/dice/play_record/DicePlayRecord/getPlayerOptions', [\app\dice\controller\play_record\DicePlayRecordController::class, 'getPlayerOptions']); Route::get('/dice/play_record/DicePlayRecord/getPlayerOptions', [\app\dice\controller\play_record\DicePlayRecordController::class, 'getPlayerOptions']);
Route::get('/dice/play_record/DicePlayRecord/getLotteryConfigOptions', [\app\dice\controller\play_record\DicePlayRecordController::class, 'getLotteryConfigOptions']); Route::get('/dice/play_record/DicePlayRecord/getLotteryConfigOptions', [\app\dice\controller\play_record\DicePlayRecordController::class, 'getLotteryConfigOptions']);
Route::get('/dice/play_record/DicePlayRecord/getRewardConfigOptions', [\app\dice\controller\play_record\DicePlayRecordController::class, 'getRewardConfigOptions']);
fastRoute('dice/player_wallet_record/DicePlayerWalletRecord', \app\dice\controller\player_wallet_record\DicePlayerWalletRecordController::class); fastRoute('dice/player_wallet_record/DicePlayerWalletRecord', \app\dice\controller\player_wallet_record\DicePlayerWalletRecordController::class);
Route::get('/dice/player_wallet_record/DicePlayerWalletRecord/getPlayerOptions', [\app\dice\controller\player_wallet_record\DicePlayerWalletRecordController::class, 'getPlayerOptions']); Route::get('/dice/player_wallet_record/DicePlayerWalletRecord/getPlayerOptions', [\app\dice\controller\player_wallet_record\DicePlayerWalletRecordController::class, 'getPlayerOptions']);
Route::get('/dice/player_wallet_record/DicePlayerWalletRecord/getPlayerWalletBefore', [\app\dice\controller\player_wallet_record\DicePlayerWalletRecordController::class, 'getPlayerWalletBefore']); Route::get('/dice/player_wallet_record/DicePlayerWalletRecord/getPlayerWalletBefore', [\app\dice\controller\player_wallet_record\DicePlayerWalletRecordController::class, 'getPlayerWalletBefore']);

View File

@@ -120,7 +120,7 @@
- **`DiceReward`**:按档位、方向组织好的多语言/展示与 `grid_number``weight``real_ev` 等,供开局加权抽取。 - **`DiceReward`**:按档位、方向组织好的多语言/展示与 `grid_number``weight``real_ev` 等,供开局加权抽取。
- **`DiceRewardConfig`**:含 **BIGWIN** 档及普通档;`getCachedMinRealEv()` 等用于全局限定。 - **`DiceRewardConfig`**:含 **BIGWIN** 档及普通档;`getCachedMinRealEv()` 等用于全局限定。
- **`dice_lottery_pool_config`**`default` / `killScore` 的 T1T5 权重及杀分相关开关、安全线、累计盈利。 - **`dice_lottery_pool_config`**`default` / `killScore` 的 T1T5 权重及杀分相关开关、安全线、累计盈利。
- **对局表 `DicePlayRecord`**:记录 `lottery_config_id``lottery_type`(付费/免费)、`ante``paid_amount``roll_array``reward_config_id`、各类中奖拆分字段等,供后台与平台对账。 - **对局表 `DicePlayRecord`**:记录 `lottery_config_id``lottery_type`(付费/免费)、`ante``paid_amount``roll_array``reward_tier`、各类中奖拆分字段等,供后台与平台对账。
--- ---