feat: 增强管理员功能与数据处理

- 在多个控制器中引入 agent_node_id,以支持基于代理节点的权限和数据过滤。
- 更新 AdminRole 和 AdminUser 模型,新增角色范围和代理节点相关功能,提升角色管理的灵活性。
- 在请求验证中添加 agent_node_id 字段,确保 API 接口支持代理节点的相关操作。
- 优化 LotterySettings 服务,支持批量写入设置,提升配置管理的效率。
- 更新仪表板和报告服务,增强数据统计功能,确保管理员能够获取更全面的统计信息。
This commit is contained in:
2026-06-02 14:36:58 +08:00
parent d5232c756f
commit 0841fbed32
96 changed files with 5004 additions and 182 deletions

View File

@@ -2,6 +2,8 @@
namespace App\Support;
use App\Models\AdminUser;
final class AdminAuthorizationRegistry
{
/**
@@ -25,6 +27,13 @@ final class AdminAuthorizationRegistry
['slug' => 'prd.admin_user.manage', 'name' => '管理员列表·可管理', 'nav_segment' => 'admin_users', 'permission_codes' => ['system.admin_user.manage']],
['slug' => 'prd.admin_role.manage', 'name' => '角色管理·可管理', 'nav_segment' => 'admin_roles', 'permission_codes' => ['system.admin_role.manage']],
['slug' => 'prd.agent.view', 'name' => '代理管理·查看', 'nav_segment' => 'agents', 'permission_codes' => ['agent.node.view']],
['slug' => 'prd.agent.manage', 'name' => '代理管理·可管理', 'nav_segment' => 'agents', 'permission_codes' => ['agent.node.manage']],
['slug' => 'prd.agent.role.view', 'name' => '代理角色·查看', 'nav_segment' => 'agents', 'permission_codes' => ['agent.node.view']],
['slug' => 'prd.agent.role.manage', 'name' => '代理角色·可管理', 'nav_segment' => 'agents', 'permission_codes' => ['agent.node.manage']],
['slug' => 'prd.agent.user.view', 'name' => '代理账号·查看', 'nav_segment' => 'agents', 'permission_codes' => ['agent.node.view']],
['slug' => 'prd.agent.user.manage', 'name' => '代理账号·可管理', 'nav_segment' => 'agents', 'permission_codes' => ['agent.node.manage']],
['slug' => 'prd.users.manage', 'name' => '用户管理·可管理', 'nav_segment' => 'players', 'permission_codes' => ['service.players.manage']],
['slug' => 'prd.users.view_finance', 'name' => '用户管理·财务查看', 'nav_segment' => 'players', 'permission_codes' => ['service.players.view', 'service.wallet.view']],
['slug' => 'prd.users.view_cs', 'name' => '用户管理·客服单用户', 'nav_segment' => 'players', 'permission_codes' => ['service.players.view', 'service.tickets.view']],
@@ -97,6 +106,7 @@ final class AdminAuthorizationRegistry
'audit' => '审计日志',
'settings' => '系统设置',
'integration' => '接入站点',
'agents' => '代理管理',
];
return array_map(
@@ -108,13 +118,20 @@ final class AdminAuthorizationRegistry
);
}
/** 侧栏分组顺序(与 {@see navigationDefinitions} 中 nav_group 一致) */
public const NAV_GROUP_ORDER = ['overview', 'agent', 'operations', 'finance', 'rules', 'platform'];
/**
* 后台菜单注册表。前端侧栏与面包屑都消费这里派生的结果。
*
* platform_only仅超管可见全局 RBAC、接入站点、赔率规则等代理账号走代理控制台与子级授权。
*
* @return list<array{
* segment: string,
* label: string,
* href: string,
* nav_group: string,
* platform_only?: bool,
* activeMatchPrefix?: string,
* requiredAny?: list<string>
* }>
@@ -122,30 +139,26 @@ final class AdminAuthorizationRegistry
public static function navigationDefinitions(): array
{
return [
// 总览
['segment' => 'dashboard', 'label' => 'Dashboard', 'href' => '/admin', 'requiredAny' => ['prd.dashboard.view']],
// 日常运营:开奖 → 注单 → 玩家
['segment' => 'draws', 'label' => 'Draws', 'href' => '/admin/draws', 'requiredAny' => ['prd.draw_result.manage', 'prd.draw_result.view', 'prd.draw_reopen.manage']],
['segment' => 'tickets', 'label' => 'Tickets', 'href' => '/admin/tickets', 'requiredAny' => ['prd.tickets.view']],
['segment' => 'players', 'label' => 'Players', 'href' => '/admin/players', 'requiredAny' => ['prd.users.manage', 'prd.users.view_finance', 'prd.users.view_cs', 'prd.player_freeze.manage']],
// 规则与参数
['segment' => 'rules_plays', 'label' => 'Play rules', 'href' => '/admin/rules/plays', 'requiredAny' => ['prd.play_switch.manage', 'prd.odds.manage', 'prd.odds.view']],
['segment' => 'rules_odds', 'label' => 'Odds & rebate', 'href' => '/admin/rules/odds', 'requiredAny' => ['prd.odds.manage', 'prd.rebate.manage', 'prd.rebate.view']],
['segment' => 'jackpot', 'label' => 'Jackpot', 'href' => '/admin/jackpot', 'activeMatchPrefix' => '/admin/jackpot', 'requiredAny' => ['prd.jackpot.manage', 'prd.jackpot.view']],
['segment' => 'risk_cap', 'label' => 'Risk cap rules', 'href' => '/admin/risk/cap', 'activeMatchPrefix' => '/admin/risk/cap', 'requiredAny' => ['prd.risk_cap.manage', 'prd.risk_cap.view']],
// 资金
['segment' => 'wallet', 'label' => 'Wallet', 'href' => '/admin/wallet/transactions', 'activeMatchPrefix' => '/admin/wallet', 'requiredAny' => ['prd.wallet_reconcile.manage', 'prd.wallet_reconcile.view', 'prd.wallet_reconcile.view_cs', 'prd.wallet_adjust.manage', 'prd.users.manage', 'prd.users.view_finance']],
['segment' => 'settlement', 'label' => 'Settlement', 'href' => '/admin/settlement-batches', 'requiredAny' => ['prd.payout.manage', 'prd.payout.review', 'prd.payout.view']],
['segment' => 'reconcile', 'label' => 'Reconcile', 'href' => '/admin/reconcile', 'requiredAny' => ['prd.wallet_reconcile.manage', 'prd.wallet_reconcile.view', 'prd.wallet_reconcile.view_cs']],
['segment' => 'reports', 'label' => 'Reports', 'href' => '/admin/reports', 'requiredAny' => ['prd.report.view']],
['segment' => 'currencies', 'label' => 'Currencies', 'href' => '/admin/currencies', 'requiredAny' => ['prd.currency.manage']],
['segment' => 'integration', 'label' => 'Integration sites', 'href' => '/admin/config/integration-sites', 'activeMatchPrefix' => '/admin/config/integration-sites', 'requiredAny' => AdminPermissionLanguage::requiredAnyPrdSlugs('integration-sites')],
// 权限与系统
['segment' => 'admin_users', 'label' => 'Admin Users', 'href' => '/admin/admin-users', 'requiredAny' => ['prd.admin_user.manage']],
['segment' => 'admin_roles', 'label' => 'Admin Roles', 'href' => '/admin/admin-roles', 'requiredAny' => ['prd.admin_role.manage']],
['segment' => 'risk', 'label' => 'Risk', 'href' => '/admin/risk', 'requiredAny' => ['prd.risk.view', 'prd.risk.manage']],
['segment' => 'audit', 'label' => 'Audit Logs', 'href' => '/admin/audit-logs', 'requiredAny' => ['prd.audit.view']],
['segment' => 'settings', 'label' => 'Settings', 'href' => '/admin/settings', 'requiredAny' => ['prd.wallet_reconcile.manage', 'prd.currency.manage']],
['segment' => 'dashboard', 'label' => 'Dashboard', 'href' => '/admin', 'nav_group' => 'overview', 'requiredAny' => ['prd.dashboard.view']],
['segment' => 'agents', 'label' => 'Agents', 'href' => '/admin/agents', 'nav_group' => 'agent', 'activeMatchPrefix' => '/admin/agents', 'requiredAny' => ['prd.agent.view', 'prd.agent.manage', 'prd.agent.role.view', 'prd.agent.role.manage', 'prd.agent.user.view', 'prd.agent.user.manage']],
['segment' => 'draws', 'label' => 'Draws', 'href' => '/admin/draws', 'nav_group' => 'operations', 'requiredAny' => ['prd.draw_result.manage', 'prd.draw_result.view', 'prd.draw_reopen.manage']],
['segment' => 'tickets', 'label' => 'Tickets', 'href' => '/admin/tickets', 'nav_group' => 'operations', 'requiredAny' => ['prd.tickets.view']],
['segment' => 'players', 'label' => 'Players', 'href' => '/admin/players', 'nav_group' => 'operations', 'requiredAny' => ['prd.users.manage', 'prd.users.view_finance', 'prd.users.view_cs', 'prd.player_freeze.manage']],
['segment' => 'settlement', 'label' => 'Settlement', 'href' => '/admin/settlement-batches', 'nav_group' => 'operations', 'requiredAny' => ['prd.payout.manage', 'prd.payout.review', 'prd.payout.view']],
['segment' => 'wallet', 'label' => 'Wallet', 'href' => '/admin/wallet/transactions', 'nav_group' => 'finance', 'activeMatchPrefix' => '/admin/wallet', 'requiredAny' => ['prd.wallet_reconcile.manage', 'prd.wallet_reconcile.view', 'prd.wallet_reconcile.view_cs', 'prd.wallet_adjust.manage', 'prd.users.manage', 'prd.users.view_finance']],
['segment' => 'reconcile', 'label' => 'Reconcile', 'href' => '/admin/reconcile', 'nav_group' => 'finance', 'requiredAny' => ['prd.wallet_reconcile.manage', 'prd.wallet_reconcile.view', 'prd.wallet_reconcile.view_cs']],
['segment' => 'reports', 'label' => 'Reports', 'href' => '/admin/reports', 'nav_group' => 'finance', 'requiredAny' => ['prd.report.view']],
['segment' => 'rules_plays', 'label' => 'Play rules', 'href' => '/admin/rules/plays', 'nav_group' => 'rules', 'platform_only' => true, 'requiredAny' => ['prd.play_switch.manage', 'prd.odds.manage', 'prd.odds.view']],
['segment' => 'rules_odds', 'label' => 'Odds & rebate', 'href' => '/admin/rules/odds', 'nav_group' => 'rules', 'platform_only' => true, 'requiredAny' => ['prd.odds.manage', 'prd.rebate.manage', 'prd.rebate.view']],
['segment' => 'jackpot', 'label' => 'Jackpot', 'href' => '/admin/jackpot', 'nav_group' => 'rules', 'platform_only' => true, 'activeMatchPrefix' => '/admin/jackpot', 'requiredAny' => ['prd.jackpot.manage', 'prd.jackpot.view']],
['segment' => 'risk_cap', 'label' => 'Risk cap rules', 'href' => '/admin/risk/cap', 'nav_group' => 'rules', 'platform_only' => true, 'activeMatchPrefix' => '/admin/risk/cap', 'requiredAny' => ['prd.risk_cap.manage', 'prd.risk_cap.view']],
['segment' => 'integration', 'label' => 'Integration sites', 'href' => '/admin/config/integration-sites', 'nav_group' => 'platform', 'platform_only' => true, 'activeMatchPrefix' => '/admin/config/integration-sites', 'requiredAny' => AdminPermissionLanguage::requiredAnyPrdSlugs('integration-sites')],
['segment' => 'currencies', 'label' => 'Currencies', 'href' => '/admin/currencies', 'nav_group' => 'platform', 'platform_only' => true, 'requiredAny' => ['prd.currency.manage']],
['segment' => 'admin_users', 'label' => 'Admin Users', 'href' => '/admin/admin-users', 'nav_group' => 'platform', 'platform_only' => true, 'requiredAny' => ['prd.admin_user.manage']],
['segment' => 'admin_roles', 'label' => 'Admin Roles', 'href' => '/admin/admin-roles', 'nav_group' => 'platform', 'platform_only' => true, 'requiredAny' => ['prd.admin_role.manage']],
['segment' => 'audit', 'label' => 'Audit Logs', 'href' => '/admin/audit-logs', 'nav_group' => 'platform', 'platform_only' => true, 'requiredAny' => ['prd.audit.view']],
['segment' => 'settings', 'label' => 'Settings', 'href' => '/admin/settings', 'nav_group' => 'platform', 'platform_only' => true, 'requiredAny' => ['prd.wallet_reconcile.manage', 'prd.currency.manage']],
['segment' => 'risk', 'label' => 'Risk', 'href' => '/admin/risk', 'nav_group' => 'platform', 'platform_only' => true, 'requiredAny' => ['prd.risk.view', 'prd.risk.manage']],
];
}
@@ -202,6 +215,7 @@ final class AdminAuthorizationRegistry
'dashboard' => ['prd.dashboard.view'],
'admin_users' => ['prd.admin_user.manage'],
'admin_roles' => ['prd.admin_role.manage'],
'agents' => ['prd.agent.view', 'prd.agent.manage', 'prd.agent.role.view', 'prd.agent.role.manage', 'prd.agent.user.view', 'prd.agent.user.manage'],
'players' => ['prd.users.manage', 'prd.users.view_finance', 'prd.users.view_cs', 'prd.player_freeze.manage'],
'currencies' => ['prd.currency.manage'],
'wallet' => ['prd.wallet_reconcile.manage', 'prd.wallet_reconcile.view', 'prd.wallet_reconcile.view_cs', 'prd.wallet_adjust.manage', 'prd.users.view_finance'],
@@ -254,17 +268,24 @@ final class AdminAuthorizationRegistry
* segment: string,
* label: string,
* href: string,
* nav_group: string,
* platform_only?: bool,
* activeMatchPrefix?: string,
* requiredAny?: list<string>
* }>
*/
public static function visibleNavigationItems(array $permissionSlugs): array
public static function visibleNavigationItems(array $permissionSlugs, ?AdminUser $admin = null): array
{
$granted = array_fill_keys($permissionSlugs, true);
$isSuperAdmin = $admin === null || $admin->isSuperAdmin();
return array_values(array_filter(
self::navigationItems(),
static function (array $item) use ($granted): bool {
static function (array $item) use ($granted, $isSuperAdmin): bool {
if (($item['platform_only'] ?? false) && ! $isSuperAdmin) {
return false;
}
$required = $item['requiredAny'] ?? [];
if ($required === []) {
return true;
@@ -366,6 +387,26 @@ final class AdminAuthorizationRegistry
['code' => 'admin.admin-roles.destroy', 'module_code' => 'system', 'name' => '删除角色', 'http_method' => 'DELETE', 'uri_pattern' => '/api/v1/admin/admin-roles/{admin_role}', 'route_name' => 'api.v1.admin.admin-roles.destroy', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'legacy_permission_slugs' => ['prd.admin_role.manage']],
['code' => 'admin.admin-roles.permissions.sync', 'module_code' => 'system', 'name' => '角色权限同步', 'http_method' => 'PUT', 'uri_pattern' => '/api/v1/admin/admin-roles/{admin_role}/permissions', 'route_name' => 'api.v1.admin.admin-roles.permissions.sync', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'legacy_permission_slugs' => ['prd.admin_role.manage']],
['code' => 'admin.agent-nodes.tree', 'module_code' => 'agent', 'name' => '代理树', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/agent-nodes/tree', 'route_name' => 'api.v1.admin.agent-nodes.tree', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['agent.node.view', 'agent.node.manage']],
['code' => 'admin.agent-nodes.store', 'module_code' => 'agent', 'name' => '创建下级代理', 'http_method' => 'POST', 'uri_pattern' => '/api/v1/admin/agent-nodes', 'route_name' => 'api.v1.admin.agent-nodes.store', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['agent.node.manage']],
['code' => 'admin.agent-nodes.show', 'module_code' => 'agent', 'name' => '代理节点详情', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/agent-nodes/{agent_node}', 'route_name' => 'api.v1.admin.agent-nodes.show', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['agent.node.view', 'agent.node.manage']],
['code' => 'admin.agent-nodes.update', 'module_code' => 'agent', 'name' => '更新代理节点', 'http_method' => 'PUT', 'uri_pattern' => '/api/v1/admin/agent-nodes/{agent_node}', 'route_name' => 'api.v1.admin.agent-nodes.update', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['agent.node.manage']],
['code' => 'admin.agent-nodes.destroy', 'module_code' => 'agent', 'name' => '删除代理节点', 'http_method' => 'DELETE', 'uri_pattern' => '/api/v1/admin/agent-nodes/{agent_node}', 'route_name' => 'api.v1.admin.agent-nodes.destroy', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['agent.node.manage']],
['code' => 'admin.agent-nodes.children', 'module_code' => 'agent', 'name' => '代理直属下级', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/agent-nodes/{agent_node}/children', 'route_name' => 'api.v1.admin.agent-nodes.children', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['agent.node.view', 'agent.node.manage']],
['code' => 'admin.agent-roles.index', 'module_code' => 'agent', 'name' => '代理角色列表', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/agent-nodes/{agent_node}/roles', 'route_name' => 'api.v1.admin.agent-roles.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['agent.node.view', 'agent.node.manage']],
['code' => 'admin.agent-roles.store', 'module_code' => 'agent', 'name' => '创建代理角色', 'http_method' => 'POST', 'uri_pattern' => '/api/v1/admin/agent-nodes/{agent_node}/roles', 'route_name' => 'api.v1.admin.agent-roles.store', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['agent.node.manage']],
['code' => 'admin.agent-roles.update', 'module_code' => 'agent', 'name' => '更新代理角色', 'http_method' => 'PUT', 'uri_pattern' => '/api/v1/admin/agent-roles/{admin_role}', 'route_name' => 'api.v1.admin.agent-roles.update', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['agent.node.manage']],
['code' => 'admin.agent-roles.permissions.sync', 'module_code' => 'agent', 'name' => '代理角色权限同步', 'http_method' => 'PUT', 'uri_pattern' => '/api/v1/admin/agent-roles/{admin_role}/permissions', 'route_name' => 'api.v1.admin.agent-roles.permissions.sync', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['agent.node.manage']],
['code' => 'admin.agent-roles.destroy', 'module_code' => 'agent', 'name' => '删除代理角色', 'http_method' => 'DELETE', 'uri_pattern' => '/api/v1/admin/agent-roles/{admin_role}', 'route_name' => 'api.v1.admin.agent-roles.destroy', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['agent.node.manage']],
['code' => 'admin.agent-admin-users.index', 'module_code' => 'agent', 'name' => '代理账号列表', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/agent-nodes/{agent_node}/admin-users', 'route_name' => 'api.v1.admin.agent-admin-users.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['agent.node.view', 'agent.node.manage']],
['code' => 'admin.agent-admin-users.store', 'module_code' => 'agent', 'name' => '创建代理账号', 'http_method' => 'POST', 'uri_pattern' => '/api/v1/admin/agent-nodes/{agent_node}/admin-users', 'route_name' => 'api.v1.admin.agent-admin-users.store', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['agent.node.manage']],
['code' => 'admin.agent-admin-users.roles.sync', 'module_code' => 'agent', 'name' => '代理账号角色同步', 'http_method' => 'PUT', 'uri_pattern' => '/api/v1/admin/agent-admin-users/{admin_user}/roles', 'route_name' => 'api.v1.admin.agent-admin-users.roles.sync', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['agent.node.manage']],
['code' => 'admin.agent-delegation-grants.index', 'module_code' => 'agent', 'name' => '代理下放上限查看', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/agent-nodes/{agent_node}/delegation-grants', 'route_name' => 'api.v1.admin.agent-delegation-grants.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['agent.node.view', 'agent.node.manage']],
['code' => 'admin.agent-delegation-grants.sync', 'module_code' => 'agent', 'name' => '代理下放上限同步', 'http_method' => 'PUT', 'uri_pattern' => '/api/v1/admin/agent-nodes/{agent_node}/delegation-grants', 'route_name' => 'api.v1.admin.agent-delegation-grants.sync', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['agent.node.manage']],
['code' => 'admin.play-types.index', 'module_code' => 'config', 'name' => '玩法类型列表', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/play-types', 'route_name' => 'api.v1.admin.play-types.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'legacy_permission_slugs' => ['prd.play_switch.manage', 'prd.odds.manage', 'prd.odds.view', 'prd.rebate.manage', 'prd.rebate.view']],
['code' => 'admin.play-types.patch', 'module_code' => 'config', 'name' => '玩法类型切换', 'http_method' => 'PATCH', 'uri_pattern' => '/api/v1/admin/play-types/{play_code}', 'route_name' => 'api.v1.admin.play-types.patch', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'legacy_permission_slugs' => ['prd.play_switch.manage']],
['code' => 'admin.config.play-versions.index', 'module_code' => 'config', 'name' => '玩法版本列表', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/config/play-versions', 'route_name' => 'api.v1.admin.config.play-versions.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'legacy_permission_slugs' => ['prd.play_switch.manage', 'prd.odds.manage', 'prd.odds.view']],
@@ -387,6 +428,7 @@ final class AdminAuthorizationRegistry
['code' => 'admin.config.risk-cap-versions.publish', 'module_code' => 'config', 'name' => '发布封顶版本', 'http_method' => 'POST', 'uri_pattern' => '/api/v1/admin/config/risk-cap-versions/{id}/publish', 'route_name' => 'api.v1.admin.config.risk-cap-versions.publish', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'legacy_permission_slugs' => ['prd.risk_cap.manage']],
['code' => 'admin.config.risk-cap-versions.destroy', 'module_code' => 'config', 'name' => '删除封顶版本', 'http_method' => 'DELETE', 'uri_pattern' => '/api/v1/admin/config/risk-cap-versions/{id}', 'route_name' => 'api.v1.admin.config.risk-cap-versions.destroy', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'legacy_permission_slugs' => ['prd.risk_cap.manage']],
['code' => 'admin.settings.index', 'module_code' => 'settings', 'name' => '系统设置列表', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/settings', 'route_name' => 'api.v1.admin.settings.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'legacy_permission_slugs' => ['prd.wallet_reconcile.manage', 'prd.rebate.manage', 'prd.rebate.view', 'prd.payout.manage']],
['code' => 'admin.settings.batch-update', 'module_code' => 'settings', 'name' => '系统设置批量更新', 'http_method' => 'PUT', 'uri_pattern' => '/api/v1/admin/settings/batch', 'route_name' => 'api.v1.admin.settings.batch-update', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'legacy_permission_slugs' => ['prd.wallet_reconcile.manage', 'prd.rebate.manage', 'prd.payout.manage']],
['code' => 'admin.settings.update', 'module_code' => 'settings', 'name' => '系统设置更新', 'http_method' => 'PUT', 'uri_pattern' => '/api/v1/admin/settings/{key}', 'route_name' => 'api.v1.admin.settings.update', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'legacy_permission_slugs' => ['prd.wallet_reconcile.manage', 'prd.rebate.manage', 'prd.payout.manage']],
['code' => 'admin.currencies.index', 'module_code' => 'settings', 'name' => '币种列表', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/currencies', 'route_name' => 'api.v1.admin.currencies.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'legacy_permission_slugs' => ['prd.currency.manage']],
['code' => 'admin.currencies.store', 'module_code' => 'settings', 'name' => '创建币种', 'http_method' => 'POST', 'uri_pattern' => '/api/v1/admin/currencies', 'route_name' => 'api.v1.admin.currencies.store', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'legacy_permission_slugs' => ['prd.currency.manage']],