[色子游戏]玩家钱包流水记录-优化样式
This commit is contained in:
@@ -14,12 +14,6 @@
|
||||
<ElCol :xs="24" :sm="24" :md="6" :lg="6" :xl="6" class="action-column">
|
||||
<div class="action-buttons-wrapper" :style="actionButtonsStyle">
|
||||
<div class="form-buttons">
|
||||
<ElButton v-if="showReset" class="reset-button" @click="handleReset" v-ripple>
|
||||
<template #icon>
|
||||
<ArtSvgIcon icon="ri:reset-right-line" />
|
||||
</template>
|
||||
{{ t('table.searchBar.reset') }}
|
||||
</ElButton>
|
||||
<ElButton
|
||||
v-if="showSearch"
|
||||
type="primary"
|
||||
@@ -33,6 +27,12 @@
|
||||
</template>
|
||||
{{ t('table.searchBar.search') }}
|
||||
</ElButton>
|
||||
<ElButton v-if="showReset" class="reset-button" @click="handleReset" v-ripple>
|
||||
<template #icon>
|
||||
<ArtSvgIcon icon="ri:reset-right-line" />
|
||||
</template>
|
||||
{{ t('table.searchBar.reset') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
<div v-if="showExpand" class="filter-toggle" @click="toggleExpand">
|
||||
<span>{{ expandToggleText }}</span>
|
||||
|
||||
@@ -61,5 +61,24 @@ export default {
|
||||
url: '/dice/player_wallet_record/DicePlayerWalletRecord/destroy',
|
||||
data: params
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取玩家选项(id、username)用于下拉
|
||||
*/
|
||||
getPlayerOptions() {
|
||||
return request.get<{ id: number; username: string }[]>({
|
||||
url: '/dice/player_wallet_record/DicePlayerWalletRecord/getPlayerOptions'
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取指定玩家当前平台币(钱包操作前)
|
||||
*/
|
||||
getPlayerWalletBefore(playerId: number | string) {
|
||||
return request.get<{ wallet_before: number }>({
|
||||
url: '/dice/player_wallet_record/DicePlayerWalletRecord/getPlayerWalletBefore',
|
||||
params: { player_id: playerId }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
<ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData">
|
||||
<template #left>
|
||||
<ElSpace wrap>
|
||||
<ElButton v-permission="'dice:player_wallet_record:index:save'" @click="showDialog('add')" v-ripple>
|
||||
<ElButton
|
||||
v-permission="'dice:player_wallet_record:index:save'"
|
||||
@click="showDialog('add')"
|
||||
v-ripple
|
||||
>
|
||||
<template #icon>
|
||||
<ArtSvgIcon icon="ri:add-fill" />
|
||||
</template>
|
||||
@@ -77,10 +81,12 @@
|
||||
import TableSearch from './modules/table-search.vue'
|
||||
import EditDialog from './modules/edit-dialog.vue'
|
||||
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = ref({
|
||||
type: undefined,
|
||||
username: undefined,
|
||||
coin_min: undefined,
|
||||
coin_max: undefined
|
||||
})
|
||||
|
||||
// 搜索处理
|
||||
@@ -89,6 +95,16 @@
|
||||
getData()
|
||||
}
|
||||
|
||||
// 类型展示:0=充值 1=提现 2=购买抽奖次数
|
||||
const typeFormatter = (row: Record<string, unknown>) =>
|
||||
row.type === 0 ? '充值' : row.type === 1 ? '提现' : row.type === 2 ? '购买抽奖次数' : '-'
|
||||
|
||||
// 用户列展示为 dicePlayer.username(兼容 dice_player)
|
||||
const usernameFormatter = (row: Record<string, any>) => {
|
||||
const player = row.dicePlayer ?? row.dice_player
|
||||
return player?.username ?? row.player_id ?? '-'
|
||||
}
|
||||
|
||||
// 表格配置
|
||||
const {
|
||||
columns,
|
||||
@@ -108,11 +124,18 @@
|
||||
apiFn: api.list,
|
||||
columnsFactory: () => [
|
||||
{ type: 'selection' },
|
||||
{ prop: 'player_id', label: '用户id' },
|
||||
{ prop: 'coin', label: '平台币变化' },
|
||||
{ prop: 'type', label: '类型' },
|
||||
{ prop: 'wallet_before', label: '钱包操作前' },
|
||||
{ prop: 'wallet_after', label: '钱包操作后' },
|
||||
{ prop: 'id', label: 'ID', width: 80 },
|
||||
{ prop: 'player_id', label: '用户', width: 120, formatter: usernameFormatter },
|
||||
{ prop: 'coin', label: '平台币变化', width: 110 },
|
||||
{ prop: 'type', label: '类型', width: 120, formatter: typeFormatter },
|
||||
{ prop: 'wallet_before', label: '钱包操作前', width: 110 },
|
||||
{ prop: 'wallet_after', label: '钱包操作后', width: 110 },
|
||||
{
|
||||
prop: 'remark',
|
||||
label: '备注',
|
||||
width: 100,
|
||||
showOverflowTooltip: true
|
||||
},
|
||||
{ prop: 'total_draw_count', label: '总抽奖次数' },
|
||||
{ prop: 'paid_draw_count', label: '购买抽奖次数' },
|
||||
{ prop: 'free_draw_count', label: '赠送抽奖次数' },
|
||||
@@ -132,5 +155,4 @@
|
||||
handleSelectionChange,
|
||||
selectedRows
|
||||
} = useSaiAdmin()
|
||||
|
||||
</script>
|
||||
|
||||
@@ -8,29 +8,67 @@
|
||||
@close="handleClose"
|
||||
>
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
|
||||
<el-form-item label="用户id" prop="player_id">
|
||||
<el-cascader v-model="formData.player_id" :options="[]" placeholder="请选择用户id" allow-clear />
|
||||
</el-form-item>
|
||||
<el-form-item label="平台币变化" prop="coin">
|
||||
<el-input-number v-model="formData.coin" placeholder="请输入平台币变化" />
|
||||
<el-form-item label="用户" prop="player_id">
|
||||
<el-select
|
||||
v-model="formData.player_id"
|
||||
placeholder="请选择用户(显示用户名)"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
:disabled="dialogType === 'edit'"
|
||||
@change="onPlayerChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in playerOptions"
|
||||
:key="item.id"
|
||||
:label="item.username"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select v-model="formData.type" :options="[]" placeholder="请选择类型" clearable />
|
||||
<el-select v-model="formData.type" placeholder="请选择类型" clearable style="width: 100%">
|
||||
<el-option label="充值" :value="0" />
|
||||
<el-option label="提现" :value="1" />
|
||||
<el-option label="购买抽奖次数" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="平台币变化" prop="coin">
|
||||
<el-input-number
|
||||
v-model="formData.coin"
|
||||
placeholder="正数增加、负数减少"
|
||||
:precision="2"
|
||||
style="width: 100%"
|
||||
@change="onCoinChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="钱包操作前" prop="wallet_before">
|
||||
<el-input-number v-model="formData.wallet_before" placeholder="请输入钱包操作前" />
|
||||
<el-input-number
|
||||
v-model="formData.wallet_before"
|
||||
placeholder="选择用户后自动带出当前平台币"
|
||||
:precision="2"
|
||||
disabled
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="钱包操作后" prop="wallet_after">
|
||||
<el-input-number v-model="formData.wallet_after" placeholder="请输入钱包操作后" />
|
||||
<el-input-number
|
||||
v-model="formData.wallet_after"
|
||||
placeholder="根据平台币变化自动计算"
|
||||
:precision="2"
|
||||
disabled
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="总抽奖次数" prop="total_draw_count">
|
||||
<el-input-number v-model="formData.total_draw_count" placeholder="请输入总抽奖次数" />
|
||||
</el-form-item>
|
||||
<el-form-item label="购买抽奖次数" prop="paid_draw_count">
|
||||
<el-input-number v-model="formData.paid_draw_count" placeholder="请输入购买抽奖次数" />
|
||||
</el-form-item>
|
||||
<el-form-item label="赠送抽奖次数" prop="free_draw_count">
|
||||
<el-input-number v-model="formData.free_draw_count" placeholder="请输入赠送抽奖次数" />
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
placeholder="选填"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -66,104 +104,120 @@
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
/**
|
||||
* 弹窗显示状态双向绑定
|
||||
*/
|
||||
/** 玩家下拉选项(id、username) */
|
||||
const playerOptions = ref<{ id: number; username: string }[]>([])
|
||||
|
||||
const visible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => emit('update:modelValue', value)
|
||||
})
|
||||
|
||||
/**
|
||||
* 表单验证规则
|
||||
*/
|
||||
const rules = reactive<FormRules>({
|
||||
player_id: [{ required: true, message: '用户id必需填写', trigger: 'blur' }],
|
||||
coin: [{ required: true, message: '平台币变化必需填写', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '类型必需填写', trigger: 'blur' }],
|
||||
total_draw_count: [{ required: true, message: '总抽奖次数必需填写', trigger: 'blur' }],
|
||||
paid_draw_count: [{ required: true, message: '购买抽奖次数必需填写', trigger: 'blur' }],
|
||||
free_draw_count: [{ required: true, message: '赠送抽奖次数必需填写', trigger: 'blur' }],
|
||||
player_id: [{ required: true, message: '请选择用户', trigger: 'change' }],
|
||||
coin: [{ required: true, message: '平台币变化必填', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '请选择类型', trigger: 'change' }]
|
||||
})
|
||||
|
||||
/**
|
||||
* 初始数据
|
||||
*/
|
||||
const initialFormData = {
|
||||
id: null,
|
||||
player_id: null,
|
||||
coin: '0.00',
|
||||
type: null,
|
||||
wallet_before: '',
|
||||
wallet_after: '',
|
||||
total_draw_count: null,
|
||||
paid_draw_count: null,
|
||||
free_draw_count: null,
|
||||
id: null as number | null,
|
||||
player_id: null as number | null,
|
||||
coin: 0 as number,
|
||||
type: null as number | null,
|
||||
wallet_before: 0 as number,
|
||||
wallet_after: 0 as number,
|
||||
remark: '' as string
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单数据
|
||||
*/
|
||||
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 = Math.round((before + coin) * 100) / 100
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
async (open) => {
|
||||
if (open) {
|
||||
initPage()
|
||||
try {
|
||||
const list = await api.getPlayerOptions()
|
||||
playerOptions.value = Array.isArray(list) ? list : []
|
||||
} catch {
|
||||
playerOptions.value = []
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* 初始化页面数据
|
||||
*/
|
||||
const initPage = async () => {
|
||||
// 先重置为初始值
|
||||
Object.assign(formData, initialFormData)
|
||||
// 如果有数据,则填充数据
|
||||
if (props.data) {
|
||||
await nextTick()
|
||||
initForm()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化表单数据
|
||||
*/
|
||||
const numKeys = ['id', 'player_id', 'coin', 'type', 'wallet_before', 'wallet_after']
|
||||
|
||||
const initForm = () => {
|
||||
if (props.data) {
|
||||
for (const key in formData) {
|
||||
if (props.data[key] != null && props.data[key] != undefined) {
|
||||
;(formData as any)[key] = props.data[key]
|
||||
if (!props.data) return
|
||||
for (const key of Object.keys(formData)) {
|
||||
if (!(key in props.data)) continue
|
||||
const val = props.data[key]
|
||||
if (numKeys.includes(key)) {
|
||||
if (key === 'id' || key === 'player_id' || key === 'type') {
|
||||
;(formData as any)[key] = val != null && val !== '' ? Number(val) : null
|
||||
} else {
|
||||
;(formData as any)[key] = val != null && val !== '' ? Number(val) : 0
|
||||
}
|
||||
} else {
|
||||
;(formData as any)[key] = val ?? ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭弹窗并重置表单
|
||||
*/
|
||||
const handleClose = () => {
|
||||
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(formData)
|
||||
await api.save(payload)
|
||||
ElMessage.success('新增成功')
|
||||
} else {
|
||||
await api.update(formData)
|
||||
await api.update(payload)
|
||||
ElMessage.success('修改成功')
|
||||
}
|
||||
emit('success')
|
||||
|
||||
@@ -8,9 +8,39 @@
|
||||
@search="handleSearch"
|
||||
@expand="handleExpand"
|
||||
>
|
||||
<el-col v-bind="setSpan(6)">
|
||||
<el-col v-bind="setSpan(5)">
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select v-model="formData.type" :options="[]" placeholder="请选择类型" clearable />
|
||||
<el-select v-model="formData.type" placeholder="全部" clearable style="width: 100%">
|
||||
<el-option label="充值" :value="0" />
|
||||
<el-option label="提现" :value="1" />
|
||||
<el-option label="购买抽奖次数" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="setSpan(5)">
|
||||
<el-form-item label="用户(用户名)" prop="username">
|
||||
<el-input v-model="formData.username" placeholder="按用户名搜索" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="setSpan(8)">
|
||||
<el-form-item label="平台币" prop="coin_min">
|
||||
<div class="coin-range-wrap">
|
||||
<el-input-number
|
||||
v-model="formData.coin_min"
|
||||
placeholder="最小"
|
||||
:precision="2"
|
||||
controls-position="right"
|
||||
class="coin-range-input"
|
||||
/>
|
||||
<span class="coin-range-sep">至</span>
|
||||
<el-input-number
|
||||
v-model="formData.coin_max"
|
||||
placeholder="最大"
|
||||
:precision="2"
|
||||
controls-position="right"
|
||||
class="coin-range-input"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</sa-search-bar>
|
||||
@@ -65,3 +95,22 @@
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.coin-range-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-width: 0; /* 允许在栅格内收缩,避免挤压右侧按钮 */
|
||||
}
|
||||
|
||||
.coin-range-input {
|
||||
flex: 1;
|
||||
min-width: 0; /* 数字框可收缩 */
|
||||
}
|
||||
|
||||
.coin-range-sep {
|
||||
color: var(--el-text-color-secondary);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user