Răsfoiți Sursa

适配user_log模块使用新的奖励枚举

- 修复REWARD_SOURCE_TYPE枚举中的常量名不匹配问题
- 更新UserLogController使用新的奖励枚举显示和筛选
- 创建UserLogSourceTypeCast类处理source_type字段转换
- 在UserLog模型中添加访问器获取枚举相关信息
- 更新UserLogService添加使用枚举的方法
- 修改FundLogCollector和ItemLogCollector根据操作类型动态选择source_type
- 后台管理界面现在显示带图标的奖励类型名称
notfff 6 luni în urmă
părinte
comite
8105f929f9

+ 67 - 36
app/Module/Game/AdminControllers/UserLogController.php

@@ -2,6 +2,7 @@
 
 namespace App\Module\Game\AdminControllers;
 
+use App\Module\Game\Enums\REWARD_SOURCE_TYPE;
 use App\Module\Game\Models\UserLog;
 use App\Module\Game\Services\UserLogService;
 use Dcat\Admin\Form;
@@ -42,20 +43,41 @@ class UserLogController extends AdminController
                 ->help('用户操作的详细描述');
 
             $grid->column('source_type', '来源类型')
-                ->using([
-                    'fund' => '资金',
-                    'item' => '物品',
-                    'farm' => '农场',
-                    'pet' => '宠物',
-                    'system' => '系统',
-                ])
-                ->label([
-                    'fund' => 'success',
-                    'item' => 'primary',
-                    'farm' => 'warning',
-                    'pet' => 'info',
-                    'system' => 'default',
-                ]);
+                ->display(function ($value) {
+                    if (!$value) {
+                        return '<span class="label label-default">未知</span>';
+                    }
+
+                    // 使用枚举获取名称和信息
+                    if (REWARD_SOURCE_TYPE::isValid($value)) {
+                        $info = REWARD_SOURCE_TYPE::getTypeInfo($value);
+                        $name = $info['name'];
+                        $icon = $info['icon'];
+                        $category = $info['category'];
+
+                        // 根据分类设置标签颜色
+                        $labelColors = [
+                            'gameplay' => 'primary',
+                            'event' => 'warning',
+                            'daily' => 'info',
+                            'achievement' => 'success',
+                            'progression' => 'success',
+                            'farm' => 'warning',
+                            'social' => 'info',
+                            'shop' => 'primary',
+                            'promotion' => 'danger',
+                            'competition' => 'success',
+                            'special' => 'warning',
+                            'system' => 'default',
+                            'unknown' => 'default'
+                        ];
+
+                        $color = $labelColors[$category] ?? 'default';
+                        return "<span class=\"label label-{$color}\" title=\"{$info['description']}\">{$icon} {$name}</span>";
+                    }
+
+                    return "<span class=\"label label-default\">{$value}</span>";
+                });
 
             $grid->column('source_id', '来源ID');
 
@@ -87,14 +109,17 @@ class UserLogController extends AdminController
             $grid->filter(function (Grid\Filter $filter) {
                 $filter->equal('user_id', '用户ID');
                 $filter->like('message', '日志消息');
+
+                // 使用枚举生成来源类型选项
+                $sourceTypeOptions = [];
+                foreach (REWARD_SOURCE_TYPE::cases() as $case) {
+                    $info = REWARD_SOURCE_TYPE::getTypeInfo($case->value);
+                    $sourceTypeOptions[$case->value] = $info['icon'] . ' ' . $info['name'];
+                }
+
                 $filter->equal('source_type', '来源类型')
-                    ->select([
-                        'fund' => '资金',
-                        'item' => '物品',
-                        'farm' => '农场',
-                        'pet' => '宠物',
-                        'system' => '系统',
-                    ]);
+                    ->select($sourceTypeOptions);
+
                 $filter->between('created_at', '创建时间')->datetime();
             });
 
@@ -141,13 +166,18 @@ class UserLogController extends AdminController
                 ->unescape();
 
             $show->field('source_type', '来源类型')
-                ->using([
-                    'fund' => '资金',
-                    'item' => '物品',
-                    'farm' => '农场',
-                    'pet' => '宠物',
-                    'system' => '系统',
-                ]);
+                ->as(function ($value) {
+                    if (!$value) {
+                        return '未知';
+                    }
+
+                    if (REWARD_SOURCE_TYPE::isValid($value)) {
+                        $info = REWARD_SOURCE_TYPE::getTypeInfo($value);
+                        return $info['icon'] . ' ' . $info['name'] . ' (' . $info['description'] . ')';
+                    }
+
+                    return $value;
+                });
 
             $show->field('source_id', '来源ID');
 
