钱包修改

This commit is contained in:
2026-04-17 11:53:19 +08:00
parent 7f3a7c34f0
commit ad74accfcc
10 changed files with 136 additions and 24 deletions

View File

@@ -6,6 +6,7 @@ use app\common\service\Jk8Services;
use Throwable; use Throwable;
use app\common\controller\Backend; use app\common\controller\Backend;
use app\admin\model\User as UserModel; use app\admin\model\User as UserModel;
use app\admin\model\UserScore;
class User extends Backend class User extends Backend
{ {
@@ -14,6 +15,7 @@ class User extends Backend
* @phpstan-var UserModel * @phpstan-var UserModel
*/ */
protected object $model; protected object $model;
protected object $score;
protected array $withJoinTable = ['userGroup']; protected array $withJoinTable = ['userGroup'];
protected $jk8Services; protected $jk8Services;
@@ -28,6 +30,7 @@ class User extends Backend
parent::initialize(); parent::initialize();
$this->jk8Services = app(Jk8Services::class); $this->jk8Services = app(Jk8Services::class);
$this->model = new UserModel(); $this->model = new UserModel();
$this->score = new UserScore();
} }
/** /**
@@ -170,4 +173,55 @@ class User extends Backend
'remark' => get_route_remark(), 'remark' => get_route_remark(),
]); ]);
} }
/**
* 钱包
* @throws Throwable
*/
public function wallet(): void
{
$miniGames = config('mini_game') ?: [];
$pk = $this->model->getPk();
$id = $this->request->param($pk);
if ($this->request->isPost()) {
$this->model = new UserScore();
parent::edit();
return;
}
$row = $this->model->find($id);
if (!$row) {
$this->error(__('Record not found'));
}
$existGameTypes = $row->userScore()
->whereIn('game_type', array_keys($miniGames))
->column('game_type');
$scoreInsert = [];
foreach ($miniGames as $key => $name) {
if (!in_array($key, $existGameTypes)) {
$scoreInsert[] = [
'user_id' => $id,
'game_type' => $key,
'score' => 0,
];
}
}
if (!empty($scoreInsert)) {
$row->userScore()->saveAll($scoreInsert);
}
$data = [
'mini_game' => $miniGames,
'score' => $row->userScore()
->whereIn('game_type', array_keys($miniGames))
->withoutField(['user_id'])
->order('game_type', 'asc')
->select()
];
$this->success('', $data);
}
} }

View File

@@ -4,6 +4,7 @@ namespace app\admin\model;
use think\Model; use think\Model;
use think\model\relation\BelongsTo; use think\model\relation\BelongsTo;
use think\model\relation\HasMany;
/** /**
* User 模型 * User 模型
@@ -49,4 +50,9 @@ class User extends Model
{ {
return $this->where(['id' => $uid])->update(['password' => hash_password($newPassword), 'salt' => '']); return $this->where(['id' => $uid])->update(['password' => hash_password($newPassword), 'salt' => '']);
} }
public function userScore(): HasMany
{
return $this->hasMany(UserScore::class, 'user_id');
}
} }

View File

@@ -0,0 +1,47 @@
<?php
namespace app\admin\model;
use think\Exception;
use think\model;
use think\model\relation\BelongsTo;
use Throwable;
use app\admin\model\UserScoreLog;
/**
* UserScoreLog 模型
* 1. 创建积分日志自动完成会员积分的添加
* 2. 创建积分日志时,请开启事务
*/
class UserScore extends model
{
protected $updateTime = false;
/**
* 更新前
* @throws Throwable
*/
public static function onBeforeUpdate($model): void
{
$before = $model->getOrigin('score');
$after = $model->score;
// 1. 只有当分数确实发生变化时才记录日志
if (bccomp($before, $after, 2) !== 0) {
// 计算分值变动after - before
$change = bcsub($after, $before);
$userScoreLog = new UserScoreLog();
$userScoreLog->save([
'user_id' => $model->user_id,
'game_type' => $model->game_type,
'before' => $before,
'after' => $after,
'score' => $change,
'memo' => '管理员手动调整', // 建议增加备注字段区分来源
]);
}
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}

View File

@@ -17,27 +17,6 @@ class UserScoreLog extends model
protected $autoWriteTimestamp = true; protected $autoWriteTimestamp = true;
protected $updateTime = false; protected $updateTime = false;
/**
* 入库前
* @throws Throwable
*/
public static function onBeforeInsert($model): void
{
$user = User::where('id', $model->user_id)->lock(true)->find();
if (!$user) {
throw new Exception("The user can't find it");
}
if (!$model->memo) {
throw new Exception("Change note cannot be blank");
}
$model->before = $user->score;
$user->score += $model->score;
$user->save();
$model->after = $user->score;
}
public static function onBeforeDelete(): bool public static function onBeforeDelete(): bool
{ {
return false; return false;

8
config/mini_game.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
return [
1001 => 'Lucky Wheel',
1002 => 'Golden Eggs',
1003 => 'Daily Mission',
1004 => 'Plinko Ball',
];

View File

@@ -5,4 +5,11 @@ export default {
'Please enter the change amount of points': '请输入积分变更数额', 'Please enter the change amount of points': '请输入积分变更数额',
'Points after change': '变更后积分', 'Points after change': '变更后积分',
'Please enter change remarks / description': '请输入变更备注/说明', 'Please enter change remarks / description': '请输入变更备注/说明',
'Game type' : '游戏',
'game_type': {
1001 : 'Lucky Wheel',
1002 : 'Golden Eggs',
1003 : 'Daily Mission',
1004 : 'Plinko Ball'
}
} }

View File

@@ -47,4 +47,5 @@ export default {
'Expand generic search': 'Expand Universal Search', 'Expand generic search': 'Expand Universal Search',
'Link address': 'Link address', 'Link address': 'Link address',
'No route found to jump~': 'Failed to find a jump route.', 'No route found to jump~': 'Failed to find a jump route.',
'Members Promotion':'Members Promotion',
} }

View File

@@ -48,4 +48,5 @@ export default {
'Expand generic search': '展开公共搜索', 'Expand generic search': '展开公共搜索',
'Link address': '链接地址', 'Link address': '链接地址',
'No route found to jump~': '没有找到可以跳转的路由~', 'No route found to jump~': '没有找到可以跳转的路由~',
'Members Promotion':'玩家钱包',
} }

