ShowHelperTrait.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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. // 兼容不同的字段名格式:reward_type 或 rewardType
  293. $rewardType = $reward['reward_type'] ?? $reward['rewardType'] ?? null;
  294. $type = REWARD_TYPE::getDescription(REWARD_TYPE::tryFrom($rewardType) ?? REWARD_TYPE::ITEM);
  295. $result[] = "{$type}: {$reward['quantity']}";
  296. }
  297. return implode('<br>', $result);
  298. });
  299. }
  300. /**
  301. * 显示消耗内容字段
  302. *
  303. * @param string $field 字段名
  304. * @param string $label 标签
  305. * @return Show\Field
  306. */
  307. public function fieldCosts(string $field = 'costs', string $label = '消耗内容')
  308. {
  309. return $this->show->field($field, $label)->as(function ($costs) {
  310. $result = [];
  311. foreach ($costs as $cost) {
  312. $result[] = "{$cost['cost_type']}: {$cost['quantity']}";
  313. }
  314. return implode('<br>', $result);
  315. });
  316. }
  317. /**
  318. * 显示任务奖励关联
  319. *
  320. * @param string $relation 关联名称
  321. * @param string $label 标签
  322. * @param callable $callback 回调函数
  323. * @return void
  324. */
  325. public function showRewards(string $relation = 'rewards', string $label = '任务奖励', callable $callback = null)
  326. {
  327. $this->show->relation($relation, $label, function ($model) use ($callback) {
  328. $grid = new Grid(new \App\Module\Task\Models\TaskReward);
  329. $grid->model()->where('task_id', $model->id);
  330. $grid->column('id', 'ID');
  331. $grid->column('reward_type', '奖励类型')->display(function ($rewardType) {
  332. return REWARD_TYPE::getDescription(REWARD_TYPE::tryFrom($rewardType) ?? REWARD_TYPE::ITEM);
  333. });
  334. $grid->column('reward_param1', '奖励参数1');
  335. $grid->column('reward_param2', '奖励参数2');
  336. $grid->column('quantity', '奖励数量');
  337. $grid->column('extra_data', '额外数据')->json();
  338. $grid->column('sort_order', '排序权重');
  339. $grid->disableCreateButton();
  340. $grid->disableActions();
  341. $grid->disableBatchDelete();
  342. $grid->disableRowSelector();
  343. if ($callback) {
  344. $callback($grid);
  345. }
  346. return $grid;
  347. });
  348. }
  349. /**
  350. * 显示任务接取消耗关联
  351. *
  352. * @param string $relation 关联名称
  353. * @param string $label 标签
  354. * @param callable $callback 回调函数
  355. * @return void
  356. */
  357. public function showCosts(string $relation = 'costs', string $label = '任务接取消耗', callable $callback = null)
  358. {
  359. $this->show->relation($relation, $label, function ($model) use ($callback) {
  360. $grid = new Grid(new \App\Module\Task\Models\TaskCost);
  361. $grid->model()->where('task_id', $model->id);
  362. $grid->column('id', 'ID');
  363. $grid->column('cost_type', '消耗类型');
  364. $grid->column('cost_param1', '消耗参数1');
  365. $grid->column('cost_param2', '消耗参数2');
  366. $grid->column('quantity', '消耗数量');
  367. $grid->column('extra_data', '额外数据')->json();
  368. $grid->disableCreateButton();
  369. $grid->disableActions();
  370. $grid->disableBatchDelete();
  371. $grid->disableRowSelector();
  372. if ($callback) {
  373. $callback($grid);
  374. }
  375. return $grid;
  376. });
  377. }
  378. /**
  379. * 显示任务达成条件关联
  380. *
  381. * @param string $relation 关联名称
  382. * @param string $label 标签
  383. * @param callable $callback 回调函数
  384. * @return void
  385. */
  386. public function showAchievementConditions(string $relation = 'achievementConditions', string $label = '任务达成条件', callable $callback = null)
  387. {
  388. $this->show->relation($relation, $label, function ($model) use ($callback) {
  389. $grid = new Grid(new \App\Module\Task\Models\TaskAchievementCondition);
  390. $grid->model()->where('task_id', $model->id);
  391. $grid->column('id', 'ID');
  392. $grid->column('condition.name', '条件名称');
  393. $grid->column('condition_type', '条件类型')->display(function ($type) {
  394. return $type == 'prerequisite' ? '前置条件' : '进度条件';
  395. });
  396. $grid->column('condition_params', '条件参数')->json();
  397. $grid->column('target_value', '目标值');
  398. $grid->column('is_required', '是否必要条件')->display(function ($isRequired) {
  399. return $isRequired ? '是' : '否';
  400. });
  401. $grid->column('sort_order', '排序权重');
  402. $grid->disableCreateButton();
  403. $grid->disableActions();
  404. $grid->disableBatchDelete();
  405. $grid->disableRowSelector();
  406. if ($callback) {
  407. $callback($grid);
  408. }
  409. return $grid;
  410. });
  411. }
  412. /**
  413. * 显示用户任务进度关联
  414. *
  415. * @param string $relation 关联名称
  416. * @param string $label 标签
  417. * @param callable $callback 回调函数
  418. * @return void
  419. */
  420. public function showUserProgress(string $relation = 'userProgress', string $label = '任务进度', callable $callback = null)
  421. {
  422. $this->show->relation($relation, $label, function ($model) use ($callback) {
  423. $grid = new Grid(new \App\Module\Task\Models\TaskUserProgress);
  424. $grid->model()->where('user_id', $model->user_id)->where('task_id', $model->task_id);
  425. $grid->column('id', 'ID');
  426. $grid->column('achievementCondition.condition.name', '条件名称');
  427. $grid->column('current_value', '当前值');
  428. $grid->column('target_value', '目标值');
  429. $grid->column('progress', '进度')->display(function () {
  430. $progress = $this->target_value > 0 ? min(100, round(($this->current_value / $this->target_value) * 100)) : 0;
  431. $percentage = $progress . '%';
  432. $color = $progress >= 100 ? 'success' : ($progress >= 50 ? 'warning' : 'info');
  433. return "<div class='progress' style='height: 20px;'>
  434. <div class='progress-bar bg-{$color}' role='progressbar' style='width: {$progress}%' aria-valuenow='{$progress}' aria-valuemin='0' aria-valuemax='100'>
  435. {$percentage}
  436. </div>
  437. </div>";
  438. });
  439. $grid->disableCreateButton();
  440. $grid->disableActions();
  441. $grid->disableBatchDelete();
  442. $grid->disableRowSelector();
  443. if ($callback) {
  444. $callback($grid);
  445. }
  446. return $grid;
  447. });
  448. }
  449. /**
  450. * 显示自动接取字段
  451. *
  452. * @param string $field 字段名
  453. * @param string $label 标签
  454. * @return Show\Field
  455. */
  456. public function fieldAutoAccept(string $field = 'auto_accept', string $label = '自动接取')
  457. {
  458. return $this->show->field($field, $label)->as(function ($value) {
  459. return $value ? '<span class="badge badge-primary">是</span>' : '<span class="badge badge-secondary">否</span>';
  460. });
  461. }
  462. /**
  463. * 显示自动完成字段
  464. *
  465. * @param string $field 字段名
  466. * @param string $label 标签
  467. * @return Show\Field
  468. */
  469. public function fieldAutoComplete(string $field = 'auto_complete', string $label = '自动完成')
  470. {
  471. return $this->show->field($field, $label)->as(function ($value) {
  472. return $value ? '<span class="badge badge-success">是</span>' : '<span class="badge badge-secondary">否</span>';
  473. });
  474. }
  475. /**
  476. * 显示自动发放奖励字段
  477. *
  478. * @param string $field 字段名
  479. * @param string $label 标签
  480. * @return Show\Field
  481. */
  482. public function fieldAutoReward(string $field = 'auto_reward', string $label = '自动奖励')
  483. {
  484. return $this->show->field($field, $label)->as(function ($value) {
  485. return $value ? '<span class="badge badge-warning">是</span>' : '<span class="badge badge-secondary">否</span>';
  486. });
  487. }
  488. /**
  489. * 显示自动重置字段
  490. *
  491. * @param string $field 字段名
  492. * @param string $label 标签
  493. * @return Show\Field
  494. */
  495. public function fieldAutoReset(string $field = 'auto_reset', string $label = '自动重置')
  496. {
  497. return $this->show->field($field, $label)->as(function ($value) {
  498. return $value ? '<span class="badge badge-info">是</span>' : '<span class="badge badge-secondary">否</span>';
  499. });
  500. }
  501. /**
  502. * 显示自动化配置汇总
  503. *
  504. * @param string $label 标签
  505. * @return Show\Field
  506. */
  507. public function fieldAutoConfig(string $label = '自动化配置')
  508. {
  509. return $this->show->field('auto_config', $label)->as(function () {
  510. $configs = [];
  511. if ($this->auto_accept) $configs[] = '<span class="badge badge-primary">自动接取</span>';
  512. if ($this->auto_complete) $configs[] = '<span class="badge badge-success">自动完成</span>';
  513. if ($this->auto_reward) $configs[] = '<span class="badge badge-warning">自动奖励</span>';
  514. if ($this->auto_reset) $configs[] = '<span class="badge badge-info">自动重置</span>';
  515. return empty($configs) ? '<span class="text-muted">无自动化配置</span>' : implode(' ', $configs);
  516. });
  517. }
  518. }