Forráskód Böngészése

修复财富等级排行榜逻辑:限制前100名、增加10分钟缓存、处理用户不在排名中的情况

notfff 7 hónapja
szülő
commit
244cd7eeae
1 módosított fájl, 93 hozzáadás és 32 törlés
  1. 93 32
      app/Module/Farm/Logics/HouseLogic.php

+ 93 - 32
app/Module/Farm/Logics/HouseLogic.php

@@ -446,31 +446,31 @@ class HouseLogic
     public function getWealthRankList(int $userId, int $page = 1, int $pageSize = 20): WealthRankDto
     {
         try {
-            // 计算偏移量
+            // 限制只显示前100名
+            $maxRankLimit = 100;
             $offset = ($page - 1) * $pageSize;
 
-            // 查询财富排行榜数据,按钻石余额降序排列,同余额按房屋等级降序排列
-            $rankList = DB::table('fund as f')
-                ->join('users as u', 'f.user_id', '=', 'u.id')
-                ->leftJoin('farm_users as fu', 'f.user_id', '=', 'fu.user_id')
-                ->select([
-                             'f.user_id',
-                             'f.balance',
-                             'u.username',
-                             'fu.house_level'
-                         ])
-                ->where('f.fund_id', 2) // 钻石资金类型
-                ->orderBy('f.balance', 'desc')
-                ->orderBy('fu.house_level', 'desc') // 同钻石余额按房屋等级排序
-                ->offset($offset)
-                ->limit($pageSize)
-                ->get()
-                ->toArray();
+            // 如果请求的数据超出前100名,返回空结果
+            if ($offset >= $maxRankLimit) {
+                return new WealthRankDto([], 0, 1, [
+                    'page' => $page,
+                    'per_page' => $pageSize,
+                    'total' => min($maxRankLimit, $this->getTotalWealthRankCount())
+                ]);
+            }
+
+            // 从缓存获取前100名数据
+            $cachedRankList = $this->getWealthRankListCache();
+
+            // 调整查询限制,确保不超过前100名
+            $actualLimit = min($pageSize, $maxRankLimit - $offset);
+            // 从缓存数据中获取当前页的数据
+            $rankList = array_slice($cachedRankList, $offset, $actualLimit);
 
             // 转换为DTO对象
             $rankItems = [];
             foreach ($rankList as $index => $item) {
-                $rank        = $offset + $index + 1;
+                $rank = $offset + $index + 1;
                 $rankItems[] = WealthRankItemDto::fromArray((array)$item, $rank);
             }
 
@@ -479,48 +479,96 @@ class HouseLogic
 
             // 构建分页信息
             $pageInfo = [
-                'page'     => $page,
+                'page' => $page,
                 'per_page' => $pageSize,
-                'total'    => $this->getTotalWealthRankCount()
+                'total' => min($maxRankLimit, $this->getTotalWealthRankCount())
             ];
 
             return new WealthRankDto($rankItems, $userRank, 1, $pageInfo);
 
         } catch (\Exception $e) {
             Log::error('获取财富排行榜失败', [
-                'user_id'   => $userId,
-                'page'      => $page,
+                'user_id' => $userId,
+                'page' => $page,
                 'page_size' => $pageSize,
-                'error'     => $e->getMessage(),
-                'trace'     => $e->getTraceAsString()
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString()
             ]);
 
             return new WealthRankDto();
         }
     }
 
+    /**
+     * 获取财富排行榜缓存数据
+     *
+     * @return array
+     */
+    private function getWealthRankListCache(): array
+    {
+        // 限制只显示前100名
+        $maxRankLimit = 100;
+
+        // 尝试从缓存获取排行榜数据
+        $cacheKey = $this->cachePrefix . 'wealth_rank:top100';
+        $cachedRankList = Cache::get($cacheKey);
+
+        if (!$cachedRankList) {
+            // 查询前100名财富排行榜数据,按钻石余额降序排列,同余额按房屋等级降序排列
+            $cachedRankList = DB::table('fund as f')
+                ->join('users as u', 'f.user_id', '=', 'u.id')
+                ->leftJoin('farm_users as fu', 'f.user_id', '=', 'fu.user_id')
+                ->select([
+                    'f.user_id',
+                    'f.balance',
+                    'u.username',
+                    'fu.house_level'
+                ])
+                ->where('f.fund_id', 2) // 钻石资金类型
+                ->orderBy('f.balance', 'desc')
+                ->orderBy('fu.house_level', 'desc') // 同钻石余额按房屋等级排序
+                ->limit($maxRankLimit)
+                ->get()
+                ->toArray();
+
+            // 缓存10分钟
+            Cache::put($cacheKey, $cachedRankList, 600);
+        }
+
+        return $cachedRankList;
+    }
+
     /**
      * 获取用户的财富排名
      *
      * @param int $userId 用户ID
-     * @return int 排名,0表示未上榜
+     * @return int 排名,0表示未上榜或超出前100名
      */
     private function getUserWealthRank(int $userId): int
     {
         try {
+            // 尝试从缓存获取用户排名
+            $cacheKey = $this->cachePrefix . 'user_wealth_rank:' . $userId;
+            $cachedRank = Cache::get($cacheKey);
+
+            if ($cachedRank !== null) {
+                return $cachedRank;
+            }
+
             // 获取用户的钻石余额和房屋等级
             $userFund = DB::table('fund as f')
                 ->leftJoin('farm_users as fu', 'f.user_id', '=', 'fu.user_id')
-                ->select([ 'f.balance', 'fu.house_level' ])
+                ->select(['f.balance', 'fu.house_level'])
                 ->where('f.user_id', $userId)
                 ->where('f.fund_id', 2) // 钻石资金类型
                 ->first();
 
             if (!$userFund) {
+                Cache::put($cacheKey, 0, 600); // 缓存10分钟
                 return 0;
             }
 
-            $userBalance    = $userFund->balance ?? 0;
+            $userBalance = $userFund->balance ?? 0;
             $userHouseLevel = $userFund->house_level ?? 0;
 
             // 计算排名:比用户余额高的用户数量 + 同余额但房屋等级更高的用户数量 + 1
@@ -536,12 +584,22 @@ class HouseLogic
                 })
                 ->count();
 
-            return $rank + 1;
+            $finalRank = $rank + 1;
+
+            // 如果用户排名超出前100名,返回0表示未上榜
+            if ($finalRank > 100) {
+                $finalRank = 0;
+            }
+
+            // 缓存用户排名10分钟
+            Cache::put($cacheKey, $finalRank, 600);
+
+            return $finalRank;
 
         } catch (\Exception $e) {
             Log::error('获取用户财富排名失败', [
                 'user_id' => $userId,
-                'error'   => $e->getMessage()
+                'error' => $e->getMessage()
             ]);
 
             return 0;
@@ -549,16 +607,19 @@ class HouseLogic
     }
 
     /**
-     * 获取财富排行榜总数
+     * 获取财富排行榜总数(限制前100名)
      *
      * @return int
      */
     private function getTotalWealthRankCount(): int
     {
         try {
-            return DB::table('fund')
+            // 获取实际用户总数,但最多返回100
+            $actualCount = DB::table('fund')
                 ->where('fund_id', 2) // 钻石资金类型
                 ->count();
+
+            return min($actualCount, 100);
         } catch (\Exception $e) {
             Log::error('获取财富排行榜总数失败', [
                 'error' => $e->getMessage()