1.所有接口需要根据agent_id绑定渠道

2.移除所有记录页面的更新按钮,只能查看数据
3.将所有软删除修改为硬删除
This commit is contained in:
2026-05-19 12:04:34 +08:00
parent b089f302de
commit 1f25280dfd
30 changed files with 325 additions and 592 deletions

View File

@@ -427,6 +427,9 @@
"rewardConfigRecord": "Dice Weight Test Records",
"playRecordTest": "Draw Records (Test Weight)",
"config": "Game Config"
},
"game": {
"title": "Game Management"
}
},
"table": {

View File

@@ -38,8 +38,31 @@
"ruleGameNameRequired": "Chinese name is required",
"ruleGameTypeRequired": "Game type is required"
},
"table": {
"search": {
"providerCode": "Provider Code",
"placeholderProviderCode": "Enter provider code",
"gameCode": "Game Code",
"placeholderGameCode": "Enter game code",
"gameType": "Game Type",
"placeholderGameType": "Enter game type",
"status": "Status",
"placeholderStatus": "Select status",
"statusEnabled": "Enabled",
"statusDisabled": "Disabled"
},
"table": {
"id": "ID",
"provider": "Provider",
"providerCode": "Provider Code",
"gameCode": "Game Code",
"gameKey": "Game Key",
"gameName": "Name (ZH)",
"gameNameEn": "Name (EN)",
"gameType": "Type",
"sort": "Sort",
"status": "Status",
"statusEnabled": "Enabled",
"statusDisabled": "Disabled",
"updateTime": "Update Time"
}
}

View File

@@ -423,6 +423,9 @@
"rewardConfigRecord": "权重测试记录",
"playRecordTest": "抽奖记录(测试权重)",
"config": "游戏配置"
},
"game": {
"title": "游戏管理"
}
},
"table": {

View File

@@ -38,8 +38,31 @@
"ruleGameNameRequired": "请输入中文名称",
"ruleGameTypeRequired": "请输入游戏类型"
},
"table": {
"search": {
"providerCode": "供应商编码",
"placeholderProviderCode": "请输入供应商编码",
"gameCode": "游戏编号",
"placeholderGameCode": "请输入游戏编号",
"gameType": "游戏类型",
"placeholderGameType": "请输入游戏类型",
"status": "状态",
"placeholderStatus": "请选择状态",
"statusEnabled": "启用",
"statusDisabled": "禁用"
},
"table": {
"id": "ID",
"provider": "供应商",
"providerCode": "供应商编码",
"gameCode": "游戏编号",
"gameKey": "游戏唯一值",
"gameName": "中文名",
"gameNameEn": "英文名",
"gameType": "类型",
"sort": "排序",
"status": "状态",
"statusEnabled": "启用",
"statusDisabled": "禁用",
"updateTime": "更新时间"
}
}

View File