@@ -180,15 +210,16 @@ class UserLogController extends AdminController
                 ->rows(3)
                 ->help('用户操作的详细描述');
 
+            // 使用枚举生成来源类型选项
+            $sourceTypeOptions = [];
+            foreach (REWARD_SOURCE_TYPE::cases() as $case) {
+                $info = REWARD_SOURCE_TYPE::getTypeInfo($case->value);
+                $sourceTypeOptions[$case->value] = $info['icon'] . ' ' . $info['name'];
+            }
+
             $form->select('source_type', '来源类型')
-                ->options([
-                    'fund' => '资金',
-                    'item' => '物品',
-                    'farm' => '农场',
-                    'pet' => '宠物',
-                    'system' => '系统',
-                ])
-                ->help('日志来源的模块类型');
+                ->options($sourceTypeOptions)
+                ->help('日志来源的模块类型,使用标准化的奖励来源枚举');
 
             $form->number('source_id', '来源ID')
                 ->help('关联的业务记录ID');

+ 56 - 0
app/Module/Game/Casts/UserLogSourceTypeCast.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace App\Module\Game\Casts;
+
+use App\Module\Game\Enums\REWARD_SOURCE_TYPE;
+use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
+
+/**
+ * 用户日志来源类型转换器
+ * 
+ * 将数据库中的字符串值转换为枚举对象,并提供相关信息
+ */
+class UserLogSourceTypeCast implements CastsAttributes
+{
+    /**
+     * 将取出的数据进行转换
+     *
+     * @param  \Illuminate\Database\Eloquent\Model  $model
+     * @param  string  $key
+     * @param  mixed  $value
+     * @param  array  $attributes
+     * @return mixed
+     */
+    public function get($model, string $key, $value, array $attributes)
+    {
+        if (!$value) {
+            return null;
+        }
+
+        // 检查是否为有效的枚举值
+        if (REWARD_SOURCE_TYPE::isValid($value)) {
+            return REWARD_SOURCE_TYPE::from($value);
+        }
+
+        // 如果不是有效的枚举值,返回原始值
+        return $value;
+    }
+
+    /**
+     * 转换成将要进行存储的值
+     *
+     * @param  \Illuminate\Database\Eloquent\Model  $model
+     * @param  string  $key
+     * @param  mixed  $value
+     * @param  array  $attributes
+     * @return mixed
+     */
+    public function set($model, string $key, $value, array $attributes)
+    {
+        if ($value instanceof REWARD_SOURCE_TYPE) {
+            return $value->value;
+        }
+
+        return $value;
+    }
+}

+ 3 - 3
app/Module/Game/Enums/REWARD_SOURCE_TYPE.php

@@ -404,7 +404,7 @@ enum REWARD_SOURCE_TYPE: string
             ],
 
             // 推广系统
