|
|
@@ -0,0 +1,267 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Module\Game\Logics\UserLogCollectors;
|
|
|
+
|
|
|
+use App\Module\Point\Models\PointLogModel;
|
|
|
+use App\Module\Point\Enums\LOG_TYPE;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 积分日志收集器
|
|
|
+ *
|
|
|
+ * 收集point_logs表的新增记录,转换为用户友好的日志消息
|
|
|
+ */
|
|
|
+class PointLogCollector extends BaseLogCollector
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * 源表名
|
|
|
+ *
|
|
|
+ * @var string
|
|
|
+ */
|
|
|
+ protected string $sourceTable = 'point_logs';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 源类型
|
|
|
+ *
|
|
|
+ * @var string
|
|
|
+ */
|
|
|
+ protected string $sourceType = 'point';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取新的记录
|
|
|
+ *
|
|
|
+ * @param int $lastProcessedId 上次处理的最大ID
|
|
|
+ * @return \Illuminate\Database\Eloquent\Collection
|
|
|
+ */
|
|
|
+ protected function getNewRecords(int $lastProcessedId)
|
|
|
+ {
|
|
|
+ return PointLogModel::where('id', '>', $lastProcessedId)
|
|
|
+ ->orderBy('id')
|
|
|
+ ->limit($this->maxRecords)
|
|
|
+ ->get();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按时间获取新记录
|
|
|
+ *
|
|
|
+ * @param int $lastProcessedTimestamp 上次处理的时间戳
|
|
|
+ * @return \Illuminate\Database\Eloquent\Collection
|
|
|
+ */
|
|
|
+ protected function getNewRecordsByTime(int $lastProcessedTimestamp)
|
|
|
+ {
|
|
|
+ return PointLogModel::where('create_time', '>', $lastProcessedTimestamp)
|
|
|
+ ->orderBy('create_time')
|
|
|
+ ->orderBy('id')
|
|
|
+ ->limit($this->maxRecords)
|
|
|
+ ->get();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取记录的时间戳
|
|
|
+ *
|
|
|
+ * @param PointLogModel $record 积分日志记录
|
|
|
+ * @return int 时间戳
|
|
|
+ */
|
|
|
+ protected function getRecordTimestamp($record): int
|
|
|
+ {
|
|
|
+ return $record->create_time;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取记录的ID
|
|
|
+ *
|
|
|
+ * @param PointLogModel $record 积分日志记录
|
|
|
+ * @return int 记录ID
|
|
|
+ */
|
|
|
+ protected function getRecordId($record): int
|
|
|
+ {
|
|
|
+ return $record->id;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转换记录为用户日志数据
|
|
|
+ *
|
|
|
+ * @param PointLogModel $record 积分日志记录
|
|
|
+ * @return array|null 用户日志数据,null表示跳过
|
|
|
+ */
|
|
|
+ protected function convertToUserLog($record): ?array
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ // 检查是否应该记录此日志
|
|
|
+ if (!$this->shouldLogRecord($record)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ // 获取积分类型名称
|
|
|
+ $pointTypeName = $record->getPointTypeName();
|
|
|
+
|
|
|
+ // 判断是获得还是消耗
|
|
|
+ $amount = abs($record->amount);
|
|
|
+ $action = $record->amount > 0 ? '获得' : '消耗';
|
|
|
+
|
|
|
+ // 解析备注信息,生成用户友好的消息
|
|
|
+ $message = $this->buildUserFriendlyMessage($record, $pointTypeName, $action, $amount);
|
|
|
+
|
|
|
+ // 使用原始记录的时间
|
|
|
+ $createdAt = date('Y-m-d H:i:s', $record->create_time);
|
|
|
+
|
|
|
+ return $this->createUserLogData(
|
|
|
+ $record->user_id,
|
|
|
+ $message,
|
|
|
+ $record->id,
|
|
|
+ $createdAt
|
|
|
+ );
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ \Illuminate\Support\Facades\Log::error("转换积分日志失败", [
|
|
|
+ 'record_id' => $record->id,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建用户友好的消息
|
|
|
+ *
|
|
|
+ * @param PointLogModel $record 积分日志记录
|
|
|
+ * @param string $pointTypeName 积分类型名称
|
|
|
+ * @param string $action 操作类型(获得/消耗)
|
|
|
+ * @param int $amount 积分数量
|
|
|
+ * @return string 用户友好的消息
|
|
|
+ */
|
|
|
+ private function buildUserFriendlyMessage(PointLogModel $record, string $pointTypeName, string $action, int $amount): string
|
|
|
+ {
|
|
|
+ // 获取操作类型名称
|
|
|
+ $operateTypeName = $this->getOperateTypeName($record->operate_type);
|
|
|
+
|
|
|
+ // 根据操作类型生成不同的消息格式
|
|
|
+ $message = match($record->operate_type) {
|
|
|
+ LOG_TYPE::TASK_COMPLETE => "完成任务{$action} {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::CHECKIN_REWARD => "签到{$action} {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::ACTIVITY_REWARD => "活动奖励{$action} {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::ACHIEVEMENT_REWARD => "成就奖励{$action} {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::REFERRAL_REWARD => "推荐奖励{$action} {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::POINT_CONSUME => "消费{$action} {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::POINT_EXCHANGE => "兑换{$action} {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::TRANSFER => $this->buildTransferMessage($record, $pointTypeName, $action, $amount),
|
|
|
+ LOG_TYPE::CIRCULATION => "积分流转{$action} {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::ADMIN_OPERATE => "管理员操作{$action} {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::FREEZE => "冻结 {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::UNFREEZE => "解冻 {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::REFUND => "退还 {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::DEDUCT => "扣除 {$amount} {$pointTypeName}",
|
|
|
+ LOG_TYPE::SYSTEM_REWARD => "系统奖励{$action} {$amount} {$pointTypeName}",
|
|
|
+ default => "{$operateTypeName}{$action} {$amount} {$pointTypeName}",
|
|
|
+ };
|
|
|
+
|
|
|
+ // 如果有备注且不是默认备注,添加到消息中
|
|
|
+ if (!empty($record->remark) && !$this->isDefaultRemark($record->remark)) {
|
|
|
+ $message .= "({$record->remark})";
|
|
|
+ }
|
|
|
+
|
|
|
+ return $message;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建转账消息
|
|
|
+ *
|
|
|
+ * @param PointLogModel $record 积分日志记录
|
|
|
+ * @param string $pointTypeName 积分类型名称
|
|
|
+ * @param string $action 操作类型(未使用,保持接口一致性)
|
|
|
+ * @param int $amount 积分数量
|
|
|
+ * @return string 转账消息
|
|
|
+ */
|
|
|
+ private function buildTransferMessage(PointLogModel $record, string $pointTypeName, string $action, int $amount): string
|
|
|
+ {
|
|
|
+ // 根据金额正负判断是转入还是转出
|
|
|
+ if ($record->amount > 0) {
|
|
|
+ return "收到转账 {$amount} {$pointTypeName}";
|
|
|
+ } else {
|
|
|
+ return "转账给他人 {$amount} {$pointTypeName}";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取操作类型名称
|
|
|
+ *
|
|
|
+ * @param LOG_TYPE $operateType 操作类型
|
|
|
+ * @return string 操作类型名称
|
|
|
+ */
|
|
|
+ private function getOperateTypeName(LOG_TYPE $operateType): string
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ return $operateType->getTypeName();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return "未知操作";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断是否为默认备注
|
|
|
+ *
|
|
|
+ * @param string $remark 备注内容
|
|
|
+ * @return bool 是否为默认备注
|
|
|
+ */
|
|
|
+ private function isDefaultRemark(string $remark): bool
|
|
|
+ {
|
|
|
+ $defaultRemarks = [
|
|
|
+ '系统操作',
|
|
|
+ '自动操作',
|
|
|
+ '默认备注',
|
|
|
+ '',
|
|
|
+ ];
|
|
|
+
|
|
|
+ return in_array(trim($remark), $defaultRemarks);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查是否应该记录此日志
|
|
|
+ *
|
|
|
+ * @param PointLogModel $record 积分日志记录
|
|
|
+ * @return bool 是否应该记录
|
|
|
+ */
|
|
|
+ private function shouldLogRecord(PointLogModel $record): bool
|
|
|
+ {
|
|
|
+ // 过滤掉测试操作
|
|
|
+ if ($record->operate_type === LOG_TYPE::TEST) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 过滤掉金额为0的记录
|
|
|
+ if ($record->amount == 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 过滤掉系统内部操作(可根据需要调整)
|
|
|
+ $internalOperations = [
|
|
|
+ // 可以在这里添加需要过滤的内部操作类型
|
|
|
+ ];
|
|
|
+
|
|
|
+ if (in_array($record->operate_type, $internalOperations)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据记录ID获取原始记录的时间戳
|
|
|
+ *
|
|
|
+ * @param int $recordId 记录ID
|
|
|
+ * @return int 时间戳
|
|
|
+ */
|
|
|
+ protected function getOriginalRecordTimestamp(int $recordId): int
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ $record = PointLogModel::find($recordId);
|
|
|
+ return $record ? $record->create_time : 0;
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ \Illuminate\Support\Facades\Log::error("获取积分日志时间戳失败", [
|
|
|
+ 'record_id' => $recordId,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|