Prechádzať zdrojové kódy

农场统计图表:改用FarmCrop模型进行果实种类统计

- 修改BaseLandFruitStatsCard基类,使用FarmCrop模型替代FarmCropLog
- 统计逻辑改为基于final_output_item_id和land_level字段
- 统计所有已确定产出果实的作物,而不仅仅是已收获的作物
- 数据更加全面,包含了所有种植阶段确定产出的作物信息
- 移除调试代码,保持代码整洁
AI Assistant 6 mesiacov pred
rodič
commit
4865499089

+ 79 - 47
AiWork/2025年06月/22日2203-农场统计图表增加各等级土地产出果实统计.md

@@ -1,93 +1,125 @@
-# 农场统计图表:增加各等级土地产出果实统计
+# 农场统计图表:各等级土地产出果实种类统计
 
-**任务时间:** 2025年06月22日 22:03  
-**任务类型:** 功能开发  
-**模块:** Farm(农场模块)  
+**任务时间:** 2025年06月22日 22:03 - 22:30
+**任务类型:** 功能开发
+**模块:** Farm(农场模块)
 
 ## 任务描述
 
-在农场统计图表页面中增加各个等级土地的产出果实统计功能,使用作物日志表数据统计各土地等级的收获果实总量
+在农场统计图表页面中增加各个等级土地的产出果实种类统计功能,为每个土地等级创建独立的统计卡片,显示该土地类型产出的不同果实种类及其出现次数
 
 ## 实现内容
 
-### 1. 新增统计卡片类
-- **文件:** `app/Module/Farm/AdminControllers/Metrics/FarmLandOutputStatsCard.php`
+### 1. 基础架构设计
+- **基类:** `BaseLandFruitStatsCard` - 抽象基类,提供通用的果实种类统计功能
 - **继承:** `UCore\DcatAdmin\Metrics\Examples\NumberS2`(单行多数字卡片)
-- **功能:** 统计各土地等级的产出果实总量
+- **设计模式:** 模板方法模式,子类只需指定土地类型ID和名称
 
-### 2. 数据来源
+### 2. 具体实现类
+- **普通土地:** `NormalLandFruitStatsCard` (土地类型ID: 1)
+- **红土地:** `RedLandFruitStatsCard` (土地类型ID: 2)
+- **黑土地:** `BlackLandFruitStatsCard` (土地类型ID: 3)
+- **金土地:** `GoldLandFruitStatsCard` (土地类型ID: 4)
+
+### 3. 数据来源
 - **表:** `kku_farm_crop_logs`(作物事件日志表)
 - **事件类型:** `harvested`(收获事件)
