完善接口和后台页面
This commit is contained in:
130
app/admin/controller/config/DepositTier.php
Normal file
130
app/admin/controller/config/DepositTier.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\config;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\game\DepositTier as DepositTierLib;
|
||||
use InvalidArgumentException;
|
||||
use support\think\Db;
|
||||
use support\Response;
|
||||
use Throwable;
|
||||
use Webman\Http\Request as WebmanRequest;
|
||||
|
||||
/**
|
||||
* 充值档位独立编辑(仅 game_config.deposit_tier)
|
||||
*/
|
||||
class DepositTier extends Backend
|
||||
{
|
||||
protected bool $modelValidate = false;
|
||||
|
||||
protected array $noNeedPermission = ['index', 'save'];
|
||||
|
||||
private function hasNodePermission(WebmanRequest $request, string $action): bool
|
||||
{
|
||||
if (!$this->auth) {
|
||||
return false;
|
||||
}
|
||||
$controllerPath = get_controller_path($request);
|
||||
if (!$controllerPath) {
|
||||
return false;
|
||||
}
|
||||
$paths = [];
|
||||
$paths[] = $controllerPath . '/' . $action;
|
||||
$parts = explode('/', $controllerPath);
|
||||
foreach ($parts as &$part) {
|
||||
if (str_contains($part, '_')) {
|
||||
$part = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $part))));
|
||||
}
|
||||
}
|
||||
$paths[] = implode('/', $parts) . '/' . $action;
|
||||
foreach (array_values(array_unique($paths)) as $path) {
|
||||
if ($this->auth->check($path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function initController(WebmanRequest $request): ?Response
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取 game_config.deposit_tier 的档位列表
|
||||
*/
|
||||
public function index(WebmanRequest $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) {
|
||||
return $response;
|
||||
}
|
||||
if (!$this->hasNodePermission($request, 'index')) {
|
||||
return $this->error(__('You have no permission'), [], 401);
|
||||
}
|
||||
if ($request->method() !== 'GET') {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
$row = Db::name('game_config')->where('config_key', DepositTierLib::CONFIG_KEY)->find();
|
||||
$items = DepositTierLib::parseFromConfigValue($row['config_value'] ?? null);
|
||||
return $this->success('', [
|
||||
'items' => $items,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存 JSON 数组(value_type=json)
|
||||
*/
|
||||
public function save(WebmanRequest $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) {
|
||||
return $response;
|
||||
}
|
||||
if (!$this->hasNodePermission($request, 'save')) {
|
||||
return $this->error(__('You have no permission'), [], 401);
|
||||
}
|
||||
if ($request->method() !== 'POST') {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
$payload = $request->post();
|
||||
if (!is_array($payload)) {
|
||||
return $this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
$items = $payload['items'] ?? null;
|
||||
if (!is_array($items)) {
|
||||
return $this->error('items 必须为数组');
|
||||
}
|
||||
try {
|
||||
$clean = DepositTierLib::prepareItemsForSave(array_values($items));
|
||||
$json = DepositTierLib::encodeForDb($clean);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
|
||||
$now = time();
|
||||
try {
|
||||
$exists = Db::name('game_config')->where('config_key', DepositTierLib::CONFIG_KEY)->find();
|
||||
if ($exists) {
|
||||
Db::name('game_config')->where('config_key', DepositTierLib::CONFIG_KEY)->update([
|
||||
'config_value' => $json,
|
||||
'value_type' => 'json',
|
||||
'update_time' => $now,
|
||||
]);
|
||||
} else {
|
||||
Db::name('game_config')->insert([
|
||||
'config_key' => DepositTierLib::CONFIG_KEY,
|
||||
'config_value' => $json,
|
||||
'value_type' => 'json',
|
||||
'remark' => '充值档位 JSON 数组(独立表单维护)',
|
||||
'create_time' => $now,
|
||||
'update_time' => $now,
|
||||
]);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
|
||||
return $this->success(__('Saved successfully'));
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,13 @@ use Webman\Http\Request as WebmanRequest;
|
||||
|
||||
/**
|
||||
* 充值订单
|
||||
*
|
||||
* 订单的"由 0 转 1(成功入账)"统一走 app\common\library\finance\DepositSettlement。
|
||||
* 当前充值接口为 mock 支付网关,点击即成功;后台不再保留人工审核按钮,
|
||||
* 如需人工补单,请通过后续专门的"补单/冲正"工具完成,而不是在这个 CRUD 里直接改 status。
|
||||
*
|
||||
* 编辑入口现在只用于"查看详情":GET 返回订单 + 关联的 user/channel 信息,
|
||||
* 阻止 POST 任何改字段的动作(保证金额、状态只能由结算服务变更)。
|
||||
*/
|
||||
class DepositOrder extends Backend
|
||||
{
|
||||
@@ -18,7 +25,7 @@ class DepositOrder extends Backend
|
||||
|
||||
protected bool $modelSceneValidate = true;
|
||||
|
||||
protected string|array $quickSearchField = ['id', 'order_no', 'pay_channel', 'remark'];
|
||||
protected string|array $quickSearchField = ['id', 'order_no', 'pay_channel', 'remark', 'deposit_tier_id', 'idempotency_key'];
|
||||
|
||||
protected string|array $defaultSortField = ['id' => 'desc'];
|
||||
|
||||
@@ -65,6 +72,69 @@ class DepositOrder extends Backend
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET 时返回关联信息,便于前端详情弹窗直接渲染 user.username / channel.name;
|
||||
* POST 一律拒绝,保证充值订单的金额/状态只能由结算服务变更。
|
||||
*/
|
||||
protected function _edit(): Response
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request ? ($this->request->post($pk) ?? $this->request->get($pk)) : null;
|
||||
if ($id === null || $id === '') {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
if ($this->request && $this->request->method() === 'POST') {
|
||||
return $this->error('充值订单为自动入账,禁止直接修改,如需补单请走专用工具');
|
||||
}
|
||||
|
||||
$row = $this->loadWithRelations(intval(strval($id)));
|
||||
if (!$row) {
|
||||
return $this->error(__('Record not found'));
|
||||
}
|
||||
if (!$this->checkChannelScoped($row)) {
|
||||
return $this->error(__('You have no permission'));
|
||||
}
|
||||
|
||||
return $this->success('', ['row' => $row]);
|
||||
}
|
||||
|
||||
private function loadWithRelations(int $id): ?array
|
||||
{
|
||||
$row = $this->model
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->with($this->withJoinTable)
|
||||
->visible([
|
||||
'user' => ['username', 'phone'],
|
||||
'channel' => ['name'],
|
||||
])
|
||||
->where($this->model->getTable() . '.id', $id)
|
||||
->find();
|
||||
if (!$row) {
|
||||
return null;
|
||||
}
|
||||
return $row->toArray();
|
||||
}
|
||||
|
||||
private function checkChannelScoped(array $row): bool
|
||||
{
|
||||
if (!$this->auth || $this->auth->isSuperAdmin()) {
|
||||
return true;
|
||||
}
|
||||
$channelIds = $this->getScopedChannelIdsForFilter();
|
||||
if ($channelIds === []) {
|
||||
return false;
|
||||
}
|
||||
$raw = $row['channel_id'] ?? null;
|
||||
if ($raw === null || $raw === '') {
|
||||
return false;
|
||||
}
|
||||
if (!is_numeric(strval($raw))) {
|
||||
return false;
|
||||
}
|
||||
return in_array(intval(strval($raw)), $channelIds, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
|
||||
@@ -5,10 +5,16 @@ namespace app\admin\controller\order;
|
||||
use app\common\controller\Backend;
|
||||
use support\think\Db;
|
||||
use support\Response;
|
||||
use Throwable;
|
||||
use Webman\Http\Request as WebmanRequest;
|
||||
|
||||
/**
|
||||
* 提现订单
|
||||
*
|
||||
* 当前审核流转:
|
||||
* - 用户端提交提现时,立即冻结余额(user.coin - apply_amount)并生成 withdraw_order(status=0)与 withdraw 流水(direction=2)。
|
||||
* - 管理员在后台审核:通过(approve)→ status=1;拒绝(reject)→ status=2 并回冲用户余额与流水。
|
||||
* - 通过流程不再额外扣钱包,因为申请时已冻结;仅在管理员调整 amount/fee 时写一条差额流水。
|
||||
*/
|
||||
class WithdrawOrder extends Backend
|
||||
{
|
||||
@@ -66,6 +72,387 @@ class WithdrawOrder extends Backend
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET 时返回关联信息,便于编辑弹窗直接渲染 user.username/channel.name
|
||||
*/
|
||||
protected function _edit(): Response
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request ? ($this->request->post($pk) ?? $this->request->get($pk)) : null;
|
||||
if ($id === null || $id === '') {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
if ($this->request && $this->request->method() === 'POST') {
|
||||
// 历史 CRUD 的 POST 编辑已被 approve/reject 替代,这里阻止直接改金额绕过审核流程
|
||||
return $this->error('请使用通过/拒绝按钮完成审核');
|
||||
}
|
||||
|
||||
$row = $this->loadWithRelations(intval(strval($id)));
|
||||
if (!$row) {
|
||||
return $this->error(__('Record not found'));
|
||||
}
|
||||
if (!$this->checkChannelScoped($row)) {
|
||||
return $this->error(__('You have no permission'));
|
||||
}
|
||||
return $this->success('', ['row' => $row]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核通过:允许调整 amount/fee;actual_amount 自动为 amount - fee。
|
||||
* 对金额差额自动在用户钱包与流水中做增减,保持账务平衡。
|
||||
*/
|
||||
public function approve(WebmanRequest $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) {
|
||||
return $response;
|
||||
}
|
||||
if ($request->method() !== 'POST') {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
$id = $this->intParam($request->post('id'));
|
||||
if ($id <= 0) {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
$newAmount = $this->decimalParam($request->post('amount'), '0');
|
||||
$newFee = $this->decimalParam($request->post('fee'), '0');
|
||||
if (bccomp($newAmount, '0', 4) <= 0) {
|
||||
return $this->error('申请金额必须大于 0');
|
||||
}
|
||||
if (bccomp($newFee, '0', 4) < 0) {
|
||||
return $this->error('手续费不能为负');
|
||||
}
|
||||
if (bccomp($newFee, $newAmount, 4) > 0) {
|
||||
return $this->error('手续费不能大于申请金额');
|
||||
}
|
||||
$newActual = bcsub($newAmount, $newFee, 4);
|
||||
|
||||
$remarkRaw = $request->post('remark');
|
||||
$remark = is_string($remarkRaw) ? trim($remarkRaw) : '';
|
||||
|
||||
$order = Db::name('withdraw_order')->where('id', $id)->find();
|
||||
if (!$order) {
|
||||
return $this->error(__('Record not found'));
|
||||
}
|
||||
if (!$this->checkChannelScoped($order)) {
|
||||
return $this->error(__('You have no permission'));
|
||||
}
|
||||
$currentStatus = $this->intParam($order['status'] ?? 0);
|
||||
if ($currentStatus !== 0) {
|
||||
return $this->error('该订单已审核,无需重复操作');
|
||||
}
|
||||
|
||||
$userId = $this->intParam($order['user_id'] ?? 0);
|
||||
if ($userId <= 0) {
|
||||
return $this->error('订单缺少用户信息');
|
||||
}
|
||||
$oldAmount = bcadd(strval($order['amount'] ?? '0'), '0', 4);
|
||||
$diff = bcsub($newAmount, $oldAmount, 4);
|
||||
|
||||
$now = time();
|
||||
$adminId = $this->intParam($this->auth->id ?? 0);
|
||||
$adminName = $this->adminDisplayName();
|
||||
$channelIdRaw = $order['channel_id'] ?? null;
|
||||
$channelId = ($channelIdRaw === null || $channelIdRaw === '')
|
||||
? null
|
||||
: $this->intParam($channelIdRaw);
|
||||
if ($remark === '') {
|
||||
$remark = '管理员(' . $adminName . ')审核通过:金额 '
|
||||
. $this->shortAmount($newAmount) . ',手续费 ' . $this->shortAmount($newFee)
|
||||
. ',实际到账 ' . $this->shortAmount($newActual);
|
||||
}
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
// 金额调整差额处理
|
||||
$cmp = bccomp($diff, '0', 4);
|
||||
if ($cmp > 0) {
|
||||
// 新金额更大:再冻结用户 diff
|
||||
$userRow = Db::name('user')->where('id', $userId)->find();
|
||||
if (!$userRow) {
|
||||
Db::rollback();
|
||||
return $this->error('关联用户不存在');
|
||||
}
|
||||
$beforeCoin = bcadd(strval($userRow['coin'] ?? '0'), '0', 4);
|
||||
if (bccomp($beforeCoin, $diff, 4) < 0) {
|
||||
Db::rollback();
|
||||
return $this->error('用户余额不足以补扣调整差额');
|
||||
}
|
||||
$afterCoin = bcsub($beforeCoin, $diff, 4);
|
||||
Db::name('user')->where('id', $userId)->update([
|
||||
'coin' => $afterCoin,
|
||||
'total_withdraw_coin' => Db::raw('total_withdraw_coin + ' . $diff),
|
||||
'update_time' => $now,
|
||||
]);
|
||||
Db::name('user_wallet_record')->insert([
|
||||
'user_id' => $userId,
|
||||
'channel_id' => $channelId,
|
||||
'biz_type' => 'withdraw',
|
||||
'direction' => 2,
|
||||
'amount' => $diff,
|
||||
'balance_before' => $beforeCoin,
|
||||
'balance_after' => $afterCoin,
|
||||
'ref_type' => 'withdraw_order',
|
||||
'ref_id' => $id,
|
||||
'idempotency_key' => 'wd_adjust_add_' . strval($order['order_no'] ?? $id) . '_' . $now,
|
||||
'operator_admin_id' => $adminId > 0 ? $adminId : null,
|
||||
'remark' => '管理员(' . $adminName . ')审核调增申请金额差额 '
|
||||
. $this->shortAmount($diff),
|
||||
'create_time' => $now,
|
||||
]);
|
||||
} elseif ($cmp < 0) {
|
||||
// 新金额更小:退回差额
|
||||
$abs = bcsub('0', $diff, 4);
|
||||
$userRow = Db::name('user')->where('id', $userId)->find();
|
||||
if (!$userRow) {
|
||||
Db::rollback();
|
||||
return $this->error('关联用户不存在');
|
||||
}
|
||||
$beforeCoin = bcadd(strval($userRow['coin'] ?? '0'), '0', 4);
|
||||
$afterCoin = bcadd($beforeCoin, $abs, 4);
|
||||
Db::name('user')->where('id', $userId)->update([
|
||||
'coin' => $afterCoin,
|
||||
'total_withdraw_coin' => Db::raw('total_withdraw_coin - ' . $abs),
|
||||
'update_time' => $now,
|
||||
]);
|
||||
Db::name('user_wallet_record')->insert([
|
||||
'user_id' => $userId,
|
||||
'channel_id' => $channelId,
|
||||
'biz_type' => 'withdraw_refund',
|
||||
'direction' => 1,
|
||||
'amount' => $abs,
|
||||
'balance_before' => $beforeCoin,
|
||||
'balance_after' => $afterCoin,
|
||||
'ref_type' => 'withdraw_order',
|
||||
'ref_id' => $id,
|
||||
'idempotency_key' => 'wd_adjust_sub_' . strval($order['order_no'] ?? $id) . '_' . $now,
|
||||
'operator_admin_id' => $adminId > 0 ? $adminId : null,
|
||||
'remark' => '管理员(' . $adminName . ')审核调减申请金额差额 '
|
||||
. $this->shortAmount($abs),
|
||||
'create_time' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
Db::name('withdraw_order')->where('id', $id)->update([
|
||||
'amount' => $newAmount,
|
||||
'fee' => $newFee,
|
||||
'actual_amount' => $newActual,
|
||||
'status' => 1,
|
||||
'review_admin_id' => $adminId > 0 ? $adminId : null,
|
||||
'review_time' => $now,
|
||||
'remark' => substr($remark, 0, 255),
|
||||
'update_time' => $now,
|
||||
]);
|
||||
Db::commit();
|
||||
} catch (Throwable $e) {
|
||||
Db::rollback();
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
|
||||
return $this->success('审核通过', [
|
||||
'id' => $id,
|
||||
'amount' => $newAmount,
|
||||
'fee' => $newFee,
|
||||
'actual_amount' => $newActual,
|
||||
'status' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核拒绝:必须填写驳回原因(remark)。
|
||||
* 回冲申请时的冻结:user.coin += amount;total_withdraw_coin -= amount;写一条 withdraw_refund 流水。
|
||||
*/
|
||||
public function reject(WebmanRequest $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) {
|
||||
return $response;
|
||||
}
|
||||
if ($request->method() !== 'POST') {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
$id = $this->intParam($request->post('id'));
|
||||
if ($id <= 0) {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
$remarkRaw = $request->post('remark');
|
||||
$remark = is_string($remarkRaw) ? trim($remarkRaw) : '';
|
||||
if ($remark === '') {
|
||||
return $this->error('请填写拒绝原因');
|
||||
}
|
||||
|
||||
$order = Db::name('withdraw_order')->where('id', $id)->find();
|
||||
if (!$order) {
|
||||
return $this->error(__('Record not found'));
|
||||
}
|
||||
if (!$this->checkChannelScoped($order)) {
|
||||
return $this->error(__('You have no permission'));
|
||||
}
|
||||
$currentStatus = $this->intParam($order['status'] ?? 0);
|
||||
if ($currentStatus !== 0) {
|
||||
return $this->error('该订单已审核,无需重复操作');
|
||||
}
|
||||
|
||||
$userId = $this->intParam($order['user_id'] ?? 0);
|
||||
if ($userId <= 0) {
|
||||
return $this->error('订单缺少用户信息');
|
||||
}
|
||||
$amount = bcadd(strval($order['amount'] ?? '0'), '0', 4);
|
||||
$channelIdRaw = $order['channel_id'] ?? null;
|
||||
$channelId = ($channelIdRaw === null || $channelIdRaw === '')
|
||||
? null
|
||||
: $this->intParam($channelIdRaw);
|
||||
|
||||
$now = time();
|
||||
$adminId = $this->intParam($this->auth->id ?? 0);
|
||||
$adminName = $this->adminDisplayName();
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$userRow = Db::name('user')->where('id', $userId)->find();
|
||||
if (!$userRow) {
|
||||
Db::rollback();
|
||||
return $this->error('关联用户不存在');
|
||||
}
|
||||
$beforeCoin = bcadd(strval($userRow['coin'] ?? '0'), '0', 4);
|
||||
$afterCoin = bcadd($beforeCoin, $amount, 4);
|
||||
Db::name('user')->where('id', $userId)->update([
|
||||
'coin' => $afterCoin,
|
||||
'total_withdraw_coin' => Db::raw('total_withdraw_coin - ' . $amount),
|
||||
'update_time' => $now,
|
||||
]);
|
||||
|
||||
Db::name('user_wallet_record')->insert([
|
||||
'user_id' => $userId,
|
||||
'channel_id' => $channelId,
|
||||
'biz_type' => 'withdraw_refund',
|
||||
'direction' => 1,
|
||||
'amount' => $amount,
|
||||
'balance_before' => $beforeCoin,
|
||||
'balance_after' => $afterCoin,
|
||||
'ref_type' => 'withdraw_order',
|
||||
'ref_id' => $id,
|
||||
'idempotency_key' => 'wd_reject_' . strval($order['order_no'] ?? $id) . '_' . $now,
|
||||
'operator_admin_id' => $adminId > 0 ? $adminId : null,
|
||||
'remark' => '管理员(' . $adminName . ')驳回提现,退回冻结金额 '
|
||||
. $this->shortAmount($amount) . ':' . $remark,
|
||||
'create_time' => $now,
|
||||
]);
|
||||
|
||||
Db::name('withdraw_order')->where('id', $id)->update([
|
||||
'status' => 2,
|
||||
'review_admin_id' => $adminId > 0 ? $adminId : null,
|
||||
'review_time' => $now,
|
||||
'remark' => substr($remark, 0, 255),
|
||||
'update_time' => $now,
|
||||
]);
|
||||
Db::commit();
|
||||
} catch (Throwable $e) {
|
||||
Db::rollback();
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
|
||||
return $this->success('审核已拒绝', [
|
||||
'id' => $id,
|
||||
'status' => 2,
|
||||
'remark' => $remark,
|
||||
]);
|
||||
}
|
||||
|
||||
private function loadWithRelations(int $id): ?array
|
||||
{
|
||||
$row = $this->model
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->with($this->withJoinTable)
|
||||
->visible([
|
||||
'user' => ['username', 'phone'],
|
||||
'channel' => ['name'],
|
||||
'reviewAdmin' => ['username'],
|
||||
])
|
||||
->where($this->model->getTable() . '.id', $id)
|
||||
->find();
|
||||
if (!$row) {
|
||||
return null;
|
||||
}
|
||||
return $row->toArray();
|
||||
}
|
||||
|
||||
private function checkChannelScoped(array|object $row): bool
|
||||
{
|
||||
if (!$this->auth || $this->auth->isSuperAdmin()) {
|
||||
return true;
|
||||
}
|
||||
$channelIds = $this->getScopedChannelIdsForFilter();
|
||||
if ($channelIds === []) {
|
||||
return false;
|
||||
}
|
||||
$raw = is_array($row) ? ($row['channel_id'] ?? null) : ($row->channel_id ?? null);
|
||||
if ($raw === null || $raw === '') {
|
||||
// 无归属渠道的数据只有超管可见
|
||||
return false;
|
||||
}
|
||||
$cid = $this->intParam($raw);
|
||||
return in_array($cid, $channelIds, true);
|
||||
}
|
||||
|
||||
private function intParam($raw): int
|
||||
{
|
||||
if ($raw === null || $raw === '') {
|
||||
return 0;
|
||||
}
|
||||
if (!is_numeric(strval($raw))) {
|
||||
return 0;
|
||||
}
|
||||
return intval(strval($raw));
|
||||
}
|
||||
|
||||
private function decimalParam($raw, string $default): string
|
||||
{
|
||||
if ($raw === null || $raw === '' || !is_numeric(strval($raw))) {
|
||||
return bcadd($default, '0', 4);
|
||||
}
|
||||
return bcadd(strval($raw), '0', 4);
|
||||
}
|
||||
|
||||
private function adminDisplayName(): string
|
||||
{
|
||||
if (!$this->auth) {
|
||||
return 'admin';
|
||||
}
|
||||
$name = $this->auth->username ?? null;
|
||||
if (is_string($name) && $name !== '') {
|
||||
return $name;
|
||||
}
|
||||
$id = $this->intParam($this->auth->id ?? 0);
|
||||
return '#' . strval($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 把 4 位小数金额压缩成最多 2 位小数用于展示(不影响落库精度)
|
||||
*/
|
||||
private function shortAmount(string $amount): string
|
||||
{
|
||||
if (!is_numeric($amount)) {
|
||||
return $amount;
|
||||
}
|
||||
$normalized = bcadd($amount, '0', 4);
|
||||
$negative = false;
|
||||
if (str_starts_with($normalized, '-')) {
|
||||
$negative = true;
|
||||
$normalized = substr($normalized, 1);
|
||||
}
|
||||
$parts = explode('.', $normalized, 2);
|
||||
$intPart = $parts[0] ?? '0';
|
||||
$fracPart = $parts[1] ?? '0000';
|
||||
$displayFrac = substr($fracPart, 0, 2);
|
||||
$v = $intPart . '.' . str_pad($displayFrac, 2, '0');
|
||||
return $negative ? ('-' . $v) : $v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,7 @@ class User extends Backend
|
||||
*/
|
||||
protected ?object $model = null;
|
||||
|
||||
protected array|string $preExcludeFields = ['id', 'uuid', 'create_time', 'update_time', 'invite_code', 'coin', 'total_deposit_coin', 'total_valid_bet_coin'];
|
||||
protected array|string $preExcludeFields = ['id', 'uuid', 'create_time', 'update_time', 'invite_code', 'coin', 'total_deposit_coin', 'total_withdraw_coin', 'bet_flow_coin'];
|
||||
|
||||
protected array $withJoinTable = ['channel', 'admin'];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user