feat: 增强环境配置与开发服务,支持局域网访问及币种管理

This commit is contained in:
2026-05-21 16:24:41 +08:00
parent 699d43fbd4
commit 7a6048de10
60 changed files with 1321 additions and 443 deletions

View File

@@ -267,7 +267,6 @@ return new class extends Migration
['parent_code' => 'service', 'menu_type' => 'page', 'code' => 'service.tickets', 'name' => '玩家注单', 'path' => '/admin/tickets', 'route_name' => 'admin.tickets.index', 'component' => 'service/tickets', 'icon' => null, 'sort_order' => 20],
['parent_code' => 'service', 'menu_type' => 'page', 'code' => 'service.wallet', 'name' => '钱包流水', 'path' => '/admin/wallet/transactions', 'route_name' => 'admin.wallet.transactions', 'component' => 'service/wallet', 'icon' => null, 'sort_order' => 30],
['parent_code' => 'service', 'menu_type' => 'page', 'code' => 'service.reconcile', 'name' => '对账管理', 'path' => '/admin/reconcile', 'route_name' => 'admin.reconcile.index', 'component' => 'service/reconcile', 'icon' => null, 'sort_order' => 40],
['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],
@@ -320,8 +319,6 @@ return new class extends Migration
['menu_code' => 'service.wallet', 'action_code' => 'manage', 'permission_code' => 'service.wallet.manage', 'name' => '钱包流水管理'],
['menu_code' => 'service.reconcile', 'action_code' => 'view', 'permission_code' => 'service.reconcile.view', 'name' => '对账查看'],
['menu_code' => 'service.reconcile', 'action_code' => 'manage', 'permission_code' => 'service.reconcile.manage', 'name' => '对账管理'],
['menu_code' => 'service.reports', 'action_code' => 'view', 'permission_code' => 'service.reports.view', 'name' => '报表查看'],
['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' => '角色权限管理'],
@@ -352,8 +349,6 @@ return new class extends Migration
['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.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']],
['code' => 'admin.reconcile.store', 'module_code' => 'reconcile', 'name' => '创建对账任务', 'http_method' => 'POST', 'uri_pattern' => '/api/v1/admin/reconcile-jobs', 'route_name' => 'api.v1.admin.reconcile-jobs.store', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['service.reconcile.manage']],
['code' => 'admin.audit.index', 'module_code' => 'audit', 'name' => '审计日志查询', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/audit-logs', 'route_name' => 'api.v1.admin.audit-logs.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['service.audit.view']],
@@ -447,10 +442,6 @@ return new class extends Migration
'prd.wallet_reconcile.manage' => ['service.wallet.manage', 'service.reconcile.manage'],
'prd.wallet_reconcile.view' => ['service.wallet.view', 'service.reconcile.view'],
'prd.wallet_reconcile.view_cs' => ['service.wallet.view', 'service.reconcile.view'],
'prd.report.all' => ['service.reports.view', 'service.reports.export'],
'prd.report.risk' => ['service.reports.view'],
'prd.report.finance' => ['service.reports.view', 'service.reports.export'],
'prd.report.player' => ['service.reports.view'],
'prd.audit.all' => ['service.audit.view'],
'prd.audit.self' => ['service.audit.view'],
'prd.audit.finance' => ['service.audit.view'],
@@ -654,10 +645,6 @@ return new class extends Migration
['slug' => 'prd.wallet_reconcile.view', 'name' => '钱包对账·查看'],
['slug' => 'prd.wallet_reconcile.view_cs', 'name' => '钱包对账·客服单用户'],
['slug' => 'prd.wallet_adjust.manage', 'name' => '补单/冲正·可管理'],
['slug' => 'prd.report.all', 'name' => '报表·全部'],
['slug' => 'prd.report.risk', 'name' => '报表·风控'],
['slug' => 'prd.report.finance', 'name' => '报表·财务'],
['slug' => 'prd.report.player', 'name' => '报表·单用户'],
['slug' => 'prd.audit.all', 'name' => '审计日志·全部'],
['slug' => 'prd.audit.self', 'name' => '审计日志·自身相关'],
['slug' => 'prd.audit.finance', 'name' => '审计日志·资金相关'],
@@ -688,7 +675,6 @@ return new class extends Migration
'prd.draw_result.manage',
'prd.payout.review',
'prd.wallet_reconcile.view',
'prd.report.risk',
'prd.audit.self',
'prd.player_freeze.manage',
],
@@ -701,14 +687,12 @@ return new class extends Migration
'prd.payout.view',
'prd.wallet_reconcile.manage',
'prd.wallet_adjust.manage',
'prd.report.finance',
'prd.audit.finance',
],
'customer_service' => [
'prd.users.view_cs',
'prd.draw_result.view',
'prd.wallet_reconcile.view_cs',
'prd.report.player',
],
];

View File