View File

@@ -4,7 +4,7 @@
<!-- 表格顶部菜单 --> <!-- 表格顶部菜单 -->
<TableHeader <TableHeader
:buttons="['refresh', 'add', 'comSearch', 'quickSearch', 'columnDisplay']" :buttons="['refresh', 'comSearch', 'quickSearch', 'columnDisplay']"
:quick-search-placeholder=" :quick-search-placeholder="
t('Quick search placeholder', { fields: t('user.moneyLog.User name') + '/' + t('user.moneyLog.User nickname') }) t('Quick search placeholder', { fields: t('user.moneyLog.User name') + '/' + t('user.moneyLog.User nickname') })
" "
@@ -41,7 +41,7 @@ defineOptions({
name: 'user/scoreLog', name: 'user/scoreLog',
}) })
const { t } = useI18n() const { t,tm } = useI18n()
const route = useRoute() const route = useRoute()
const defalutUser = (route.query.user_id ?? '') as string const defalutUser = (route.query.user_id ?? '') as string
const state = reactive({ const state = reactive({
@@ -63,6 +63,15 @@ const baTable = new baTableClass(
operator: 'LIKE', operator: 'LIKE',
operatorPlaceholder: t('Fuzzy query'), operatorPlaceholder: t('Fuzzy query'),
}, },
{
label: t('user.scoreLog.Game type'),
prop: 'game_type',
align: 'center',
operator: 'eq',
sortable: false,
render: 'tag',
replaceValue: { ...tm('user.scoreLog.game_type') },
},
{ label: t('user.scoreLog.Change points'), prop: 'score', align: 'center', operator: 'RANGE', sortable: 'custom' }, { label: t('user.scoreLog.Change points'), prop: 'score', align: 'center', operator: 'RANGE', sortable: 'custom' },
{ label: t('user.moneyLog.Before change'), prop: 'before', align: 'center', operator: 'RANGE', sortable: 'custom' }, { label: t('user.moneyLog.Before change'), prop: 'before', align: 'center', operator: 'RANGE', sortable: 'custom' },
{ label: t('user.moneyLog.After change'), prop: 'after', align: 'center', operator: 'RANGE', sortable: 'custom' }, { label: t('user.moneyLog.After change'), prop: 'after', align: 'center', operator: 'RANGE', sortable: 'custom' },

View File

@@ -49,7 +49,7 @@ const optButtons: OptButton[] = [
title: 'Members Promotion', title: 'Members Promotion',
text: '', text: '',
type: 'primary', type: 'primary',
icon: 'el-icon-EditPen', icon: 'el-icon-Wallet',
class: 'table-row-custom', class: 'table-row-custom',
disabledTip: false, disabledTip: false,
loading: (row: TableRow) => walletLoadingId.value === row.id, loading: (row: TableRow) => walletLoadingId.value === row.id,