[色子游戏]玩家抽奖记录-新增字段保存中奖详情记录信息
This commit is contained in:
@@ -62,6 +62,18 @@
|
||||
{{ row.is_win === 0 ? '无' : row.is_win === 1 ? '中奖' : '-' }}
|
||||
</ElTag>
|
||||
</template>
|
||||
<!-- 方向 tag -->
|
||||
<template #direction="{ row }">
|
||||
<ElTag size="small" :type="row.direction === 0 ? 'primary' : 'warning'">
|
||||
{{ row.direction === 0 ? '顺时针' : row.direction === 1 ? '逆时针' : '-' }}
|
||||
</ElTag>
|
||||
</template>
|
||||
<!-- 摇取点数 tag -->
|
||||
<template #roll_array="{ row }">
|
||||
<ElTag size="small">
|
||||
{{ formatRollArray(row.roll_array) }}
|
||||
</ElTag>
|
||||
</template>
|
||||
<!-- 操作列 -->
|
||||
<template #operation="{ row }">
|
||||
<div class="flex gap-2">
|
||||
@@ -106,7 +118,8 @@
|
||||
win_coin_min: undefined,
|
||||
win_coin_max: undefined,
|
||||
reward_ui_text: undefined,
|
||||
reward_tier: undefined
|
||||
reward_tier: undefined,
|
||||
direction: undefined
|
||||
})
|
||||
|
||||
// 搜索处理
|
||||
@@ -122,6 +135,21 @@
|
||||
const rewardTierFormatter = (row: Record<string, any>) =>
|
||||
row?.diceRewardConfig?.tier ?? row?.reward_config_id ?? '-'
|
||||
|
||||
/** 摇取点数格式化为 1,3,4,5,6,6 */
|
||||
function formatRollArray(val: unknown): string {
|
||||
if (val == null || val === '') return '-'
|
||||
if (Array.isArray(val)) return val.join(',')
|
||||
if (typeof val === 'string') {
|
||||
try {
|
||||
const arr = JSON.parse(val)
|
||||
return Array.isArray(arr) ? arr.join(',') : val
|
||||
} catch {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return String(val)
|
||||
}
|
||||
|
||||
// 表格配置
|
||||
const {
|
||||
columns,
|
||||
@@ -156,6 +184,10 @@
|
||||
{ prop: 'lottery_type', label: '抽奖类型', width: 100, useSlot: true },
|
||||
{ prop: 'is_win', label: '中奖', width: 80, useSlot: true },
|
||||
{ prop: 'win_coin', label: '赢取平台币' },
|
||||
{ prop: 'direction', label: '方向', width: 90, useSlot: true },
|
||||
{ prop: 'start_index', label: '起始索引', width: 90 },
|
||||
{ prop: 'target_index', label: '终点索引', width: 90 },
|
||||
{ prop: 'roll_array', label: '摇取点数', width: 140, useSlot: true },
|
||||
{
|
||||
prop: 'reward_config_id',
|
||||
label: '奖励配置',
|
||||
|
||||
@@ -75,6 +75,53 @@
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="方向" prop="direction">
|
||||
<el-select
|
||||
v-model="formData.direction"
|
||||
placeholder="请选择方向"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
:disabled="dialogType === 'edit'"
|
||||
>
|
||||
<el-option label="顺时针" :value="0" />
|
||||
<el-option label="逆时针" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="起始索引" prop="start_index">
|
||||
<el-input-number
|
||||
v-model="formData.start_index"
|
||||
placeholder="起始索引"
|
||||
:min="0"
|
||||
style="width: 100%"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="终点索引" prop="target_index">
|
||||
<el-input-number
|
||||
v-model="formData.target_index"
|
||||
placeholder="终点索引"
|
||||
:min="0"
|
||||
style="width: 100%"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="摇取点数" prop="rollArrayItems">
|
||||
<div class="roll-array-wrap">
|
||||
<el-input-number
|
||||
v-for="(_, i) in 6"
|
||||
:key="i"
|
||||
v-model="formData.rollArrayItems[i]"
|
||||
:min="1"
|
||||
:max="6"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
placeholder=""
|
||||
class="roll-array-input"
|
||||
:disabled="dialogType === 'edit'"
|
||||
/>
|
||||
</div>
|
||||
<div class="roll-array-hint">固定 6 个数,每个 1~6</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="奖励配置" prop="reward_config_id">
|
||||
<el-select
|
||||
v-model="formData.reward_config_id"
|
||||
@@ -141,6 +188,23 @@
|
||||
lottery_type: [{ required: true, message: '请选择抽奖类型', trigger: 'change' }],
|
||||
is_win: [{ required: true, message: '请选择中奖', trigger: 'change' }],
|
||||
win_coin: [{ required: true, message: '赢取平台币必填', trigger: 'blur' }],
|
||||
rollArrayItems: [
|
||||
{
|
||||
validator: (_rule: any, value: (number | null)[], callback: (e?: Error) => void) => {
|
||||
if (!value || value.length !== 6) {
|
||||
callback(new Error('摇取点数必须为 6 个数'))
|
||||
return
|
||||
}
|
||||
const ok = value.every((n) => n != null && n >= 1 && n <= 6)
|
||||
if (!ok) {
|
||||
callback(new Error('摇取点数必须填写 6 个数,每个 1~6'))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
},
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
reward_config_id: [{ required: true, message: '请选择奖励配置', trigger: 'change' }]
|
||||
})
|
||||
|
||||
@@ -155,10 +219,20 @@
|
||||
lottery_type: null as number | null,
|
||||
is_win: null as number | null,
|
||||
win_coin: null as number | null,
|
||||
direction: null as number | null,
|
||||
start_index: null as number | null,
|
||||
target_index: null as number | null,
|
||||
roll_array: null as string | number[] | null,
|
||||
reward_config_id: null as number | null
|
||||
}
|
||||
|
||||
const formData = reactive({ ...initialFormData })
|
||||
/** 摇取点数固定 6 位 [n0..n5],每项 1~6 */
|
||||
const rollArrayItemsDefault = (): (number | null)[] => [null, null, null, null, null, null]
|
||||
|
||||
const formData = reactive({
|
||||
...initialFormData,
|
||||
rollArrayItems: rollArrayItemsDefault() as (number | null)[]
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
@@ -188,7 +262,7 @@
|
||||
)
|
||||
|
||||
const initPage = async () => {
|
||||
Object.assign(formData, { ...initialFormData })
|
||||
Object.assign(formData, { ...initialFormData, rollArrayItems: rollArrayItemsDefault() })
|
||||
if (props.data) {
|
||||
await nextTick()
|
||||
initForm()
|
||||
@@ -204,16 +278,47 @@
|
||||
'lottery_type',
|
||||
'is_win',
|
||||
'win_coin',
|
||||
'direction',
|
||||
'start_index',
|
||||
'target_index',
|
||||
'roll_array',
|
||||
'reward_config_id'
|
||||
]
|
||||
keys.forEach((key) => {
|
||||
const val = props.data![key]
|
||||
if (val != null && val !== undefined) {
|
||||
;(formData as Record<string, unknown>)[key] = val
|
||||
if (key === 'roll_array') {
|
||||
formData.roll_array = val
|
||||
formData.rollArrayItems = parseRollArrayToItems(val)
|
||||
} else {
|
||||
;(formData as Record<string, unknown>)[key] = val
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 将接口的 roll_array 转为固定 6 项数组,不足补 null */
|
||||
function parseRollArrayToItems(val: unknown): (number | null)[] {
|
||||
let arr: number[] = []
|
||||
if (Array.isArray(val)) {
|
||||
arr = val.map((n) => (typeof n === 'number' && !Number.isNaN(n) ? n : 0)).slice(0, 6)
|
||||
} else if (typeof val === 'string') {
|
||||
try {
|
||||
const parsed = JSON.parse(val)
|
||||
arr = Array.isArray(parsed) ? parsed.slice(0, 6).map((n: any) => Number(n) || 0) : []
|
||||
} catch {
|
||||
arr = val
|
||||
.split(',')
|
||||
.map((n) => parseInt(n, 10))
|
||||
.filter((n) => !Number.isNaN(n))
|
||||
.slice(0, 6)
|
||||
}
|
||||
}
|
||||
const items: (number | null)[] = [...arr]
|
||||
while (items.length < 6) items.push(null)
|
||||
return items.slice(0, 6)
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
visible.value = false
|
||||
formRef.value?.resetFields()
|
||||
@@ -223,19 +328,56 @@
|
||||
if (!formRef.value) return
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
const payload = { ...formData } as Record<string, unknown>
|
||||
// 将 6 个输入值拼成 [1,2,3,4,5,6] 格式,确保每项为 1~6 的整数
|
||||
const items = formData.rollArrayItems
|
||||
payload.roll_array = items.map((n) => {
|
||||
const v = n != null ? Number(n) : 1
|
||||
return Math.min(6, Math.max(1, Number.isNaN(v) ? 1 : Math.floor(v)))
|
||||
})
|
||||
delete payload.rollArrayItems
|
||||
if (props.dialogType === 'add') {
|
||||
const rest = { ...formData } as Record<string, unknown>
|
||||
delete rest.id
|
||||
await api.save(rest)
|
||||
delete payload.id
|
||||
await api.save(payload)
|
||||
ElMessage.success('新增成功')
|
||||
} else {
|
||||
await api.update(formData)
|
||||
await api.update(payload)
|
||||
ElMessage.success('修改成功')
|
||||
}
|
||||
emit('success')
|
||||
handleClose()
|
||||
} catch (error) {
|
||||
console.log('表单验证失败:', error)
|
||||
} catch (error: any) {
|
||||
let msg = '表单验证失败,请检查必填项与格式'
|
||||
if (error?.message) {
|
||||
msg = error.message
|
||||
} else if (typeof error === 'string') {
|
||||
msg = error
|
||||
} else if (error && typeof error === 'object') {
|
||||
const first = Object.values(error).find((v: any) => v?.[0]?.message)
|
||||
if (first && Array.isArray(first)) {
|
||||
msg = (first[0] as any).message || msg
|
||||
}
|
||||
}
|
||||
ElMessage.warning(msg)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.roll-array-wrap {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.roll-array-input {
|
||||
width: 72px;
|
||||
}
|
||||
|
||||
.roll-array-hint {
|
||||
margin-top: 6px;
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -34,6 +34,14 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="setSpan(6)">
|
||||
<el-form-item label="方向" prop="direction">
|
||||
<el-select v-model="formData.direction" placeholder="全部" clearable style="width: 100%">
|
||||
<el-option label="顺时针" :value="0" />
|
||||
<el-option label="逆时针" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="setSpan(6)">
|
||||
<el-form-item label="赢取平台币" prop="win_coin_min">
|
||||
<div class="range-wrap">
|
||||
|
||||
@@ -48,6 +48,7 @@ class DicePlayRecordController extends BaseController
|
||||
['win_coin_max', ''],
|
||||
['reward_ui_text', ''],
|
||||
['reward_tier', ''],
|
||||
['direction', ''],
|
||||
]);
|
||||
$query = $this->logic->search($where);
|
||||
$query->with([
|
||||
|
||||
@@ -24,4 +24,36 @@ class DicePlayRecordLogic extends BaseLogic
|
||||
$this->model = new DicePlayRecord();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加前:roll_array 转为 JSON 字符串(数据库为 string 类型)
|
||||
*/
|
||||
public function add(array $data): mixed
|
||||
{
|
||||
$data = $this->normalizeRollArray($data);
|
||||
return parent::add($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改前:roll_array 转为 JSON 字符串(数据库为 string 类型)
|
||||
*/
|
||||
public function edit($id, array $data): mixed
|
||||
{
|
||||
$data = $this->normalizeRollArray($data);
|
||||
return parent::edit($id, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 roll_array 从数组转为 JSON 字符串
|
||||
*/
|
||||
private function normalizeRollArray(array $data): array
|
||||
{
|
||||
if (!array_key_exists('roll_array', $data)) {
|
||||
return $data;
|
||||
}
|
||||
$val = $data['roll_array'];
|
||||
if (is_array($val)) {
|
||||
$data['roll_array'] = json_encode($val, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,12 @@ use think\model\relation\BelongsTo;
|
||||
* @property $lottery_type 抽奖类型
|
||||
* @property $is_win 中奖
|
||||
* @property $win_coin 赢取平台币
|
||||
* @property $direction 方向:0=顺时针,1=逆时针
|
||||
* @property $reward_config_id 奖励配置id
|
||||
* @property $lottery_id 奖池
|
||||
* @property $start_index 起始索引
|
||||
* @property $target_index 结束索引
|
||||
* @property $roll_array 摇取点数,格式:[1,2,3,4,5,6]
|
||||
* @property $lottery_name 奖池名
|
||||
* @property $create_time 创建时间
|
||||
* @property $update_time 修改时间
|
||||
@@ -157,4 +161,12 @@ class DicePlayRecord extends BaseModel
|
||||
$query->whereRaw('1=0');
|
||||
}
|
||||
}
|
||||
|
||||
/** 方向 0=顺时针 1=逆时针 */
|
||||
public function searchDirectionAttr($query, $value)
|
||||
{
|
||||
if ($value !== '' && $value !== null) {
|
||||
$query->where('direction', '=', $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ class DicePlayRecordValidate extends BaseValidate
|
||||
'is_win' => 'require',
|
||||
'win_coin' => 'require',
|
||||
'reward_config_id' => 'require',
|
||||
'roll_array' => 'require|checkRollArray',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -35,6 +36,7 @@ class DicePlayRecordValidate extends BaseValidate
|
||||
'is_win' => '中奖必须填写',
|
||||
'win_coin' => '赢取平台币必须填写',
|
||||
'reward_config_id' => '奖励配置必须填写',
|
||||
'roll_array.require' => '摇取点数必须填写',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -48,6 +50,7 @@ class DicePlayRecordValidate extends BaseValidate
|
||||
'is_win',
|
||||
'win_coin',
|
||||
'reward_config_id',
|
||||
'roll_array',
|
||||
],
|
||||
'update' => [
|
||||
'player_id',
|
||||
@@ -56,7 +59,36 @@ class DicePlayRecordValidate extends BaseValidate
|
||||
'is_win',
|
||||
'win_coin',
|
||||
'reward_config_id',
|
||||
'roll_array',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* 验证 roll_array:必须为 6 个元素,每个值在 1~6 之间
|
||||
* @param mixed $value
|
||||
* @param mixed $rule
|
||||
* @param array $data
|
||||
* @param string $field
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function checkRollArray($value, $rule = '', array $data = [], string $field = '')
|
||||
{
|
||||
if (is_string($value)) {
|
||||
$decoded = json_decode($value, true);
|
||||
$value = is_array($decoded) ? $decoded : [];
|
||||
}
|
||||
if (!is_array($value)) {
|
||||
return '摇取点数必须为数组';
|
||||
}
|
||||
if (count($value) !== 6) {
|
||||
return '摇取点数必须为 6 个数';
|
||||
}
|
||||
foreach ($value as $i => $n) {
|
||||
$v = is_numeric($n) ? (int) $n : null;
|
||||
if ($v === null || $v < 1 || $v > 6) {
|
||||
return '摇取点数第' . ($i + 1) . '个值必须在 1~6 之间';
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user