[色子游戏]抽奖记录(测试权重)-优化

[API]记录抽奖券DicePlayerTicketRecord
This commit is contained in:
2026-03-25 18:51:29 +08:00
parent f8cf85dd01
commit d793a511ee
27 changed files with 256 additions and 47 deletions

View File

@@ -8,6 +8,8 @@
"direction": "Direction",
"isBigWin": "Is Big Win",
"winCoin": "Win Coin",
"paidAmount": "Paid Amount",
"ante": "Ante",
"rewardTier": "Reward Tier",
"rollNumber": "Roll Number",
"paid": "Paid",
@@ -23,6 +25,8 @@
"lotteryPoolConfig": "Lottery Pool Config",
"drawType": "Draw Type",
"isBigWin": "Is Big Win",
"paidAmount": "Paid Amount",
"ante": "Ante",
"winCoin": "Win Coin",
"superWinCoin": "Super Win Coin",
"rewardWinCoin": "Reward Win Coin",

View File

@@ -19,6 +19,7 @@
"search": {
"player": "Player",
"useCoins": "Use Coins",
"ante": "Ante",
"totalDrawCount": "Total Draw Count",
"paidDrawCount": "Paid Draw Count",
"freeDrawCount": "Free Draw Count",
@@ -29,6 +30,7 @@
"id": "ID",
"playerUsername": "Player Username",
"useCoins": "Use Coins",
"ante": "Ante",
"totalDrawCount": "Total Draw Count",
"paidDrawCount": "Paid Draw Count",
"freeDrawCount": "Free Draw Count",

View File

@@ -61,6 +61,7 @@
"stepFree": "Free ticket",
"labelLotteryTypePaid": "Test pool type",
"labelLotteryTypeFree": "Test pool type",
"labelAnte": "Ante",
"placeholderPaidPool": "Leave empty for custom tier odds below (default: default)",
"placeholderFreePool": "Leave empty for custom tier odds below (default: killScore)",
"tierProbHint": "Custom tier odds (T1T5), each 0100%, sum of five must not exceed 100%",
@@ -73,6 +74,7 @@
"btnNext": "Next",
"btnStart": "Start test",
"btnCancel": "Cancel",
"warnAnte": "Ante must be greater than 0",
"warnTotalSpins": "At least one of paid/free direction spin counts must be greater than 0",
"warnPaidTierSumPositive": "When no paid pool is selected, T1T5 odds sum must be greater than 0",
"warnPaidTierSumMax": "Paid T1T5 odds sum cannot exceed 100%",

View File

@@ -12,6 +12,7 @@
"platformProfit": "Platform Profit",
"totalDrawCount": "Total Draw Count",
"createdBy": "Created By",
"remark": "Remark",
"createTime": "Create Time",
"statusFail": "Failed",
"statusDone": "Done",

View File

@@ -8,7 +8,7 @@
"placeholderLotteryPool": "请选择彩金池配置",
"drawType": "抽奖类型",
"paid": "付费",
"free": "赠送",
"free": "免费",
"isBigWin": "是否中大奖",
"noBigWin": "无",
"bigWin": "中大奖",
@@ -53,7 +53,7 @@
"nameFuzzy": "名称模糊",
"uiTextFuzzy": "前端显示文本模糊",
"paid": "付费",
"free": "赠送",
"free": "免费",
"noBigWin": "无",
"bigWin": "中大奖",
"clockwise": "顺时针",

View File

@@ -8,10 +8,12 @@
"direction": "方向",
"isBigWin": "是否中大奖",
"winCoin": "赢取平台币",
"paidAmount": "付费金额",
"ante": "底注",
"rewardTier": "奖励档位",
"rollNumber": "摇取点数和",
"paid": "付费",
"free": "赠送",
"free": "免费",
"clockwise": "顺时针",
"anticlockwise": "逆时针",
"noBigWin": "无",
@@ -23,6 +25,8 @@
"lotteryPoolConfig": "彩金池配置",
"drawType": "抽奖类型",
"isBigWin": "是否中大奖",
"paidAmount": "付费金额",
"ante": "底注",
"winCoin": "赢取平台币",
"superWinCoin": "中大奖平台币",
"rewardWinCoin": "摇色子中奖平台币",

View File

@@ -19,6 +19,7 @@
"search": {
"player": "玩家",
"useCoins": "消耗硬币",
"ante": "底注",
"totalDrawCount": "总抽奖次数",
"paidDrawCount": "购买抽奖次数",
"freeDrawCount": "赠送抽奖次数",
@@ -29,6 +30,7 @@
"id": "ID",
"playerUsername": "玩家用户名",
"useCoins": "消耗硬币",
"ante": "底注",
"totalDrawCount": "总抽奖次数",
"paidDrawCount": "购买抽奖次数",
"freeDrawCount": "赠送抽奖次数",

View File

@@ -61,6 +61,7 @@
"stepFree": "免费抽奖券",
"labelLotteryTypePaid": "测试数据档位类型",
"labelLotteryTypeFree": "测试数据档位类型",
"labelAnte": "底注 ante",
"placeholderPaidPool": "不选则下方自定义档位概率(默认 default",
"placeholderFreePool": "不选则下方自定义档位概率(默认 killScore",
"tierProbHint": "自定义档位概率T1T5每档 0-100%,五档之和不能超过 100%",
@@ -73,6 +74,7 @@
"btnNext": "下一步",
"btnStart": "开始测试",
"btnCancel": "取消",
"warnAnte": "底注 ante 必须大于 0",
"warnTotalSpins": "付费或免费至少一种方向次数之和大于 0",
"warnPaidTierSumPositive": "付费未选奖池时T1T5 档位概率之和需大于 0",
"warnPaidTierSumMax": "付费档位概率 T1T5 之和不能超过 100%",

View File

@@ -12,6 +12,7 @@
"platformProfit": "平台赚取金额",
"totalDrawCount": "总抽奖次数",
"createdBy": "创建管理员",
"remark": "备注",
"createTime": "创建时间",
"statusFail": "失败",
"statusDone": "完成",

View File

@@ -61,6 +61,7 @@ export default {
* 可选 lottery_config_id不选则传 paid_tier_weights / free_tier_weightsT1-T5
*/
startWeightTest(params: {
ante?: number
lottery_config_id?: number
paid_lottery_config_id?: number
free_lottery_config_id?: number

View File

@@ -58,19 +58,37 @@
<!-- 抽奖类型 -->
<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>
<!-- 是否中大奖 -->
<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>
<!-- 方向 -->
<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>
<!-- 摇取点数 -->
@@ -132,6 +150,8 @@
lottery_type: undefined,
direction: undefined,
is_win: undefined,
paid_amount: undefined,
ante: undefined,
win_coin_min: undefined,
win_coin_max: undefined,
reward_tier: undefined,
@@ -208,9 +228,16 @@
columnsFactory: () => [
{ type: 'selection' },
{ prop: 'id', label: 'page.table.id', width: 80 },
{ prop: 'lottery_config_id', label: 'page.table.lotteryPoolConfig', width: 120, useSlot: true },
{
prop: 'lottery_config_id',
label: 'page.table.lotteryPoolConfig',
width: 120,
useSlot: true
},
{ prop: 'lottery_type', label: 'page.table.drawType', 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: 'ante', label: 'page.table.ante', width: 90 },
{ prop: 'win_coin', label: 'page.table.winCoin', width: 110 },
{ prop: 'super_win_coin', label: 'page.table.superWinCoin', width: 120 },
{ prop: 'reward_win_coin', label: 'page.table.rewardWinCoin', width: 140 },
@@ -222,7 +249,13 @@
{ prop: 'reward_config_id', label: 'page.table.rewardConfig', width: 100, useSlot: true },
{ prop: 'status', label: 'page.table.status', width: 80, useSlot: true },
{ prop: 'create_time', label: 'page.table.createTime', 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

@@ -28,6 +28,24 @@
<el-option :label="$t('page.search.anticlockwise')" :value="1" />
</el-select>
</el-form-item>
<el-form-item :label="$t('page.search.ante')" prop="ante">
<el-input-number
v-model="formData.ante"
:placeholder="$t('table.searchBar.all')"
:precision="0"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
<el-form-item :label="$t('page.search.paidAmount')" prop="paid_amount">
<el-input-number
v-model="formData.paid_amount"
:placeholder="$t('table.searchBar.all')"
:precision="0"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
<el-form-item :label="$t('page.search.isBigWin')" prop="is_win">
<el-select v-model="formData.is_win" :placeholder="$t('form.placeholderSelect')" clearable style="width: 100%">
<el-option :label="$t('page.search.noBigWin')" :value="0" />
@@ -153,6 +171,8 @@
lottery_config_id: null,
lottery_type: null,
is_win: null,
ante: 1,
paid_amount: 0,
win_coin: 0,
direction: null,
reward_tier: undefined as string | undefined,

View File

@@ -32,6 +32,28 @@
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="setSpan(6)">
<el-form-item :label="$t('page.search.paidAmount')" prop="paid_amount">
<el-input-number
v-model="formData.paid_amount"
:placeholder="$t('table.searchBar.all')"
:precision="0"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col v-bind="setSpan(6)">
<el-form-item :label="$t('page.search.ante')" prop="ante">
<el-input-number
v-model="formData.ante"
:placeholder="$t('table.searchBar.all')"
:precision="0"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col v-bind="setSpan(6)">
<el-form-item :label="$t('page.search.winCoin')" prop="win_coin_min">
<div class="range-wrap">

View File

@@ -82,6 +82,7 @@
username: undefined,
use_coins_min: undefined,
use_coins_max: undefined,
ante: undefined,
total_ticket_count_min: undefined,
total_ticket_count_max: undefined,
paid_ticket_count_min: undefined,
@@ -136,6 +137,7 @@
formatter: (row: Record<string, any>) => usernameFormatter(row)
},
{ prop: 'use_coins', label: 'page.table.useCoins', align: 'center' },
{ prop: 'ante', label: 'page.table.ante', align: 'center' },
{ prop: 'total_ticket_count', label: 'page.table.totalDrawCount', align: 'center' },
{ prop: 'paid_ticket_count', label: 'page.table.paidDrawCount', align: 'center' },
{ prop: 'free_ticket_count', label: 'page.table.freeDrawCount', align: 'center' },

View File

@@ -34,6 +34,18 @@
</div>
</el-form-item>
</el-col>
<el-col v-bind="setSpan(6)">
<el-form-item :label="$t('page.search.ante')" prop="ante">
<el-input-number
v-model="formData.ante"
:placeholder="$t('table.searchBar.all')"
:min="1"
:precision="0"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col v-bind="setSpan(6)">
<el-form-item :label="$t('page.search.totalDrawCount')" prop="total_ticket_count_min">
<div class="range-wrap">

View File

@@ -12,6 +12,9 @@
{{ $t('page.weightTest.alertBody') }}
</ElAlert>
<ElForm ref="formRef" :model="form" label-width="140px">
<ElFormItem :label="$t('page.weightTest.labelAnte')" prop="ante" required>
<ElInputNumber v-model="form.ante" :min="1" :step="1" style="width: 100%" />
</ElFormItem>
<ElSteps :active="currentStep" finish-status="success" simple class="steps-wrap">
<ElStep :title="$t('page.weightTest.stepPaid')" />
<ElStep :title="$t('page.weightTest.stepFree')" />
@@ -187,6 +190,7 @@
const formRef = ref()
const currentStep = ref(0)
const form = reactive({
ante: 1,
paid_lottery_config_id: undefined as number | undefined,
free_lottery_config_id: undefined as number | undefined,
paid_tier_weights: { T1: 20, T2: 20, T3: 20, T4: 20, T5: 20 } as Record<string, number>,
@@ -270,6 +274,7 @@
function buildPayload() {
const payload: Record<string, unknown> = {
ante: form.ante,
paid_s_count: form.paid_s_count,
paid_n_count: form.paid_n_count,
free_s_count: form.free_s_count,
@@ -289,6 +294,10 @@
}
function validateForm(): boolean {
if (form.ante == null || form.ante <= 0) {
ElMessage.warning(t('page.weightTest.warnAnte'))
return false
}
if (form.paid_s_count + form.paid_n_count + form.free_s_count + form.free_n_count <= 0) {
ElMessage.warning(t('page.weightTest.warnTotalSpins'))
return false

View File

@@ -214,6 +214,13 @@
align: 'center',
showOverflowTooltip: true
},
{
prop: 'remark',
label: 'page.table.remark',
width: 220,
align: 'center',
showOverflowTooltip: true
},
{ prop: 'create_time', label: 'page.table.createTime', width: 170, align: 'center' },
{
prop: 'operation',