-            self::PROMOTION_REWARD->value => [
+            self::URSPROMOTION_REWARD->value => [
                 'name' => 'URS推广奖励',
                 'description' => 'URS推广系统发放的奖励',
                 'category' => 'promotion',
@@ -412,7 +412,7 @@ enum REWARD_SOURCE_TYPE: string
                 'icon' => '💰',
                 'priority' => 50
             ],
-            self::USER_REGISTER_TEST->value => [
+            self::URSPROMOTION_REGISTER->value => [
                 'name' => 'URS推广注册测试',
                 'description' => 'URS推广系统注册测试奖励',
                 'category' => 'promotion',
@@ -420,7 +420,7 @@ enum REWARD_SOURCE_TYPE: string
                 'icon' => '🧪',
                 'priority' => 51
             ],
-            self::PROMOTION_LEVEL->value => [
+            self::URSPROMOTION_LEVEL->value => [
                 'name' => '推广等级',
                 'description' => '推广等级提升获得的奖励',
                 'category' => 'promotion',

+ 85 - 4
app/Module/Game/Logics/UserLogCollectors/FundLogCollector.php

@@ -4,6 +4,7 @@ namespace App\Module\Game\Logics\UserLogCollectors;
 
 use App\Module\Fund\Models\FundLogModel;
 use App\Module\Fund\Services\AccountService;
+use App\Module\Game\Enums\REWARD_SOURCE_TYPE;
 
 /**
  * 资金日志收集器
@@ -20,11 +21,11 @@ class FundLogCollector extends BaseLogCollector
     protected string $sourceTable = 'fund_logs';
 
     /**
-     * 源类型
+     * 默认源类型 - 使用系统奖励枚举
      *
      * @var string
      */
-    protected string $sourceType = 'fund';
+    protected string $sourceType = 'system';
 
     /**
      * 商店商品名称缓存
@@ -111,11 +112,15 @@ class FundLogCollector extends BaseLogCollector
             // 使用原始记录的时间
             $createdAt = date('Y-m-d H:i:s', $record->create_time);
 
-            return $this->createUserLogData(
+            // 根据操作类型选择合适的source_type
+            $sourceType = $this->getSourceTypeByRemark($record->remark);
+
+            return $this->createUserLogDataWithSourceType(
                 $record->user_id,
                 $message,
                 $record->id,
-                $createdAt
+                $createdAt,
+                $sourceType
             );
 
         } catch (\Exception $e) {
@@ -339,4 +344,80 @@ class FundLogCollector extends BaseLogCollector
 
         return $this->convertToUserLog($record);
     }
+
+    /**
+     * 根据备注信息获取合适的source_type
+     *
+     * @param string $remark 备注内容
+     * @return string
+     */
+    private function getSourceTypeByRemark(string $remark): string
+    {
+        $remarkInfo = $this->parseRemark($remark);
+
+        if (isset($remarkInfo['source'])) {
+            switch ($remarkInfo['source']) {
+                case 'shop_buy':
+                    return REWARD_SOURCE_TYPE::SHOP_PURCHASE->value;
+
+                case 'chest_open':
+                case '开启宝箱':
+                    return REWARD_SOURCE_TYPE::CHEST->value;
+
+                case 'house_upgrade':
+                case 'land_upgrade':
+                    return REWARD_SOURCE_TYPE::FARM_UPGRADE->value;
+
+                case 'task_reward':
+                    return REWARD_SOURCE_TYPE::TASK->value;
+
+                case 'system_gift':
+                    return REWARD_SOURCE_TYPE::SYSTEM->value;
+
+                case 'admin_operation':
+                    return REWARD_SOURCE_TYPE::ADMIN_GRANT->value;
+
+                case 'test_command':
+                    return REWARD_SOURCE_TYPE::TEST->value;
+
+                default:
+                    return REWARD_SOURCE_TYPE::SYSTEM->value;
+            }
+        }
+
+        return REWARD_SOURCE_TYPE::SYSTEM->value;
+    }
+
+    /**
+     * 创建用户日志数据数组(带自定义source_type)
+     *
+     * @param int $userId 用户ID
+     * @param string $message 日志消息
+     * @param int $sourceId 来源记录ID
+     * @param string|null $originalTime 原始时间(业务发生时间),null则使用当前时间
+     * @param string $sourceType 来源类型
+     * @return array
+     */
+    protected function createUserLogDataWithSourceType(
+        int $userId,
+        string $message,
+        int $sourceId,
+        ?string $originalTime = null,
+        string $sourceType = null
+    ): array {
+        $now = now()->toDateTimeString();
+        $originalTime = $originalTime ?? $now;
+        $sourceType = $sourceType ?? $this->sourceType;
+
+        return [
+            'user_id' => $userId,
+            'message' => $message,
+            'source_type' => $sourceType,
+            'source_id' => $sourceId,
+            'source_table' => $this->sourceTable,
+            'original_time' => $originalTime,      // 原始业务时间
+            'collected_at' => $now,               // 收集时间
+            'created_at' => $now,                 // 兼容字段
+        ];
+    }
 }

+ 87 - 4
app/Module/Game/Logics/UserLogCollectors/ItemLogCollector.php

@@ -4,6 +4,7 @@ namespace App\Module\Game\Logics\UserLogCollectors;
 
 use App\Module\GameItems\Models\ItemTransactionLog;
 use App\Module\GameItems\Services\ItemService;
+use App\Module\Game\Enums\REWARD_SOURCE_TYPE;
 
 /**
  * 物品日志收集器
@@ -20,11 +21,11 @@ class ItemLogCollector extends BaseLogCollector
     protected string $sourceTable = 'item_transaction_logs';
 
     /**
-     * 源类型
+     * 默认源类型
      *
      * @var string
      */
-    protected string $sourceType = 'item';
+    protected string $sourceType = 'system';
 
     /**
      * 物品名称缓存
@@ -103,11 +104,15 @@ class ItemLogCollector extends BaseLogCollector
                 return null; // 跳过无法生成消息的记录
             }
 
-            return $this->createUserLogData(
+            // 根据操作类型选择合适的source_type
+            $sourceType = $this->getSourceTypeByOperation($record->source_type);
+
+            return $this->createUserLogDataWithSourceType(
                 $record->user_id,
                 $message,
                 $record->id,
-                $record->created_at
+                $record->created_at,
+                $sourceType
             );
 
         } catch (\Exception $e) {
@@ -426,4 +431,82 @@ class ItemLogCollector extends BaseLogCollector
 
         return !empty($extraInfo) ? '(' . implode(',', $extraInfo) . ')' : '';
     }
+
+    /**
+     * 根据操作类型获取合适的source_type
+     *
+     * @param string $sourceType 原始来源类型
+     * @return string
+     */
+    private function getSourceTypeByOperation(string $sourceType): string
+    {
+        switch ($sourceType) {
+            case 'house_upgrade':
+            case 'land_upgrade':
+                return REWARD_SOURCE_TYPE::FARM_UPGRADE->value;
+
+            case 'land_sow':
+                return REWARD_SOURCE_TYPE::FARM_PLANT->value;
+
+            case 'land_remove_crop':
+                return REWARD_SOURCE_TYPE::LAND_REMOVE_CROP->value;
+
+            case 'shop_buy':
+                return REWARD_SOURCE_TYPE::SHOP_PURCHASE->value;
+
+            case 'task_reward':
+                return REWARD_SOURCE_TYPE::TASK->value;
+
+            case 'admin_add':
+                return REWARD_SOURCE_TYPE::ADMIN_GRANT->value;
+
+            case 'chest':
+                return REWARD_SOURCE_TYPE::CHEST->value;
+
+            case 'craft':
+                return REWARD_SOURCE_TYPE::CRAFT->value;
+
+            case 'farm':
+                return REWARD_SOURCE_TYPE::FARM_HARVEST->value;
+
+            case 'pet':
+                return REWARD_SOURCE_TYPE::SYSTEM->value;
+
+            default:
+                return REWARD_SOURCE_TYPE::SYSTEM->value;
+        }
+    }
+
+    /**
+     * 创建用户日志数据数组(带自定义source_type)
+     *
+     * @param int $userId 用户ID
+     * @param string $message 日志消息
+     * @param int $sourceId 来源记录ID
+     * @param string|null $originalTime 原始时间(业务发生时间),null则使用当前时间
+     * @param string $sourceType 来源类型
+     * @return array
+     */
+    protected function createUserLogDataWithSourceType(
+        int $userId,
+        string $message,
+        int $sourceId,
+        ?string $originalTime = null,
+        string $sourceType = null
+    ): array {
+        $now = now()->toDateTimeString();
+        $originalTime = $originalTime ?? $now;
+        $sourceType = $sourceType ?? $this->sourceType;
+
+        return [
+            'user_id' => $userId,
+            'message' => $message,
+            'source_type' => $sourceType,
+            'source_id' => $sourceId,
+            'source_table' => $this->sourceTable,
+            'original_time' => $originalTime,      // 原始业务时间
+            'collected_at' => $now,               // 收集时间
+            'created_at' => $now,                 // 兼容字段
+        ];
+    }
 }

+ 113 - 0
app/Module/Game/Models/UserLog.php

@@ -2,6 +2,8 @@
 
 namespace App\Module\Game\Models;
 
+use App\Module\Game\Casts\UserLogSourceTypeCast;
+use App\Module\Game\Enums\REWARD_SOURCE_TYPE;
 use UCore\ModelCore;
 
 /**
@@ -76,6 +78,7 @@ class UserLog extends ModelCore
     protected $casts = [
         'user_id' => 'integer',
         'source_id' => 'integer',
+        'source_type' => UserLogSourceTypeCast::class,
         'original_time' => 'datetime',
         'collected_at' => 'datetime',
         'created_at' => 'datetime',
@@ -226,4 +229,114 @@ class UserLog extends ModelCore
         }
         return $this->collected_at->timestamp - $this->original_time->timestamp;
     }
+
+    /**
+     * 获取来源类型名称
+     *
+     * @return string
+     */
+    public function getSourceTypeNameAttribute(): string
+    {
+        if (!$this->source_type) {
+            return '未知';
+        }
+
+        if ($this->source_type instanceof REWARD_SOURCE_TYPE) {
+            $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type->value);
+            return $info['name'];
+        }
+
+        // 兼容旧数据
+        if (is_string($this->source_type) && REWARD_SOURCE_TYPE::isValid($this->source_type)) {
+            $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type);
+            return $info['name'];
+        }
+
+        return $this->source_type;
+    }
+
+    /**
+     * 获取来源类型图标
+     *
+     * @return string
+     */
+    public function getSourceTypeIconAttribute(): string
+    {
+        if (!$this->source_type) {
+            return '❓';
+        }
+
+        if ($this->source_type instanceof REWARD_SOURCE_TYPE) {
+            $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type->value);
+            return $info['icon'];
+        }
+
+        // 兼容旧数据
+        if (is_string($this->source_type) && REWARD_SOURCE_TYPE::isValid($this->source_type)) {
+            $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type);
+            return $info['icon'];
+        }
+
+        return '❓';
+    }
+
+    /**
+     * 获取来源类型分类
+     *
+     * @return string
+     */
+    public function getSourceTypeCategoryAttribute(): string
+    {
+        if (!$this->source_type) {
+            return 'unknown';
+        }
+
+        if ($this->source_type instanceof REWARD_SOURCE_TYPE) {
+            $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type->value);
+            return $info['category'];
+        }
+
+        // 兼容旧数据
+        if (is_string($this->source_type) && REWARD_SOURCE_TYPE::isValid($this->source_type)) {
+            $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type);
+            return $info['category'];
+        }
+
+        return 'unknown';
+    }
+
+    /**
+     * 获取来源类型完整信息
+     *
+     * @return array
+     */
+    public function getSourceTypeInfoAttribute(): array
+    {
+        if (!$this->source_type) {
+            return [
+                'name' => '未知',
+                'description' => '未知来源类型',
+                'category' => 'unknown',
+                'icon' => '❓',
+                'priority' => 999
+            ];
+        }
+
+        if ($this->source_type instanceof REWARD_SOURCE_TYPE) {
+            return REWARD_SOURCE_TYPE::getTypeInfo($this->source_type->value);
+        }
+
+        // 兼容旧数据
+        if (is_string($this->source_type) && REWARD_SOURCE_TYPE::isValid($this->source_type)) {
+            return REWARD_SOURCE_TYPE::getTypeInfo($this->source_type);
+        }
+
+        return [
+            'name' => $this->source_type,
+            'description' => '未知来源类型',
+            'category' => 'unknown',
+            'icon' => '❓',
+            'priority' => 999
+        ];
+    }
 }

