Răsfoiți Sursa

完成宝箱系统后台菜单更新

1. 菜单结构调整
   - 在游戏系统设置->游戏物品管理下添加'宝箱配置管理'菜单
   - 在游戏运营管理->游戏物品管理下添加'奖励组保底计数'菜单
   - 隐藏已废弃的菜单项:宝箱消耗配置、宝箱内容、用户宝箱保底计数

2. 新增后台管理功能
   - 创建GameRewardGroupPityCountController控制器
   - 创建GameRewardGroupPityCountRepository仓库
   - 支持保底计数的查看和管理
   - 提供保底进度可视化显示

3. 菜单权限配置
   - 宝箱配置管理: /admin/game-items/chest-configs
   - 奖励组保底计数: /admin/game/reward-group-pity-counts
   - 保留宝箱开启记录查看功能

4. 使用MCP执行SQL完成菜单更新
   - 添加新菜单项到数据库
   - 标记废弃菜单为隐藏状态
   - 清理重复菜单项
notfff 7 luni în urmă
părinte
comite
bcadc62c4e

+ 150 - 0
app/Console/Commands/UpdateChestAdminMenu.php

@@ -0,0 +1,150 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Module\System\Models\AdminMenu;
+use Illuminate\Console\Command;
+
+class UpdateChestAdminMenu extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'admin:update-chest-menu';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '更新宝箱系统的后台管理菜单';
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $this->info('开始更新宝箱系统后台菜单...');
+
+        // 1. 在游戏物品管理(215)下添加宝箱配置管理菜单
+        $this->addChestConfigMenu();
+
+        // 2. 更新已废弃菜单的状态
+        $this->updateDeprecatedMenus();
+
+        // 3. 添加保底机制相关菜单
+        $this->addPityMenus();
+
+        $this->info('宝箱系统后台菜单更新完成!');
+        return 0;
+    }
+
+    /**
+     * 添加宝箱配置管理菜单
+     */
+    private function addChestConfigMenu()
+    {
+        // 获取游戏物品管理菜单ID
+        $gameItemsMenu = AdminMenu::where('title', '游戏物品管理')
+            ->where('parent_id', 259)
+            ->first();
+
+        if (!$gameItemsMenu) {
+            $this->error('未找到游戏物品管理菜单');
+            return;
+        }
+
+        // 获取当前最大order值
+        $maxOrder = AdminMenu::where('parent_id', $gameItemsMenu->id)->max('order');
+        $nextOrder = $maxOrder ? $maxOrder + 1 : 35;
+
+        // 创建宝箱配置管理菜单
+        $chestConfigMenu = AdminMenu::firstOrCreate(
+            [
+                'title' => '宝箱配置管理',
+                'parent_id' => $gameItemsMenu->id
+            ],
+            [
+                'uri' => 'game-items/chest-configs',
+                'icon' => 'fa-treasure-chest',
+                'order' => $nextOrder,
+                'show' => 1
+            ]
+        );
+
+        $this->info("✓ 添加宝箱配置管理菜单: {$chestConfigMenu->title}, ID: {$chestConfigMenu->id}");
+    }
+
+    /**
+     * 更新已废弃菜单的状态
+     */
+    private function updateDeprecatedMenus()
+    {
+        // 标记已废弃的菜单项(不删除,只是标记为不显示或添加说明)
+        $deprecatedMenus = [
+            '宝箱消耗配置' => 'game-items-chest-costs',
+            '宝箱内容' => 'game-items-chest-contents'
+        ];
+
+        foreach ($deprecatedMenus as $title => $uri) {
+            $menu = AdminMenu::where('title', $title)->where('uri', $uri)->first();
+            if ($menu) {
+                // 更新标题,添加废弃标记
+                $newTitle = $title . ' (已废弃)';
+                $menu->update([
+                    'title' => $newTitle,
+                    'show' => 0  // 隐藏菜单
+                ]);
+                $this->info("✓ 标记废弃菜单: {$title} -> {$newTitle}");
+            }
+        }
+    }
+
+    /**
+     * 添加保底机制相关菜单
+     */
+    private function addPityMenus()
+    {
+        // 在游戏运营管理 -> 游戏物品管理(423)下添加保底相关菜单
+        $gameItemsManageMenu = AdminMenu::where('id', 423)->first();
+
+        if (!$gameItemsManageMenu) {
+            $this->error('未找到游戏运营管理下的游戏物品管理菜单');
+            return;
+        }
+
+        // 获取当前最大order值
+        $maxOrder = AdminMenu::where('parent_id', $gameItemsManageMenu->id)->max('order');
+        $nextOrder = $maxOrder ? $maxOrder + 1 : 73;
+
+        // 创建奖励组保底计数菜单
+        $pityCountMenu = AdminMenu::firstOrCreate(
+            [
+                'title' => '奖励组保底计数',
+                'parent_id' => $gameItemsManageMenu->id
+            ],
+            [
+                'uri' => 'game/reward-group-pity-counts',
+                'icon' => 'fa-chart-line',
+                'order' => $nextOrder,
+                'show' => 1
+            ]
+        );
+
+        $this->info("✓ 添加奖励组保底计数菜单: {$pityCountMenu->title}, ID: {$pityCountMenu->id}");
+
+        // 更新原有的"用户宝箱保底计数"菜单标题
+        $oldPityMenu = AdminMenu::where('title', '用户宝箱保底计数')->first();
+        if ($oldPityMenu) {
+            $oldPityMenu->update([
+                'title' => '用户宝箱保底计数 (旧系统)',
+                'show' => 0  // 隐藏旧系统菜单
+            ]);
+            $this->info("✓ 更新旧保底菜单: 用户宝箱保底计数 -> 用户宝箱保底计数 (旧系统)");
+        }
+    }
+}

