$log->id, 'user_id' => $log->user_id, 'point_id' => $log->point_id, 'amount' => $log->amount, 'operate_id' => $log->operate_id, 'operate_type' => $log->operate_type->value, 'operate_type_name' => $log->getOperateTypeName(), 'remark' => $log->remark, 'create_time' => $log->create_time, 'create_ip' => $log->create_ip, 'later_balance' => $log->later_balance, 'before_balance' => $log->before_balance, 'is_income' => $log->isIncome(), 'is_expense' => $log->isExpense(), ]); } return $result; } /** * 获取用户指定时间范围的积分日志 * * @param int $userId 用户ID * @param int $startTime 开始时间 * @param int $endTime 结束时间 * @param int|null $pointId 积分类型ID(可选) * @return array 日志DTO数组 */ public static function getUserLogsByTimeRange( int $userId, int $startTime, int $endTime, ?int $pointId = null ): array { $logs = PointLogModel::getUserLogsByTimeRange($userId, $startTime, $endTime, $pointId); $result = []; foreach ($logs as $log) { $result[] = new PointLogDto([ 'id' => $log->id, 'user_id' => $log->user_id, 'point_id' => $log->point_id, 'amount' => $log->amount, 'operate_id' => $log->operate_id, 'operate_type' => $log->operate_type->value, 'operate_type_name' => $log->getOperateTypeName(), 'remark' => $log->remark, 'create_time' => $log->create_time, 'create_ip' => $log->create_ip, 'later_balance' => $log->later_balance, 'before_balance' => $log->before_balance, 'is_income' => $log->isIncome(), 'is_expense' => $log->isExpense(), ]); } return $result; } /** * 获取用户积分收支统计 * * @param int $userId 用户ID * @param int|null $pointId 积分类型ID(可选) * @param int|null $startTime 开始时间(可选) * @param int|null $endTime 结束时间(可选) * @return array 统计信息 */ public static function getUserPointStats( int $userId, ?int $pointId = null, ?int $startTime = null, ?int $endTime = null ): array { $query = PointLogModel::where('user_id', $userId); if ($pointId !== null) { $query->where('point_id', $pointId); } if ($startTime !== null && $endTime !== null) { $query->whereBetween('create_time', [$startTime, $endTime]); } $logs = $query->get(); $stats = [ 'total_logs' => $logs->count(), 'total_income' => 0, 'total_expense' => 0, 'income_count' => 0, 'expense_count' => 0, 'by_operate_type' => [], ]; foreach ($logs as $log) { if ($log->isIncome()) { $stats['total_income'] += $log->amount; $stats['income_count']++; } else { $stats['total_expense'] += abs($log->amount); $stats['expense_count']++; } $operateTypeName = $log->getOperateTypeName(); if (!isset($stats['by_operate_type'][$operateTypeName])) { $stats['by_operate_type'][$operateTypeName] = [ 'count' => 0, 'total_amount' => 0, ]; } $stats['by_operate_type'][$operateTypeName]['count']++; $stats['by_operate_type'][$operateTypeName]['total_amount'] += $log->amount; } return $stats; } /** * 验证日志记录的完整性 * * @param int $logId 日志ID * @return bool 是否完整 */ public static function verifyLogIntegrity(int $logId): bool { $log = PointLogModel::find($logId); return $log ? $log->verifyIntegrity() : false; } /** * 批量验证日志记录的完整性 * * @param array $logIds 日志ID数组 * @return array 验证结果数组 */ public static function batchVerifyLogIntegrity(array $logIds): array { $results = []; foreach ($logIds as $logId) { $results[$logId] = self::verifyLogIntegrity($logId); } return $results; } /** * 获取积分日志统计信息(按操作类型) * * @param int|null $pointId 积分类型ID(可选) * @param int|null $startTime 开始时间(可选) * @param int|null $endTime 结束时间(可选) * @return array 统计信息 */ public static function getLogStatsByOperateType( ?int $pointId = null, ?int $startTime = null, ?int $endTime = null ): array { $query = PointLogModel::query(); if ($pointId !== null) { $query->where('point_id', $pointId); } if ($startTime !== null && $endTime !== null) { $query->whereBetween('create_time', [$startTime, $endTime]); } $logs = $query->get(); $stats = []; foreach ($logs as $log) { $operateType = $log->operate_type->value; $operateTypeName = $log->getOperateTypeName(); if (!isset($stats[$operateType])) { $stats[$operateType] = [ 'operate_type' => $operateType, 'operate_type_name' => $operateTypeName, 'count' => 0, 'total_amount' => 0, 'income_count' => 0, 'expense_count' => 0, 'income_amount' => 0, 'expense_amount' => 0, ]; } $stats[$operateType]['count']++; $stats[$operateType]['total_amount'] += $log->amount; if ($log->isIncome()) { $stats[$operateType]['income_count']++; $stats[$operateType]['income_amount'] += $log->amount; } else { $stats[$operateType]['expense_count']++; $stats[$operateType]['expense_amount'] += abs($log->amount); } } return array_values($stats); } /** * 获取每日积分变化统计 * * @param int $userId 用户ID * @param int $pointId 积分类型ID * @param int $days 统计天数 * @return array 每日统计数组 */ public static function getDailyPointStats(int $userId, int $pointId, int $days = 30): array { $endTime = time(); $startTime = $endTime - ($days * 24 * 60 * 60); $logs = PointLogModel::where('user_id', $userId) ->where('point_id', $pointId) ->whereBetween('create_time', [$startTime, $endTime]) ->orderBy('create_time') ->get(); $dailyStats = []; // 初始化每日统计 for ($i = 0; $i < $days; $i++) { $date = date('Y-m-d', $endTime - ($i * 24 * 60 * 60)); $dailyStats[$date] = [ 'date' => $date, 'income' => 0, 'expense' => 0, 'net_change' => 0, 'log_count' => 0, ]; } // 统计每日数据 foreach ($logs as $log) { $date = date('Y-m-d', $log->create_time); if (isset($dailyStats[$date])) { $dailyStats[$date]['log_count']++; if ($log->isIncome()) { $dailyStats[$date]['income'] += $log->amount; } else { $dailyStats[$date]['expense'] += abs($log->amount); } $dailyStats[$date]['net_change'] = $dailyStats[$date]['income'] - $dailyStats[$date]['expense']; } } return array_values($dailyStats); } /** * 搜索积分日志 * * @param array $filters 搜索条件 * @param int $limit 限制数量 * @return array 日志数组 */ public static function searchLogs(array $filters, int $limit = 50): array { $query = PointLogModel::query(); if (isset($filters['user_id'])) { $query->where('user_id', $filters['user_id']); } if (isset($filters['point_id'])) { $query->where('point_id', $filters['point_id']); } if (isset($filters['operate_type'])) { $query->where('operate_type', $filters['operate_type']); } if (isset($filters['operate_id'])) { $query->where('operate_id', 'like', '%' . $filters['operate_id'] . '%'); } if (isset($filters['start_time']) && isset($filters['end_time'])) { $query->whereBetween('create_time', [$filters['start_time'], $filters['end_time']]); } if (isset($filters['min_amount'])) { $query->where('amount', '>=', $filters['min_amount']); } if (isset($filters['max_amount'])) { $query->where('amount', '<=', $filters['max_amount']); } $logs = $query->orderBy('create_time', 'desc')->limit($limit)->get(); $result = []; foreach ($logs as $log) { $result[] = [ 'id' => $log->id, 'user_id' => $log->user_id, 'point_id' => $log->point_id, 'amount' => $log->amount, 'operate_id' => $log->operate_id, 'operate_type' => $log->operate_type->value, 'operate_type_name' => $log->getOperateTypeName(), 'remark' => $log->remark, 'create_time' => $log->create_time, 'create_ip' => $log->create_ip, 'later_balance' => $log->later_balance, 'before_balance' => $log->before_balance, 'is_income' => $log->isIncome(), 'is_expense' => $log->isExpense(), ]; } return $result; } }