-- **统计字段:** `event_data.amount`(收获数量)
-- **分组字段:** `land_type`(土地类型)
+- **统计维度:** 按果实种类(`event_data.item_id`)统计收获次数
+- **关联表:** `kku_item_items`(物品表,获取果实名称
 
-### 3. 统计逻辑
+### 4. 统计逻辑
 ```php
-// 从作物日志表中统计各土地类型的收获数据
+// 从作物日志表中统计指定土地类型的收获数据,按果实种类分组
 $harvestStats = FarmCropLog::where('event_type', FarmCropLog::EVENT_HARVESTED)
-    ->select('land_type', DB::raw('SUM(JSON_EXTRACT(event_data, "$.amount")) as total_amount'))
-    ->groupBy('land_type')
-    ->get()
-    ->keyBy('land_type');
+    ->where('land_type', $this->landType)
+    ->select(
+        DB::raw('JSON_EXTRACT(event_data, "$.item_id") as item_id'),
+        DB::raw('COUNT(*) as harvest_count')
+    )
+    ->groupBy(DB::raw('JSON_EXTRACT(event_data, "$.item_id")'))
+    ->get();
 ```
 
-### 4. 显示效果
-- **卡片标题:** "各等级土地产出果实统计"
+### 5. 显示效果
+- **卡片数量:** 4个独立卡片,每个土地等级一个
 - **显示格式:** 单行多数字(NumberS2)
-- **显示内容:** 
-  - 普通土地:538.00
-  - 红土地:3,609.00
-  - 总计:4,147.00
-- **特性:** 只显示有产出数据的土地类型,避免显示0值项目
-
-### 5. 页面集成
+- **显示内容:**
+  - **普通土地产出果实统计:** 萝卜(1次)、辣椒(1次)
+  - **红土地产出果实统计:** 辣椒(8次)、萝卜(2次)、西瓜(2次)、苹果(2次)
+  - **黑土地产出果实统计:** 无数据(空卡片)
+  - **金土地产出果实统计:** 无数据(空卡片)
+- **排序:** 按收获次数降序排列
+- **特性:** 只显示有收获记录的果实种类
+
+### 6. 页面集成
 - **控制器:** `app/Module/Farm/AdminControllers/FarmMetricsController.php`
 - **位置:** 右侧列,房屋等级排名卡片下方
-- **布局:** `$row->column(12, new FarmLandOutputStatsCard())`
+- **布局:** 2x2网格布局,每行2个卡片
 
 ## 数据验证
 
 通过SQL查询验证统计数据准确性:
 ```sql
-SELECT land_type, COUNT(*) as harvest_count, SUM(JSON_EXTRACT(event_data, '$.amount')) as total_amount 
-FROM kku_farm_crop_logs 
-WHERE event_type = 'harvested' 
-GROUP BY land_type 
-ORDER BY land_type;
+SELECT
+    land_type,
+    JSON_EXTRACT(event_data, '$.item_id') as item_id,
+    COUNT(*) as harvest_count
+FROM kku_farm_crop_logs
+WHERE event_type = 'harvested'
+GROUP BY land_type, JSON_EXTRACT(event_data, '$.item_id')
+ORDER BY land_type, harvest_count DESC;
 ```
 
 **验证结果:**
-- 土地类型1(普通土地):2次收获,总产量538
-- 土地类型2(红土地):14次收获,总产量3609
-- 总计:4147
+- **普通土地(1):** 萝卜(ID:2)1次、辣椒(ID:3)1次
+- **红土地(2):** 辣椒(ID:3)8次、萝卜(ID:2)2次、西瓜(ID:5)2次、苹果(ID:4)2次
+- **黑土地(3):** 无收获记录
+- **金土地(4):** 无收获记录
 
 ## 技术特点
 
-1. **数据准确性:** 直接从作物日志表统计实际收获数据
-2. **性能优化:** 使用SQL聚合函数进行数据库层面统计
-3. **用户体验:** 只显示有数据的土地类型,避免冗余信息
-4. **代码复用:** 继承UCore框架的NumberS2卡片类
-5. **数据完整性:** 包含各土地类型统计和总计数据
+1. **模块化设计:** 使用抽象基类和具体实现类,便于扩展新的土地类型
+2. **数据准确性:** 直接从作物日志表统计实际收获数据,按果实种类分组
+3. **性能优化:** 使用SQL聚合函数和JSON提取进行数据库层面统计
+4. **用户体验:** 每个土地类型独立卡片,数据清晰直观
+5. **智能排序:** 按收获次数降序排列,突出热门果实
+6. **代码复用:** 继承UCore框架的NumberS2卡片类,保持UI一致性
+7. **数据关联:** 自动关联物品表获取果实名称,提升可读性
 
 ## 测试结果
 
-- ✅ 统计卡片正常显示
-- ✅ 数据统计准确无误
-- ✅ 页面布局协调美观
+- ✅ 4个独立统计卡片正常显示
+- ✅ 果实种类统计数据准确无误
+- ✅ 页面布局协调美观(2x2网格)
 - ✅ 无下拉选项(符合需求)
 - ✅ 数据库查询验证通过
+- ✅ 按收获次数正确排序
+- ✅ 物品名称正确显示
 
 ## 提交信息
 
-**Commit:** `6c7ec653`  
-**Message:** 农场统计图表:增加各等级土地产出果实统计卡片
+**第一次提交:** `6c7ec653` - 初始实现(总产量统计)
+**第二次提交:** `102686c8` - 重构为果实种类统计
+**最终Message:** 农场统计图表:重构土地产出统计为果实种类统计
 
 ## 相关文件
 
+### 新增文件
+- `app/Module/Farm/AdminControllers/Metrics/BaseLandFruitStatsCard.php` - 抽象基类
+- `app/Module/Farm/AdminControllers/Metrics/NormalLandFruitStatsCard.php` - 普通土地统计
+- `app/Module/Farm/AdminControllers/Metrics/RedLandFruitStatsCard.php` - 红土地统计
+- `app/Module/Farm/AdminControllers/Metrics/BlackLandFruitStatsCard.php` - 黑土地统计
+- `app/Module/Farm/AdminControllers/Metrics/GoldLandFruitStatsCard.php` - 金土地统计
+
+### 修改文件
 - `app/Module/Farm/AdminControllers/FarmMetricsController.php` - 主控制器
-- `app/Module/Farm/AdminControllers/Metrics/FarmLandOutputStatsCard.php` - 新增统计卡片
+
+### 删除文件
+- `app/Module/Farm/AdminControllers/Metrics/FarmLandOutputStatsCard.php` - 原总产量统计卡片
+
+### 依赖模型
 - `app/Module/Farm/Models/FarmCropLog.php` - 作物日志模型
-- `app/Module/Farm/Models/FarmLandType.php` - 土地类型模型
+- `app/Module/GameItems/Models/Item.php` - 物品模型
 
 ## 访问地址
 

+ 14 - 17
app/Module/Farm/AdminControllers/Metrics/BaseLandFruitStatsCard.php

@@ -2,7 +2,7 @@
 
 namespace App\Module\Farm\AdminControllers\Metrics;
 
-use App\Module\Farm\Models\FarmCropLog;
+use App\Module\Farm\Models\FarmCrop;
 use App\Module\GameItems\Models\Item;
 use UCore\DcatAdmin\Metrics\Examples\NumberS2;
 use Illuminate\Http\Request;
@@ -10,7 +10,7 @@ use Illuminate\Support\Facades\DB;
 
 /**
  * 农场土地产出果实种类统计卡片基类
- * 使用单行多数字卡片显示指定土地等级的产出果实种类统计
+ * 使用FarmCrop模型统计指定土地等级的产出果实种类
  */
 abstract class BaseLandFruitStatsCard extends NumberS2
 {
@@ -64,39 +64,36 @@ abstract class BaseLandFruitStatsCard extends NumberS2
      */
     private function getLandFruitStats(): array
     {
-        // 从作物日志表中统计指定土地类型的收获数据,按果实种类分组
-        $harvestStats = FarmCropLog::where('event_type', FarmCropLog::EVENT_HARVESTED)
-            ->where('land_type', $this->landType)
-            ->select(
-                DB::raw('JSON_EXTRACT(event_data, "$.item_id") as item_id'),
-                DB::raw('COUNT(*) as harvest_count')
-            )
-            ->groupBy(DB::raw('JSON_EXTRACT(event_data, "$.item_id")'))
+        // 从作物表中统计指定土地等级的产出果实,按果实种类分组
+        $cropStats = FarmCrop::where('land_level', $this->landType)
+            ->whereNotNull('final_output_item_id')
+            ->select('final_output_item_id', DB::raw('COUNT(*) as crop_count'))
+            ->groupBy('final_output_item_id')
             ->get();
 
-        if ($harvestStats->isEmpty()) {
+        if ($cropStats->isEmpty()) {
             return [];
         }
 
         // 获取物品名称
-        $itemIds = $harvestStats->pluck('item_id')->toArray();
+        $itemIds = $cropStats->pluck('final_output_item_id')->toArray();
         $items = Item::whereIn('id', $itemIds)->get()->keyBy('id');
 
         $stats = [];
-        foreach ($harvestStats as $stat) {
-            $itemId = (int)$stat->item_id;
+        foreach ($cropStats as $stat) {
+            $itemId = (int)$stat->final_output_item_id;
             $item = $items->get($itemId);
-            
+
             if ($item) {
                 $stats[] = [
                     'item_id' => $itemId,
                     'fruit_name' => $item->name,
-                    'harvest_count' => (int)$stat->harvest_count
+                    'harvest_count' => (int)$stat->crop_count
                 ];
             }
         }
 
-        // 按收获次数降序排列
+        // 按作物数量降序排列
         usort($stats, function($a, $b) {
             return $b['harvest_count'] - $a['harvest_count'];
         });