feat: 更新玩法配置管理,简化字段并增强功能
- 将玩法相关的显示名称字段统一为 `display_name`,移除多语言字段。 - 在 `PlayTypePatchController` 中新增即时切换玩法开关的功能,并推送大厅更新。 - 优化多个控制器和服务中的权限检查与数据处理逻辑,提升代码可读性与维护性。
This commit is contained in:
@@ -297,7 +297,6 @@ return new class extends Migration
|
||||
|
||||
$actionIds = DB::table('admin_action_catalog')->pluck('id', 'code');
|
||||
$menuActions = [
|
||||
['menu_code' => 'dashboard', 'action_code' => 'view', 'permission_code' => 'dashboard.view', 'name' => '仪表盘查看'],
|
||||
['menu_code' => 'draw.results', 'action_code' => 'view', 'permission_code' => 'draw.results.view', 'name' => '开奖结果查看'],
|
||||
['menu_code' => 'draw.review', 'action_code' => 'review', 'permission_code' => 'draw.review.review', 'name' => '开奖审核'],
|
||||
['menu_code' => 'draw.review', 'action_code' => 'publish', 'permission_code' => 'draw.review.publish', 'name' => '开奖发布'],
|
||||
@@ -340,7 +339,7 @@ return new class extends Migration
|
||||
private function seedApiResources(Carbon $now): void
|
||||
{
|
||||
$resources = [
|
||||
['code' => 'admin.dashboard', 'module_code' => 'dashboard', 'name' => '后台仪表盘', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/dashboard', 'route_name' => 'api.v1.admin.dashboard', 'auth_mode' => 'login_only', 'is_audit_required' => false, 'permission_codes' => ['dashboard.view']],
|
||||
['code' => 'admin.dashboard', 'module_code' => 'dashboard', 'name' => '后台仪表盘', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/dashboard', 'route_name' => 'api.v1.admin.dashboard', 'auth_mode' => 'login_only', 'is_audit_required' => false, 'permission_codes' => []],
|
||||
['code' => 'admin.draws.index', 'module_code' => 'draw', 'name' => '期开奖列表', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/draws', 'route_name' => 'api.v1.admin.draws.index', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['draw.results.view']],
|
||||
['code' => 'admin.draws.show', 'module_code' => 'draw', 'name' => '期开奖详情', 'http_method' => 'GET', 'uri_pattern' => '/api/v1/admin/draws/{draw}', 'route_name' => 'api.v1.admin.draws.show', 'auth_mode' => 'permission_required', 'is_audit_required' => false, 'permission_codes' => ['draw.results.view']],
|
||||
['code' => 'admin.draws.publish', 'module_code' => 'draw', 'name' => '开奖发布', 'http_method' => 'POST', 'uri_pattern' => '/api/v1/admin/draws/{draw}/result-batches/{batch}/publish', 'route_name' => 'api.v1.admin.draws.result-batches.publish', 'auth_mode' => 'permission_required', 'is_audit_required' => true, 'permission_codes' => ['draw.review.publish']],
|
||||
@@ -454,7 +453,7 @@ return new class extends Migration
|
||||
foreach ($legacyRoles as $role) {
|
||||
$roleId = (int) $role->id;
|
||||
|
||||
$grantedPermissions = ['dashboard.view' => true];
|
||||
$grantedPermissions = [];
|
||||
foreach ($legacyRolePermissions->get((int) $role->id, collect()) as $pivot) {
|
||||
$permissionId = (int) $pivot->permission_id;
|
||||
$legacySlug = $legacyPermissionById[$permissionId] ?? null;
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
foreach (['play_types', 'play_config_items'] as $table) {
|
||||
Schema::table($table, function (Blueprint $blueprint): void {
|
||||
$blueprint->string('display_name', 64)->nullable()->after('bet_mode');
|
||||
});
|
||||
|
||||
DB::table($table)->update([
|
||||
'display_name' => DB::raw(
|
||||
"COALESCE(
|
||||
NULLIF(TRIM(display_name_zh), ''),
|
||||
NULLIF(TRIM(display_name_en), ''),
|
||||
NULLIF(TRIM(display_name_ne), ''),
|
||||
play_code
|
||||
)",
|
||||
),
|
||||
]);
|
||||
|
||||
Schema::table($table, function (Blueprint $blueprint): void {
|
||||
$blueprint->dropColumn(['display_name_zh', 'display_name_en', 'display_name_ne']);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
foreach (['play_types', 'play_config_items'] as $table) {
|
||||
Schema::table($table, function (Blueprint $blueprint): void {
|
||||
$blueprint->string('display_name_zh', 64)->nullable()->after('bet_mode');
|
||||
$blueprint->string('display_name_en', 64)->nullable()->after('display_name_zh');
|
||||
$blueprint->string('display_name_ne', 64)->nullable()->after('display_name_en');
|
||||
});
|
||||
|
||||
DB::table($table)->update([
|
||||
'display_name_zh' => DB::raw('display_name'),
|
||||
'display_name_en' => DB::raw('display_name'),
|
||||
'display_name_ne' => DB::raw('display_name'),
|
||||
]);
|
||||
|
||||
Schema::table($table, function (Blueprint $blueprint): void {
|
||||
$blueprint->dropColumn('display_name');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$actionIds = DB::table('admin_action_catalog')->pluck('id', 'code');
|
||||
$menuIds = DB::table('admin_menus')->pluck('id', 'code');
|
||||
|
||||
$walletMenuId = $menuIds['service.wallet'] ?? null;
|
||||
$updateActionId = $actionIds['update'] ?? null;
|
||||
if ($walletMenuId !== null && $updateActionId !== null) {
|
||||
$exists = DB::table('admin_menu_actions')
|
||||
->where('permission_code', 'service.wallet.adjust')
|
||||
->exists();
|
||||
|
||||
if (! $exists) {
|
||||
DB::table('admin_menu_actions')->insert([
|
||||
'menu_id' => $walletMenuId,
|
||||
'action_id' => $updateActionId,
|
||||
'permission_code' => 'service.wallet.adjust',
|
||||
'name' => '钱包补单/冲正',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$oddsMenuId = $menuIds['config.odds'] ?? null;
|
||||
$viewActionId = $actionIds['view'] ?? null;
|
||||
if ($oddsMenuId !== null && $viewActionId !== null) {
|
||||
$exists = DB::table('admin_menu_actions')
|
||||
->where('permission_code', 'config.odds.view')
|
||||
->exists();
|
||||
|
||||
if (! $exists) {
|
||||
DB::table('admin_menu_actions')->insert([
|
||||
'menu_id' => $oddsMenuId,
|
||||
'action_id' => $viewActionId,
|
||||
'permission_code' => 'config.odds.view',
|
||||
'name' => '赔率配置查看',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
DB::table('admin_menu_actions')
|
||||
->whereIn('permission_code', ['service.wallet.adjust', 'config.odds.view'])
|
||||
->delete();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/** @var list<string> */
|
||||
private const STALE_PERMISSION_CODES = [
|
||||
'dashboard.view',
|
||||
'service.reports.view',
|
||||
'service.reports.export',
|
||||
];
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
$menuActionIds = DB::table('admin_menu_actions')
|
||||
->whereIn('permission_code', self::STALE_PERMISSION_CODES)
|
||||
->pluck('id');
|
||||
|
||||
if ($menuActionIds->isNotEmpty()) {
|
||||
DB::table('admin_menu_actions')
|
||||
->whereIn('id', $menuActionIds->all())
|
||||
->delete();
|
||||
}
|
||||
|
||||
$staleReportMenuId = DB::table('admin_menus')
|
||||
->where('code', 'service.reports')
|
||||
->value('id');
|
||||
|
||||
if ($staleReportMenuId !== null) {
|
||||
$hasActions = DB::table('admin_menu_actions')
|
||||
->where('menu_id', (int) $staleReportMenuId)
|
||||
->exists();
|
||||
|
||||
if (! $hasActions) {
|
||||
DB::table('admin_menus')
|
||||
->where('id', (int) $staleReportMenuId)
|
||||
->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
// 数据清理迁移,不回滚以免再现僵尸 permission_code。
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
use App\Support\AdminAuthorizationRegistry;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$menuActionId = DB::table('admin_menu_actions')
|
||||
->where('permission_code', 'dashboard.view')
|
||||
->value('id');
|
||||
|
||||
if ($menuActionId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$resource = collect(AdminAuthorizationRegistry::resources())
|
||||
->firstWhere('code', 'admin.dashboard.analytics');
|
||||
|
||||
if ($resource === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$resourceId = DB::table('admin_api_resources')
|
||||
->where('code', 'admin.dashboard.analytics')
|
||||
->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' => 'admin.dashboard.analytics',
|
||||
'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) {
|
||||
$actionId = DB::table('admin_menu_actions')
|
||||
->where('permission_code', $permissionCode)
|
||||
->value('id');
|
||||
if ($actionId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('admin_api_resource_bindings')->insert([
|
||||
'api_resource_id' => (int) $resourceId,
|
||||
'menu_action_id' => (int) $actionId,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$resourceId = DB::table('admin_api_resources')
|
||||
->where('code', 'admin.dashboard.analytics')
|
||||
->value('id');
|
||||
|
||||
if ($resourceId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
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,51 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('settlement_batches', function (Blueprint $table): void {
|
||||
if (! Schema::hasColumn('settlement_batches', 'review_status')) {
|
||||
$table->string('review_status', 32)->default('pending')->after('total_jackpot_payout_amount');
|
||||
}
|
||||
if (! Schema::hasColumn('settlement_batches', 'reviewed_by')) {
|
||||
$table->foreignId('reviewed_by')->nullable()->after('review_status')->constrained('admin_users')->nullOnDelete();
|
||||
}
|
||||
if (! Schema::hasColumn('settlement_batches', 'reviewed_at')) {
|
||||
$table->timestamp('reviewed_at')->nullable()->after('reviewed_by');
|
||||
}
|
||||
if (! Schema::hasColumn('settlement_batches', 'review_remark')) {
|
||||
$table->string('review_remark', 255)->nullable()->after('reviewed_at');
|
||||
}
|
||||
if (! Schema::hasColumn('settlement_batches', 'paid_at')) {
|
||||
$table->timestamp('paid_at')->nullable()->after('review_remark');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('settlement_batches', function (Blueprint $table): void {
|
||||
if (Schema::hasColumn('settlement_batches', 'paid_at')) {
|
||||
$table->dropColumn('paid_at');
|
||||
}
|
||||
if (Schema::hasColumn('settlement_batches', 'review_remark')) {
|
||||
$table->dropColumn('review_remark');
|
||||
}
|
||||
if (Schema::hasColumn('settlement_batches', 'reviewed_at')) {
|
||||
$table->dropColumn('reviewed_at');
|
||||
}
|
||||
if (Schema::hasColumn('settlement_batches', 'reviewed_by')) {
|
||||
$table->dropForeign(['reviewed_by']);
|
||||
$table->dropColumn('reviewed_by');
|
||||
}
|
||||
if (Schema::hasColumn('settlement_batches', 'review_status')) {
|
||||
$table->dropColumn('review_status');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
use App\Support\AdminPermissionBridge;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/** @var list<array{menu_code: string, action_code: string, permission_code: string, name: string}> */
|
||||
private const NEW_MENU_ACTIONS = [
|
||||
['menu_code' => 'dashboard', 'action_code' => 'view', 'permission_code' => 'dashboard.view', 'name' => '仪表盘查看'],
|
||||
['menu_code' => 'service.report', 'action_code' => 'export', 'permission_code' => 'service.report.export', 'name' => '报表导出'],
|
||||
['menu_code' => 'risk.monitor', 'action_code' => 'manage', 'permission_code' => 'risk.monitor.manage', 'name' => '风控监控管理'],
|
||||
];
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$menuIds = DB::table('admin_menus')->pluck('id', 'code');
|
||||
$actionIds = DB::table('admin_action_catalog')->pluck('id', 'code');
|
||||
|
||||
$menuActionIds = [];
|
||||
foreach (self::NEW_MENU_ACTIONS as $row) {
|
||||
$menuId = $menuIds[$row['menu_code']] ?? null;
|
||||
$actionId = $actionIds[$row['action_code']] ?? null;
|
||||
if ($menuId === null || $actionId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$exists = DB::table('admin_menu_actions')
|
||||
->where('permission_code', $row['permission_code'])
|
||||
->exists();
|
||||
|
||||
if ($exists) {
|
||||
$menuActionIds[$row['permission_code']] = (int) DB::table('admin_menu_actions')
|
||||
->where('permission_code', $row['permission_code'])
|
||||
->value('id');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$menuActionIds[$row['permission_code']] = (int) DB::table('admin_menu_actions')->insertGetId([
|
||||
'menu_id' => (int) $menuId,
|
||||
'action_id' => (int) $actionId,
|
||||
'permission_code' => $row['permission_code'],
|
||||
'name' => $row['name'],
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->grantMenuActionsToAllRoles($menuActionIds, $now);
|
||||
$this->grantReportExportToReportViewRoles($menuActionIds['service.report.export'] ?? null, $now);
|
||||
$this->grantTicketsViewToLegacyRoles($menuActionIds, $now);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$codes = array_column(self::NEW_MENU_ACTIONS, 'permission_code');
|
||||
$ids = DB::table('admin_menu_actions')->whereIn('permission_code', $codes)->pluck('id');
|
||||
foreach ($ids as $id) {
|
||||
DB::table('admin_role_menu_actions')->where('menu_action_id', (int) $id)->delete();
|
||||
DB::table('admin_user_menu_actions')->where('menu_action_id', (int) $id)->delete();
|
||||
DB::table('admin_api_resource_bindings')->where('menu_action_id', (int) $id)->delete();
|
||||
DB::table('admin_menu_actions')->where('id', (int) $id)->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, int> $menuActionIds
|
||||
*/
|
||||
private function grantMenuActionsToAllRoles(array $menuActionIds, Carbon $now): void
|
||||
{
|
||||
$dashboardId = $menuActionIds['dashboard.view'] ?? null;
|
||||
if ($dashboardId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$roleIds = DB::table('admin_roles')->pluck('id');
|
||||
foreach ($roleIds as $roleId) {
|
||||
DB::table('admin_role_menu_actions')->updateOrInsert([
|
||||
'role_id' => (int) $roleId,
|
||||
'menu_action_id' => $dashboardId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function grantReportExportToReportViewRoles(?int $exportMenuActionId, Carbon $now): void
|
||||
{
|
||||
if ($exportMenuActionId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$viewMenuActionId = DB::table('admin_menu_actions')
|
||||
->where('permission_code', 'service.report.view')
|
||||
->value('id');
|
||||
|
||||
if ($viewMenuActionId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$roleIds = DB::table('admin_role_menu_actions')
|
||||
->where('menu_action_id', (int) $viewMenuActionId)
|
||||
->distinct()
|
||||
->pluck('role_id');
|
||||
|
||||
foreach ($roleIds as $roleId) {
|
||||
DB::table('admin_role_menu_actions')->updateOrInsert([
|
||||
'role_id' => (int) $roleId,
|
||||
'menu_action_id' => $exportMenuActionId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 原注单入口依赖多种 prd.*;迁移为独立的 prd.tickets.view。
|
||||
*
|
||||
* @param array<string, int> $menuActionIds
|
||||
*/
|
||||
private function grantTicketsViewToLegacyRoles(array $menuActionIds, Carbon $now): void
|
||||
{
|
||||
$ticketsViewId = DB::table('admin_menu_actions')
|
||||
->where('permission_code', 'service.tickets.view')
|
||||
->value('id');
|
||||
|
||||
if ($ticketsViewId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$legacySlugs = [
|
||||
'prd.users.view_cs',
|
||||
'prd.users.manage',
|
||||
'prd.users.view_finance',
|
||||
'prd.draw_result.view',
|
||||
'prd.draw_result.manage',
|
||||
'prd.payout.view',
|
||||
'prd.payout.review',
|
||||
'prd.payout.manage',
|
||||
];
|
||||
|
||||
$roleIds = $this->roleIdsWithAnyLegacySlug($legacySlugs);
|
||||
|
||||
foreach ($roleIds as $roleId) {
|
||||
DB::table('admin_role_menu_actions')->updateOrInsert([
|
||||
'role_id' => (int) $roleId,
|
||||
'menu_action_id' => (int) $ticketsViewId,
|
||||
]);
|
||||
}
|
||||
|
||||
$riskViewId = DB::table('admin_menu_actions')
|
||||
->where('permission_code', 'risk.monitor.view')
|
||||
->value('id');
|
||||
$riskManageId = $menuActionIds['risk.monitor.manage'] ?? null;
|
||||
|
||||
if ($riskManageId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$riskRoleIds = $this->roleIdsWithAnyLegacySlug([
|
||||
'prd.draw_result.manage',
|
||||
'prd.draw_result.view',
|
||||
'prd.risk.manage',
|
||||
'prd.risk.view',
|
||||
]);
|
||||
|
||||
foreach ($riskRoleIds as $roleId) {
|
||||
if ($riskViewId !== null) {
|
||||
DB::table('admin_role_menu_actions')->updateOrInsert([
|
||||
'role_id' => (int) $roleId,
|
||||
'menu_action_id' => (int) $riskViewId,
|
||||
]);
|
||||
}
|
||||
DB::table('admin_role_menu_actions')->updateOrInsert([
|
||||
'role_id' => (int) $roleId,
|
||||
'menu_action_id' => (int) $riskManageId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过角色已授权的 menu_action 反推曾拥有指定 prd.* 的角色(legacy 表已废弃)。
|
||||
*
|
||||
* @param list<string> $legacySlugs
|
||||
* @return list<int>
|
||||
*/
|
||||
private function roleIdsWithAnyLegacySlug(array $legacySlugs): array
|
||||
{
|
||||
$codes = [];
|
||||
foreach ($legacySlugs as $slug) {
|
||||
$codes = array_merge($codes, AdminPermissionBridge::menuActionCodesForLegacy($slug));
|
||||
}
|
||||
$codes = array_values(array_unique($codes));
|
||||
|
||||
if ($codes === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$menuActionIds = DB::table('admin_menu_actions')
|
||||
->whereIn('permission_code', $codes)
|
||||
->where('status', 1)
|
||||
->pluck('id');
|
||||
|
||||
if ($menuActionIds->isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return DB::table('admin_role_menu_actions')
|
||||
->whereIn('menu_action_id', $menuActionIds->map(fn ($id) => (int) $id)->all())
|
||||
->distinct()
|
||||
->pluck('role_id')
|
||||
->map(fn ($id) => (int) $id)
|
||||
->all();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,112 @@
|
||||
<?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();
|
||||
|
||||
if (! DB::table('admin_action_catalog')->where('code', 'manual_burst')->exists()) {
|
||||
DB::table('admin_action_catalog')->insert([
|
||||
'code' => 'manual_burst',
|
||||
'name' => '手动爆池',
|
||||
'sort_order' => 85,
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
$jackpotMenuId = (int) DB::table('admin_menus')->where('code', 'config.jackpot')->value('id');
|
||||
$manualBurstActionId = (int) DB::table('admin_action_catalog')->where('code', 'manual_burst')->value('id');
|
||||
|
||||
if ($jackpotMenuId <= 0 || $manualBurstActionId <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
DB::table('admin_menu_actions')->updateOrInsert(
|
||||
['permission_code' => 'jackpot.pool.manual_burst'],
|
||||
[
|
||||
'menu_id' => $jackpotMenuId,
|
||||
'action_id' => $manualBurstActionId,
|
||||
'name' => 'Jackpot 手动爆池',
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
);
|
||||
|
||||
if (Schema::hasTable('admin_permissions')) {
|
||||
DB::table('admin_permissions')->updateOrInsert(
|
||||
['slug' => 'prd.jackpot.manual_burst'],
|
||||
[
|
||||
'name' => 'Jackpot 手动爆池·仅超管',
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
$menuActionId = (int) DB::table('admin_menu_actions')
|
||||
->where('permission_code', 'jackpot.pool.manual_burst')
|
||||
->value('id');
|
||||
|
||||
$superRoleId = (int) DB::table('admin_roles')->where('slug', 'super_admin')->value('id');
|
||||
if ($superRoleId > 0 && $menuActionId > 0) {
|
||||
if (Schema::hasTable('admin_role_legacy_permissions')) {
|
||||
DB::table('admin_role_legacy_permissions')->updateOrInsert(
|
||||
[
|
||||
'role_id' => $superRoleId,
|
||||
'permission_slug' => 'prd.jackpot.manual_burst',
|
||||
],
|
||||
[
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
DB::table('admin_role_menu_actions')->updateOrInsert(
|
||||
[
|
||||
'role_id' => $superRoleId,
|
||||
'menu_action_id' => $menuActionId,
|
||||
],
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
$resourceId = DB::table('admin_api_resources')
|
||||
->where('code', 'admin.jackpot.pools.manual-burst')
|
||||
->value('id');
|
||||
|
||||
if ($resourceId !== null && $menuActionId > 0) {
|
||||
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' => $menuActionId,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
if ($superRoleId > 0 && Schema::hasTable('admin_role_api_resources')) {
|
||||
DB::table('admin_role_api_resources')->updateOrInsert([
|
||||
'role_id' => $superRoleId,
|
||||
'api_resource_id' => (int) $resourceId,
|
||||
], []);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
// 避免误删线上已调整的授权绑定。
|
||||
}
|
||||
};
|
||||
@@ -39,17 +39,22 @@ final class AdminRbacAndUserSeeder extends Seeder
|
||||
['name' => '风控运营员'],
|
||||
);
|
||||
$this->syncRolePermissions($risk, [
|
||||
'prd.dashboard.view',
|
||||
'prd.play_switch.manage',
|
||||
'prd.odds.manage',
|
||||
'prd.risk_cap.manage',
|
||||
'prd.rebate.manage',
|
||||
'prd.jackpot.manage',
|
||||
'prd.draw_result.manage',
|
||||
'prd.risk.view',
|
||||
'prd.risk.manage',
|
||||
'prd.payout.review',
|
||||
'prd.tickets.view',
|
||||
'prd.wallet_reconcile.view',
|
||||
'prd.audit.view',
|
||||
'prd.player_freeze.manage',
|
||||
'prd.report.view',
|
||||
'prd.report.export',
|
||||
]);
|
||||
|
||||
$finance = AdminRole::query()->updateOrCreate(
|
||||
@@ -57,16 +62,19 @@ final class AdminRbacAndUserSeeder extends Seeder
|
||||
['name' => '财务/对账员'],
|
||||
);
|
||||
$this->syncRolePermissions($finance, [
|
||||
'prd.dashboard.view',
|
||||
'prd.users.view_finance',
|
||||
'prd.risk_cap.view',
|
||||
'prd.rebate.view',
|
||||
'prd.jackpot.view',
|
||||
'prd.draw_result.view',
|
||||
'prd.payout.view',
|
||||
'prd.tickets.view',
|
||||
'prd.wallet_reconcile.manage',
|
||||
'prd.wallet_adjust.manage',
|
||||
'prd.audit.view',
|
||||
'prd.report.view',
|
||||
'prd.report.export',
|
||||
]);
|
||||
|
||||
$cs = AdminRole::query()->updateOrCreate(
|
||||
@@ -74,7 +82,9 @@ final class AdminRbacAndUserSeeder extends Seeder
|
||||
['name' => '客服人员'],
|
||||
);
|
||||
$this->syncRolePermissions($cs, [
|
||||
'prd.dashboard.view',
|
||||
'prd.users.view_cs',
|
||||
'prd.tickets.view',
|
||||
'prd.draw_result.view',
|
||||
'prd.wallet_reconcile.view_cs',
|
||||
'prd.report.view',
|
||||
|
||||
@@ -11,6 +11,8 @@ use App\Lottery\DrawStatus;
|
||||
use App\Models\TicketOrder;
|
||||
use App\Models\TransferOrder;
|
||||
use App\Models\DrawResultBatch;
|
||||
use App\Models\SettlementBatch;
|
||||
use App\Lottery\SettlementBatchStatus;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Lottery\DrawResultBatchStatus;
|
||||
@@ -54,7 +56,8 @@ final class DashboardHallFixtureSeeder extends Seeder
|
||||
DB::transaction(function () use ($draw, $player): void {
|
||||
$this->seedRiskPools($draw);
|
||||
$this->seedTicketOrders($draw, $player);
|
||||
$this->seedPendingReviewBatch($draw);
|
||||
$resultBatch = $this->seedPendingReviewBatch($draw);
|
||||
$this->seedSettlementBatches($draw, $resultBatch);
|
||||
$this->seedAbnormalTransfers($player);
|
||||
});
|
||||
|
||||
@@ -269,12 +272,12 @@ final class DashboardHallFixtureSeeder extends Seeder
|
||||
);
|
||||
}
|
||||
|
||||
private function seedPendingReviewBatch(Draw $draw): void
|
||||
private function seedPendingReviewBatch(Draw $draw): DrawResultBatch
|
||||
{
|
||||
$max = (int) DrawResultBatch::query()->where('draw_id', $draw->id)->max('result_version');
|
||||
$next = max(1, $max + 1);
|
||||
|
||||
DrawResultBatch::query()->firstOrCreate(
|
||||
return DrawResultBatch::query()->firstOrCreate(
|
||||
[
|
||||
'draw_id' => $draw->id,
|
||||
'result_version' => $next,
|
||||
@@ -291,6 +294,35 @@ final class DashboardHallFixtureSeeder extends Seeder
|
||||
);
|
||||
}
|
||||
|
||||
private function seedSettlementBatches(Draw $draw, DrawResultBatch $resultBatch): void
|
||||
{
|
||||
$now = Carbon::now()->utc();
|
||||
$rows = [
|
||||
[1, SettlementBatchStatus::PendingReview, 3, 1, 15_000, 5_000, $now->copy()->subHours(2), null],
|
||||
[2, SettlementBatchStatus::Approved, 3, 2, 20_000, 5_000, $now->copy()->subHour(), $now->copy()->subMinutes(30)],
|
||||
[3, SettlementBatchStatus::Completed, 3, 2, 20_000, 5_000, $now->copy()->subMinutes(45), $now->copy()->subMinutes(10)],
|
||||
];
|
||||
|
||||
foreach ($rows as [$version, $status, $tickets, $wins, $payout, $jackpot, $started, $finished]) {
|
||||
SettlementBatch::query()->firstOrCreate(
|
||||
[
|
||||
'draw_id' => $draw->id,
|
||||
'settle_version' => $version,
|
||||
],
|
||||
[
|
||||
'result_batch_id' => (int) $resultBatch->id,
|
||||
'status' => $status->value,
|
||||
'total_ticket_count' => $tickets,
|
||||
'total_win_count' => $wins,
|
||||
'total_payout_amount' => $payout,
|
||||
'total_jackpot_payout_amount' => $jackpot,
|
||||
'started_at' => $started,
|
||||
'finished_at' => $finished,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function seedAbnormalTransfers(Player $player): void
|
||||
{
|
||||
$rows = [
|
||||
|
||||
@@ -82,6 +82,20 @@ final class LotterySettingsSeeder extends Seeder
|
||||
'是否在 draw tick 中自动对 `settling` 期号跑结算;false 时仅能通过后台 POST settlement/run 触发',
|
||||
);
|
||||
|
||||
LotterySettings::put(
|
||||
'settlement.auto_approve_on_tick',
|
||||
true,
|
||||
'settlement',
|
||||
'冷静期结束后自动结算批次是否由 tick 自动审核通过;false 时需人工审核',
|
||||
);
|
||||
|
||||
LotterySettings::put(
|
||||
'settlement.auto_payout_on_tick',
|
||||
true,
|
||||
'settlement',
|
||||
'结算批次审核通过后是否由 tick 自动派彩入账;false 时需人工执行 payout',
|
||||
);
|
||||
|
||||
LotterySettings::put(
|
||||
'settlement.apply_rebate_to_payout',
|
||||
false,
|
||||
|
||||
@@ -69,9 +69,7 @@ final class OperationalConfigV1Seeder extends Seeder
|
||||
'category' => $pt->category,
|
||||
'dimension' => $pt->dimension,
|
||||
'bet_mode' => $pt->bet_mode,
|
||||
'display_name_zh' => $pt->display_name_zh,
|
||||
'display_name_en' => $pt->display_name_en,
|
||||
'display_name_ne' => $pt->display_name_ne,
|
||||
'display_name' => $pt->display_name,
|
||||
'is_enabled' => (bool) $pt->is_enabled,
|
||||
'min_bet_amount' => 100,
|
||||
'max_bet_amount' => 500_000_000,
|
||||
|
||||
@@ -64,9 +64,7 @@ final class PlayOperationalAlignmentSeeder extends Seeder
|
||||
'category' => $pt->category,
|
||||
'dimension' => $pt->dimension,
|
||||
'bet_mode' => $pt->bet_mode,
|
||||
'display_name_zh' => $pt->display_name_zh,
|
||||
'display_name_en' => $pt->display_name_en,
|
||||
'display_name_ne' => $pt->display_name_ne,
|
||||
'display_name' => $pt->display_name,
|
||||
'is_enabled' => (bool) $pt->is_enabled,
|
||||
'min_bet_amount' => self::MIN_BET,
|
||||
'max_bet_amount' => self::MAX_BET,
|
||||
|
||||
@@ -79,9 +79,7 @@ final class PlayTypeSeeder extends Seeder
|
||||
'category' => $category,
|
||||
'dimension' => $dimension,
|
||||
'bet_mode' => $betMode,
|
||||
'display_name_zh' => $name,
|
||||
'display_name_en' => $name,
|
||||
'display_name_ne' => $name,
|
||||
'display_name' => $name,
|
||||
'is_enabled' => $isEnabled,
|
||||
'sort_order' => $sortOrder,
|
||||
'supports_multi_number' => $supportsMultiNumber,
|
||||
|
||||
Reference in New Issue
Block a user