@@ -0,0 +1,109 @@
<?php
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use App\Support\AdminAuthorizationRegistry;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
public function up(): void
{
$now = Carbon::now();
$menuActionIds = DB::table('admin_menu_actions')->pluck('id', 'permission_code');
$resources = array_values(array_filter(
AdminAuthorizationRegistry::resources(),
static fn (array $resource): bool => str_starts_with((string) $resource['code'], 'admin.currencies.'),
));
foreach ($resources as $resource) {
$resourceId = DB::table('admin_api_resources')
->where('code', $resource['code'])
->value('id');
$payload = [
'module_code' => $resource['module_code'],
'name' => $resource['name'],
'http_method' => $resource['http_method'],
'uri_pattern' => $resource['uri_pattern'],
'route_name' => $resource['route_name'],
'auth_mode' => $resource['auth_mode'],
'is_audit_required' => $resource['is_audit_required'],
'status' => 1,
'meta_json' => null,
'updated_at' => $now,
];
if ($resourceId === null) {
$resourceId = DB::table('admin_api_resources')->insertGetId($payload + [
'code' => $resource['code'],
'created_at' => $now,
]);
} else {
DB::table('admin_api_resources')
->where('id', (int) $resourceId)
->update($payload);
}
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,
]);
}
}
$roleResourceRows = DB::table('admin_role_menu_actions as rma')
->join('admin_api_resource_bindings as arb', 'arb.menu_action_id', '=', 'rma.menu_action_id')
->join('admin_api_resources as ar', 'ar.id', '=', 'arb.api_resource_id')
->whereIn('ar.code', array_column($resources, 'code'))
->select('rma.role_id', 'arb.api_resource_id')
->distinct()
->get();
foreach ($roleResourceRows as $row) {
DB::table('admin_role_api_resources')->updateOrInsert([
'role_id' => (int) $row->role_id,
'api_resource_id' => (int) $row->api_resource_id,
], []);
}
}
public function down(): void
{
$resourceCodes = ['admin.currencies.index', 'admin.currencies.store', 'admin.currencies.update'];
$resourceIds = DB::table('admin_api_resources')
->whereIn('code', $resourceCodes)
->pluck('id')
->all();
if ($resourceIds === []) {
return;
}
DB::table('admin_role_api_resources')
->whereIn('api_resource_id', $resourceIds)
->delete();
DB::table('admin_api_resource_bindings')
->whereIn('api_resource_id', $resourceIds)
->delete();
DB::table('admin_api_resources')
->whereIn('id', $resourceIds)
->delete();
}
};

View File

@@ -0,0 +1,105 @@
<?php
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use App\Support\AdminAuthorizationRegistry;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
public function up(): void
{
$now = Carbon::now();
$menuActionIds = DB::table('admin_menu_actions')->pluck('id', 'permission_code');
$resource = collect(AdminAuthorizationRegistry::resources())
->first(static fn (array $item): bool => $item['code'] === 'admin.currencies.destroy');
if ($resource === null) {
return;
}
$resourceId = DB::table('admin_api_resources')
->where('code', $resource['code'])
->value('id');
$payload = [
'module_code' => $resource['module_code'],
'name' => $resource['name'],
'http_method' => $resource['http_method'],
'uri_pattern' => $resource['uri_pattern'],
'route_name' => $resource['route_name'],
'auth_mode' => $resource['auth_mode'],
'is_audit_required' => $resource['is_audit_required'],
'status' => 1,
'meta_json' => null,
'updated_at' => $now,
];
if ($resourceId === null) {
$resourceId = DB::table('admin_api_resources')->insertGetId($payload + [
'code' => $resource['code'],
'created_at' => $now,
]);
} else {
DB::table('admin_api_resources')
->where('id', (int) $resourceId)
->update($payload);
}
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,
]);
}
$roleResourceRows = DB::table('admin_role_menu_actions as rma')
->join('admin_api_resource_bindings as arb', 'arb.menu_action_id', '=', 'rma.menu_action_id')
->where('arb.api_resource_id', (int) $resourceId)
->select('rma.role_id')
->distinct()
->get();
foreach ($roleResourceRows as $row) {
DB::table('admin_role_api_resources')->updateOrInsert([
'role_id' => (int) $row->role_id,
'api_resource_id' => (int) $resourceId,
], []);
}
}
public function down(): void
{
$resourceId = DB::table('admin_api_resources')
->where('code', 'admin.currencies.destroy')
->value('id');
if ($resourceId === null) {
return;
}
DB::table('admin_role_api_resources')
->where('api_resource_id', (int) $resourceId)
->delete();
DB::table('admin_api_resource_bindings')
->where('api_resource_id', (int) $resourceId)
->delete();
DB::table('admin_api_resources')
->where('id', (int) $resourceId)
->delete();
}
};

View File