+ 1 - 1
app/Module/Game/AdminControllers/GameConsumeItemController.php

@@ -214,7 +214,7 @@ class GameConsumeItemController extends AdminController
                         return Item::pluck('name', 'id')->toArray();
                     } elseif ($conditionType == CONSUME_TYPE::CURRENCY->value) {
                         return FundCurrencyModel::pluck('name', 'id')->toArray();
-                    } elseif ($conditionType == CONSUME_TYPE::FUND->value) {
+                    } elseif ($conditionType == CONSUME_TYPE::FUND_CONFIG->value) {
                         return FundConfigModel::pluck('name', 'id')->toArray();
                     }
 

+ 58 - 0
app/Module/Game/AdminControllers/GameRewardGroupPityCountController.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace App\Module\Game\AdminControllers;
+
+use App\Module\Game\AdminRepositories\GameRewardGroupPityCountRepository;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use UCore\DcatAdmin\AdminController;
+
+/**
+ * 奖励组保底计数控制器
+ * 
+ * 路由: /admin/game/reward-group-pity-counts
+ */
+class GameRewardGroupPityCountController extends AdminController
+{
+    /**
+     * 获取仓库实例
+     *
+     * @return GameRewardGroupPityCountRepository
+     */
+    protected function repository(): GameRewardGroupPityCountRepository
+    {
+        return new GameRewardGroupPityCountRepository();
+    }
+
+    /**
+     * 列表页面
+     *
+     * @return Grid
+     */
+    protected function grid(): Grid
+    {
+        return $this->repository()->grid();
+    }
+
+    /**
+     * 详情页面
+     *
+     * @param mixed $id
+     * @return Show
+     */
+    protected function detail($id): Show
+    {
+        return $this->repository()->detail($id);
+    }
+
+    /**
+     * 表单页面
+     *
+     * @return Form
+     */
+    protected function form(): Form
+    {
+        return $this->repository()->form();
+    }
+}

+ 206 - 0
app/Module/Game/AdminRepositories/GameRewardGroupPityCountRepository.php