+ 22 - 0
app/Module/Game/Services/UserLogService.php

@@ -2,6 +2,7 @@
 
 namespace App\Module\Game\Services;
 
+use App\Module\Game\Enums\REWARD_SOURCE_TYPE;
 use App\Module\Game\Logics\UserLogLogic;
 use App\Module\Game\Models\UserLog;
 use Illuminate\Pagination\LengthAwarePaginator;
@@ -33,6 +34,27 @@ class UserLogService
         return UserLogLogic::log($userId, $message, $sourceType, $sourceId, $sourceTable);
     }
 
+    /**
+     * 使用枚举记录用户日志
+     *
+     * @param int $userId 用户ID
+     * @param string $message 日志消息
+     * @param REWARD_SOURCE_TYPE|null $sourceType 来源类型枚举
+     * @param int|null $sourceId 来源记录ID
+     * @param string|null $sourceTable 来源表名
+     * @return UserLog|null
+     */
+    public static function logWithEnum(
+        int $userId,
+        string $message,
+        ?REWARD_SOURCE_TYPE $sourceType = null,
+        ?int $sourceId = null,
+        ?string $sourceTable = null
+    ): ?UserLog {
+        $sourceTypeValue = $sourceType ? $sourceType->value : null;
+        return UserLogLogic::log($userId, $message, $sourceTypeValue, $sourceId, $sourceTable);
+    }
+
     /**
      * 批量记录用户日志
      *