FarmUserSummaryController.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. <?php
  2. namespace App\Module\Game\AdminControllers;
  3. use App\Module\Farm\Enums\DISASTER_TYPE;
  4. use App\Module\Farm\Enums\GROWTH_STAGE;
  5. use App\Module\Farm\Models\FarmCrop;
  6. use App\Module\Farm\Models\FarmGodBuff;
  7. use App\Module\Farm\Models\FarmHouseConfig;
  8. use App\Module\Farm\Models\FarmLand;
  9. use App\Module\Farm\Models\FarmUser;
  10. use App\Module\Farm\Services\DisasterService;
  11. use App\Module\Fund\Models\FundModel;
  12. use App\Module\Fund\Services\AccountService;
  13. use App\Module\GameItems\Enums\ITEM_TYPE;
  14. use App\Module\GameItems\Models\ItemUser;
  15. use App\Module\User\Models\User;
  16. use Dcat\Admin\Grid;
  17. use Dcat\Admin\Layout\Content;
  18. use Dcat\Admin\Layout\Row;
  19. use Dcat\Admin\Widgets\Card;
  20. use Dcat\Admin\Widgets\Table;
  21. use Dcat\Admin\Widgets\Alert;
  22. use Spatie\RouteAttributes\Attributes\Get;
  23. use Spatie\RouteAttributes\Attributes\Resource;
  24. use UCore\DcatAdmin\AdminController;
  25. /**
  26. * 农场用户信息汇总控制器
  27. *
  28. * 用于展示用户的农场信息汇总,包括房屋、土地、作物、物品和代币信息
  29. */
  30. #[Resource('farm-user-summary', names: 'dcat.admin.farm-user-summary')]
  31. class FarmUserSummaryController extends AdminController
  32. {
  33. /**
  34. * 页面标题
  35. *
  36. * @var string
  37. */
  38. protected $title = '农场用户信息汇总';
  39. /**
  40. * 用户列表页面
  41. *
  42. * @param Content $content
  43. * @return Content
  44. */
  45. public function index(Content $content)
  46. {
  47. return $content
  48. ->title($this->title)
  49. ->description('查看用户的农场信息汇总')
  50. ->body($this->grid());
  51. }
  52. /**
  53. * 查看指定用户的农场信息汇总
  54. *
  55. * @param int $userId 用户ID
  56. * @param Content $content
  57. * @return Content
  58. */
  59. #[Get('farm-user-summary/{userId}', name: 'dcat.admin.farm-user-summary.show')]
  60. public function show($userId, Content $content)
  61. {
  62. // 记录请求信息
  63. \Illuminate\Support\Facades\Log::info('访问农场用户信息汇总', [
  64. 'user_id' => $userId,
  65. 'referer' => request()->header('referer'),
  66. 'user_agent' => request()->header('user-agent'),
  67. 'ip' => request()->ip(),
  68. 'url' => request()->fullUrl(),
  69. ]);
  70. // 查找用户
  71. $user = User::find($userId);
  72. if (!$user) {
  73. admin_error('错误', "用户 {$userId} 不存在");
  74. \Illuminate\Support\Facades\Log::warning('访问不存在的用户', [ 'user_id' => $userId ]);
  75. return redirect()->route('dcat.admin.farm-user-summary');
  76. }
  77. // 检查是否存在农场用户记录
  78. $farmUser = FarmUser::where('user_id', $userId)->first();
  79. if (!$farmUser) {
  80. admin_warning('提示', "用户 {$userId} 没有农场信息");
  81. \Illuminate\Support\Facades\Log::info('用户没有农场信息', [ 'user_id' => $userId ]);
  82. // 不重定向,继续显示用户信息,只是提示没有农场信息
  83. }
  84. return $content
  85. ->title($this->title)
  86. ->description("用户 {$user->username}(ID: {$user->id})的农场信息汇总")
  87. ->body(function (Row $row) use ($user) {
  88. // 第一行:用户基本信息和房屋信息
  89. $row->column(6, $this->userInfoCard($user));
  90. $row->column(6, $this->houseInfoCard($user->id));
  91. // 第二行:土地信息和作物信息
  92. $row->column(12, $this->landInfoCard($user->id));
  93. // 第三行:物品信息
  94. $row->column(12, $this->itemInfoCard($user->id));
  95. // 第四行:代币信息
  96. $row->column(12, $this->fundInfoCard($user->id));
  97. // 第五行:神像buff信息
  98. $row->column(12, $this->buffInfoCard($user->id));
  99. });
  100. }
  101. /**
  102. * 用户基本信息卡片
  103. *
  104. * @param User $user 用户对象
  105. * @return Card
  106. */
  107. protected function userInfoCard(User $user)
  108. {
  109. $userInfo = $user->info;
  110. $avatar = $userInfo ? $userInfo->avatar : '';
  111. $nickname = $userInfo ? $userInfo->nickname : '';
  112. $content = <<<HTML
  113. <div class="row">
  114. <div class="col-md-4">
  115. <img src="/saaa/{$avatar}" class="img-fluid rounded" style="max-width: 100px;" >
  116. </div>
  117. <div class="col-md-8">
  118. <p><strong>用户ID:</strong>{$user->id}</p>
  119. <p><strong>用户名:</strong>{$user->username}</p>
  120. <p><strong>昵称:</strong>{$nickname}</p>
  121. <p><strong>注册时间:</strong>{$user->created_at}</p>
  122. </div>
  123. </div>
  124. HTML;
  125. return new Card('用户基本信息', $content);
  126. }
  127. /**
  128. * 房屋信息卡片
  129. *
  130. * @param int $userId 用户ID
  131. * @return Card
  132. */
  133. protected function houseInfoCard($userId)
  134. {
  135. // 获取用户的农场信息
  136. $farmUser = FarmUser::where('user_id', $userId)->first();
  137. if (!$farmUser) {
  138. return new Card('房屋信息', new Alert('warning', '该用户没有农场信息'));
  139. }
  140. // 获取房屋配置信息
  141. $houseConfig = FarmHouseConfig::where('level', $farmUser->house_level)->first();
  142. if (!$houseConfig) {
  143. return new Card('房屋信息', new Alert('warning', "找不到房屋等级 {$farmUser->house_level} 的配置信息"));
  144. }
  145. $content = <<<HTML
  146. <div class="row">
  147. <div class="col-md-12">
  148. <p><strong>房屋等级:</strong>{$farmUser->house_level}</p>
  149. <p><strong>最后升级时间:</strong>{$farmUser->last_upgrade_time}</p>
  150. <p><strong>产出加成:</strong>{$houseConfig->output_bonus}</p>
  151. <p><strong>特殊土地上限:</strong>{$houseConfig->special_land_limit}</p>
  152. <p><strong>可用土地数量:</strong>{$houseConfig->available_lands}</p>
  153. HTML;
  154. // 如果有降级天数,显示降级信息
  155. if ($houseConfig->downgrade_days) {
  156. $content .= "<p><strong>降级天数:</strong>{$houseConfig->downgrade_days}</p>";
  157. }
  158. $content .= <<<HTML
  159. </div>
  160. </div>
  161. <div class="row mt-2">
  162. <div class="col-md-12">
  163. <a href="javascript:void(0);" class="btn btn-sm btn-primary" onclick="window.open('/admin/farm-house-configs', '_blank')">查看房屋配置</a>
  164. </div>
  165. </div>
  166. HTML;
  167. return new Card('房屋信息', $content);
  168. }
  169. /**
  170. * 土地信息卡片
  171. *
  172. * @param int $userId 用户ID
  173. * @return Card
  174. */
  175. protected function landInfoCard($userId)
  176. {
  177. // 获取用户的土地信息
  178. /**
  179. * @var FarmLand $land
  180. */
  181. $lands = FarmLand::with([ 'landType', 'crop.seed' ])
  182. ->where('user_id', $userId)
  183. ->get();
  184. if ($lands->isEmpty()) {
  185. return new Card('土地信息', new Alert('warning', '该用户没有土地信息'));
  186. }
  187. // 土地类型统计
  188. $landTypeStats = $lands->groupBy('land_type')->map->count();
  189. // 土地状态统计
  190. $landStatusStats = $lands->groupBy('status')->map->count();
  191. // 灾害统计
  192. $disasterStats = [
  193. 1 => 0, // 干旱
  194. 2 => 0, // 虫害
  195. 3 => 0, // 杂草
  196. ];
  197. // 统计活跃的灾害
  198. foreach ($lands as $land) {
  199. if ($land->crop && !empty($land->crop->disasters)) {
  200. foreach ($land->crop->disasters as $disaster) {
  201. if (($disaster['status'] ?? '') === 'active') {
  202. $type = $disaster['type'] ?? 0;
  203. if (isset($disasterStats[$type])) {
  204. $disasterStats[$type]++;
  205. }
  206. }
  207. }
  208. }
  209. }
  210. // 创建土地类型、状态和灾害的统计表格
  211. $statsContent = '<div class="row">';
  212. // 土地类型统计
  213. $statsContent .= '<div class="col-md-4">';
  214. $statsContent .= '<h5>土地类型统计</h5>';
  215. $statsContent .= '<table class="table table-sm table-bordered">';
  216. $statsContent .= '<thead><tr><th>土地类型</th><th>数量</th></tr></thead>';
  217. $statsContent .= '<tbody>';
  218. $landTypeNames = [
  219. 1 => '普通土地',
  220. 2 => '红土地',
  221. 3 => '黑土地',
  222. 4 => '金土地',
  223. 5 => '蓝土地',
  224. 6 => '紫土地',
  225. ];
  226. foreach ($landTypeStats as $typeId => $count) {
  227. $typeName = $landTypeNames[$typeId] ?? "类型{$typeId}";
  228. $statsContent .= "<tr><td>{$typeName}</td><td>{$count}</td></tr>";
  229. }
  230. $statsContent .= '</tbody></table></div>';
  231. // 土地状态统计
  232. $statsContent .= '<div class="col-md-4">';
  233. $statsContent .= '<h5>土地状态统计</h5>';
  234. $statsContent .= '<table class="table table-sm table-bordered">';
  235. $statsContent .= '<thead><tr><th>土地状态</th><th>数量</th></tr></thead>';
  236. $statsContent .= '<tbody>';
  237. $landStatusNames = [
  238. 0 => '空闲',
  239. 1 => '种植中',
  240. 2 => '灾害',
  241. 3 => '可收获',
  242. 4 => '枯萎',
  243. ];
  244. foreach ($landStatusStats as $statusId => $count) {
  245. $statusName = $landStatusNames[$statusId] ?? "状态{$statusId}";
  246. $statsContent .= "<tr><td>{$statusName}</td><td>{$count}</td></tr>";
  247. }
  248. $statsContent .= '</tbody></table></div>';
  249. // 灾害统计
  250. $statsContent .= '<div class="col-md-4">';
  251. $statsContent .= '<h5>灾害统计</h5>';
  252. $statsContent .= '<table class="table table-sm table-bordered">';
  253. $statsContent .= '<thead><tr><th>灾害类型</th><th>数量</th><th>减产比例</th></tr></thead>';
  254. $statsContent .= '<tbody>';
  255. $disasterNames = DISASTER_TYPE::getAll();
  256. $totalDisasters = 0;
  257. $d = DisasterService::getAllDisasters();
  258. foreach ($disasterStats as $typeId => $count) {
  259. $typeName = $disasterNames[$typeId] ?? "未知灾害{$typeId}";
  260. $penalty = $d[$typeId];
  261. $totalDisasters += $count;
  262. $statsContent .= "<tr><td>{$typeName}</td><td>{$count}</td><td>{$penalty}</td></tr>";
  263. }
  264. // 添加总计行
  265. $totalPenalty = $totalDisasters > 0 ? ($totalDisasters * 5) . '%' : '0%';
  266. $statsContent .= "<tr class='table-info'><td><strong>总计</strong></td><td>{$totalDisasters}</td><td>{$totalPenalty}</td></tr>";
  267. $statsContent .= '</tbody></table></div>';
  268. $statsContent .= '</div>';
  269. // 创建土地详情表格
  270. $headers = [
  271. 'ID', '位置', '土地类型', '状态', '种植作物', '种植时间', '生长阶段', '本阶段开始时间', '本阶段结束时间',
  272. '灾害情况'
  273. ];
  274. $rows = [];
  275. foreach ($lands as $land) {
  276. $landType = $land->landType ? $land->landType->name : "类型{$land->land_type}";
  277. $status = $landStatusNames[$land->status] ?? "状态{$land->status}";
  278. $crop = $land->crop;
  279. $cropInfo = '无';
  280. $plantTime = '';
  281. $growthStage = '';
  282. $stageStartTime = '';
  283. $stageEndTime = '';
  284. $disasterInfo = '无';
  285. if ($crop) {
  286. $seedName = $crop->seed ? $crop->seed->name : "种子{$crop->seed_id}";
  287. $cropInfo = $seedName;
  288. $plantTime = $crop->plant_time;
  289. $growthStage = $this->getGrowthStageName($crop->growth_stage);
  290. $stageStartTime = $crop->stage_start_time;
  291. $stageEndTime = $crop->stage_end_time;
  292. // 处理灾害信息
  293. if (!empty($crop->disasters)) {
  294. $disasterInfo = $this->formatDisasterInfo($crop->disasters);
  295. }
  296. }
  297. $rows[] = [
  298. $land->id,
  299. $land->position,
  300. $landType,
  301. $status,
  302. $cropInfo,
  303. $plantTime,
  304. $growthStage,
  305. $stageStartTime,
  306. $stageEndTime,
  307. $disasterInfo,
  308. ];
  309. }
  310. $table = new Table($headers, $rows);
  311. $content = $statsContent . '<div class="mt-3">' . $table->render() . '</div>';
  312. $content .= <<<HTML
  313. <div class="row mt-2">
  314. <div class="col-md-12">
  315. <a href="javascript:void(0);" class="btn btn-sm btn-primary"
  316. onclick="window.open('/admin/farm-lands?user_id={$userId}', '_blank')">查看土地详情</a>
  317. <a href="javascript:void(0);" class="btn btn-sm btn-primary"
  318. onclick="window.open('/admin/farm-crops?user_id={$userId}', '_blank')">查看作物详情</a>
  319. </div>
  320. </div>
  321. HTML;
  322. return new Card('土地信息', $content);
  323. }
  324. /**
  325. * 获取生长阶段名称
  326. *
  327. * @param GROWTH_STAGE|int $stage 生长阶段枚举或整数值
  328. * @return string 生长阶段名称
  329. */
  330. protected function getGrowthStageName($stage)
  331. {
  332. // 如果传入的是整数,转换为枚举
  333. if (is_int($stage)) {
  334. try {
  335. $stage = GROWTH_STAGE::from($stage);
  336. } catch (\ValueError) {
  337. return "未知阶段{$stage}";
  338. }
  339. }
  340. // 如果是null,返回未知
  341. if ($stage === null) {
  342. return "未知阶段";
  343. }
  344. // 获取阶段名称
  345. try {
  346. $stageNames = GROWTH_STAGE::getAll();
  347. $stageValue = $stage->value;
  348. return $stageNames[$stageValue] ?? "阶段{$stageValue}";
  349. } catch (\Throwable) {
  350. return "错误阶段";
  351. }
  352. }
  353. /**
  354. * 物品信息卡片
  355. *
  356. * @param int $userId 用户ID
  357. * @return Card
  358. */
  359. protected function itemInfoCard($userId)
  360. {
  361. // 获取用户的物品信息
  362. $items = ItemUser::with('item')
  363. ->where('user_id', $userId)
  364. ->orderBy('quantity', 'desc')
  365. ->limit(20)
  366. ->get();
  367. if ($items->isEmpty()) {
  368. return new Card('物品信息', new Alert('warning', '该用户没有物品信息'));
  369. }
  370. // 创建物品表格
  371. $headers = [ '物品ID', '物品名称', '数量', '物品类型', '过期时间' ];
  372. $rows = [];
  373. foreach ($items as $item) {
  374. $itemName = $item->item ? $item->item->name : "物品{$item->item_id}";
  375. $itemType = $item->item ? $this->getItemTypeName($item->item->type) : '';
  376. $rows[] = [
  377. $item->item_id,
  378. $itemName,
  379. $item->quantity,
  380. $itemType,
  381. $item->expire_at ?: '永久',
  382. ];
  383. }
  384. $table = new Table($headers, $rows);
  385. // 获取用户物品总数
  386. $totalCount = ItemUser::where('user_id', $userId)->count();
  387. $content = <<<HTML
  388. <div class="alert alert-info">
  389. 用户共有 {$totalCount} 种物品,下表显示数量最多的前20种物品
  390. </div>
  391. {$table->render()}
  392. <div class="row mt-2">
  393. <div class="col-md-12">
  394. <a href="javascript:void(0);" class="btn btn-sm btn-primary" onclick="window.open('/admin/game-items-user-items?user_id={$userId}', '_blank')">查看物品详情</a>
  395. </div>
  396. </div>
  397. HTML;
  398. return new Card('物品信息', $content);
  399. }
  400. /**
  401. * 获取物品类型名称
  402. *
  403. * @param ITEM_TYPE|int $type 物品类型枚举或整数值
  404. * @return string 物品类型名称
  405. */
  406. protected function getItemTypeName($type)
  407. {
  408. // 如果传入的是整数,转换为枚举
  409. if (is_int($type)) {
  410. try {
  411. $type = ITEM_TYPE::from($type);
  412. } catch (\ValueError) {
  413. return "未知类型{$type}";
  414. }
  415. }
  416. // 如果是null,返回未知
  417. if ($type === null) {
  418. return "未知类型";
  419. }
  420. // 获取类型名称
  421. try {
  422. $typeNames = ITEM_TYPE::getValueDescription();
  423. $typeValue = $type->value;
  424. return $typeNames[$typeValue] ?? "类型{$typeValue}";
  425. } catch (\Throwable) {
  426. return "错误类型";
  427. }
  428. }
  429. /**
  430. * 格式化灾害信息
  431. *
  432. * @param array $disasters 灾害数组
  433. * @return string 格式化后的灾害信息
  434. */
  435. protected function formatDisasterInfo(array $disasters): string
  436. {
  437. if (empty($disasters)) {
  438. return '无';
  439. }
  440. $result = [];
  441. foreach ($disasters as $disaster) {
  442. $type = $disaster['type'] ?? 0;
  443. $status = $disaster['status'] ?? 'active'; // 默认为活跃状态
  444. // 获取灾害类型名称
  445. $typeName = DISASTER_TYPE::getName($type);
  446. // 灾害状态
  447. $statusText = $status === 'active' ? '<span class="badge badge-danger">活跃</span>' : '<span class="badge badge-secondary">已处理</span>';
  448. // 灾害开始时间
  449. $startTime = isset($disaster['start_time']) ? date('Y-m-d H:i:s', $disaster['start_time']) : '未知';
  450. // 灾害结束时间(如果有)
  451. $endTime = '';
  452. if (isset($disaster['end_time']) && $disaster['end_time'] > 0) {
  453. $endTime = date('Y-m-d H:i:s', $disaster['end_time']);
  454. }
  455. // 减产比例 - 从DisasterService获取默认值
  456. $defaultPenalties = \App\Module\Farm\Services\DisasterService::getAllDisasters();
  457. $defaultPenalty = $defaultPenalties[$type] ?? 0.05;
  458. $penalty = isset($disaster['penalty']) ? ($disaster['penalty'] * 100) . '%' : ($defaultPenalty * 100) . '%';
  459. // 组合灾害信息
  460. $disasterInfo = "<div><strong>{$typeName}</strong>: {$statusText}</div>";
  461. $disasterInfo .= "<div>开始: {$startTime}</div>";
  462. if ($endTime) {
  463. $disasterInfo .= "<div>结束: {$endTime}</div>";
  464. }
  465. $disasterInfo .= "<div>减产: {$penalty}</div>";
  466. // 如果有额外的灾害信息,也显示出来
  467. if (isset($disaster['id'])) {
  468. $disasterInfo .= "<div>ID: {$disaster['id']}</div>";
  469. }
  470. $result[] = $disasterInfo;
  471. }
  472. return implode('<hr style="margin: 5px 0;">', $result);
  473. }
  474. /**
  475. * 代币信息卡片
  476. *
  477. * @param int $userId 用户ID
  478. * @return Card
  479. */
  480. protected function fundInfoCard($userId)
  481. {
  482. // 获取用户的代币信息
  483. $funds = FundModel::where('user_id', $userId)->get();
  484. if ($funds->isEmpty()) {
  485. return new Card('代币信息', new Alert('warning', '该用户没有代币信息'));
  486. }
  487. // 获取资金类型名称映射
  488. $fundNames = AccountService::getFundsDesc();
  489. // 创建代币表格
  490. $headers = [ '账户ID', '账户名称', '余额', '更新时间' ];
  491. $rows = [];
  492. foreach ($funds as $fund) {
  493. try {
  494. $fundIdValue = $fund->fund_id->value();
  495. $fundName = $fundNames[$fundIdValue] ?? "账户{$fundIdValue}";
  496. $balance = $fund->balance;
  497. $rows[] = [
  498. $fundIdValue,
  499. $fundName,
  500. $balance,
  501. $fund->update_time ? date('Y-m-d H:i:s', $fund->update_time) : '',
  502. ];
  503. } catch (\Throwable) {
  504. // 如果出现异常,添加一个错误行
  505. $rows[] = [
  506. $fund->id ?? '未知',
  507. '数据错误',
  508. $fund->balance ?? '未知',
  509. $fund->update_time ? date('Y-m-d H:i:s', $fund->update_time) : '',
  510. ];
  511. }
  512. }
  513. $table = new Table($headers, $rows);
  514. $content = <<<HTML
  515. {$table->render()}
  516. <div class="row mt-2">
  517. <div class="col-md-12">
  518. <a href="javascript:void(0);" class="btn btn-sm btn-primary" onclick="window.open('/admin/fund-accounts?user_id={$userId}', '_blank')">查看账户详情</a>
  519. </div>
  520. </div>
  521. HTML;
  522. return new Card('代币信息', $content);
  523. }
  524. /**
  525. * 神像buff信息卡片
  526. *
  527. * @param int $userId 用户ID
  528. * @return Card
  529. */
  530. protected function buffInfoCard($userId)
  531. {
  532. // 获取用户的神像buff信息
  533. $buffs = FarmGodBuff::where('user_id', $userId)
  534. ->orderBy('expire_time', 'desc')
  535. ->get();
  536. if ($buffs->isEmpty()) {
  537. return new Card('神像加持信息', new Alert('warning', '该用户没有神像加持信息'));
  538. }
  539. // 创建buff表格
  540. $headers = [ '加持类型', '过期时间', '状态' ];
  541. $rows = [];
  542. $buffTypeNames = [
  543. 1 => '丰收之神',
  544. 2 => '雨露之神',
  545. 3 => '屠草之神',
  546. 4 => '拭虫之神',
  547. ];
  548. foreach ($buffs as $buff) {
  549. try {
  550. $buffType = $buffTypeNames[$buff->buff_type] ?? "类型{$buff->buff_type}";
  551. $isActive = now()->lt($buff->expire_time);
  552. $status = $isActive ? '<span class="badge badge-success">生效中</span>' : '<span class="badge badge-secondary">已过期</span>';
  553. $rows[] = [
  554. $buffType,
  555. $buff->expire_time,
  556. $status,
  557. ];
  558. } catch (\Throwable) {
  559. // 如果出现异常,添加一个错误行
  560. $rows[] = [
  561. '数据错误',
  562. $buff->expire_time ?? '未知',
  563. '<span class="badge badge-danger">数据错误</span>',
  564. ];
  565. }
  566. }
  567. $table = new Table($headers, $rows);
  568. $content = $table->render();
  569. return new Card('神像加持信息', $content);
  570. }
  571. /**
  572. * 用户列表网格
  573. *
  574. * @return Grid
  575. */
  576. protected function grid()
  577. {
  578. return Grid::make(User::with([ 'info', 'farmUser' ]), function (Grid $grid) {
  579. $grid->column('id', 'ID')->sortable();
  580. // 用户基本信息
  581. $grid->column('username', '用户名');
  582. $grid->column('info.nickname', '昵称');
  583. // 农场信息
  584. $grid->column('farmUser.house_level', '房屋等级')->sortable();
  585. // 土地统计
  586. $grid->column('id', '土地统计')->display(function ($userId) {
  587. $lands = FarmLand::where('user_id', $userId)->get();
  588. if ($lands->isEmpty()) {
  589. return '<span class="text-muted">无土地</span>';
  590. }
  591. $landTypeStats = $lands->groupBy('land_type')->map->count();
  592. $totalLands = $lands->count();
  593. $html = "<div>总计: {$totalLands}块土地</div>";
  594. $landTypeNames = [
  595. 1 => '普通土地',
  596. 2 => '红土地',
  597. 3 => '黑土地',
  598. 4 => '金土地',
  599. 5 => '蓝土地',
  600. 6 => '紫土地',
  601. ];
  602. foreach ($landTypeStats as $typeId => $count) {
  603. $typeName = $landTypeNames[$typeId] ?? "类型{$typeId}";
  604. $html .= "<div>{$typeName}: {$count}块</div>";
  605. }
  606. return $html;
  607. });
  608. // 作物统计
  609. $grid->column('id', '作物统计')->display(function ($userId) {
  610. $crops = FarmCrop::where('user_id', $userId)->count();
  611. return $crops > 0 ? "{$crops}种作物" : '<span class="text-muted">无作物</span>';
  612. });
  613. // 物品统计
  614. $grid->column('id', '物品统计')->display(function ($userId) {
  615. $itemCount = ItemUser::where('user_id', $userId)->count();
  616. return $itemCount > 0 ? "{$itemCount}种物品" : '<span class="text-muted">无物品</span>';
  617. });
  618. // 代币统计
  619. $grid->column('id', '代币统计')->display(function ($userId) {
  620. $fundCount = FundModel::where('user_id', $userId)->count();
  621. return $fundCount > 0 ? "{$fundCount}个账户" : '<span class="text-muted">无账户</span>';
  622. });
  623. $grid->column('created_at', '创建时间')->sortable();
  624. // 添加查看详情操作
  625. $grid->actions(function (Grid\Displayers\Actions $actions) {
  626. // 禁用默认操作按钮
  627. $actions->disableDelete();
  628. $actions->disableEdit();
  629. $actions->disableQuickEdit();
  630. // 修改查看按钮,使其打开详情页
  631. $actions->append('<a href="' . admin_url('farm-user-summary/' . $actions->getKey()) . '" class="btn btn-sm btn-primary">查看详情</a>');
  632. });
  633. // 禁用创建按钮
  634. $grid->disableCreateButton();
  635. // 禁用批量操作
  636. $grid->disableBatchActions();
  637. // 添加搜索
  638. $grid->filter(function (Grid\Filter $filter) {
  639. $filter->equal('id', '用户ID');
  640. $filter->like('username', '用户名');
  641. $filter->like('info.nickname', '昵称');
  642. $filter->equal('farmUser.house_level', '房屋等级');
  643. });
  644. });
  645. }
  646. }