feat(admin): 完善后台角色管理与权限同步,新增当前管理员信息接口

This commit is contained in:
2026-05-19 14:39:54 +08:00
parent 063cb98311
commit 057ddecaa1
30 changed files with 1286 additions and 124 deletions

View File

@@ -270,6 +270,7 @@ return new class extends Migration
['parent_code' => 'service', 'menu_type' => 'page', 'code' => 'service.reports', 'name' => '报表导出', 'path' => '/admin/reports', 'route_name' => 'admin.reports.index', 'component' => 'service/reports', 'icon' => null, 'sort_order' => 50],
['parent_code' => 'service', 'menu_type' => 'page', 'code' => 'service.audit', 'name' => '审计日志', 'path' => '/admin/audit-logs', 'route_name' => 'admin.audit.index', 'component' => 'service/audit', 'icon' => null, 'sort_order' => 60],
['parent_code' => null, 'menu_type' => 'page', 'code' => 'system.admin_user', 'name' => '管理员权限', 'path' => '/admin/admin-users', 'route_name' => 'admin.system.admin-users', 'component' => 'system/admin-users', 'icon' => 'users-round', 'sort_order' => 70],
['parent_code' => null, 'menu_type' => 'page', 'code' => 'system.admin_role', 'name' => '角色管理', 'path' => '/admin/admin-roles', 'route_name' => 'admin.system.admin-roles', 'component' => 'system/admin-roles', 'icon' => 'shield-check', 'sort_order' => 71],
];
$menuIds = [];
@@ -313,6 +314,7 @@ return new class extends Migration
['menu_code' => 'settlement.batch', 'action_code' => 'manage', 'permission_code' => 'settlement.batch.manage', 'name' => '结算执行'],
['menu_code' => 'service.players', 'action_code' => 'view', 'permission_code' => 'service.players.view', 'name' => '玩家查询查看'],
['menu_code' => 'service.players', 'action_code' => 'manage', 'permission_code' => 'service.players.manage', 'name' => '玩家查询管理'],
['menu_code' => 'service.players', 'action_code' => 'update', 'permission_code' => 'service.players.freeze', 'name' => '冻结解冻玩家'],
['menu_code' => 'service.tickets', 'action_code' => 'view', 'permission_code' => 'service.tickets.view', 'name' => '玩家注单查看'],
['menu_code' => 'service.wallet', 'action_code' => 'view', 'permission_code' => 'service.wallet.view', 'name' => '钱包流水查看'],
['menu_code' => 'service.wallet', 'action_code' => 'manage', 'permission_code' => 'service.wallet.manage', 'name' => '钱包流水管理'],
@@ -322,6 +324,7 @@ return new class extends Migration
['menu_code' => 'service.reports', 'action_code' => 'export', 'permission_code' => 'service.reports.export', 'name' => '报表导出'],
['menu_code' => 'service.audit', 'action_code' => 'view', 'permission_code' => 'service.audit.view', 'name' => '审计查看'],
['menu_code' => 'system.admin_user', 'action_code' => 'manage', 'permission_code' => 'system.admin_user.manage', 'name' => '管理员权限管理'],
['menu_code' => 'system.admin_role', 'action_code' => 'manage', 'permission_code' => 'system.admin_role.manage', 'name' => '角色权限管理'],
];
foreach ($menuActions as $row) {
@@ -347,8 +350,8 @@ return new class extends Migration
['code' => 'admin.draws.settlement.run', 'module_code' => 'settlement', 'name' => '执行结算', 'http_method' => 'POST', 'uri_pattern' => '/api/v1/admin/draws/{draw}/settlement/run', 'route_name' => 'api.v1.admin.draws.settlement.run', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['settlement.batch.manage', 'settlement.batch.review']],
['code' => 'admin.wallet.transactions', 'module_code' => 'wallet', 'name' => '钱包流水查询', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/wallet/transactions', 'route_name' => 'api.v1.admin.wallet.transactions', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['service.wallet.view', 'service.wallet.manage']],
['code' => 'admin.wallet.transfer-orders', 'module_code' => 'wallet', 'name' => '转账单查询', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/wallet/transfer-orders', 'route_name' => 'api.v1.admin.wallet.transfer-orders', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['service.wallet.view', 'service.wallet.manage']],
['code' => 'admin.players.wallets', 'module_code' => 'player_service', 'name' => '玩家钱包查看', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/players/{player}/wallets', 'route_name' => 'api.v1.admin.players.wallets', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['service.players.view', 'service.players.manage']],
['code' => 'admin.players.ticket-items', 'module_code' => 'player_service', 'name' => '玩家注单查看', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/players/{player}/ticket-items', 'route_name' => 'api.v1.admin.players.ticket-items.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['service.tickets.view']],
['code' => 'admin.players.wallets', 'module_code' => 'player_service', 'name' => '玩家钱包查看', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/players/{player}/wallets', 'route_name' => 'api.v1.admin.players.wallets', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['service.players.manage', 'service.wallet.view']],
['code' => 'admin.players.ticket-items', 'module_code' => 'player_service', 'name' => '玩家注单查看', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/players/{player}/ticket-items', 'route_name' => 'api.v1.admin.players.ticket-items.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['service.players.manage', 'service.tickets.view']],
['code' => 'admin.reports.index', 'module_code' => 'report', 'name' => '报表任务列表', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/report-jobs', 'route_name' => 'api.v1.admin.report-jobs.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['service.reports.view', 'service.reports.export']],
['code' => 'admin.reports.store', 'module_code' => 'report', 'name' => '创建报表任务', 'http_method' => 'POST', 'uri_pattern' => '/api/v1/admin/report-jobs', 'route_name' => 'api.v1.admin.report-jobs.store', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['service.reports.export']],
['code' => 'admin.reconcile.index', 'module_code' => 'reconcile', 'name' => '对账任务列表', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/reconcile-jobs', 'route_name' => 'api.v1.admin.reconcile-jobs.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['service.reconcile.view', 'service.reconcile.manage']],
@@ -427,7 +430,7 @@ return new class extends Migration
$legacyToNewPermissionMap = [
'prd.users.manage' => ['service.players.manage'],
'prd.users.view_finance' => ['service.players.view', 'service.wallet.view'],
'prd.users.view_cs' => ['service.players.view', 'service.tickets.view', 'service.wallet.view'],
'prd.users.view_cs' => ['service.players.view', 'service.tickets.view'],
'prd.play_switch.manage' => ['config.play.manage'],
'prd.odds.manage' => ['config.odds.manage'],
'prd.risk_cap.manage' => ['config.risk_cap.manage'],
@@ -452,7 +455,7 @@ return new class extends Migration
'prd.audit.self' => ['service.audit.view'],
'prd.audit.finance' => ['service.audit.view'],
'prd.admin_user.manage' => ['system.admin_user.manage'],
'prd.player_freeze.manage' => ['service.players.manage'],
'prd.player_freeze.manage' => ['service.players.freeze'],
'prd.wallet_adjust.manage' => ['service.wallet.manage'],
'prd.draw_reopen.manage' => ['draw.review.publish'],
];

View File

@@ -0,0 +1,51 @@
<?php
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
public function up(): void
{
$now = Carbon::now();
$currencyCodes = DB::table('currencies')
->where('is_enabled', true)
->where('is_bettable', true)
->pluck('code')
->filter(static fn ($code): bool => is_string($code) && trim($code) !== '')
->map(static fn (string $code): string => strtoupper($code))
->unique()
->values();
if ($currencyCodes->isEmpty()) {
$currencyCodes = collect([strtoupper((string) config('lottery.default_currency', 'NPR'))]);
}
foreach ($currencyCodes as $currencyCode) {
$exists = DB::table('jackpot_pools')->where('currency_code', $currencyCode)->exists();
if ($exists) {
continue;
}
DB::table('jackpot_pools')->insert([
'currency_code' => $currencyCode,
'current_amount' => 0,
'contribution_rate' => '0.0200',
'trigger_threshold' => 100_000_000,
'payout_rate' => '0.5000',
'force_trigger_draw_gap' => 100,
'min_bet_amount' => 100,
'status' => 0,
'last_trigger_draw_id' => null,
'created_at' => $now,
'updated_at' => $now,
]);
}
}
public function down(): void
{
// 保留奖池配置与水位,避免回滚误删运营数据。
}
};

View File

@@ -0,0 +1,48 @@
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use App\Support\AdminPermissionBridge;
return new class extends Migration
{
public function up(): void
{
Schema::create('admin_role_legacy_permissions', function (Blueprint $table): void {
$table->foreignId('role_id')->constrained('admin_roles')->cascadeOnDelete();
$table->string('permission_slug', 128);
$table->timestamps();
$table->primary(['role_id', 'permission_slug'], 'pk_admin_role_legacy_permissions');
});
$now = now();
$roleCodes = DB::table('admin_role_menu_actions as rma')
->join('admin_menu_actions as ma', 'ma.id', '=', 'rma.menu_action_id')
->where('ma.status', 1)
->select('rma.role_id', 'ma.permission_code')
->get()
->groupBy('role_id');
foreach ($roleCodes as $roleId => $rows) {
$slugs = AdminPermissionBridge::legacySlugsGrantedByMenuActionCodes(
$rows->pluck('permission_code')->all(),
);
foreach ($slugs as $slug) {
DB::table('admin_role_legacy_permissions')->insert([
'role_id' => (int) $roleId,
'permission_slug' => $slug,
'created_at' => $now,
'updated_at' => $now,
]);
}
}
}
public function down(): void
{
Schema::dropIfExists('admin_role_legacy_permissions');
}
};

View File

@@ -0,0 +1,124 @@
<?php
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
use App\Support\AdminAuthorizationRegistry;
use App\Support\AdminPermissionBridge;
return new class extends Migration
{
public function up(): void
{
$now = Carbon::now();
$actionCatalogId = (int) DB::table('admin_action_catalog')->where('code', 'manage')->value('id');
$adminUserMenuId = (int) DB::table('admin_menus')->where('code', 'system.admin_user')->value('id');
if ($adminUserMenuId > 0) {
$adminUserMenu = DB::table('admin_menus')->where('id', $adminUserMenuId)->first();
DB::table('admin_menus')->updateOrInsert(
['code' => 'system.admin_role'],
[
'parent_id' => $adminUserMenu->parent_id,
'menu_type' => 'page',
'name' => '角色管理',
'path' => '/admin/admin-roles',
'route_name' => 'admin.system.admin-roles',
'component' => 'system/admin-roles',
'icon' => 'shield-check',
'active_menu_code' => null,
'sort_order' => ((int) $adminUserMenu->sort_order) + 1,
'is_visible' => true,
'is_cache' => false,
'is_external' => false,
'status' => 1,
'meta_json' => null,
'created_at' => $now,
'updated_at' => $now,
],
);
}
$menuId = (int) DB::table('admin_menus')->where('code', 'system.admin_role')->value('id');
if ($actionCatalogId > 0 && $menuId > 0) {
DB::table('admin_menu_actions')->updateOrInsert(
['permission_code' => 'system.admin_role.manage'],
[
'menu_id' => $menuId,
'action_id' => $actionCatalogId,
'name' => '角色权限管理',
'status' => 1,
'created_at' => $now,
'updated_at' => $now,
],
);
}
$menuActionIds = DB::table('admin_menu_actions')->pluck('id', 'permission_code');
foreach (AdminAuthorizationRegistry::resources() as $resource) {
$resourceId = DB::table('admin_api_resources')
->where('code', $resource['code'])
->value('id');
if ($resourceId === null) {
continue;
}
DB::table('admin_api_resource_bindings')
->where('api_resource_id', (int) $resourceId)
->delete();
foreach ($resource['permission_codes'] as $permissionCode) {
$menuActionId = $menuActionIds[$permissionCode] ?? null;
if ($menuActionId === null) {
continue;
}
DB::table('admin_api_resource_bindings')->insert([
'api_resource_id' => (int) $resourceId,
'menu_action_id' => (int) $menuActionId,
'created_at' => $now,
'updated_at' => $now,
]);
}
}
$adminRoleSlug = 'prd.admin_role.manage';
$adminUserSlug = 'prd.admin_user.manage';
$roleIds = DB::table('admin_role_legacy_permissions')
->where('permission_slug', $adminUserSlug)
->pluck('role_id')
->all();
foreach ($roleIds as $roleId) {
DB::table('admin_role_legacy_permissions')->updateOrInsert(
[
'role_id' => (int) $roleId,
'permission_slug' => $adminRoleSlug,
],
[
'created_at' => $now,
'updated_at' => $now,
],
);
foreach (AdminPermissionBridge::menuActionCodesForLegacy($adminRoleSlug) as $permissionCode) {
$menuActionId = $menuActionIds[$permissionCode] ?? null;
if ($menuActionId === null) {
continue;
}
DB::table('admin_role_menu_actions')->updateOrInsert([
'role_id' => (int) $roleId,
'menu_action_id' => (int) $menuActionId,
]);
}
}
}
public function down(): void
{
// 不回滚授权数据,避免删除线上已经显式授予的角色管理权限。
}
};

View File

@@ -0,0 +1,82 @@
<?php
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
use App\Support\AdminAuthorizationRegistry;
return new class extends Migration
{
public function up(): void
{
$now = Carbon::now();
$playersMenuId = (int) DB::table('admin_menus')->where('code', 'service.players')->value('id');
$updateActionId = (int) DB::table('admin_action_catalog')->where('code', 'update')->value('id');
if ($playersMenuId > 0 && $updateActionId > 0) {
DB::table('admin_menu_actions')->updateOrInsert(
['permission_code' => 'service.players.freeze'],
[
'menu_id' => $playersMenuId,
'action_id' => $updateActionId,
'name' => '冻结解冻玩家',
'status' => 1,
'created_at' => $now,
'updated_at' => $now,
],
);
}
$menuActionIds = DB::table('admin_menu_actions')->pluck('id', 'permission_code');
$playerResourceBindings = [
'admin.players.index' => ['service.players.manage', 'service.players.view'],
'admin.players.store' => ['service.players.manage'],
'admin.players.show' => ['service.players.manage', 'service.players.view'],
'admin.players.update' => ['service.players.manage'],
'admin.players.destroy' => ['service.players.manage'],
'admin.players.freeze' => ['service.players.freeze'],
'admin.players.unfreeze' => ['service.players.freeze'],
'admin.players.wallets' => ['service.players.manage', 'service.wallet.view'],
'admin.players.ticket-items' => ['service.players.manage', 'service.tickets.view'],
];
foreach (AdminAuthorizationRegistry::resources() as $resource) {
if (($resource['module_code'] ?? null) !== 'player_service') {
continue;
}
$resourceId = DB::table('admin_api_resources')
->where('code', $resource['code'])
->value('id');
if ($resourceId === null) {
continue;
}
DB::table('admin_api_resource_bindings')
->where('api_resource_id', (int) $resourceId)
->delete();
$permissionCodes = $playerResourceBindings[$resource['code']] ?? $resource['permission_codes'];
foreach ($permissionCodes as $permissionCode) {
$menuActionId = $menuActionIds[$permissionCode] ?? null;
if ($menuActionId === null) {
continue;
}
DB::table('admin_api_resource_bindings')->insert([
'api_resource_id' => (int) $resourceId,
'menu_action_id' => (int) $menuActionId,
'created_at' => $now,
'updated_at' => $now,
]);
}
}
}
public function down(): void
{
// 不回滚授权绑定,避免误删线上已调整的资源权限关系。
}
};