Files
webman-buildadmin/app/admin/controller/config/DepositTier.php
zhenhui 0f28c0fd2a 1.新增充值档位配置
2.新增充值/提现配置
2026-04-21 18:31:43 +08:00

422 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\admin\controller\config;
use app\common\controller\Backend;
use app\common\library\game\DepositTier as DepositTierLib;
use app\common\service\GameHotDataCoordinator;
use app\common\service\GameHotDataLock;
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;
}
/**
* 列表baTablelist / total / remark支持 quickSearch、分页
*/
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);
$quickSearch = $request->get('quickSearch', '');
if (is_string($quickSearch) && trim($quickSearch) !== '') {
$q = mb_strtolower(trim($quickSearch));
$items = array_values(array_filter($items, static function (array $it) use ($q): bool {
$id = isset($it['id']) && is_string($it['id']) ? mb_strtolower($it['id']) : '';
$t = isset($it['title']) && is_string($it['title']) ? mb_strtolower($it['title']) : '';
$te = isset($it['title_en']) && is_string($it['title_en']) ? mb_strtolower($it['title_en']) : '';
return $q === '' || str_contains($id, $q) || str_contains($t, $q) || str_contains($te, $q);
}));
}
$orderRaw = $request->get('order', '');
if (is_string($orderRaw) && str_contains($orderRaw, ',')) {
$parts = explode(',', $orderRaw, 2);
$field = trim($parts[0]);
$dir = strtolower(trim($parts[1] ?? 'asc'));
if ($field === 'sort') {
usort($items, static function (array $a, array $b) use ($dir): int {
$sa = isset($a['sort']) && is_numeric($a['sort']) ? intval($a['sort']) : 0;
$sb = isset($b['sort']) && is_numeric($b['sort']) ? intval($b['sort']) : 0;
if ($sa !== $sb) {
return $dir === 'desc' ? ($sb <=> $sa) : ($sa <=> $sb);
}
$ida = isset($a['id']) && is_string($a['id']) ? $a['id'] : '';
$idb = isset($b['id']) && is_string($b['id']) ? $b['id'] : '';
return strcmp($ida, $idb);
});
}
}
$total = count($items);
$pageRaw = $request->get('page', '1');
$limitRaw = $request->get('limit', '20');
$page = is_numeric($pageRaw) ? max(1, intval($pageRaw)) : 1;
$limit = is_numeric($limitRaw) ? max(1, min(500, intval($limitRaw))) : 20;
$offset = ($page - 1) * $limit;
$pageRows = array_slice($items, $offset, $limit);
return $this->success('', [
'list' => $pageRows,
'total' => $total,
'remark' => '',
'items' => $pageRows,
]);
}
/**
* 单条读取(弹窗编辑)
*/
public function edit(WebmanRequest $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) {
return $response;
}
if (!$this->hasNodePermission($request, 'edit')) {
return $this->error(__('You have no permission'), [], 401);
}
if ($request->method() === 'GET') {
$id = $request->get('id', '');
if (!is_string($id) || trim($id) === '') {
return $this->error(__('Parameter error'));
}
$row = Db::name('game_config')->where('config_key', DepositTierLib::CONFIG_KEY)->find();
$items = DepositTierLib::parseFromConfigValue($row['config_value'] ?? null);
$found = null;
foreach ($items as $it) {
if (!is_array($it)) {
continue;
}
$rid = $it['id'] ?? '';
if (is_string($rid) && $rid === $id) {
$found = $it;
break;
}
}
if ($found === null) {
return $this->error(__('Record not found'));
}
return $this->success('', ['row' => $found]);
}
if ($request->method() === 'POST') {
if (!$this->hasNodePermission($request, 'edit')) {
return $this->error(__('You have no permission'), [], 401);
}
$payload = $request->post();
if (!is_array($payload)) {
return $this->error(__('Parameter %s can not be empty', ['']));
}
$id = isset($payload['id']) && is_string($payload['id']) ? trim($payload['id']) : '';
if ($id === '') {
return $this->error(__('Parameter error'));
}
$cfgRow = Db::name('game_config')->where('config_key', DepositTierLib::CONFIG_KEY)->find();
$items = DepositTierLib::parseFromConfigValue($cfgRow['config_value'] ?? null);
$foundIdx = -1;
$foundRow = null;
foreach ($items as $k => $it) {
if (!is_array($it)) {
continue;
}
$rid = $it['id'] ?? '';
if (is_string($rid) && $rid === $id) {
$foundIdx = $k;
$foundRow = $it;
break;
}
}
if ($foundIdx < 0 || $foundRow === null) {
return $this->error(__('Record not found'));
}
$items[$foundIdx] = $this->mergeDepositTierEditPayload($foundRow, $payload, $id);
return $this->persistTierList($items);
}
return $this->error(__('Parameter error'));
}
/**
* 新增一条档位
*/
public function add(WebmanRequest $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) {
return $response;
}
if (!$this->hasNodePermission($request, 'add')) {
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', ['']));
}
$cfgRow = Db::name('game_config')->where('config_key', DepositTierLib::CONFIG_KEY)->find();
$items = DepositTierLib::parseFromConfigValue($cfgRow['config_value'] ?? null);
$newId = isset($payload['id']) && is_string($payload['id']) ? trim($payload['id']) : '';
if ($newId === '') {
$newId = DepositTierLib::generateId();
}
foreach ($items as $it) {
if (!is_array($it)) {
continue;
}
$rid = $it['id'] ?? '';
if (is_string($rid) && $rid === $newId) {
return $this->error('档位 ID 已存在');
}
}
$items[] = $this->normalizeFormRow($payload, $newId);
return $this->persistTierList($items);
}
/**
* 删除(支持批量 ids
*/
public function del(WebmanRequest $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) {
return $response;
}
if (!$this->hasNodePermission($request, 'del')) {
return $this->error(__('You have no permission'), [], 401);
}
if ($request->method() !== 'DELETE') {
return $this->error(__('Parameter error'));
}
$ids = $request->get('ids', []);
if (!is_array($ids)) {
if (is_string($ids) && $ids !== '') {
$ids = [$ids];
} else {
$ids = [];
}
}
$idSet = [];
foreach ($ids as $id) {
if (is_string($id) && trim($id) !== '') {
$idSet[trim($id)] = true;
}
}
if ($idSet === []) {
return $this->error(__('Parameter error'));
}
$cfgRow = Db::name('game_config')->where('config_key', DepositTierLib::CONFIG_KEY)->find();
$items = DepositTierLib::parseFromConfigValue($cfgRow['config_value'] ?? null);
$filtered = [];
foreach ($items as $it) {
if (!is_array($it)) {
continue;
}
$rid = isset($it['id']) && is_string($it['id']) ? $it['id'] : '';
if ($rid !== '' && isset($idSet[$rid])) {
continue;
}
$filtered[] = $it;
}
return $this->persistTierList($filtered);
}
/**
* 整表保存 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 必须为数组');
}
return $this->persistTierList($items);
}
/**
* @param list<array<string, mixed>> $items
*/
private function persistTierList(array $items): Response
{
try {
$clean = DepositTierLib::prepareItemsForSave(array_values($items));
$json = DepositTierLib::encodeForDb($clean);
} catch (InvalidArgumentException $e) {
return $this->error($e->getMessage());
}
$now = time();
$resourceKey = GameHotDataLock::safeResourceKeyForConfig(DepositTierLib::CONFIG_KEY);
$lock = GameHotDataLock::tryAcquire(GameHotDataLock::TYPE_GAME_CONFIG, $resourceKey);
if (!$lock['acquired']) {
return $this->error('该配置正在被其他操作占用,请稍后再试');
}
try {
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());
}
GameHotDataCoordinator::afterGameConfigKeyCommitted(DepositTierLib::CONFIG_KEY);
return $this->success(__('Saved successfully'));
} finally {
GameHotDataLock::release(GameHotDataLock::TYPE_GAME_CONFIG, $resourceKey, $lock['token'], $lock['redis_lock']);
}
}
/**
* 弹窗整表提交与列表内开关:未出现在 payload 中的字段沿用 $current。
*
* @param array<string, mixed> $current
* @param array<string, mixed> $payload
*
* @return array<string, mixed>
*/
private function mergeDepositTierEditPayload(array $current, array $payload, string $id): array
{
$merged = [];
$merged['id'] = $id;
if (array_key_exists('sort', $payload)) {
$merged['sort'] = $payload['sort'];
} else {
$merged['sort'] = $current['sort'] ?? 0;
}
if (array_key_exists('status', $payload)) {
$merged['status'] = $payload['status'];
} else {
$merged['status'] = $current['status'] ?? 0;
}
$stringKeys = ['title', 'title_en', 'currency', 'pay_amount', 'amount', 'bonus_amount', 'desc', 'desc_en'];
foreach ($stringKeys as $key) {
if (array_key_exists($key, $payload)) {
$merged[$key] = $payload[$key];
} else {
$merged[$key] = $current[$key] ?? ($key === 'bonus_amount' ? '0' : '');
}
}
return $this->normalizeFormRow($merged, $id);
}
/**
* @param array<string, mixed> $payload
*
* @return array<string, mixed>
*/
private function normalizeFormRow(array $payload, string $id): array
{
$sort = isset($payload['sort']) && is_numeric($payload['sort']) ? intval($payload['sort']) : 0;
$status = 0;
$st = $payload['status'] ?? 1;
if ($st === true || $st === 1 || $st === '1') {
$status = 1;
}
return [
'id' => $id,
'title' => isset($payload['title']) && is_string($payload['title']) ? $payload['title'] : '',
'title_en' => isset($payload['title_en']) && is_string($payload['title_en']) ? $payload['title_en'] : '',
'currency' => isset($payload['currency']) && is_string($payload['currency']) ? $payload['currency'] : '',
'pay_amount' => $payload['pay_amount'] ?? '',
'amount' => $payload['amount'] ?? '',
'bonus_amount' => $payload['bonus_amount'] ?? '0',
'desc' => isset($payload['desc']) && is_string($payload['desc']) ? $payload['desc'] : '',
'desc_en' => isset($payload['desc_en']) && is_string($payload['desc_en']) ? $payload['desc_en'] : '',
'sort' => $sort,
'status' => $status,
];
}
}