[色子游戏]玩家-新增玩家钱包操作

This commit is contained in:
2026-03-04 15:04:11 +08:00
parent 00d964ad80
commit 0492e08cc7
10 changed files with 368 additions and 11 deletions

View File

@@ -80,5 +80,21 @@ export default {
url: '/dice/player_wallet_record/DicePlayerWalletRecord/getPlayerWalletBefore',
params: { player_id: playerId }
})
},
/**
* 管理员钱包操作(加点/扣点):更新玩家平台币并创建流水记录
* type 3=加点 4=扣点
*/
adminOperate(params: {
player_id: number
type: 3 | 4
coin: number
remark?: string
}) {
return request.post<any>({
url: '/dice/player_wallet_record/DicePlayerWalletRecord/adminOperate',
data: params
})
}
}

View File

@@ -51,9 +51,16 @@
@change="(v: string | number | boolean) => handleStatusChange(row, v ? 1 : 0)"
/>
</template>
<!-- 平台币tag 展示 -->
<!-- 平台币tag 可点击打开钱包操作弹窗 -->
<template #coin="{ row }">
<ElTag type="info" size="small">{{ row.coin ?? 0 }}</ElTag>
<ElTag
type="info"
size="small"
class="cursor-pointer hover:opacity-80"
@click="openWalletOperate(row)"
>
{{ row.coin ?? 0 }}
</ElTag>
</template>
<!-- 操作列 -->
<template #operation="{ row }">
@@ -80,6 +87,13 @@
:data="dialogData"
@success="refreshData"
/>
<!-- 钱包操作弹窗加点/扣点 -->
<WalletOperateDialog
v-model="walletDialogVisible"
:player="walletOperatePlayer"
@success="refreshData"
/>
</div>
</template>
@@ -89,6 +103,7 @@
import api from '../../api/player/index'
import TableSearch from './modules/table-search.vue'
import EditDialog from './modules/edit-dialog.vue'
import WalletOperateDialog from './modules/WalletOperateDialog.vue'
// 搜索表单
const searchForm = ref({
@@ -188,4 +203,13 @@
handleSelectionChange,
selectedRows
} = useSaiAdmin()
// 钱包操作弹窗(从平台币 tag 点击打开)
const walletDialogVisible = ref(false)
const walletOperatePlayer = ref<Record<string, any> | null>(null)
function openWalletOperate(row: Record<string, any>) {
walletOperatePlayer.value = row
walletDialogVisible.value = true
}
</script>

View File

@@ -0,0 +1,172 @@
<template>
<el-dialog
v-model="visible"
title="玩家钱包操作"
width="480px"
align-center
:close-on-click-modal="false"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
<el-form-item label="玩家">
<el-input :model-value="player?.username" disabled placeholder="-" />
</el-form-item>
<el-form-item label="钱包余额">
<el-input-number
:model-value="walletBalance"
disabled
:precision="2"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="操作类型" prop="type">
<el-select v-model="formData.type" placeholder="请选择" clearable style="width: 100%">
<el-option label="加点" :value="3" />
<el-option label="扣点" :value="4" />
</el-select>
</el-form-item>
<el-form-item label="平台币变动" prop="coin">
<el-input-number
v-model="formData.coin"
:min="0.01"
:precision="2"
placeholder="正数,扣点时不能超过余额"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
<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>
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import walletRecordApi from '../../../api/player_wallet_record/index'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
interface PlayerRow {
id: number
username?: string
coin?: number
}
interface Props {
modelValue: boolean
player: PlayerRow | null
}
interface Emits {
(e: 'update:modelValue', value: boolean): void
(e: 'success'): void
}
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
player: null
})
const emit = defineEmits<Emits>()
const formRef = ref<FormInstance>()
const submitting = ref(false)
const visible = computed({
get: () => props.modelValue,
set: (v) => emit('update:modelValue', v)
})
const walletBalance = computed(() => {
const c = props.player?.coin
return c != null && c !== '' ? Number(c) : 0
})
const rules = reactive<FormRules>({
type: [{ required: true, message: '请选择操作类型', trigger: 'change' }],
coin: [
{ required: true, message: '请输入平台币变动', trigger: 'blur' },
{
validator: (_rule, value, callback) => {
const n = Number(value)
if (Number.isNaN(n) || n <= 0) {
callback(new Error('平台币变动必须大于 0'))
return
}
if (formData.type === 4 && n > walletBalance.value) {
callback(new Error('扣点不能超过当前余额'))
return
}
callback()
},
trigger: 'blur'
}
]
})
const initialFormData = {
type: null as 3 | 4 | null,
coin: null as number | null,
remark: ''
}
const formData = reactive({ ...initialFormData })
watch(
() => props.modelValue,
(open) => {
if (open) {
Object.assign(formData, initialFormData)
formData.type = 3
}
}
)
const handleClose = () => {
visible.value = false
formRef.value?.resetFields()
}
const handleSubmit = async () => {
if (!formRef.value || !props.player?.id) return
try {
await formRef.value.validate()
const coin = Number(formData.coin) || 0
if (coin <= 0) {
ElMessage.warning('平台币变动必须大于 0')
return
}
if (formData.type === 4 && coin > walletBalance.value) {
ElMessage.warning('扣点不能超过当前余额')
return
}
submitting.value = true
await walletRecordApi.adminOperate({
player_id: props.player.id,
type: formData.type!,
coin,
remark: formData.remark?.trim() || undefined
})
ElMessage.success('操作成功')
emit('success')
handleClose()
} catch (e) {
if ((e as any)?.message) ElMessage.warning((e as any).message)
} finally {
submitting.value = false
}
}
</script>