@@ -46,12 +46,21 @@ export async function loadPageLocale(routePath: string): Promise<void> {
const modules = locale === LanguageEnum.EN ? enModules : zhModules
const tryPaths: string[] = [path]
// 兼容别名路由:例如 /user 实际页面为 /system/user
// 兼容别名路由:菜单 path 为短名但 locale 文件位于模块子目录
// 例如:/user -> system/user/game -> dice/game
if (!path.includes('/')) {
tryPaths.push(`system/${path}`)
}
if (path === 'user') {
tryPaths.push('system/user')
// 兜底:在任意一级子目录下查找同名文件
const suffix = `/${path}.json`
const localePrefix = `./langs/${locale}/`
for (const key of Object.keys(modules)) {
if (key.startsWith(localePrefix) && key.endsWith(suffix)) {
const candidate = key.slice(localePrefix.length, -'.json'.length)
if (!tryPaths.includes(candidate)) {
tryPaths.push(candidate)
}
}
}
}
let matchedPath: string | null = null

View File

@@ -61,6 +61,10 @@ export const MAP_PATH_TO_MENU_I18N_KEY: Record<string, string> = {
'/dice/play_record_test/index': 'menus.dice.playRecordTest',
'/dice/config': 'menus.dice.config',
'/dice/config/index': 'menus.dice.config',
'game': 'menus.game.title',
'game/index': 'menus.game.title',
'/game': 'menus.game.title',
'/game/index': 'menus.game.title',
'/result/success': 'menus.result.success',
'/result/fail': 'menus.result.fail',
'/exception/403': 'menus.exception.forbidden',

View File

@@ -39,18 +39,6 @@ export default {
})
},
/**
* 更新数据
* @param params 数据参数
* @returns 执行结果
*/
update(params: Record<string, any>) {
return request.put<any>({
url: '/core/dice/play_record/DicePlayRecord/update',
data: params
})
},
/**
* 删除数据
* @param id 数据ID

View File

@@ -39,18 +39,6 @@ export default {
})
},
/**
* 更新数据
* @param params 数据参数
* @returns 执行结果
*/
update(params: Record<string, any>) {
return request.put<any>({
url: '/core/dice/play_record_test/DicePlayRecordTest/update',
data: params
})
},
/**
* 删除数据
* @param id 数据ID

View File

@@ -39,18 +39,6 @@ export default {
})
},
/**
* 更新数据
* @param params 数据参数
* @returns 执行结果
*/
update(params: Record<string, any>) {
return request.put<any>({
url: '/core/dice/player_ticket_record/DicePlayerTicketRecord/update',
data: params
})
},
/**
* 删除数据
* @param id 数据ID

View File

@@ -39,18 +39,6 @@ export default {
})
},
/**
* 更新数据
* @param params 数据参数
* @returns 执行结果
*/
update(params: Record<string, any>) {
return request.put<any>({
url: '/core/dice/player_wallet_record/DicePlayerWalletRecord/update',
data: params
})
},
/**
* 删除数据
* @param id 数据ID

View File

@@ -39,18 +39,6 @@ export default {
})
},
/**
* 更新数据
* @param params 数据参数
* @returns 执行结果
*/
update(params: Record<string, any>) {
return request.put<any>({
url: '/core/dice/reward_config_record/DiceRewardConfigRecord/update',
data: params
})
},
/**
* 删除数据
* @param id 数据ID

View File

@@ -10,7 +10,7 @@
<template #icon>
<ArtSvgIcon icon="ri:add-fill" />
</template>
新增
{{ $t('table.actions.add') }}
</ElButton>
<ElButton
v-permission="'dice:game:index:destroy'"
@@ -21,7 +21,7 @@
<template #icon>
<ArtSvgIcon icon="ri:delete-bin-5-line" />
</template>
删除
{{ $t('table.actions.delete') }}
</ElButton>
</ElSpace>
</template>
@@ -108,20 +108,20 @@
apiParams: { limit: 100 },
columnsFactory: () => [
{ type: 'selection', align: 'center' },
{ prop: 'id', label: 'ID', width: 80, align: 'center' },
{ prop: 'provider', label: '供应商', minWidth: 120, align: 'center' },
{ prop: 'provider_code', label: '供应商编码', minWidth: 120, align: 'center' },
{ prop: 'game_code', label: '游戏编号', minWidth: 120, align: 'center' },
{ prop: 'game_key', label: '游戏唯一值', minWidth: 120, align: 'center' },
{ prop: 'game_name', label: '中文名', minWidth: 120, align: 'center' },
{ prop: 'game_name_en', label: '英文名', minWidth: 120, align: 'center' },
{ prop: 'game_type', label: '类型', minWidth: 90, align: 'center' },
{ prop: 'sort', label: '排序', width: 80, align: 'center' },
{ prop: 'status', label: '状态', width: 90, align: 'center', useSlot: true },
{ prop: 'update_time', label: '更新时间', minWidth: 160, align: 'center' },
{ prop: 'id', label: 'page.table.id', width: 80, align: 'center' },
{ prop: 'provider', label: 'page.table.provider', minWidth: 120, align: 'center' },
{ prop: 'provider_code', label: 'page.table.providerCode', minWidth: 120, align: 'center' },
{ prop: 'game_code', label: 'page.table.gameCode', minWidth: 120, align: 'center' },
{ prop: 'game_key', label: 'page.table.gameKey', minWidth: 120, align: 'center' },
{ prop: 'game_name', label: 'page.table.gameName', minWidth: 120, align: 'center' },
{ prop: 'game_name_en', label: 'page.table.gameNameEn', minWidth: 120, align: 'center' },
{ prop: 'game_type', label: 'page.table.gameType', minWidth: 90, align: 'center' },
{ prop: 'sort', label: 'page.table.sort', width: 80, align: 'center' },
{ prop: 'status', label: 'page.table.status', width: 90, align: 'center', useSlot: true },
{ prop: 'update_time', label: 'page.table.updateTime', minWidth: 160, align: 'center' },
{
prop: 'operation',
label: '操作',
label: 'table.actions.operation',
width: 110,
align: 'center',
fixed: 'right',

View File

@@ -8,25 +8,41 @@
@search="handleSearch"
>
<el-col v-bind="setSpan(6)">
<el-form-item label="供应商编码" prop="provider_code">
<el-input v-model="formData.provider_code" placeholder="请输入供应商编码" clearable />
<el-form-item :label="$t('page.search.providerCode')" prop="provider_code">
<el-input
v-model="formData.provider_code"
:placeholder="$t('page.search.placeholderProviderCode')"
clearable
/>
</el-form-item>
</el-col>
<el-col v-bind="setSpan(6)">
<el-form-item label="游戏编号" prop="game_code">
<el-input v-model="formData.game_code" placeholder="请输入游戏编号" clearable />
<el-form-item :label="$t('page.search.gameCode')" prop="game_code">
<el-input
v-model="formData.game_code"
:placeholder="$t('page.search.placeholderGameCode')"
clearable
/>
</el-form-item>
</el-col>
<el-col v-bind="setSpan(6)">
<el-form-item label="游戏类型" prop="game_type">
<el-input v-model="formData.game_type" placeholder="请输入游戏类型" clearable />
<el-form-item :label="$t('page.search.gameType')" prop="game_type">
<el-input
v-model="formData.game_type"
:placeholder="$t('page.search.placeholderGameType')"
clearable
/>
</el-form-item>
</el-col>
<el-col v-bind="setSpan(6)">
<el-form-item label="状态" prop="status">
<el-select v-model="formData.status" placeholder="请选择状态" clearable>
<el-option label="启用" :value="1" />
<el-option label="禁用" :value="0" />
<el-form-item :label="$t('page.search.status')" prop="status">
<el-select
v-model="formData.status"
:placeholder="$t('page.search.placeholderStatus')"
clearable
>
<el-option :label="$t('page.search.statusEnabled')" :value="1" />
<el-option :label="$t('page.search.statusDisabled')" :value="0" />
</el-select>
</el-form-item>
</el-col>

View File

@@ -1,13 +1,13 @@
<template>
<el-dialog
v-model="visible"
:title="dialogType === 'add' ? $t('page.form.dialogTitleAdd') : $t('page.form.dialogTitleEdit')"
:title="$t('page.form.dialogTitleEdit')"
width="600px"
align-center
:close-on-click-modal="false"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
<el-form ref="formRef" :model="formData" label-width="120px">
<el-form-item :label="$t('page.form.player')" prop="player_id">
<el-select
v-model="formData.player_id"
@@ -15,7 +15,7 @@
clearable
filterable
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
>
<el-option
v-for="item in playerOptions"
@@ -32,7 +32,7 @@
clearable
filterable
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
>
<el-option
v-for="item in lotteryConfigOptions"
@@ -48,7 +48,7 @@
:placeholder="$t('form.placeholderSelect')"
clearable
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
>
<el-option :label="$t('page.form.paid')" :value="0" />
<el-option :label="$t('page.form.free')" :value="1" />
@@ -60,7 +60,7 @@
:placeholder="$t('form.placeholderSelect')"
clearable
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
>
<el-option :label="$t('page.form.noBigWin')" :value="0" />
<el-option :label="$t('page.form.bigWin')" :value="1" />
@@ -72,7 +72,7 @@
:placeholder="$t('page.form.placeholderWinCoin')"
:precision="0"
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.superWinCoin')" prop="super_win_coin">
@@ -82,7 +82,7 @@
:precision="0"
:min="0"
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.rewardWinCoin')" prop="reward_win_coin">
@@ -92,7 +92,7 @@
:precision="0"
:min="0"
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.direction')" prop="direction">
@@ -101,7 +101,7 @@
:placeholder="$t('page.form.placeholderDirection')"
clearable
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
>
<el-option :label="$t('page.form.clockwise')" :value="0" />
<el-option :label="$t('page.form.anticlockwise')" :value="1" />
@@ -113,7 +113,7 @@
:placeholder="$t('page.form.placeholderStartIndex')"
:min="0"
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.targetIndex')" prop="target_index">
@@ -122,7 +122,7 @@
:placeholder="$t('page.form.placeholderTargetIndex')"
:min="0"
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.rollArray')" prop="rollArrayItems">
@@ -137,7 +137,7 @@
controls-position="right"
placeholder=""
class="roll-array-input"
:disabled="dialogType === 'edit'"
disabled
/>
</div>
<div class="roll-array-hint">{{ $t('page.form.rollArrayHint') }}</div>
@@ -150,7 +150,7 @@
:max="30"
:precision="0"
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.rewardTier')" prop="reward_tier">
@@ -160,7 +160,7 @@
clearable
filterable
style="width: 100%"
:disabled="true"
disabled
>
<el-option label="T1" value="T1" />
<el-option label="T2" value="T2" />
@@ -172,20 +172,15 @@
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleClose">{{ dialogType === 'edit' ? $t('form.close') : $t('common.cancel') }}</el-button>
<el-button v-if="dialogType === 'add'" type="primary" @click="handleSubmit">{{ $t('table.form.submit') }}</el-button>
<el-button @click="handleClose">{{ $t('form.close') }}</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import api from '../../../api/play_record/index'
import { useI18n } from 'vue-i18n'
import { getChannelDeptRequestParams, withChannelDeptParams } from '@/composables/useChannelDeptScope'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
const { t } = useI18n()
import { getChannelDeptRequestParams } from '@/composables/useChannelDeptScope'
import type { FormInstance } from 'element-plus'
interface Props {
modelValue: boolean
@@ -200,7 +195,7 @@
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
dialogType: 'add',
dialogType: 'edit',
data: undefined
})
@@ -213,32 +208,6 @@
set: (value) => emit('update:modelValue', value)
})
const rules = computed<FormRules>(() => ({
player_id: [{ required: true, message: t('page.form.rulePlayerRequired'), trigger: 'change' }],
lottery_config_id: [{ required: true, message: t('page.form.ruleLotteryConfigRequired'), trigger: 'change' }],
lottery_type: [{ required: true, message: t('page.form.ruleLotteryTypeRequired'), trigger: 'change' }],
is_win: [{ required: true, message: t('page.form.ruleIsWinRequired'), trigger: 'change' }],
win_coin: [{ required: true, message: t('page.form.ruleWinCoinRequired'), trigger: 'blur' }],
rollArrayItems: [
{
validator: (_rule: any, value: (number | null)[], callback: (e?: Error) => void) => {
if (!value || value.length !== 5) {
callback(new Error(t('page.form.ruleRollArrayLength')))
return
}
const ok = value.every((n) => n != null && n >= 1 && n <= 6)
if (!ok) {
callback(new Error(t('page.form.ruleRollArrayValues')))
return
}
callback()
},
trigger: 'change'
}
],
reward_tier: [{ required: true, message: t('page.form.ruleRewardTierRequired'), trigger: 'change' }]
}))
const playerOptions = ref<Array<{ id: number; username: string }>>([])
const lotteryConfigOptions = ref<Array<{ id: number; name: string }>>([])
@@ -376,46 +345,6 @@
visible.value = false
formRef.value?.resetFields()
}
const handleSubmit = async () => {
if (!formRef.value) return
try {
await formRef.value.validate()
const payload = { ...formData } as Record<string, unknown>
// 将 5 个输入值拼成 [1,2,3,4,5] 格式,确保每项为 16 的整数
const items = formData.rollArrayItems
const rollArray = items.map((n) => {
const v = n != null ? Number(n) : 1
return Math.min(6, Math.max(1, Number.isNaN(v) ? 1 : Math.floor(v)))
})
payload.roll_array = rollArray
payload.roll_number = formData.roll_number ?? rollArray.reduce((s, n) => s + n, 0)
delete payload.rollArrayItems
if (props.dialogType === 'add') {
delete payload.id
await api.save(withChannelDeptParams(payload))
ElMessage.success(t('page.form.addSuccess'))
} else {
await api.update(withChannelDeptParams(payload))
ElMessage.success(t('page.form.editSuccess'))
}
emit('success')
handleClose()
} catch (error: any) {
let msg = t('page.form.validateFailed')
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>

View File

@@ -1,15 +1,15 @@
<template>
<el-dialog
v-model="visible"
:title="dialogType === 'add' ? $t('page.form.titleAdd') : $t('page.form.titleEdit')"
:title="$t('page.form.titleEdit')"
width="600px"
align-center
:close-on-click-modal="false"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
<el-form ref="formRef" :model="formData" label-width="120px">
<el-form-item :label="$t('page.form.labelLotteryConfigId')" prop="lottery_config_id">
<el-input v-model="formData.lottery_config_id" :placeholder="$t('page.form.placeholderLotteryConfigId')" />
<el-input v-model="formData.lottery_config_id" :placeholder="$t('page.form.placeholderLotteryConfigId')" disabled />
</el-form-item>
<el-form-item :label="$t('page.form.drawType')" prop="lottery_type">
<el-select
@@ -17,13 +17,20 @@
:placeholder="$t('form.placeholderSelect')"
clearable
style="width: 100%"
disabled
>
<el-option :label="$t('page.search.paid')" :value="0" />
<el-option :label="$t('page.search.free')" :value="1" />
</el-select>
</el-form-item>
<el-form-item :label="$t('page.search.direction')" prop="direction">
<el-select v-model="formData.direction" :placeholder="$t('form.placeholderSelect')" clearable style="width: 100%">
<el-select
v-model="formData.direction"
:placeholder="$t('form.placeholderSelect')"
clearable
style="width: 100%"
disabled
>
<el-option :label="$t('page.search.clockwise')" :value="0" />
<el-option :label="$t('page.search.anticlockwise')" :value="1" />
</el-select>
@@ -35,6 +42,7 @@
:precision="0"
controls-position="right"
style="width: 100%"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.search.paidAmount')" prop="paid_amount">
@@ -44,10 +52,11 @@
:precision="0"
controls-position="right"
style="width: 100%"
disabled
/>
</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-select v-model="formData.is_win" :placeholder="$t('form.placeholderSelect')" clearable style="width: 100%" disabled>
<el-option :label="$t('page.search.noBigWin')" :value="0" />
<el-option :label="$t('page.search.bigWin')" :value="1" />
</el-select>
@@ -59,6 +68,7 @@
:precision="0"
controls-position="right"
style="width: 100%"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.search.rewardTier')" prop="reward_tier">
@@ -67,6 +77,7 @@
:placeholder="$t('page.form.placeholderRewardTier')"
clearable
style="width: 100%"
disabled
>
<el-option label="T1" value="T1" />
<el-option label="T2" value="T2" />
@@ -77,19 +88,19 @@
</el-select>
</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-input v-model="formData.start_index" :placeholder="$t('page.form.placeholderStartIndex')" disabled />
</el-form-item>
<el-form-item :label="$t('page.form.labelTargetIndex')" prop="target_index">
<el-input v-model="formData.target_index" :placeholder="$t('page.form.placeholderTargetIndex')" />
<el-input v-model="formData.target_index" :placeholder="$t('page.form.placeholderTargetIndex')" disabled />
</el-form-item>
<el-form-item :label="$t('page.search.rollNumber')" prop="roll_number">
<el-input v-model="formData.roll_number" :placeholder="$t('page.form.placeholderRollNumber')" />
<el-input v-model="formData.roll_number" :placeholder="$t('page.form.placeholderRollNumber')" disabled />
</el-form-item>
<el-form-item :label="$t('page.form.labelRollArray')" prop="roll_array">
<el-input v-model="formData.roll_array" :placeholder="$t('page.form.placeholderRollArray')" />
<el-input v-model="formData.roll_array" :placeholder="$t('page.form.placeholderRollArray')" disabled />
</el-form-item>
<el-form-item :label="$t('page.form.labelStatus')" prop="status">
<sa-radio v-model="formData.status" dict="data_status" />
<sa-radio v-model="formData.status" dict="data_status" disabled />
</el-form-item>
<el-form-item :label="$t('page.table.superWinCoin')" prop="super_win_coin">
<el-input-number
@@ -98,6 +109,7 @@
:precision="0"
controls-position="right"
style="width: 100%"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.table.rewardWinCoin')" prop="reward_win_coin">
@@ -107,25 +119,21 @@
:precision="0"
controls-position="right"
style="width: 100%"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.labelAdminId')" prop="admin_id">
<el-input v-model="formData.admin_id" :placeholder="$t('page.form.placeholderAdminId')" />
<el-input v-model="formData.admin_id" :placeholder="$t('page.form.placeholderAdminId')" disabled />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="handleSubmit">{{ $t('table.form.submit') }}</el-button>
<el-button @click="handleClose">{{ $t('form.close') }}</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import api from '../../../api/play_record_test/index'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { useI18n } from 'vue-i18n'
import { withChannelDeptParams } from '@/composables/useChannelDeptScope'
import type { FormInstance } from 'element-plus'
interface Props {
modelValue: boolean
@@ -140,12 +148,11 @@
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
dialogType: 'add',
dialogType: 'edit',
data: undefined
})
const emit = defineEmits<Emits>()
const { t } = useI18n()
const formRef = ref<FormInstance>()
@@ -157,18 +164,6 @@
set: (value) => emit('update:modelValue', value)
})
/**
* 表单验证规则
*/
const rules = computed<FormRules>(() => ({
lottery_config_id: [{ required: true, message: t('page.form.ruleLotteryConfigIdRequired'), trigger: 'blur' }],
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_tier: [{ required: true, message: t('page.form.ruleRewardTierRequired'), trigger: 'blur' }],
status: [{ required: true, message: t('page.form.ruleStatusRequired'), trigger: 'blur' }]
}))
/**
* 初始数据
*/
@@ -198,7 +193,7 @@
const formData = reactive({ ...initialFormData })
/**
* 监听弹窗打开,初始化表单数据
* 监听弹窗打开,初始化表单数据(仅查看)
*/
watch(
() => props.modelValue,
@@ -213,9 +208,7 @@
* 初始化页面数据
*/
const initPage = async () => {
// 先重置为初始值
Object.assign(formData, initialFormData)
// 如果有数据,则填充数据
if (props.data) {
await nextTick()
initForm()
@@ -223,7 +216,7 @@
}
/**
* 初始化表单数据
* 回填表单数据
*/
function normalizePlatformCoin(val: unknown): number {
if (val === '' || val === null || val === undefined) return 0
@@ -245,34 +238,11 @@
}
}
/**
* 关闭弹窗并重置表单
* 关闭弹窗
*/
const handleClose = () => {
visible.value = false
formRef.value?.resetFields()
}
/**
* 提交表单
*/
const handleSubmit = async () => {
if (!formRef.value) return
try {
await formRef.value.validate()
const payload = { ...formData }
if (props.dialogType === 'add') {
await api.save(withChannelDeptParams(payload))
ElMessage.success(t('page.form.addSuccess'))
} else {
await api.update(withChannelDeptParams(payload))
ElMessage.success(t('page.form.editSuccess'))
}
emit('success')
handleClose()
} catch (error) {
console.log('表单验证失败:', error)
}
}
</script>

View File

@@ -1,13 +1,13 @@
<template>
<el-dialog
v-model="visible"
:title="dialogType === 'add' ? $t('page.form.dialogTitleAdd') : $t('page.form.dialogTitleEdit')"
:title="$t('page.form.dialogTitleEdit')"
width="600px"
align-center
:close-on-click-modal="false"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
<el-form ref="formRef" :model="formData" label-width="120px">
<el-form-item :label="$t('page.form.player')" prop="player_id">
<el-select
v-model="formData.player_id"
@@ -15,7 +15,7 @@
clearable
filterable
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
>
<el-option
v-for="item in playerOptions"
@@ -30,7 +30,7 @@
v-model="formData.use_coins"
:placeholder="$t('page.form.placeholderUseCoins')"
:min="0"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.paidDrawCount')" prop="paid_ticket_count">
@@ -38,8 +38,7 @@
v-model="formData.paid_ticket_count"
:placeholder="$t('page.form.placeholderPaidDrawCount')"
:min="0"
@change="onTicketCountChange"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.freeDrawCount')" prop="free_ticket_count">
@@ -47,8 +46,7 @@
v-model="formData.free_ticket_count"
:placeholder="$t('page.form.placeholderFreeDrawCount')"
:min="0"
@change="onTicketCountChange"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.totalDrawCount')" prop="total_ticket_count">
@@ -68,25 +66,20 @@
maxlength="500"
show-word-limit
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="handleSubmit">{{ $t('table.form.submit') }}</el-button>
<el-button @click="handleClose">{{ $t('form.close') }}</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import api from '../../../api/player_ticket_record/index'
import { useI18n } from 'vue-i18n'
import { getChannelDeptRequestParams, withChannelDeptParams } from '@/composables/useChannelDeptScope'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
const { t } = useI18n()
import { getChannelDeptRequestParams } from '@/composables/useChannelDeptScope'
import type { FormInstance } from 'element-plus'
interface Props {
modelValue: boolean
@@ -101,7 +94,7 @@
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
dialogType: 'add',
dialogType: 'edit',
data: undefined
})
@@ -117,17 +110,6 @@
set: (value) => emit('update:modelValue', value)
})
/**
* 表单验证规则
*/
const rules = reactive<FormRules>({
player_id: [{ required: true, message: t('page.form.rulePlayerRequired'), trigger: 'change' }],
use_coins: [{ required: true, message: t('page.form.ruleUseCoinsRequired'), trigger: 'blur' }],
paid_ticket_count: [{ required: true, message: t('page.form.rulePaidDrawRequired'), trigger: 'blur' }],
free_ticket_count: [{ required: true, message: t('page.form.ruleFreeDrawRequired'), trigger: 'blur' }],
remark: [{ required: true, message: t('page.form.ruleRemarkRequired'), trigger: 'blur' }]
})
/** 玩家下拉选项id、username */
const playerOptions = ref<Array<{ id: number; username: string }>>([])
@@ -138,10 +120,6 @@
return paid + free
})
function onTicketCountChange() {
formData.total_ticket_count = totalTicketCountComputed.value
}
/**
* 初始数据
*/
@@ -161,7 +139,7 @@
const formData = reactive({ ...initialFormData })
/**
* 监听弹窗打开,初始化表单并拉取玩家选项(与 player_wallet_record 一致)
* 监听弹窗打开,初始化表单并拉取玩家选项
*/
watch(
() => props.modelValue,
@@ -182,7 +160,7 @@
)
/**
* 初始化页面数据(仅重置表单、回填编辑数据,不在此处请求玩家列表)
* 初始化页面数据
*/
const initPage = async () => {
Object.assign(formData, { ...initialFormData })
@@ -193,7 +171,7 @@
}
/**
* 初始化表单数据
* 回填表单数据
*/
const initForm = () => {
if (!props.data) return
@@ -215,34 +193,10 @@
}
/**
* 关闭弹窗并重置表单
* 关闭弹窗
*/
const handleClose = () => {
visible.value = false
formRef.value?.resetFields()
}
/**
* 提交表单total_ticket_count 由 paid_ticket_count + free_ticket_count 自动求和,提交前写入)
*/
const handleSubmit = async () => {
if (!formRef.value) return
try {
formData.total_ticket_count = totalTicketCountComputed.value
await formRef.value.validate()
if (props.dialogType === 'add') {
const rest = { ...formData } as Record<string, unknown>
delete rest.id
await api.save(withChannelDeptParams(rest))
ElMessage.success(t('page.form.addSuccess'))
} else {
await api.update(withChannelDeptParams(formData))
ElMessage.success(t('page.form.editSuccess'))
}
emit('success')
handleClose()
} catch (error) {
console.log('表单验证失败:', error)
}
}
</script>

