GameRewardGroupController.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <?php
  2. namespace App\Module\Game\AdminControllers;
  3. use App\Module\Game\AdminControllers\Actions\DuplicateRewardGroupAction;
  4. use App\Module\Game\AdminControllers\Actions\RandomRewardAction;
  5. use App\Module\Game\AdminControllers\Actions\BatchRandomRewardAction;
  6. use App\Module\Game\Enums\REWARD_TYPE;
  7. use App\Module\Game\Enums\REWARD_MODE;
  8. use App\Module\Game\Models\GameRewardGroup;
  9. use App\Module\Game\Models\GameRewardItem;
  10. use App\Module\Game\Repositorys\GameRewardGroupRepository;
  11. use App\Module\GameItems\Models\Item;
  12. use App\Module\Fund\Models\FundCurrencyModel;
  13. use Dcat\Admin\Form;
  14. use Dcat\Admin\Grid;
  15. use Dcat\Admin\Show;
  16. use Dcat\Admin\Http\Controllers\AdminController;
  17. use Spatie\RouteAttributes\Attributes\Resource;
  18. use UCore\Helper\Color;
  19. /**
  20. * 奖励组管理控制器
  21. */
  22. #[Resource('game-reward-groups', names: 'dcat.admin.game-reward-groups')]
  23. class GameRewardGroupController extends AdminController
  24. {
  25. /**
  26. * 标题
  27. *
  28. * @return string
  29. */
  30. protected function title()
  31. {
  32. return '奖励组管理';
  33. }
  34. /**
  35. * 创建表格
  36. *
  37. * @return Grid
  38. */
  39. protected function grid()
  40. {
  41. return Grid::make(new GameRewardGroupRepository(), function (Grid $grid) {
  42. // 预加载奖励项和标签关联数据
  43. $grid->model()->with(['rewardItems', 'tags']);
  44. $grid->column('id', 'ID')->sortable();
  45. $grid->column('name', '名称');
  46. $grid->column('code', '编码');
  47. $grid->column('description', '描述')->limit(30);
  48. $grid->column('is_random', '随机发放')->bool();
  49. $grid->column('random_count', '随机数量');
  50. $grid->column('reward_mode', '奖励模式')->display(function ($value) {
  51. return REWARD_MODE::getName($value ?? 1);
  52. });
  53. // 标签列
  54. $grid->column('tags', '标签')->display(function () {
  55. return $this->formatTags();
  56. })->width(200);
  57. // 奖励详情列
  58. $grid->column('reward_details', '奖励详情')->display(function () {
  59. return $this->formatRewardDetails();
  60. })->width(300);
  61. $grid->column('created_at', '创建时间');
  62. $grid->column('updated_at', '更新时间');
  63. $grid->filter(function (Grid\Filter $filter) {
  64. $filter->equal('id', 'ID');
  65. $filter->like('name', '名称');
  66. $filter->like('code', '编码');
  67. $filter->equal('is_random', '随机发放')->select([0 => '否', 1 => '是']);
  68. $filter->equal('reward_mode', '奖励模式')->select(REWARD_MODE::getAll());
  69. // 标签筛选
  70. $tagRepository = new \App\Module\Game\Repositorys\GameTagRepository();
  71. $filter->whereHas('tags', '标签', function ($query) {
  72. $query->where('id', request('tags'));
  73. })->select($tagRepository->getActiveTagOptions());
  74. });
  75. // 使用 RowAction 类添加行操作按钮
  76. $grid->actions(function (Grid\Displayers\Actions $actions) {
  77. // 添加复制按钮
  78. $actions->append(new DuplicateRewardGroupAction());
  79. // 添加随机奖励按钮
  80. $actions->append(new RandomRewardAction());
  81. $actions->append(new BatchRandomRewardAction(10));
  82. $actions->append(new BatchRandomRewardAction(100));
  83. $actions->disableDelete();
  84. });
  85. });
  86. }
  87. /**
  88. * 创建详情页
  89. *
  90. * @param mixed $id
  91. * @return Show
  92. */
  93. protected function detail($id)
  94. {
  95. return Show::make($id, new GameRewardGroupRepository(['tags']), function (Show $show) use ($id) {
  96. $show->field('id', 'ID');
  97. $show->field('name', '名称');
  98. $show->field('code', '编码');
  99. $show->field('description', '描述');
  100. $show->field('is_random', '随机发放')->using([0 => '否', 1 => '是']);
  101. $show->field('random_count', '随机数量');
  102. $show->field('reward_mode', '奖励模式')->as(function ($value) {
  103. return REWARD_MODE::getName($value ?? 1);
  104. });
  105. // 标签显示
  106. $show->field('tags', '标签')->as(function ($tags) {
  107. if (empty($tags)) {
  108. return '<span class="text-muted">无标签</span>';
  109. }
  110. $tagHtml = [];
  111. foreach ($tags as $tag) {
  112. $tagHtml[] = sprintf(
  113. '<span class="badge" style="background-color: %s; color: %s;">%s</span>',
  114. $tag['color'],
  115. Color::getContrastColor($tag['coler']),
  116. $tag['name']
  117. );
  118. }
  119. return implode(' ', $tagHtml);
  120. });
  121. $show->field('created_at', '创建时间');
  122. $show->field('updated_at', '更新时间');
  123. // 显示奖励项
  124. $show->divider();
  125. $show->field('reward_items', '奖励项')->unescape()->as(function () use ($id) {
  126. // 获取奖励组及其奖励项
  127. $group = GameRewardGroup::with('rewardItems')->find($id);
  128. if (!$group || $group->rewardItems->isEmpty()) {
  129. return '<span class="text-muted">暂无奖励项</span>';
  130. }
  131. $html = '<div class="reward-items-list">';
  132. foreach ($group->rewardItems as $item) {
  133. // 使用统一的奖励类型描述器
  134. $displayText = \App\Module\Game\Services\RewardTypeDescriptor::formatRewardDisplayFromModel($item, true);
  135. $weight = $item->weight;
  136. $guaranteed = $item->is_guaranteed ? '必中' : '非必中';
  137. $html .= '<div class="reward-item mb-2 p-2 border rounded">';
  138. $html .= $displayText;
  139. $html .= '<br><small class="text-muted">';
  140. $html .= '权重: ' . $weight . ' | ' . $guaranteed;
  141. // 显示概率信息(如果有)
  142. if ($item->probability !== null) {
  143. $html .= ' | 概率: ' . $item->probability . '%';
  144. }
  145. // 显示随机数量范围信息
  146. if ($item->min_quantity !== null || $item->max_quantity !== null) {
  147. $html .= ' | 随机数量: ';
  148. if ($item->min_quantity !== null && $item->max_quantity !== null) {
  149. $html .= $item->min_quantity . '-' . $item->max_quantity;
  150. } elseif ($item->min_quantity !== null) {
  151. $html .= $item->min_quantity . '+';
  152. } elseif ($item->max_quantity !== null) {
  153. $html .= '1-' . $item->max_quantity;
  154. }
  155. }
  156. if ($item->param1 || $item->param2) {
  157. $html .= ' | 参数: ' . $item->param1 . ',' . $item->param2;
  158. }
  159. $html .= '</small>';
  160. $html .= '</div>';
  161. }
  162. $html .= '</div>';
  163. // 添加管理链接
  164. $html .= '<div class="mt-3">';
  165. $html .= '<a href="' . admin_url('game-reward-items?group_id=' . $id) . '" target="_blank" class="btn btn-sm btn-primary">';
  166. $html .= '<i class="fa fa-list"></i> 管理奖励项';
  167. $html .= '</a>';
  168. $html .= '</div>';
  169. return $html;
  170. });
  171. });
  172. }
  173. /**
  174. * 获取奖励类型名称
  175. *
  176. * @param int $rewardType 奖励类型
  177. * @return string 奖励类型名称
  178. */
  179. public function getRewardTypeName(int $rewardType): string
  180. {
  181. switch ($rewardType) {
  182. case REWARD_TYPE::ITEM->value:
  183. return '物品';
  184. case REWARD_TYPE::CURRENCY->value:
  185. return '货币';
  186. case REWARD_TYPE::PET_EXP->value:
  187. return '宠物经验';
  188. case REWARD_TYPE::PET_ENERGY->value:
  189. return '宠物体力';
  190. case REWARD_TYPE::OTHER->value:
  191. return '其他';
  192. default:
  193. return '未知';
  194. }
  195. }
  196. /**
  197. * 根据奖励项获取实际内容描述
  198. *
  199. * @param GameRewardItem $item 奖励项
  200. * @return string 奖励内容描述
  201. */
  202. public function getRewardContent(GameRewardItem $item): string
  203. {
  204. switch ($item->reward_type) {
  205. case REWARD_TYPE::ITEM->value:
  206. // 物品奖励
  207. try {
  208. $gameItem = Item::find($item->target_id);
  209. if ($gameItem) {
  210. $content = "<strong>{$gameItem->name}</strong> (ID: {$item->target_id})";
  211. // 添加参数说明
  212. $params = [];
  213. if ($item->param1 > 0) {
  214. $params[] = "品质: {$item->param1}";
  215. }
  216. if ($item->param2 > 0) {
  217. $params[] = "绑定: {$item->param2}";
  218. }
  219. if (!empty($params)) {
  220. $content .= "<br><small>" . implode(', ', $params) . "</small>";
  221. }
  222. return $content;
  223. }
  224. } catch (\Exception $e) {
  225. // 忽略异常,返回默认内容
  226. }
  227. return "物品 (ID: {$item->target_id})";
  228. case REWARD_TYPE::CURRENCY->value:
  229. // 货币奖励
  230. try {
  231. $currency = FundCurrencyModel::find($item->target_id);
  232. if ($currency) {
  233. $content = "<strong>{$currency->name}</strong> (ID: {$item->target_id})";
  234. // 添加参数说明
  235. $params = [];
  236. if ($item->param1 > 0) {
  237. $params[] = "来源: {$item->param1}";
  238. }
  239. if (!empty($params)) {
  240. $content .= "<br><small>" . implode(', ', $params) . "</small>";
  241. }
  242. return $content;
  243. }
  244. } catch (\Exception $e) {
  245. // 忽略异常,返回默认内容
  246. }
  247. return "货币 (ID: {$item->target_id})";
  248. case REWARD_TYPE::PET_EXP->value:
  249. // 宠物经验奖励
  250. return "宠物经验 (宠物ID: {$item->target_id})";
  251. case REWARD_TYPE::PET_ENERGY->value:
  252. // 宠物体力奖励
  253. return "宠物体力 (宠物ID: {$item->target_id})";
  254. case REWARD_TYPE::FARM_SHRINE->value:
  255. // 神像奖励(农场buff)
  256. try {
  257. $shrineName = \App\Module\Farm\Enums\BUFF_TYPE::getName($item->target_id);
  258. $durationHours = $item->param2 > 0 ? $item->param2 : 24;
  259. $content = "<strong>{$shrineName}</strong> (类型: {$item->target_id})";
  260. $content .= "<br><small>持续时间: {$durationHours}小时</small>";
  261. // 添加参数说明
  262. $params = [];
  263. if ($item->param1 > 0) {
  264. $params[] = "神像类型: {$item->param1}";
  265. }
  266. if ($item->param2 > 0) {
  267. $params[] = "持续时间: {$item->param2}小时";
  268. }
  269. if (!empty($params)) {
  270. $content .= "<br><small>" . implode(', ', $params) . "</small>";
  271. }
  272. return $content;
  273. } catch (\Exception $e) {
  274. return "神像 (类型: {$item->target_id})";
  275. }
  276. case REWARD_TYPE::OTHER->value:
  277. // 其他奖励
  278. return "其他奖励 (ID: {$item->target_id})";
  279. default:
  280. return "未知奖励类型 (ID: {$item->target_id})";
  281. }
  282. }
  283. /**
  284. * 创建表单
  285. *
  286. * @return Form
  287. */
  288. protected function form()
  289. {
  290. return Form::make(new GameRewardGroupRepository(['tags']), function (Form $form) {
  291. $form->display('id', 'ID');
  292. $form->text('name', '名称')->required();
  293. $form->text('code', '编码')->required()->rules('required|alpha_dash|unique:game_reward_groups,code,' . $form->getKey());
  294. $form->textarea('description', '描述');
  295. $form->switch('is_random', '随机发放')->default(0);
  296. $form->number('random_count', '随机数量')->default(1)->min(1)->help('随机发放时的奖励数量,仅当随机发放开启时有效');
  297. $form->select('reward_mode', '奖励模式')
  298. ->options(REWARD_MODE::getAll())
  299. ->default(REWARD_MODE::WEIGHT_SELECTION->value)
  300. ->help('权重选择模式:传统的权重选择机制;独立概率模式:每个奖励项独立判断是否获得');
  301. // 标签选择
  302. $tagRepository = new \App\Module\Game\Repositorys\GameTagRepository();
  303. $form->multipleSelect('tags', '标签')
  304. ->options($tagRepository->getActiveTagOptions())
  305. ->help('可以选择多个标签来分类管理奖励组');
  306. $form->display('created_at', '创建时间');
  307. $form->display('updated_at', '更新时间');
  308. // 添加提示信息,告知用户如何管理奖励项
  309. if ($form->isEditing()) {
  310. $id = $form->getKey();
  311. $form->html('<div class="alert alert-info">
  312. <p><i class="fa fa-info-circle"></i> 奖励项管理已移至单独页面,请保存当前表单后使用以下链接管理奖励项:</p>
  313. <a href="'.admin_url('game-reward-items?group_id='.$id).'" class="btn btn-primary" target="_blank">
  314. <i class="fa fa-list"></i> 管理奖励项
  315. </a>
  316. </div>');
  317. } else {
  318. $form->html('<div class="alert alert-info">
  319. <p><i class="fa fa-info-circle"></i> 奖励项管理已移至单独页面,请先保存当前表单,然后才能添加奖励项。</p>
  320. </div>');
  321. }
  322. });
  323. }
  324. /**
  325. * 格式化数量文本
  326. *
  327. * @param GameRewardItem $item
  328. * @return string
  329. */
  330. private function formatQuantityText(GameRewardItem $item): string
  331. {
  332. // 如果设置了最小和最大数量,显示范围
  333. if ($item->min_quantity !== null && $item->max_quantity !== null) {
  334. if ($item->min_quantity == $item->max_quantity) {
  335. return (string)$item->min_quantity;
  336. } else {
  337. return $item->min_quantity . '-' . $item->max_quantity;
  338. }
  339. }
  340. // 如果只设置了最小数量
  341. if ($item->min_quantity !== null) {
  342. return $item->min_quantity . '+';
  343. }
  344. // 如果只设置了最大数量
  345. if ($item->max_quantity !== null) {
  346. return '1-' . $item->max_quantity;
  347. }
  348. // 默认使用固定数量
  349. return (string)$item->quantity;
  350. }
  351. }