', $lastProcessedId) ->orderBy('id') ->limit($this->maxRecords) ->get(); } /** * 获取源表的最大ID * * 重写父类方法,使用模型查询以获得更好的性能 * * @return int */ public function getSourceTableMaxId(): int { return PointLogModel::max('id') ?: 0; } /** * 转换记录为用户日志数据 * * @param PointLogModel $record 积分日志记录 * @return array|null 用户日志数据,null表示跳过 */ protected function convertToUserLog($record): ?array { try { // 检查是否应该记录此日志 if (!$this->shouldLogRecord($record)) { return null; } // 获取积分类型名称 $pointTypeName = $this->getPointTypeName($record->point_type); // 判断是获得还是消耗 $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::PLANTING_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 { // 使用静态映射避免调用可能有问题的方法 $operateTypeNames = [ 'TASK_COMPLETE' => '任务完成', 'CHECKIN_REWARD' => '签到奖励', 'ACTIVITY_REWARD' => '活动奖励', 'ACHIEVEMENT_REWARD' => '成就奖励', 'REFERRAL_REWARD' => '推荐奖励', 'PLANTING_REWARD' => '种植奖励', 'POINT_CONSUME' => '积分消费', 'POINT_EXCHANGE' => '积分兑换', 'TRANSFER' => '积分转账', 'CIRCULATION' => '积分流转', 'ADMIN_OPERATE' => '管理员操作', 'FREEZE' => '积分冻结', 'UNFREEZE' => '积分解冻', 'REFUND' => '积分退还', 'DEDUCT' => '积分扣除', 'SYSTEM_REWARD' => '系统奖励', ]; $typeName = $operateType->name ?? (string)$operateType; return $operateTypeNames[$typeName] ?? "未知操作"; } 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; } /** * 获取积分类型名称 * * @param mixed $pointType 积分类型 * @return string */ private function getPointTypeName($pointType): string { // 使用静态映射避免调用可能有问题的方法 $pointTypeNames = [ 1 => '经验积分', 2 => '活动积分', 3 => '任务积分', 4 => '签到积分', // 可以根据需要添加更多 ]; $pointKey = is_object($pointType) ? $pointType->value : $pointType; return $pointTypeNames[$pointKey] ?? "积分{$pointKey}"; } }