From 95684c784e2fd45aae5a134738830666c8dcff12 Mon Sep 17 00:00:00 2001 From: zhouzp <1558048883@qq.com> Date: Wed, 22 Apr 2026 16:38:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=99=E9=A2=9D=E5=8F=98=E5=8A=A8=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/user/MoneyLog.php | 111 +++++++++++++++++- app/admin/controller/user/User.php | 4 +- app/admin/model/UserMoneyLog.php | 11 ++ app/common/service/JK8Services.php | 23 +++- web/src/lang/backend/en/user/moneyLog.ts | 14 +++ web/src/lang/backend/en/user/user.ts | 1 + web/src/lang/backend/zh-cn/user/moneyLog.ts | 14 +++ web/src/lang/backend/zh-cn/user/user.ts | 1 + web/src/views/backend/user/moneyLog/index.vue | 44 ++++++- .../views/backend/user/moneyLog/popupForm.vue | 96 ++++++++++++--- web/src/views/backend/user/user/index.vue | 1 + web/src/views/backend/user/user/popupForm.vue | 18 +-- 12 files changed, 306 insertions(+), 32 deletions(-) diff --git a/app/admin/controller/user/MoneyLog.php b/app/admin/controller/user/MoneyLog.php index 20f86f1..97d61e6 100644 --- a/app/admin/controller/user/MoneyLog.php +++ b/app/admin/controller/user/MoneyLog.php @@ -2,6 +2,7 @@ namespace app\admin\controller\user; +use app\common\service\Jk8Services; use Throwable; use app\admin\model\User; use app\admin\model\UserMoneyLog; @@ -15,19 +16,63 @@ class MoneyLog extends Backend */ protected object $model; - protected array $withJoinTable = ['user']; + protected array $withJoinTable = ['user', 'admin']; + protected array $withTable = ['scoreLog']; // 排除字段 protected string|array $preExcludeFields = ['create_time']; protected string|array $quickSearchField = ['user.username', 'user.nickname']; + protected $jk8Services; public function initialize(): void { parent::initialize(); + $this->jk8Services = app(Jk8Services::class); $this->model = new UserMoneyLog(); } + /** + * 验证逻辑 + */ + protected function validateModelData(array $data, string $scene = ''): void + { + if (!$this->modelValidate) return; + + $validateClass = str_replace("\\model\\", "\\validate\\", get_class($this->model)); + if (class_exists($validateClass)) { + $validate = new $validateClass(); + if ($scene) $validate->scene($scene); + $validate->check($data); + } + } + + /** + * 查看 + * @throws Throwable + */ + public function index(): void + { + if ($this->request->param('select')) { + $this->select(); + } + + list($where, $alias, $limit, $order) = $this->queryBuilder(); + $res = $this->model + ->withJoin($this->withJoinTable, $this->withJoinType) + ->with($this->withTable) + ->alias($alias) + ->where($where) + ->order($order) + ->paginate($limit); + + $this->success('', [ + 'list' => $res->items(), + 'total' => $res->total(), + 'remark' => get_route_remark(), + ]); + } + /** * 添加 * @param int $userId @@ -36,7 +81,45 @@ class MoneyLog extends Backend public function add(int $userId = 0): void { if ($this->request->isPost()) { - parent::add(); + $data = $this->request->post(); + if (!$data) { + $this->error(__('Parameter %s can not be empty', [''])); + } + $result = false; + $data = $this->excludeFields($data); + + $user = User::where('id', $data['user_id'])->find(); + if ($data['type'] == 2) { + $data['money'] = -$data['money']; + } + if ($user->money + $data['money'] < 0) { + $this->error(__('Insufficient Credit')); + } + + try { + // 模型验证 + $this->validateModelData($data, 'add'); + $transactionId = $this->jk8Services->setScore($user['jk_username'], $data['money']); + } catch (Throwable $e) { + $this->error($e->getMessage()); + } + + $this->model->startTrans(); + try { + $data['transaction_id'] = $transactionId; + $data['created_by'] = $this->auth->getInfo()['id']; +// $data['type'] = $data['money'] > 0 ? 1 : 2; + $result = $this->model->save($data); + $this->model->commit(); + } catch (Throwable $e) { + $this->model->rollback(); + $this->error($e->getMessage()); + } + if ($result !== false) { + $this->success(__('Added successfully')); + } else { + $this->error(__('No rows were added')); + } } $user = User::where('id', $userId)->find(); @@ -47,4 +130,28 @@ class MoneyLog extends Backend 'user' => $user ]); } + + /** + * 编辑 + * @throws Throwable + */ + public function edit(): void + { + $pk = $this->model->getPk(); + $id = $this->request->param($pk); + $row = $this->model->find($id); + if (!$row) { + $this->error(__('Record not found')); + } + $user = User::where('id', $row['user_id'])->find(); + if ($this->request->isPost()) { + parent::edit(); + return; + } + $row['username'] = $user['username']; + $row['nickname'] = $user['nickname']; + $this->success('', [ + 'row' => $row + ]); + } } \ No newline at end of file diff --git a/app/admin/controller/user/User.php b/app/admin/controller/user/User.php index a8c839e..b73670a 100644 --- a/app/admin/controller/user/User.php +++ b/app/admin/controller/user/User.php @@ -95,7 +95,8 @@ class User extends Backend try { // 模型验证 $this->validateModelData($data, 'add'); - $jkId = $this->jk8Services->register($data['username'], $data['nickname'] ?? '', $data['referrer_code'] ?? ''); + $jkId = $this->jk8Services->register($data['mobile'], $data['nickname'] ?? '', $data['referrer_code'] ?? ''); + $jkUserName = $this->jk8Services->getAllUsers($jkId); } catch (Throwable $e) { $this->error($e->getMessage()); } @@ -103,6 +104,7 @@ class User extends Backend $this->model->startTrans(); try { $data['jk_user_id'] = $jkId; + $data['jk_username'] = $jkUserName; $result = $this->model->save($data); $this->model->commit(); diff --git a/app/admin/model/UserMoneyLog.php b/app/admin/model/UserMoneyLog.php index bff4062..99cbe02 100644 --- a/app/admin/model/UserMoneyLog.php +++ b/app/admin/model/UserMoneyLog.php @@ -2,6 +2,7 @@ namespace app\admin\model; +use think\model\relation\HasMany; use Throwable; use think\model; use think\Exception; @@ -77,4 +78,14 @@ class UserMoneyLog extends model { return $this->belongsTo(User::class, 'user_id'); } + + public function admin(): BelongsTo + { + return $this->belongsTo(Admin::class, 'created_by'); + } + + public function scoreLog(): hasMany + { + return $this->hasMany(UserScoreLog::class, 'money_log_id'); + } } \ No newline at end of file diff --git a/app/common/service/JK8Services.php b/app/common/service/JK8Services.php index 477a765..cb21f59 100644 --- a/app/common/service/JK8Services.php +++ b/app/common/service/JK8Services.php @@ -56,6 +56,23 @@ class Jk8Services return $result['data']['id']; } + /** + * 用户注册 + * @param int|null $userId + * @return string + * @throws Exception + */ + public function getAllUsers(int $userId = null): string + { + $params = $this->createParam('/users/getAllUsers', [ + 'id' => $userId, + ]); + $result = doCurl($this->domain, $params); + if (($result['status'] ?? '') === 'ERROR') { + throw new Exception($result['data']['message'] ?? 'Remote API Error'); + } + return $result['data']['users'][0]['username'] ?? ''; + } /** * 获取促销列表 * @param string $userId @@ -77,19 +94,21 @@ class Jk8Services /** * 转账 * @param string $username + * @param float $amount * @return array|mixed|null * @throws Exception */ - public function setScore(string $username): mixed + public function setScore(string $username, float $amount): mixed { $params = $this->createParam('/member/setScore', [ 'username' => $username, + 'amount' => $amount ]); $result = doCurl($this->domain, $params); if (($result['status'] ?? '') === 'ERROR') { throw new Exception($result['data']['message'] ?? 'Remote API Error'); } - return $result; + return $result['data']['transactionId']; } /** diff --git a/web/src/lang/backend/en/user/moneyLog.ts b/web/src/lang/backend/en/user/moneyLog.ts index 0714c79..20c7ed6 100644 --- a/web/src/lang/backend/en/user/moneyLog.ts +++ b/web/src/lang/backend/en/user/moneyLog.ts @@ -13,4 +13,18 @@ export default { 'Balance after change': 'Balance after change', 'Please enter change remarks / description': 'Please enter change remarks/description', User: 'User', + 'Transaction id': 'Transaction id', + 'Created by': 'Created by', + 'type': '类型', + 'type_list': { + 1 : 'Deposit', + 2 : 'Withdraw', + }, + 'Game Ticket' : 'Game Ticket', + 'game_type': { + 1001 : 'Lucky Wheel', + 1002 : 'Golden Eggs', + 1003 : 'Daily Mission', + 1004 : 'Plinko Ball' + } } diff --git a/web/src/lang/backend/en/user/user.ts b/web/src/lang/backend/en/user/user.ts index 6fc2d04..5eff12d 100644 --- a/web/src/lang/backend/en/user/user.ts +++ b/web/src/lang/backend/en/user/user.ts @@ -2,6 +2,7 @@ export default { 'User name': 'Username', nickname: 'Nickname', 'jk user id': 'JK8 UserId', + 'jk user name': 'JK8 UserName', 'referrer code': 'referrerCode', group: 'Group', avatar: 'Avatar', diff --git a/web/src/lang/backend/zh-cn/user/moneyLog.ts b/web/src/lang/backend/zh-cn/user/moneyLog.ts index 7f40880..3128766 100644 --- a/web/src/lang/backend/zh-cn/user/moneyLog.ts +++ b/web/src/lang/backend/zh-cn/user/moneyLog.ts @@ -13,4 +13,18 @@ export default { 'Balance after change': '变更后余额', 'Please enter change remarks / description': '请输入变更备注/说明', User: '用户', + 'Transaction id': '订单号', + 'Created by': '来源', + 'type': '类型', + 'type_list': { + 1 : '存款', + 2 : '取款', + }, + 'Game Ticket' : '游戏门票', + 'game_type': { + 1001 : 'Lucky Wheel', + 1002 : 'Golden Eggs', + 1003 : 'Daily Mission', + 1004 : 'Plinko Ball' + } } diff --git a/web/src/lang/backend/zh-cn/user/user.ts b/web/src/lang/backend/zh-cn/user/user.ts index 8ad3a80..27a041c 100644 --- a/web/src/lang/backend/zh-cn/user/user.ts +++ b/web/src/lang/backend/zh-cn/user/user.ts @@ -2,6 +2,7 @@ export default { 'User name': '用户名', nickname: '昵称', 'jk user id': 'JK8 UserId', + 'jk user name': 'JK8 UserName', 'referrer code': '推荐码', group: '分组', avatar: '头像', diff --git a/web/src/views/backend/user/moneyLog/index.vue b/web/src/views/backend/user/moneyLog/index.vue index b620f7f..ddeee99 100644 --- a/web/src/views/backend/user/moneyLog/index.vue +++ b/web/src/views/backend/user/moneyLog/index.vue @@ -36,12 +36,13 @@ import { baTableApi } from '/@/api/common' import TableHeader from '/@/components/table/header/index.vue' import Table from '/@/components/table/index.vue' import baTableClass from '/@/utils/baTable' - +import scoreLog from '/@/lang/backend/zh-cn/user/scoreLog' +import { defaultOptButtons } from '/@/components/table' defineOptions({ name: 'user/moneyLog', }) -const { t } = useI18n() +const { t, tm } = useI18n() const route = useRoute() const defalutUser = (route.query.user_id ?? '') as string const state = reactive({ @@ -53,8 +54,15 @@ const baTable = new baTableClass( { column: [ { type: 'selection', align: 'center', operator: false }, - { label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 }, - { label: t('user.moneyLog.User ID'), prop: 'user_id', align: 'center', width: 70 }, + { + label: t('user.moneyLog.Created by'), + prop: 'admin.username', + align: 'center', + width: 70, + formatter: (row: TableRow) => { + return row.admin?.username || 'web' + } + }, { label: t('user.moneyLog.User name'), prop: 'user.username', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') }, { label: t('user.moneyLog.User nickname'), @@ -66,6 +74,33 @@ const baTable = new baTableClass( { label: t('user.moneyLog.Change balance'), prop: 'money', 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.Transaction id'), prop: 'transaction_id', align: 'center', operator: 'RANGE', sortable: 'custom' }, + { + label: t('user.moneyLog.Game Ticket'), + prop: 'scoreLog', + align: 'center', + // 使用渲染函数手动构建显示内容 + formatter: (row: TableRow) => { + if (!row.scoreLog || row.scoreLog.length === 0) return '-' + return row.scoreLog.map((item: any) => { + const gameName = scoreLog.game_type[item.game_type] || item.game_type + return `${gameName}: ${item.score}` + }).join(' | ') + } + }, + { + label: t('user.moneyLog.type'), + prop: 'type', + align: 'center', + operator: 'eq', + sortable: false, + render: 'tag', + custom: { + '1': 'success', + '2': 'danger', + }, + replaceValue: { ...tm('user.moneyLog.type_list') }, + }, { label: t('user.moneyLog.remarks'), prop: 'memo', @@ -75,6 +110,7 @@ const baTable = new baTableClass( showOverflowTooltip: true, }, { label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 }, + { label: t('Operate'), align: 'center', width: '60', render: 'buttons', buttons: defaultOptButtons(['edit']) }, ], dblClickNotEditColumn: ['all'], }, diff --git a/web/src/views/backend/user/moneyLog/popupForm.vue b/web/src/views/backend/user/moneyLog/popupForm.vue index 50570b4..0e07918 100644 --- a/web/src/views/backend/user/moneyLog/popupForm.vue +++ b/web/src/views/backend/user/moneyLog/popupForm.vue @@ -37,27 +37,71 @@ field: 'nickname_text', remoteUrl: '/admin/user.User/index', onChange: getAdd, + disabled: baTable.form.operate == 'Edit' }" /> - + - - + + - + + + + - + + +