@@ -0,0 +1,206 @@
+<?php
+
+namespace App\Module\Game\AdminRepositories;
+
+use App\Module\Game\Models\GameRewardGroup;
+use App\Module\Game\Models\GameRewardGroupPityCount;
+use App\Module\Game\Models\GameRewardItem;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use UCore\DcatAdmin\GridHelper;
+use UCore\DcatAdmin\ShowHelper;
+use UCore\DcatAdmin\FormHelper;
+use UCore\DcatAdmin\FilterHelper;
+
+/**
+ * 奖励组保底计数仓库
+ */
+class GameRewardGroupPityCountRepository
+{
+    /**
+     * 列表页面
+     *
+     * @return Grid
+     */
+    public function grid(): Grid
+    {
+        return Grid::make(GameRewardGroupPityCount::with(['user', 'rewardGroup', 'rewardItem']), function (Grid $grid) {
+            $grid->column('id', 'ID')->sortable();
+            
+            $grid->column('user.username', '用户名')
+                ->link(function ($value) {
+                    return admin_url("users/{$this->user_id}");
+                });
+            
+            $grid->column('user_id', '用户ID')->sortable();
+            
+            $grid->column('rewardGroup.name', '奖励组')
+                ->link(function ($value) {
+                    return admin_url("game/reward-groups/{$this->reward_group_id}");
+                });
+            
+            $grid->column('rewardItem.name', '奖励项')
+                ->display(function () {
+                    if ($this->rewardItem) {
+                        return $this->rewardItem->name;
+                    }
+                    return '未知奖励项';
+                });
+            
+            $grid->column('count', '当前计数')
+                ->display(function ($value) {
+                    $threshold = $this->pity_threshold;
+                    $percentage = $threshold > 0 ? round(($value / $threshold) * 100, 1) : 0;
+                    $color = $percentage >= 80 ? 'danger' : ($percentage >= 50 ? 'warning' : 'success');
+                    return "<span class='badge badge-{$color}'>{$value} ({$percentage}%)</span>";
+                });
+            
+            $grid->column('pity_threshold', '保底阈值')->sortable();
+            
+            $grid->column('progress', '保底进度')
+                ->display(function () {
+                    if ($this->pity_threshold <= 0) {
+                        return '<span class="text-muted">未启用</span>';
+                    }
+                    
+                    $percentage = round(($this->count / $this->pity_threshold) * 100, 1);
+                    $color = $percentage >= 100 ? 'success' : ($percentage >= 80 ? 'warning' : 'info');
+                    
+                    return "<div class='progress' style='height: 20px;'>
+                        <div class='progress-bar bg-{$color}' style='width: {$percentage}%'>
+                            {$percentage}%
+                        </div>
+                    </div>";
+                });
+            
+            $grid->column('last_attempt_at', '最后尝试时间')
+                ->display(function ($value) {
+                    return $value ? $value->format('Y-m-d H:i:s') : '-';
+                });
+            
+            $grid->column('last_hit_at', '最后命中时间')
+                ->display(function ($value) {
+                    return $value ? $value->format('Y-m-d H:i:s') : '-';
+                });
+            
+            $grid->column('created_at', '创建时间')->sortable();
+            $grid->column('updated_at', '更新时间')->sortable();
+
+            // 筛选器
+            $grid->filter(function (Grid\Filter $filter) {
+                FilterHelper::defaultDateRange($filter);
+                
+                $filter->equal('user_id', '用户ID');
+                $filter->like('user.username', '用户名');
+                
+                $filter->equal('reward_group_id', '奖励组')
+                    ->select(GameRewardGroup::pluck('name', 'id'));
+                
+                $filter->between('count', '当前计数');
+                $filter->between('pity_threshold', '保底阈值');
+                
+                $filter->where(function ($query) {
+                    $query->whereRaw('count >= pity_threshold');
+                }, '已达保底', 'reached_pity')->checkbox();
+            });
+
+            // 工具栏
+            GridHelper::defaultToolbar($grid);
+            
+            // 禁用新增和编辑(这些记录由系统自动管理)
+            $grid->disableCreateButton();
+            $grid->disableEditButton();
+            
+            // 只允许查看详情
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->disableEdit();
+                $actions->disableDelete();
+            });
+
+            // 排序
+            $grid->model()->orderBy('updated_at', 'desc');
+        });
+    }
+
+    /**
+     * 详情页面
+     *
+     * @param mixed $id
+     * @return Show
+     */
+    public function detail($id): Show
+    {
+        return Show::make($id, GameRewardGroupPityCount::with(['user', 'rewardGroup', 'rewardItem']), function (Show $show) {
+            ShowHelper::defaultShow($show);
+
+            $show->field('id', 'ID');
+            
+            $show->field('user.username', '用户名')
+                ->link(function ($value) {
+                    return admin_url("users/{$this->user_id}");
+                });
+            
+            $show->field('user_id', '用户ID');
+            
+            $show->field('rewardGroup.name', '奖励组')
+                ->link(function ($value) {
+                    return admin_url("game/reward-groups/{$this->reward_group_id}");
+                });
+            
+            $show->field('rewardItem.name', '奖励项');
+            
+            $show->field('count', '当前计数');
+            $show->field('pity_threshold', '保底阈值');
+            
+            $show->field('progress', '保底进度')
+                ->as(function () {
+                    if ($this->pity_threshold <= 0) {
+                        return '未启用保底机制';
+                    }
+                    
+                    $percentage = round(($this->count / $this->pity_threshold) * 100, 1);
+                    $status = $percentage >= 100 ? '已达保底' : '未达保底';
+                    
+                    return "{$percentage}% ({$status})";
+                });
+            
+            $show->field('last_attempt_at', '最后尝试时间');
+            $show->field('last_hit_at', '最后命中时间');
+            $show->field('created_at', '创建时间');
+            $show->field('updated_at', '更新时间');
+
+            // 禁用编辑和删除
+            $show->disableEditButton();
+            $show->disableDeleteButton();
+        });
+    }
+
+    /**
+     * 表单页面(仅用于查看,不允许编辑)
+     *
+     * @return Form
+     */
+    public function form(): Form
+    {
+        return Form::make(GameRewardGroupPityCount::class, function (Form $form) {
+            FormHelper::defaultForm($form);
+
+            $form->display('id', 'ID');
+            $form->display('user_id', '用户ID');
+            $form->display('reward_group_id', '奖励组ID');
+            $form->display('reward_item_id', '奖励项ID');
+            $form->display('count', '当前计数');
+            $form->display('pity_threshold', '保底阈值');
+            $form->display('last_attempt_at', '最后尝试时间');
+            $form->display('last_hit_at', '最后命中时间');
+            $form->display('created_at', '创建时间');
+            $form->display('updated_at', '更新时间');
+
+            // 禁用所有操作
+            $form->disableCreatingCheck();
+            $form->disableEditingCheck();
+            $form->disableViewCheck();
+        });
+    }
+}

+ 1 - 1
app/Module/Game/Enums/CONSUME_TYPE.php

@@ -48,7 +48,7 @@ enum CONSUME_TYPE: int
         return [
             self::ITEM->value        => '物品',
             self::FUND_CONFIG->value => '账户种类',
-            self::CURRENCY->value    => '币种',
+            self::CURRENCY->value    => '币种(CURRENCY)',
         ];
     }