@@ -0,0 +1,143 @@
<?php
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
public function up(): void
{
$now = Carbon::now();
$serviceMenuId = (int) DB::table('admin_menus')->where('code', 'service')->value('id');
$manageActionId = (int) DB::table('admin_action_catalog')->where('code', 'manage')->value('id');
if ($serviceMenuId > 0) {
DB::table('admin_menus')->updateOrInsert(
['code' => 'service.currency'],
[
'parent_id' => $serviceMenuId,
'menu_type' => 'page',
'name' => '币种管理',
'path' => '/admin/settings/currencies',
'route_name' => 'admin.settings.currencies',
'component' => 'settings/currencies',
'icon' => null,
'active_menu_code' => null,
'sort_order' => 70,
'is_visible' => false,
'is_cache' => false,
'is_external' => false,
'status' => 1,
'meta_json' => null,
'created_at' => $now,
'updated_at' => $now,
],
);
}
$currencyMenuId = (int) DB::table('admin_menus')->where('code', 'service.currency')->value('id');
if ($currencyMenuId > 0 && $manageActionId > 0) {
DB::table('admin_menu_actions')->updateOrInsert(
['permission_code' => 'service.currency.manage'],
[
'menu_id' => $currencyMenuId,
'action_id' => $manageActionId,
'name' => '币种管理',
'status' => 1,
'created_at' => $now,
'updated_at' => $now,
],
);
}
if (Schema::hasTable('admin_permissions')) {
DB::table('admin_permissions')->updateOrInsert(
['slug' => 'prd.currency.manage'],
[
'name' => '币种管理·可管理',
'updated_at' => $now,
'created_at' => $now,
],
);
}
$currencyActionId = DB::table('admin_menu_actions')
->where('permission_code', 'service.currency.manage')
->value('id');
if ($currencyActionId === null) {
return;
}
$roleIds = DB::table('admin_role_legacy_permissions')
->where('permission_slug', 'prd.users.manage')
->pluck('role_id')
->all();
foreach ($roleIds as $roleId) {
DB::table('admin_role_legacy_permissions')->updateOrInsert(
[
'role_id' => (int) $roleId,
'permission_slug' => 'prd.currency.manage',
],
[
'created_at' => $now,
'updated_at' => $now,
],
);
DB::table('admin_role_menu_actions')->updateOrInsert(
[
'role_id' => (int) $roleId,
'menu_action_id' => (int) $currencyActionId,
],
[],
);
}
$currencyResourceIds = DB::table('admin_api_resources')
->whereIn('code', [
'admin.currencies.index',
'admin.currencies.store',
'admin.currencies.update',
'admin.currencies.destroy',
])
->pluck('id')
->all();
foreach ($currencyResourceIds as $resourceId) {
DB::table('admin_api_resource_bindings')
->where('api_resource_id', (int) $resourceId)
->delete();
DB::table('admin_api_resource_bindings')->insert([
'api_resource_id' => (int) $resourceId,
'menu_action_id' => (int) $currencyActionId,
'created_at' => $now,
'updated_at' => $now,
]);
}
$roleResourceRows = DB::table('admin_role_menu_actions as rma')
->join('admin_api_resource_bindings as arb', 'arb.menu_action_id', '=', 'rma.menu_action_id')
->whereIn('arb.api_resource_id', $currencyResourceIds)
->select('rma.role_id', 'arb.api_resource_id')
->distinct()
->get();
foreach ($roleResourceRows as $row) {
DB::table('admin_role_api_resources')->updateOrInsert([
'role_id' => (int) $row->role_id,
'api_resource_id' => (int) $row->api_resource_id,
], []);
}
}
public function down(): void
{
// 不自动回滚线上角色与资源绑定,避免误删已调整的授权。
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
public function up(): void
{
DB::table('admin_menus')
->where('code', 'service.currency')
->update([
'path' => '/admin/currencies',
'route_name' => 'admin.currencies',
'updated_at' => now(),
]);
}
public function down(): void
{
DB::table('admin_menus')
->where('code', 'service.currency')
->update([
'path' => '/admin/settings/currencies',
'route_name' => 'admin.settings.currencies',
'updated_at' => now(),
]);
}
};

View File

@@ -66,7 +66,6 @@ final class AdminRbacAndUserSeeder extends Seeder
'prd.draw_result.manage',
'prd.payout.review',
'prd.wallet_reconcile.view',
'prd.report.risk',
'prd.audit.self',
'prd.player_freeze.manage',
]);
@@ -84,7 +83,6 @@ final class AdminRbacAndUserSeeder extends Seeder
'prd.payout.view',
'prd.wallet_reconcile.manage',
'prd.wallet_adjust.manage',
'prd.report.finance',
'prd.audit.finance',
]);
@@ -96,7 +94,6 @@ final class AdminRbacAndUserSeeder extends Seeder
'prd.users.view_cs',
'prd.draw_result.view',
'prd.wallet_reconcile.view_cs',
'prd.report.player',
]);
$username = 'admin';