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', FinanceCashierConfigLib::CONFIG_KEY)->find(); $cfg = FinanceCashierConfigLib::parseFromConfigValue($row['config_value'] ?? null); $currencies = []; if (isset($cfg['currencies']) && is_array($cfg['currencies'])) { foreach ($cfg['currencies'] as $item) { if (!is_array($item)) { continue; } $code = isset($item['code']) && is_string($item['code']) ? strtoupper(trim($item['code'])) : ''; if ($code === '') { continue; } $currencies[] = $code; } } $currencies = array_values(array_unique($currencies)); if ($currencies === []) { $currencies = ['MYR', 'CNY', 'USD', 'USDT', 'VND', 'THB', 'SGD', 'IDR']; } return $this->success('', ['list' => $currencies]); } 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; } /** * 列表(baTable:list / 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(__('Tier ID already exists')); } } $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 must be an array')); } return $this->persistTierList($items); } /** * @param list> $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(__('This config is locked by another operation, please try again later')); } 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 $current * @param array $payload * * @return array */ 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 $payload * * @return array */ 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, ]; } }