View File

@@ -102,9 +102,23 @@
getData()
}
// 类型展示0=充值 1=提现 2=购买抽奖次数
const typeFormatter = (row: Record<string, unknown>) =>
row.type === 0 ? '充值' : row.type === 1 ? '提现' : row.type === 2 ? '购买抽奖次数' : '-'
// 类型展示0=充值 1=提现 2=购买抽奖次数 3=管理员加点 4=管理员扣点
const typeFormatter = (row: Record<string, unknown>) => {
const t = row.type
if (t === 0) return '充值'
if (t === 1) return '提现'
if (t === 2) return '购买抽奖次数'
if (t === 3) return '管理员加点'
if (t === 4) return '管理员扣点'
return '-'
}
// 操作人:关联管理员用户名
const operatorFormatter = (row: Record<string, any>) => {
const op = row.operator ?? row.operator_id
if (op && typeof op === 'object' && op.username) return op.username
return row.user_id ?? '-'
}
// 用户列展示为 dicePlayer.username兼容 dice_player
const usernameFormatter = (row: Record<string, any>) => {
@@ -135,6 +149,12 @@
{ prop: 'player_id', label: '用户', width: 120, formatter: usernameFormatter },
{ prop: 'coin', label: '平台币变化', width: 110 },
{ prop: 'type', label: '类型', width: 120, formatter: typeFormatter },
{
prop: 'user_id',
label: '操作人',
width: 100,
formatter: operatorFormatter
},
{ prop: 'wallet_before', label: '钱包操作前', width: 110 },
{ prop: 'wallet_after', label: '钱包操作后', width: 110 },
{

View File

@@ -31,6 +31,8 @@
<el-option label="充值" :value="0" />
<el-option label="提现" :value="1" />
<el-option label="购买抽奖次数" :value="2" />
<el-option label="管理员加点" :value="3" />
<el-option label="管理员扣点" :value="4" />
</el-select>
</el-form-item>
<el-form-item label="平台币变化" prop="coin">

View File

@@ -14,6 +14,8 @@
<el-option label="充值" :value="0" />
<el-option label="提现" :value="1" />
<el-option label="购买抽奖次数" :value="2" />
<el-option label="管理员加点" :value="3" />
<el-option label="管理员扣点" :value="4" />
</el-select>
</el-form-item>
</el-col>