ViewReferralTreeAction.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. namespace App\Module\UrsPromotion\AdminControllers\Actions;
  3. use App\Module\UrsPromotion\Models\UrsUserReferral;
  4. use App\Module\UrsPromotion\Services\UrsReferralService;
  5. use Dcat\Admin\Widgets\Modal;
  6. use UCore\DcatAdmin\RowAction;
  7. /**
  8. * 查看推荐下级树操作
  9. *
  10. * 显示用户的下级推荐关系树结构
  11. */
  12. class ViewReferralTreeAction extends RowAction
  13. {
  14. /**
  15. * 操作按钮标题
  16. *
  17. * @var string
  18. */
  19. protected $title = '下级树';
  20. /**
  21. * 检查是否允许显示此操作
  22. *
  23. * @return bool
  24. */
  25. public function allowed()
  26. {
  27. // 所有记录都允许查看关系树
  28. return true;
  29. }
  30. /**
  31. * 渲染操作按钮
  32. *
  33. * @return string
  34. */
  35. public function render2()
  36. {
  37. $row = $this->getRow();
  38. $ursUserId = $row->urs_user_id;
  39. // 获取推荐关系树数据
  40. $treeData = $this->getReferralTreeData($ursUserId);
  41. // 构建树形结构HTML
  42. $treeHtml = $this->buildTreeHtml($treeData);
  43. return Modal::make()
  44. ->xl()
  45. ->title("URS用户 {$ursUserId} 的下级推荐树")
  46. ->body($treeHtml)
  47. ->button("<i class=\"fa fa-sitemap\"></i> {$this->title}");
  48. }
  49. /**
  50. * 获取推荐关系树数据
  51. *
  52. * @param int $ursUserId
  53. * @return array
  54. */
  55. private function getReferralTreeData(int $ursUserId): array
  56. {
  57. // 获取直推用户
  58. $directReferrals = UrsUserReferral::where('urs_referrer_id', $ursUserId)
  59. ->where('status', UrsUserReferral::STATUS_VALID)
  60. ->with(['userMapping.user.info'])
  61. ->get();
  62. $tree = [
  63. 'user_id' => $ursUserId,
  64. 'direct' => [],
  65. 'indirect' => [],
  66. 'third' => []
  67. ];
  68. foreach ($directReferrals as $direct) {
  69. $directData = [
  70. 'urs_user_id' => $direct->urs_user_id,
  71. 'farm_user_id' => $direct->userMapping->user_id ?? null,
  72. 'username' => $direct->userMapping->user->username ?? '未进入农场',
  73. 'nickname' => $direct->userMapping->user->info->nickname ?? '无昵称',
  74. 'referral_time' => $direct->referral_time,
  75. 'children' => []
  76. ];
  77. // 获取间推用户(直推用户的下级)
  78. $indirectReferrals = UrsUserReferral::where('urs_referrer_id', $direct->urs_user_id)
  79. ->where('status', UrsUserReferral::STATUS_VALID)
  80. ->with(['userMapping.user.info'])
  81. ->get();
  82. foreach ($indirectReferrals as $indirect) {
  83. $indirectData = [
  84. 'urs_user_id' => $indirect->urs_user_id,
  85. 'farm_user_id' => $indirect->userMapping->user_id ?? null,
  86. 'username' => $indirect->userMapping->user->username ?? '未进入农场',
  87. 'nickname' => $indirect->userMapping->user->info->nickname ?? '无昵称',
  88. 'referral_time' => $indirect->referral_time,
  89. 'children' => []
  90. ];
  91. // 获取三推用户(间推用户的下级)
  92. $thirdReferrals = UrsUserReferral::where('urs_referrer_id', $indirect->urs_user_id)
  93. ->where('status', UrsUserReferral::STATUS_VALID)
  94. ->with(['userMapping.user.info'])
  95. ->get();
  96. foreach ($thirdReferrals as $third) {
  97. $indirectData['children'][] = [
  98. 'urs_user_id' => $third->urs_user_id,
  99. 'farm_user_id' => $third->userMapping->user_id ?? null,
  100. 'username' => $third->userMapping->user->username ?? '未进入农场',
  101. 'nickname' => $third->userMapping->user->info->nickname ?? '无昵称',
  102. 'referral_time' => $third->referral_time,
  103. ];
  104. }
  105. $directData['children'][] = $indirectData;
  106. }
  107. $tree['direct'][] = $directData;
  108. }
  109. return $tree;
  110. }
  111. /**
  112. * 构建树形结构HTML
  113. *
  114. * @param array $treeData
  115. * @return string
  116. */
  117. private function buildTreeHtml(array $treeData): string
  118. {
  119. $html = '<div class="referral-tree-container">';
  120. $html .= '<style>
  121. .referral-tree-container { font-family: Arial, sans-serif; }
  122. .tree-node { margin: 10px 0; padding: 10px; border: 1px solid #ddd; border-radius: 5px; }
  123. .tree-level-1 { background-color: #e8f5e8; margin-left: 0; }
  124. .tree-level-2 { background-color: #e8f0ff; margin-left: 30px; }
  125. .tree-level-3 { background-color: #fff8e8; margin-left: 60px; }
  126. .user-info { font-weight: bold; color: #333; }
  127. .user-meta { font-size: 12px; color: #666; margin-top: 5px; }
  128. .level-badge { display: inline-block; padding: 2px 6px; border-radius: 3px; font-size: 11px; color: white; }
  129. .level-1 { background-color: #28a745; }
  130. .level-2 { background-color: #007bff; }
  131. .level-3 { background-color: #ffc107; color: #333; }
  132. </style>';
  133. $html .= '<h5><i class="fa fa-user"></i> 根用户: URS-' . $treeData['user_id'] . '</h5>';
  134. if (empty($treeData['direct'])) {
  135. $html .= '<p class="text-muted">暂无下级推荐用户</p>';
  136. } else {
  137. $html .= '<div class="tree-structure">';
  138. foreach ($treeData['direct'] as $direct) {
  139. $html .= $this->renderUserNode($direct, 1);
  140. }
  141. $html .= '</div>';
  142. }
  143. $html .= '</div>';
  144. return $html;
  145. }
  146. /**
  147. * 渲染用户节点
  148. *
  149. * @param array $user
  150. * @param int $level
  151. * @return string
  152. */
  153. private function renderUserNode(array $user, int $level): string
  154. {
  155. $levelNames = [1 => '直推', 2 => '间推', 3 => '三推'];
  156. $levelClass = "tree-level-{$level}";
  157. $badgeClass = "level-{$level}";
  158. $html = "<div class='tree-node {$levelClass}'>";
  159. $html .= "<span class='level-badge {$badgeClass}'>{$levelNames[$level]}</span> ";
  160. $html .= "<span class='user-info'>URS-{$user['urs_user_id']}</span>";
  161. if ($user['farm_user_id']) {
  162. $html .= " → 农场用户ID: {$user['farm_user_id']} | {$user['username']} ({$user['nickname']})";
  163. } else {
  164. $html .= " → <span class='text-warning'>未进入农场</span>";
  165. }
  166. $html .= "<div class='user-meta'>";
  167. $html .= "推荐时间: {$user['referral_time']}";
  168. $html .= "</div>";
  169. // 渲染子节点
  170. if (!empty($user['children']) && $level < 3) {
  171. foreach ($user['children'] as $child) {
  172. $html .= $this->renderUserNode($child, $level + 1);
  173. }
  174. }
  175. $html .= "</div>";
  176. return $html;
  177. }
  178. }