UrsPromotionRankingCard.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. namespace App\Module\UrsPromotion\AdminControllers\Metrics;
  3. use App\Module\UrsPromotion\Models\UrsUserMapping;
  4. use App\Module\UrsPromotion\Models\UrsUserReferral;
  5. use App\Module\User\Models\User;
  6. use Dcat\Admin\Widgets\Metrics\Card;
  7. use Illuminate\Http\Request;
  8. use Illuminate\Support\Facades\DB;
  9. /**
  10. * URS推广用户排名卡片
  11. * 显示直推、间推、三推、团队推广用户数量排名
  12. */
  13. class UrsPromotionRankingCard extends Card
  14. {
  15. /**
  16. * 卡片高度
  17. */
  18. protected $height = 400;
  19. /**
  20. * 卡片标题
  21. */
  22. protected $title = 'URS推广排行榜';
  23. /**
  24. * 初始化卡片
  25. */
  26. public function __construct()
  27. {
  28. if ($options = $this->defaultChartOptions()) {
  29. $this->chartOptions = $options;
  30. }
  31. $this->init();
  32. }
  33. /**
  34. * 处理请求
  35. *
  36. * @param Request $request
  37. * @return mixed|void
  38. */
  39. public function handle(Request $request)
  40. {
  41. $rankings = $this->getPromotionRankings();
  42. $this->withContent($rankings);
  43. }
  44. /**
  45. * 获取推广排名数据
  46. *
  47. * @return array
  48. */
  49. private function getPromotionRankings(): array
  50. {
  51. // 获取直推排名前10
  52. $directRanking = $this->getDirectRanking();
  53. // 获取间推排名前10
  54. $indirectRanking = $this->getIndirectRanking();
  55. // 获取三推排名前10
  56. $thirdRanking = $this->getThirdRanking();
  57. // 获取团队总数排名前10
  58. $teamRanking = $this->getTeamRanking();
  59. return [
  60. 'direct' => $directRanking,
  61. 'indirect' => $indirectRanking,
  62. 'third' => $thirdRanking,
  63. 'team' => $teamRanking,
  64. ];
  65. }
  66. /**
  67. * 获取直推排名
  68. * 统计每个推荐人的直接推荐数量
  69. *
  70. * @return array
  71. */
  72. private function getDirectRanking(): array
  73. {
  74. return UrsUserReferral::select([
  75. 'urs_promotion_user_referrals.urs_referrer_id',
  76. 'urs_promotion_user_referrals.referrer_id',
  77. 'users.username as nickname',
  78. DB::raw('COUNT(*) as direct_count')
  79. ])
  80. ->leftJoin('users', 'urs_promotion_user_referrals.referrer_id', '=', 'users.id')
  81. ->where('urs_promotion_user_referrals.status', UrsUserReferral::STATUS_VALID)
  82. ->groupBy('urs_promotion_user_referrals.urs_referrer_id', 'urs_promotion_user_referrals.referrer_id', 'users.username')
  83. ->orderBy('direct_count', 'desc')
  84. ->limit(10)
  85. ->get()
  86. ->toArray();
  87. }
  88. /**
  89. * 获取间推排名
  90. * 统计每个推荐人的间接推荐数量(二级推荐)
  91. *
  92. * @return array
  93. */
  94. private function getIndirectRanking(): array
  95. {
  96. // 暂时返回空数组,间推统计比较复杂
  97. return [];
  98. }
  99. /**
  100. * 获取三推排名
  101. * 统计每个推荐人的三级推荐数量
  102. *
  103. * @return array
  104. */
  105. private function getThirdRanking(): array
  106. {
  107. // 暂时返回空数组,三推统计比较复杂
  108. return [];
  109. }
  110. /**
  111. * 获取团队总数排名
  112. * 统计每个推荐人的团队总人数(直推+间推+三推)
  113. *
  114. * @return array
  115. */
  116. private function getTeamRanking(): array
  117. {
  118. // 团队排名与直推排名相同,统计直推数量
  119. return $this->getDirectRanking();
  120. }
  121. /**
  122. * 设置卡片内容
  123. *
  124. * @param array $rankings 排名数据
  125. * @return $this
  126. */
  127. public function withContent(array $rankings)
  128. {
  129. $directHtml = $this->buildRankingHtml($rankings['direct'], 'direct_count', '直推');
  130. $indirectHtml = $this->buildRankingHtml($rankings['indirect'], 'indirect_count', '间推');
  131. $thirdHtml = $this->buildRankingHtml($rankings['third'], 'third_count', '三推');
  132. $teamHtml = $this->buildRankingHtml($rankings['team'], 'team_count', '团队');
  133. return $this->content(
  134. <<<HTML
  135. <div class="row">
  136. <div class="col-6">
  137. <h6 class="text-primary">直推排行榜</h6>
  138. {$directHtml}
  139. </div>
  140. <div class="col-6">
  141. <h6 class="text-success">间推排行榜</h6>
  142. {$indirectHtml}
  143. </div>
  144. </div>
  145. <div class="row mt-3">
  146. <div class="col-6">
  147. <h6 class="text-warning">三推排行榜</h6>
  148. {$thirdHtml}
  149. </div>
  150. <div class="col-6">
  151. <h6 class="text-info">团队排行榜</h6>
  152. {$teamHtml}
  153. </div>
  154. </div>
  155. HTML
  156. );
  157. }
  158. /**
  159. * 构建排名HTML
  160. *
  161. * @param array $data 排名数据
  162. * @param string $countField 数量字段
  163. * @param string $type 类型名称
  164. * @return string
  165. */
  166. private function buildRankingHtml(array $data, string $countField, string $type): string
  167. {
  168. if (empty($data)) {
  169. return '<small class="text-muted">暂无数据</small>';
  170. }
  171. $html = '<div class="ranking-list">';
  172. foreach ($data as $index => $item) {
  173. $rank = $index + 1;
  174. // 处理数组和对象两种数据格式
  175. $itemArray = is_object($item) ? (array)$item : $item;
  176. $nickname = $itemArray['nickname'] ?? 'URS用户' . ($itemArray['urs_referrer_id'] ?? $itemArray['urs_user_id'] ?? '');
  177. $count = $itemArray[$countField] ?? 0;
  178. $badgeClass = $rank <= 3 ? 'badge-warning' : 'badge-secondary';
  179. $html .= <<<HTML
  180. <div class="d-flex justify-content-between align-items-center mb-1">
  181. <span class="badge {$badgeClass}">{$rank}</span>
  182. <span class="text-truncate mx-2" style="max-width: 80px;" title="{$nickname}">{$nickname}</span>
  183. <span class="font-weight-bold">{$count}</span>
  184. </div>
  185. HTML;
  186. }
  187. $html .= '</div>';
  188. return $html;
  189. }
  190. }