ShowHelperTrait.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. <?php
  2. namespace App\Module\Task\AdminControllers\Helper;
  3. use App\Module\Task\Enums\RESET_TYPE;
  4. use App\Module\Task\Enums\REWARD_TYPE;
  5. use App\Module\Task\Enums\TASK_STATUS;
  6. use App\Module\Task\Enums\TASK_TYPE;
  7. use App\Module\Task\Models\Task;
  8. use App\Module\Task\Models\TaskCategory;
  9. use Dcat\Admin\Grid;
  10. use Dcat\Admin\Show;
  11. /**
  12. * 详情页辅助特性
  13. *
  14. * 提供任务模块后台控制器的详情页构建功能
  15. */
  16. trait ShowHelperTrait
  17. {
  18. /**
  19. * 显示ID字段
  20. *
  21. * @param string $field 字段名
  22. * @param string $label 标签
  23. * @return Show\Field
  24. */
  25. public function fieldId(string $field = 'id', string $label = 'ID')
  26. {
  27. return $this->show->field($field, $label);
  28. }
  29. /**
  30. * 显示名称字段
  31. *
  32. * @param string $field 字段名
  33. * @param string $label 标签
  34. * @return Show\Field
  35. */
  36. public function fieldName(string $field = 'name', string $label = '名称')
  37. {
  38. return $this->show->field($field, $label);
  39. }
  40. /**
  41. * 显示描述字段
  42. *
  43. * @param string $field 字段名
  44. * @param string $label 标签
  45. * @return Show\Field
  46. */
  47. public function fieldDescription(string $field = 'description', string $label = '描述')
  48. {
  49. return $this->show->field($field, $label);
  50. }
  51. /**
  52. * 显示父级分类字段
  53. *
  54. * @param string $field 字段名
  55. * @param string $label 标签
  56. * @return Show\Field
  57. */
  58. public function fieldParentCategory(string $field = 'parent_id', string $label = '父级分类')
  59. {
  60. return $this->show->field($field, $label)->as(function ($parentId) {
  61. if ($parentId == 0) {
  62. return '无';
  63. }
  64. $parent = TaskCategory::find($parentId);
  65. return $parent ? $parent->name : '未知';
  66. });
  67. }
  68. /**
  69. * 显示排序权重字段
  70. *
  71. * @param string $field 字段名
  72. * @param string $label 标签
  73. * @return Show\Field
  74. */
  75. public function fieldSortOrder(string $field = 'sort_order', string $label = '排序权重')
  76. {
  77. return $this->show->field($field, $label);
  78. }
  79. /**
  80. * 显示是否激活字段
  81. *
  82. * @param string $field 字段名
  83. * @param string $label 标签
  84. * @return Show\Field
  85. */
  86. public function fieldIsActive(string $field = 'is_active', string $label = '是否激活')
  87. {
  88. return $this->show->field($field, $label)->as(function ($isActive) {
  89. return $isActive ? '是' : '否';
  90. });
  91. }
  92. /**
  93. * 显示创建时间字段
  94. *
  95. * @param string $field 字段名
  96. * @param string $label 标签
  97. * @return Show\Field
  98. */
  99. public function fieldCreatedAt(string $field = 'created_at', string $label = '创建时间')
  100. {
  101. return $this->show->field($field, $label);
  102. }
  103. /**
  104. * 显示更新时间字段
  105. *
  106. * @param string $field 字段名
  107. * @param string $label 标签
  108. * @return Show\Field
  109. */
  110. public function fieldUpdatedAt(string $field = 'updated_at', string $label = '更新时间')
  111. {
  112. return $this->show->field($field, $label);
  113. }
  114. /**
  115. * 显示任务类型字段
  116. *
  117. * @param string $field 字段名
  118. * @param string $label 标签
  119. * @return Show\Field
  120. */
  121. public function fieldTaskType(string $field = 'type', string $label = '任务类型')
  122. {
  123. return $this->show->field($field, $label)->as(function ($type) {
  124. return TASK_TYPE::getDescription(TASK_TYPE::tryFrom($type) ?? TASK_TYPE::DAILY);
  125. });
  126. }
  127. /**
  128. * 显示重置类型字段
  129. *
  130. * @param string $field 字段名
  131. * @param string $label 标签
  132. * @return Show\Field
  133. */
  134. public function fieldResetType(string $field = 'reset_type', string $label = '重置类型')
  135. {
  136. return $this->show->field($field, $label)->as(function ($resetType) {
  137. return RESET_TYPE::getDescription(RESET_TYPE::tryFrom($resetType) ?? RESET_TYPE::NONE);
  138. });
  139. }
  140. /**
  141. * 显示任务状态字段
  142. *
  143. * @param string $field 字段名
  144. * @param string $label 标签
  145. * @return Show\Field
  146. */
  147. public function fieldTaskStatus(string $field = 'status', string $label = '任务状态')
  148. {
  149. return $this->show->field($field, $label)->as(function ($status) {
  150. return TASK_STATUS::getDescription(TASK_STATUS::from($status));
  151. });
  152. }
  153. /**
  154. * 显示奖励类型字段
  155. *
  156. * @param string $field 字段名
  157. * @param string $label 标签
  158. * @return Show\Field
  159. */
  160. public function fieldRewardType(string $field = 'reward_type', string $label = '奖励类型')
  161. {
  162. return $this->show->field($field, $label)->as(function ($rewardType) {
  163. return REWARD_TYPE::getDescription(REWARD_TYPE::tryFrom($rewardType) ?? REWARD_TYPE::ITEM);
  164. });
  165. }
  166. /**
  167. * 显示条件类型字段
  168. *
  169. * @param string $field 字段名
  170. * @param string $label 标签
  171. * @return Show\Field
  172. */
  173. public function fieldConditionType(string $field = 'condition_type', string $label = '条件类型')
  174. {
  175. return $this->show->field($field, $label)->as(function ($type) {
  176. return $type == 'prerequisite' ? '前置条件' : '进度条件';
  177. });
  178. }
  179. /**
  180. * 显示是否必要条件字段
  181. *
  182. * @param string $field 字段名
  183. * @param string $label 标签
  184. * @return Show\Field
  185. */
  186. public function fieldIsRequired(string $field = 'is_required', string $label = '是否必要条件')
  187. {
  188. return $this->show->field($field, $label)->as(function ($isRequired) {
  189. return $isRequired ? '是' : '否';
  190. });
  191. }
  192. /**
  193. * 显示JSON字段
  194. *
  195. * @param string $field 字段名
  196. * @param string $label 标签
  197. * @return Show\Field
  198. */
  199. public function fieldJson(string $field, string $label)
  200. {
  201. return $this->show->field($field, $label)->json();
  202. }
  203. /**
  204. * 显示前置任务字段
  205. *
  206. * @param string $field 字段名
  207. * @param string $label 标签
  208. * @return Show\Field
  209. */
  210. public function fieldPrerequisiteTasks(string $field = 'prerequisite_tasks', string $label = '前置任务')
  211. {
  212. return $this->show->field($field, $label)->as(function ($prerequisiteTasks) {
  213. if (empty($prerequisiteTasks)) {
  214. return '无';
  215. }
  216. $tasks = Task::whereIn('id', $prerequisiteTasks)->pluck('name', 'id')->toArray();
  217. $result = [];
  218. foreach ($prerequisiteTasks as $taskId) {
  219. $result[] = $tasks[$taskId] ?? "任务#{$taskId}";
  220. }
  221. return implode('<br>', $result);
  222. });
  223. }
  224. /**
  225. * 显示时间限制字段
  226. *
  227. * @param string $field 字段名
  228. * @param string $label 标签
  229. * @return Show\Field
  230. */
  231. public function fieldTimeLimit(string $field = 'time_limit', string $label = '时间限制(秒)')
  232. {
  233. return $this->show->field($field, $label)->as(function ($timeLimit) {
  234. return $timeLimit ? $timeLimit . '秒' : '无限制';
  235. });
  236. }
  237. /**
  238. * 显示最大完成次数字段
  239. *
  240. * @param string $field 字段名
  241. * @param string $label 标签
  242. * @return Show\Field
  243. */
  244. public function fieldMaxCompletions(string $field = 'max_completions', string $label = '最大完成次数')
  245. {
  246. return $this->show->field($field, $label)->as(function ($maxCompletions) {
  247. return $maxCompletions ? $maxCompletions : '无限制';
  248. });
  249. }
  250. /**
  251. * 显示进度字段
  252. *
  253. * @param string $field 字段名
  254. * @param string $label 标签
  255. * @return Show\Field
  256. */
  257. public function fieldProgress(string $field = 'progress', string $label = '进度')
  258. {
  259. return $this->show->field($field, $label)->as(function ($progress) {
  260. return $progress . '%';
  261. });
  262. }
  263. /**
  264. * 显示计算的进度字段
  265. *
  266. * @param string $currentField 当前值字段名
  267. * @param string $targetField 目标值字段名
  268. * @param string $label 标签
  269. * @return Show\Field
  270. */
  271. public function fieldCalculatedProgress(string $currentField = 'current_value', string $targetField = 'target_value', string $label = '进度')
  272. {
  273. return $this->show->field('progress', $label)->as(function () use ($currentField, $targetField) {
  274. $current = $this->{$currentField};
  275. $target = $this->{$targetField};
  276. $progress = $target > 0 ? min(100, round(($current / $target) * 100)) : 0;
  277. return $progress . '%';
  278. });
  279. }
  280. /**
  281. * 显示奖励内容字段
  282. *
  283. * @param string $field 字段名
  284. * @param string $label 标签
  285. * @return Show\Field
  286. */
  287. public function fieldRewards(string $field = 'rewards', string $label = '奖励内容')
  288. {
  289. return $this->show->field($field, $label)->as(function ($rewards) {
  290. $result = [];
  291. foreach ($rewards as $reward) {
  292. $type = REWARD_TYPE::getDescription(REWARD_TYPE::tryFrom($reward['reward_type']) ?? REWARD_TYPE::ITEM);
  293. $result[] = "{$type}: {$reward['quantity']}";
  294. }
  295. return implode('<br>', $result);
  296. });
  297. }
  298. /**
  299. * 显示消耗内容字段
  300. *
  301. * @param string $field 字段名
  302. * @param string $label 标签
  303. * @return Show\Field
  304. */
  305. public function fieldCosts(string $field = 'costs', string $label = '消耗内容')
  306. {
  307. return $this->show->field($field, $label)->as(function ($costs) {
  308. $result = [];
  309. foreach ($costs as $cost) {
  310. $result[] = "{$cost['cost_type']}: {$cost['quantity']}";
  311. }
  312. return implode('<br>', $result);
  313. });
  314. }
  315. /**
  316. * 显示任务奖励关联
  317. *
  318. * @param string $relation 关联名称
  319. * @param string $label 标签
  320. * @param callable $callback 回调函数
  321. * @return void
  322. */
  323. public function showRewards(string $relation = 'rewards', string $label = '任务奖励', callable $callback = null)
  324. {
  325. $this->show->relation($relation, $label, function ($model) use ($callback) {
  326. $grid = new Grid(new \App\Module\Task\Models\TaskReward);
  327. $grid->model()->where('task_id', $model->id);
  328. $grid->column('id', 'ID');
  329. $grid->column('reward_type', '奖励类型')->display(function ($rewardType) {
  330. return REWARD_TYPE::getDescription(REWARD_TYPE::tryFrom($rewardType) ?? REWARD_TYPE::ITEM);
  331. });
  332. $grid->column('reward_param1', '奖励参数1');
  333. $grid->column('reward_param2', '奖励参数2');
  334. $grid->column('quantity', '奖励数量');
  335. $grid->column('extra_data', '额外数据')->json();
  336. $grid->column('sort_order', '排序权重');
  337. $grid->disableCreateButton();
  338. $grid->disableActions();
  339. $grid->disableBatchDelete();
  340. $grid->disableRowSelector();
  341. if ($callback) {
  342. $callback($grid);
  343. }
  344. return $grid;
  345. });
  346. }
  347. /**
  348. * 显示任务接取消耗关联
  349. *
  350. * @param string $relation 关联名称
  351. * @param string $label 标签
  352. * @param callable $callback 回调函数
  353. * @return void
  354. */
  355. public function showCosts(string $relation = 'costs', string $label = '任务接取消耗', callable $callback = null)
  356. {
  357. $this->show->relation($relation, $label, function ($model) use ($callback) {
  358. $grid = new Grid(new \App\Module\Task\Models\TaskCost);
  359. $grid->model()->where('task_id', $model->id);
  360. $grid->column('id', 'ID');
  361. $grid->column('cost_type', '消耗类型');
  362. $grid->column('cost_param1', '消耗参数1');
  363. $grid->column('cost_param2', '消耗参数2');
  364. $grid->column('quantity', '消耗数量');
  365. $grid->column('extra_data', '额外数据')->json();
  366. $grid->disableCreateButton();
  367. $grid->disableActions();
  368. $grid->disableBatchDelete();
  369. $grid->disableRowSelector();
  370. if ($callback) {
  371. $callback($grid);
  372. }
  373. return $grid;
  374. });
  375. }
  376. /**
  377. * 显示任务达成条件关联
  378. *
  379. * @param string $relation 关联名称
  380. * @param string $label 标签
  381. * @param callable $callback 回调函数
  382. * @return void
  383. */
  384. public function showAchievementConditions(string $relation = 'achievementConditions', string $label = '任务达成条件', callable $callback = null)
  385. {
  386. $this->show->relation($relation, $label, function ($model) use ($callback) {
  387. $grid = new Grid(new \App\Module\Task\Models\TaskAchievementCondition);
  388. $grid->model()->where('task_id', $model->id);
  389. $grid->column('id', 'ID');
  390. $grid->column('condition.name', '条件名称');
  391. $grid->column('condition_type', '条件类型')->display(function ($type) {
  392. return $type == 'prerequisite' ? '前置条件' : '进度条件';
  393. });
  394. $grid->column('condition_params', '条件参数')->json();
  395. $grid->column('target_value', '目标值');
  396. $grid->column('is_required', '是否必要条件')->display(function ($isRequired) {
  397. return $isRequired ? '是' : '否';
  398. });
  399. $grid->column('sort_order', '排序权重');
  400. $grid->disableCreateButton();
  401. $grid->disableActions();
  402. $grid->disableBatchDelete();
  403. $grid->disableRowSelector();
  404. if ($callback) {
  405. $callback($grid);
  406. }
  407. return $grid;
  408. });
  409. }
  410. /**
  411. * 显示用户任务进度关联
  412. *
  413. * @param string $relation 关联名称
  414. * @param string $label 标签
  415. * @param callable $callback 回调函数
  416. * @return void
  417. */
  418. public function showUserProgress(string $relation = 'userProgress', string $label = '任务进度', callable $callback = null)
  419. {
  420. $this->show->relation($relation, $label, function ($model) use ($callback) {
  421. $grid = new Grid(new \App\Module\Task\Models\TaskUserProgress);
  422. $grid->model()->where('user_id', $model->user_id)->where('task_id', $model->task_id);
  423. $grid->column('id', 'ID');
  424. $grid->column('achievementCondition.condition.name', '条件名称');
  425. $grid->column('current_value', '当前值');
  426. $grid->column('target_value', '目标值');
  427. $grid->column('progress', '进度')->display(function () {
  428. $progress = $this->target_value > 0 ? min(100, round(($this->current_value / $this->target_value) * 100)) : 0;
  429. $percentage = $progress . '%';
  430. $color = $progress >= 100 ? 'success' : ($progress >= 50 ? 'warning' : 'info');
  431. return "<div class='progress' style='height: 20px;'>
  432. <div class='progress-bar bg-{$color}' role='progressbar' style='width: {$progress}%' aria-valuenow='{$progress}' aria-valuemin='0' aria-valuemax='100'>
  433. {$percentage}
  434. </div>
  435. </div>";
  436. });
  437. $grid->disableCreateButton();
  438. $grid->disableActions();
  439. $grid->disableBatchDelete();
  440. $grid->disableRowSelector();
  441. if ($callback) {
  442. $callback($grid);
  443. }
  444. return $grid;
  445. });
  446. }
  447. /**
  448. * 显示自动接取字段
  449. *
  450. * @param string $field 字段名
  451. * @param string $label 标签
  452. * @return Show\Field
  453. */
  454. public function fieldAutoAccept(string $field = 'auto_accept', string $label = '自动接取')
  455. {
  456. return $this->show->field($field, $label)->as(function ($value) {
  457. return $value ? '<span class="badge badge-primary">是</span>' : '<span class="badge badge-secondary">否</span>';
  458. });
  459. }
  460. /**
  461. * 显示自动完成字段
  462. *
  463. * @param string $field 字段名
  464. * @param string $label 标签
  465. * @return Show\Field
  466. */
  467. public function fieldAutoComplete(string $field = 'auto_complete', string $label = '自动完成')
  468. {
  469. return $this->show->field($field, $label)->as(function ($value) {
  470. return $value ? '<span class="badge badge-success">是</span>' : '<span class="badge badge-secondary">否</span>';
  471. });
  472. }
  473. /**
  474. * 显示自动发放奖励字段
  475. *
  476. * @param string $field 字段名
  477. * @param string $label 标签
  478. * @return Show\Field
  479. */
  480. public function fieldAutoReward(string $field = 'auto_reward', string $label = '自动奖励')
  481. {
  482. return $this->show->field($field, $label)->as(function ($value) {
  483. return $value ? '<span class="badge badge-warning">是</span>' : '<span class="badge badge-secondary">否</span>';
  484. });
  485. }
  486. /**
  487. * 显示自动重置字段
  488. *
  489. * @param string $field 字段名
  490. * @param string $label 标签
  491. * @return Show\Field
  492. */
  493. public function fieldAutoReset(string $field = 'auto_reset', string $label = '自动重置')
  494. {
  495. return $this->show->field($field, $label)->as(function ($value) {
  496. return $value ? '<span class="badge badge-info">是</span>' : '<span class="badge badge-secondary">否</span>';
  497. });
  498. }
  499. /**
  500. * 显示自动化配置汇总
  501. *
  502. * @param string $label 标签
  503. * @return Show\Field
  504. */
  505. public function fieldAutoConfig(string $label = '自动化配置')
  506. {
  507. return $this->show->field('auto_config', $label)->as(function () {
  508. $configs = [];
  509. if ($this->auto_accept) $configs[] = '<span class="badge badge-primary">自动接取</span>';
  510. if ($this->auto_complete) $configs[] = '<span class="badge badge-success">自动完成</span>';
  511. if ($this->auto_reward) $configs[] = '<span class="badge badge-warning">自动奖励</span>';
  512. if ($this->auto_reset) $configs[] = '<span class="badge badge-info">自动重置</span>';
  513. return empty($configs) ? '<span class="text-muted">无自动化配置</span>' : implode(' ', $configs);
  514. });
  515. }
  516. }