View File

@@ -1,13 +1,13 @@
<template>
<el-dialog
v-model="visible"
:title="dialogType === 'add' ? $t('page.form.dialogTitleAdd') : $t('page.form.dialogTitleEdit')"
:title="$t('page.form.dialogTitleEdit')"
width="600px"
align-center
:close-on-click-modal="false"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
<el-form ref="formRef" :model="formData" label-width="120px">
<el-form-item :label="$t('page.form.user')" prop="player_id">
<el-select
v-model="formData.player_id"
@@ -15,8 +15,7 @@
clearable
filterable
style="width: 100%"
:disabled="dialogType === 'edit'"
@change="onPlayerChange"
disabled
>
<el-option
v-for="item in playerOptions"
@@ -32,7 +31,7 @@
:placeholder="$t('page.form.placeholderType')"
clearable
style="width: 100%"
:disabled="dialogType === 'edit'"
disabled
>
<el-option :label="$t('page.form.typeRecharge')" :value="0" />
<el-option :label="$t('page.form.typeWithdraw')" :value="1" />
@@ -48,8 +47,7 @@
:precision="2"
:step="1"
style="width: 100%"
@change="onCoinChange"
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
<el-form-item :label="$t('page.form.walletBefore')" prop="wallet_before">
@@ -78,25 +76,20 @@
:placeholder="$t('page.form.placeholderRemark')"
maxlength="500"
show-word-limit
:disabled="dialogType === 'edit'"
disabled
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="handleSubmit">{{ $t('table.form.submit') }}</el-button>
<el-button @click="handleClose">{{ $t('form.close') }}</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import api from '../../../api/player_wallet_record/index'
import { useI18n } from 'vue-i18n'
import { getChannelDeptRequestParams, withChannelDeptParams } from '@/composables/useChannelDeptScope'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
const { t } = useI18n()
import { getChannelDeptRequestParams } from '@/composables/useChannelDeptScope'
import type { FormInstance } from 'element-plus'
interface Props {
modelValue: boolean
@@ -111,7 +104,7 @@
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
dialogType: 'add',
dialogType: 'edit',
data: undefined
})
@@ -127,12 +120,6 @@
set: (value) => emit('update:modelValue', value)
})
const rules = reactive<FormRules>({
player_id: [{ required: true, message: t('page.form.ruleUserRequired'), trigger: 'change' }],
coin: [{ required: true, message: t('page.form.ruleCoinRequired'), trigger: 'blur' }],
type: [{ required: true, message: t('page.form.ruleTypeRequired'), trigger: 'change' }]
})
const initialFormData: {
id: number | null
player_id: number | null
@@ -153,36 +140,6 @@
const formData = reactive({ ...initialFormData })
/** 选择用户后拉取当前平台币作为钱包操作前 */
async function onPlayerChange(playerId: number | null) {
if (playerId == null) {
formData.wallet_before = 0
calcWalletAfter()
return
}
try {
const res = await api.getPlayerWalletBefore(playerId)
const before = res?.wallet_before ?? 0
formData.wallet_before = Number(before)
calcWalletAfter()
} catch {
formData.wallet_before = 0
calcWalletAfter()
}
}
/** 平台币变化时重算钱包操作后 */
function onCoinChange() {
calcWalletAfter()
}
/** 钱包操作后 = 钱包操作前 + 平台币变化 */
function calcWalletAfter() {
const before = Number(formData.wallet_before) || 0
const coin = Number(formData.coin) || 0
formData.wallet_after = Number((before + coin).toFixed(2))
}
watch(
() => props.modelValue,
async (open) => {
@@ -230,24 +187,4 @@
visible.value = false
formRef.value?.resetFields()
}
const handleSubmit = async () => {
if (!formRef.value) return
try {
await formRef.value.validate()
calcWalletAfter()
const payload = { ...formData }
if (props.dialogType === 'add') {
await api.save(withChannelDeptParams(payload))
ElMessage.success(t('page.form.addSuccess'))
} else {
await api.update(withChannelDeptParams(payload))
ElMessage.success(t('page.form.editSuccess'))
}
emit('success')
handleClose()
} catch (error) {
console.log('表单验证失败:', error)
}
}
</script>

View File

@@ -1,36 +1,31 @@
<template>
<el-dialog
v-model="visible"
:title="dialogType === 'add' ? $t('page.form.titleAdd') : $t('page.form.titleEdit')"
:title="$t('page.form.titleEdit')"
width="600px"
align-center
:close-on-click-modal="false"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
<el-form ref="formRef" :model="formData" label-width="120px">
<el-form-item :label="$t('page.form.labelTestCount')" prop="test_count">
<el-input v-model="formData.test_count" :placeholder="$t('page.form.placeholderTestCount')" />
<el-input v-model="formData.test_count" :placeholder="$t('page.form.placeholderTestCount')" disabled />
</el-form-item>
<el-form-item :label="$t('page.form.labelWeightSnapshot')" prop="weight_config_snapshot">
<el-input v-model="formData.weight_config_snapshot" :placeholder="$t('page.form.placeholderWeightSnapshot')" />
<el-input v-model="formData.weight_config_snapshot" :placeholder="$t('page.form.placeholderWeightSnapshot')" disabled />
</el-form-item>
<el-form-item :label="$t('page.form.labelResultCounts')" prop="result_counts">
<el-input v-model="formData.result_counts" :placeholder="$t('page.form.placeholderResultCounts')" />
<el-input v-model="formData.result_counts" :placeholder="$t('page.form.placeholderResultCounts')" disabled />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="handleSubmit">{{ $t('table.form.submit') }}</el-button>
<el-button @click="handleClose">{{ $t('form.close') }}</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import api from '../../../api/reward_config_record/index'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { useI18n } from 'vue-i18n'
import { withChannelDeptParams } from '@/composables/useChannelDeptScope'
import type { FormInstance } from 'element-plus'
interface Props {
modelValue: boolean
@@ -45,12 +40,11 @@
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
dialogType: 'add',
dialogType: 'edit',
data: undefined
})
const emit = defineEmits<Emits>()
const { t } = useI18n()
const formRef = ref<FormInstance>()
@@ -62,13 +56,6 @@
set: (value) => emit('update:modelValue', value)
})
/**
* 表单验证规则
*/
const rules = computed<FormRules>(() => ({
test_count: [{ required: true, message: t('page.form.ruleTestCountRequired'), trigger: 'blur' }]
}))
/**
* 初始数据
*/
@@ -76,7 +63,7 @@
id: null,
test_count: 100,
weight_config_snapshot: '',
result_counts: '',
result_counts: ''
}
/**
@@ -85,7 +72,7 @@
const formData = reactive({ ...initialFormData })
/**
* 监听弹窗打开,初始化表单数据
* 监听弹窗打开,初始化表单数据(仅查看)
*/
watch(
() => props.modelValue,
@@ -100,9 +87,7 @@
* 初始化页面数据
*/
const initPage = async () => {
// 先重置为初始值
Object.assign(formData, initialFormData)
// 如果有数据,则填充数据
if (props.data) {
await nextTick()
initForm()
@@ -110,7 +95,7 @@
}
/**
* 初始化表单数据
* 回填表单数据
*/
const initForm = () => {
if (props.data) {
@@ -123,31 +108,10 @@
}
/**
* 关闭弹窗并重置表单
* 关闭弹窗
*/
const handleClose = () => {
visible.value = false
formRef.value?.resetFields()
}
/**
* 提交表单
*/
const handleSubmit = async () => {
if (!formRef.value) return
try {
await formRef.value.validate()
if (props.dialogType === 'add') {
await api.save(withChannelDeptParams(formData))
ElMessage.success(t('page.form.addSuccess'))
} else {
await api.update(withChannelDeptParams(formData))
ElMessage.success(t('page.form.editSuccess'))
}
emit('success')
handleClose()
} catch (error) {
console.log('表单验证失败:', error)
}
}
</script>