feat: 增强管理员功能与数据处理
- 在多个控制器中引入 agent_node_id,以支持基于代理节点的权限和数据过滤。 - 更新 AdminRole 和 AdminUser 模型,新增角色范围和代理节点相关功能,提升角色管理的灵活性。 - 在请求验证中添加 agent_node_id 字段,确保 API 接口支持代理节点的相关操作。 - 优化 LotterySettings 服务,支持批量写入设置,提升配置管理的效率。 - 更新仪表板和报告服务,增强数据统计功能,确保管理员能够获取更全面的统计信息。
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Support\AdminAuthorizationRegistry;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
private const RESOURCE_CODE = 'admin.settings.batch-update';
|
||||
|
||||
private const CLONE_BINDINGS_FROM = 'admin.settings.update';
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$resource = collect(AdminAuthorizationRegistry::resources())
|
||||
->first(fn (array $item): bool => $item['code'] === self::RESOURCE_CODE);
|
||||
|
||||
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();
|
||||
|
||||
$sourceResourceId = DB::table('admin_api_resources')
|
||||
->where('code', self::CLONE_BINDINGS_FROM)
|
||||
->value('id');
|
||||
|
||||
if ($sourceResourceId !== null) {
|
||||
$bindings = DB::table('admin_api_resource_bindings')
|
||||
->where('api_resource_id', (int) $sourceResourceId)
|
||||
->get(['menu_action_id']);
|
||||
|
||||
foreach ($bindings as $binding) {
|
||||
DB::table('admin_api_resource_bindings')->insert([
|
||||
'api_resource_id' => (int) $resourceId,
|
||||
'menu_action_id' => (int) $binding->menu_action_id,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (Schema::hasTable('admin_role_api_resources')) {
|
||||
$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', self::RESOURCE_CODE)->value('id');
|
||||
if ($resourceId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Schema::hasTable('admin_role_api_resources')) {
|
||||
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();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('agent_nodes', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->foreignId('admin_site_id')->constrained('admin_sites')->cascadeOnDelete();
|
||||
$table->foreignId('parent_id')->nullable()->constrained('agent_nodes')->nullOnDelete();
|
||||
$table->string('path', 512);
|
||||
$table->unsignedSmallInteger('depth')->default(0);
|
||||
$table->string('code', 64);
|
||||
$table->string('name', 128);
|
||||
$table->unsignedTinyInteger('status')->default(1)->comment('1=enabled,0=disabled');
|
||||
$table->foreignId('created_by')->nullable()->constrained('admin_users')->nullOnDelete();
|
||||
$table->json('extra_json')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['admin_site_id', 'code'], 'uk_agent_nodes_site_code');
|
||||
$table->index(['admin_site_id', 'parent_id'], 'idx_agent_nodes_site_parent');
|
||||
$table->index('path', 'idx_agent_nodes_path');
|
||||
});
|
||||
|
||||
Schema::create('admin_user_agents', function (Blueprint $table): void {
|
||||
$table->foreignId('admin_user_id')->primary()->constrained('admin_users')->cascadeOnDelete();
|
||||
$table->foreignId('agent_node_id')->constrained('agent_nodes')->cascadeOnDelete();
|
||||
$table->boolean('is_primary')->default(true);
|
||||
$table->timestamp('granted_at')->nullable();
|
||||
});
|
||||
|
||||
$this->seedRootAgentNodes();
|
||||
$this->backfillAdminUserAgents();
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('admin_user_agents');
|
||||
Schema::dropIfExists('agent_nodes');
|
||||
}
|
||||
|
||||
private function seedRootAgentNodes(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$sites = DB::table('admin_sites')->orderBy('id')->get(['id', 'code', 'name']);
|
||||
|
||||
foreach ($sites as $site) {
|
||||
if (DB::table('agent_nodes')->where('admin_site_id', (int) $site->id)->where('depth', 0)->exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$code = 'root-'.(string) $site->code;
|
||||
$nodeId = DB::table('agent_nodes')->insertGetId([
|
||||
'admin_site_id' => (int) $site->id,
|
||||
'parent_id' => null,
|
||||
'path' => '/',
|
||||
'depth' => 0,
|
||||
'code' => $code,
|
||||
'name' => (string) $site->name,
|
||||
'status' => 1,
|
||||
'created_by' => null,
|
||||
'extra_json' => null,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
DB::table('agent_nodes')->where('id', $nodeId)->update([
|
||||
'path' => '/'.$nodeId.'/',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function backfillAdminUserAgents(): void
|
||||
{
|
||||
$superRoleId = DB::table('admin_roles')->where('slug', 'super_admin')->value('id');
|
||||
$now = Carbon::now();
|
||||
|
||||
$userIds = DB::table('admin_users')->pluck('id');
|
||||
foreach ($userIds as $userId) {
|
||||
$userId = (int) $userId;
|
||||
if (DB::table('admin_user_agents')->where('admin_user_id', $userId)->exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($superRoleId !== null) {
|
||||
$isSuper = DB::table('admin_user_site_roles')
|
||||
->where('admin_user_id', $userId)
|
||||
->where('role_id', (int) $superRoleId)
|
||||
->exists();
|
||||
if ($isSuper) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$siteId = DB::table('admin_user_site_roles')
|
||||
->where('admin_user_id', $userId)
|
||||
->orderBy('site_id')
|
||||
->value('site_id');
|
||||
|
||||
if ($siteId === null) {
|
||||
$siteId = DB::table('admin_sites')->where('is_default', true)->value('id')
|
||||
?? DB::table('admin_sites')->orderBy('id')->value('id');
|
||||
}
|
||||
|
||||
if ($siteId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rootId = DB::table('agent_nodes')
|
||||
->where('admin_site_id', (int) $siteId)
|
||||
->where('depth', 0)
|
||||
->value('id');
|
||||
|
||||
if ($rootId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('admin_user_agents')->insert([
|
||||
'admin_user_id' => $userId,
|
||||
'agent_node_id' => (int) $rootId,
|
||||
'is_primary' => true,
|
||||
'granted_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Support\AdminAuthorizationRegistry;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$viewActionId = DB::table('admin_action_catalog')->where('code', 'view')->value('id');
|
||||
$manageActionId = DB::table('admin_action_catalog')->where('code', 'manage')->value('id');
|
||||
if ($viewActionId === null || $manageActionId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$systemMenuId = DB::table('admin_menus')->where('code', 'system')->value('id');
|
||||
if ($systemMenuId === null) {
|
||||
$systemMenuId = DB::table('admin_menus')->insertGetId([
|
||||
'parent_id' => null,
|
||||
'menu_type' => 'directory',
|
||||
'code' => 'system',
|
||||
'name' => '系统',
|
||||
'path' => null,
|
||||
'route_name' => null,
|
||||
'component' => null,
|
||||
'icon' => null,
|
||||
'active_menu_code' => null,
|
||||
'sort_order' => 90,
|
||||
'is_visible' => true,
|
||||
'is_cache' => false,
|
||||
'is_external' => false,
|
||||
'status' => 1,
|
||||
'meta_json' => null,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
$agentMenuId = DB::table('admin_menus')->where('code', 'system.agents')->value('id');
|
||||
if ($agentMenuId === null) {
|
||||
$agentMenuId = DB::table('admin_menus')->insertGetId([
|
||||
'parent_id' => (int) $systemMenuId,
|
||||
'menu_type' => 'page',
|
||||
'code' => 'system.agents',
|
||||
'name' => '代理管理',
|
||||
'path' => '/admin/agents',
|
||||
'route_name' => 'admin.agents',
|
||||
'component' => 'agents/index',
|
||||
'icon' => null,
|
||||
'active_menu_code' => null,
|
||||
'sort_order' => 25,
|
||||
'is_visible' => true,
|
||||
'is_cache' => false,
|
||||
'is_external' => false,
|
||||
'status' => 1,
|
||||
'meta_json' => null,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ([
|
||||
['permission_code' => 'agent.node.view', 'action_id' => (int) $viewActionId, 'name' => '代理节点查看'],
|
||||
['permission_code' => 'agent.node.manage', 'action_id' => (int) $manageActionId, 'name' => '代理节点管理'],
|
||||
] as $row) {
|
||||
if (DB::table('admin_menu_actions')->where('permission_code', $row['permission_code'])->exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('admin_menu_actions')->insert([
|
||||
'menu_id' => (int) $agentMenuId,
|
||||
'action_id' => $row['action_id'],
|
||||
'permission_code' => $row['permission_code'],
|
||||
'name' => $row['name'],
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $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.agent-nodes.'),
|
||||
));
|
||||
|
||||
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();
|
||||
|
||||
$permissionCodes = $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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (! Schema::hasTable('admin_role_api_resources')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$superRoleId = DB::table('admin_roles')->where('slug', 'super_admin')->value('id');
|
||||
if ($superRoleId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($resources as $resource) {
|
||||
$resourceId = DB::table('admin_api_resources')->where('code', $resource['code'])->value('id');
|
||||
if ($resourceId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('admin_role_api_resources')->updateOrInsert([
|
||||
'role_id' => (int) $superRoleId,
|
||||
'api_resource_id' => (int) $resourceId,
|
||||
], []);
|
||||
}
|
||||
|
||||
$menuActionIdList = DB::table('admin_menu_actions')
|
||||
->whereIn('permission_code', ['agent.node.view', 'agent.node.manage'])
|
||||
->pluck('id');
|
||||
|
||||
foreach ($menuActionIdList as $menuActionId) {
|
||||
DB::table('admin_role_menu_actions')->updateOrInsert([
|
||||
'role_id' => (int) $superRoleId,
|
||||
'menu_action_id' => (int) $menuActionId,
|
||||
], []);
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$codes = [
|
||||
'admin.agent-nodes.tree',
|
||||
'admin.agent-nodes.store',
|
||||
'admin.agent-nodes.show',
|
||||
'admin.agent-nodes.update',
|
||||
'admin.agent-nodes.children',
|
||||
];
|
||||
|
||||
foreach ($codes as $code) {
|
||||
$resourceId = DB::table('admin_api_resources')->where('code', $code)->value('id');
|
||||
if ($resourceId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Schema::hasTable('admin_role_api_resources')) {
|
||||
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();
|
||||
}
|
||||
|
||||
DB::table('admin_menu_actions')
|
||||
->whereIn('permission_code', ['agent.node.view', 'agent.node.manage'])
|
||||
->delete();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('admin_roles', function (Blueprint $table): void {
|
||||
$table->foreignId('owner_agent_id')->nullable()->after('sort_order')->constrained('agent_nodes')->nullOnDelete();
|
||||
$table->foreignId('delegated_from_role_id')->nullable()->after('owner_agent_id')->constrained('admin_roles')->nullOnDelete();
|
||||
$table->string('scope_type', 16)->default('system')->after('delegated_from_role_id');
|
||||
});
|
||||
|
||||
Schema::create('admin_user_agent_roles', function (Blueprint $table): void {
|
||||
$table->foreignId('admin_user_id')->constrained('admin_users')->cascadeOnDelete();
|
||||
$table->foreignId('agent_node_id')->constrained('agent_nodes')->cascadeOnDelete();
|
||||
$table->foreignId('role_id')->constrained('admin_roles')->cascadeOnDelete();
|
||||
$table->timestamp('granted_at')->nullable();
|
||||
$table->primary(['admin_user_id', 'agent_node_id', 'role_id'], 'pk_admin_user_agent_roles');
|
||||
});
|
||||
|
||||
Schema::table('players', function (Blueprint $table): void {
|
||||
$table->foreignId('agent_node_id')->nullable()->after('site_code')->constrained('agent_nodes')->nullOnDelete();
|
||||
$table->index(['site_code', 'agent_node_id'], 'idx_players_site_agent');
|
||||
});
|
||||
|
||||
DB::table('admin_roles')->update(['scope_type' => 'system']);
|
||||
|
||||
$this->backfillAdminUserAgentRoles();
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('players', function (Blueprint $table): void {
|
||||
$table->dropIndex('idx_players_site_agent');
|
||||
$table->dropConstrainedForeignId('agent_node_id');
|
||||
});
|
||||
|
||||
Schema::dropIfExists('admin_user_agent_roles');
|
||||
|
||||
Schema::table('admin_roles', function (Blueprint $table): void {
|
||||
$table->dropConstrainedForeignId('delegated_from_role_id');
|
||||
$table->dropConstrainedForeignId('owner_agent_id');
|
||||
$table->dropColumn('scope_type');
|
||||
});
|
||||
}
|
||||
|
||||
private function backfillAdminUserAgentRoles(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$rows = DB::table('admin_user_site_roles as usr')
|
||||
->join('admin_user_agents as uaa', 'uaa.admin_user_id', '=', 'usr.admin_user_id')
|
||||
->join('agent_nodes as an', static function ($join): void {
|
||||
$join->on('an.id', '=', 'uaa.agent_node_id')
|
||||
->on('an.admin_site_id', '=', 'usr.site_id');
|
||||
})
|
||||
->select(['usr.admin_user_id', 'uaa.agent_node_id', 'usr.role_id', 'usr.granted_at'])
|
||||
->get();
|
||||
|
||||
foreach ($rows as $row) {
|
||||
DB::table('admin_user_agent_roles')->updateOrInsert(
|
||||
[
|
||||
'admin_user_id' => (int) $row->admin_user_id,
|
||||
'agent_node_id' => (int) $row->agent_node_id,
|
||||
'role_id' => (int) $row->role_id,
|
||||
],
|
||||
[
|
||||
'granted_at' => $row->granted_at ?? $now,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Support\AdminAuthorizationRegistry;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* 代理角色/账号 API 绑定到已有 agent.node.view / agent.node.manage 动作(同菜单下 action 唯一)。
|
||||
*/
|
||||
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.agent-roles.')
|
||||
|| str_starts_with((string) $resource['code'], 'admin.agent-admin-users.'),
|
||||
));
|
||||
|
||||
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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (! Schema::hasTable('admin_role_api_resources')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$superRoleId = DB::table('admin_roles')->where('slug', 'super_admin')->value('id');
|
||||
if ($superRoleId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($resources as $resource) {
|
||||
$resourceId = DB::table('admin_api_resources')->where('code', $resource['code'])->value('id');
|
||||
if ($resourceId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('admin_role_api_resources')->updateOrInsert([
|
||||
'role_id' => (int) $superRoleId,
|
||||
'api_resource_id' => (int) $resourceId,
|
||||
], []);
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$codes = [
|
||||
'admin.agent-roles.update',
|
||||
'admin.agent-roles.destroy',
|
||||
'admin.agent-roles.permissions.sync',
|
||||
'admin.agent-roles.index',
|
||||
'admin.agent-roles.store',
|
||||
'admin.agent-admin-users.index',
|
||||
'admin.agent-admin-users.store',
|
||||
'admin.agent-admin-users.roles.sync',
|
||||
];
|
||||
|
||||
foreach ($codes as $code) {
|
||||
$resourceId = DB::table('admin_api_resources')->where('code', $code)->value('id');
|
||||
if ($resourceId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Schema::hasTable('admin_role_api_resources')) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('agent_delegation_grants', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->foreignId('parent_agent_id')->constrained('agent_nodes')->cascadeOnDelete();
|
||||
$table->foreignId('child_agent_id')->constrained('agent_nodes')->cascadeOnDelete();
|
||||
$table->foreignId('menu_action_id')->constrained('admin_menu_actions')->cascadeOnDelete();
|
||||
$table->boolean('can_delegate')->default(false);
|
||||
$table->foreignId('granted_by')->nullable()->constrained('admin_users')->nullOnDelete();
|
||||
$table->timestamp('granted_at')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['child_agent_id', 'menu_action_id'], 'uk_agent_delegation_child_action');
|
||||
$table->index(['parent_agent_id', 'child_agent_id'], 'idx_agent_delegation_parent_child');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('agent_delegation_grants');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 将未归属玩家挂到对应主站根代理(与 agent_nodes depth=0 1:1)。
|
||||
*/
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (! \Illuminate\Support\Facades\Schema::hasColumn('players', 'agent_node_id')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$roots = DB::table('agent_nodes as an')
|
||||
->join('admin_sites as s', 's.id', '=', 'an.admin_site_id')
|
||||
->where('an.depth', 0)
|
||||
->get(['an.id as root_id', 's.code as site_code']);
|
||||
|
||||
foreach ($roots as $root) {
|
||||
DB::table('players')
|
||||
->where('site_code', (string) $root->site_code)
|
||||
->whereNull('agent_node_id')
|
||||
->update(['agent_node_id' => (int) $root->root_id]);
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
// 不回滚归属,避免误清空业务绑定。
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user