where('is_admin_operation', false) // 只显示用户交易,不显示管理员操作 ->orderBy('created_at', 'desc'); if ($itemId) { $query->where('item_id', $itemId); } $transactions = $query->paginate($pageSize, ['*'], 'page', $page); $result = []; foreach ($transactions->items() as $transaction) { // 根据交易类型确定显示的用户ID // USER_SELL表示用户卖出,显示卖方ID;USER_BUY表示用户买入,显示买方ID $userId = ($transaction->transaction_type->value === 'USER_SELL') ? $transaction->seller_id : $transaction->buyer_id; $result[] = [ 'id' => $transaction->id, 'user_id' => $userId, 'item_id' => $transaction->item_id, 'quantity' => $transaction->quantity, 'price' => $transaction->price, 'total_amount' => $transaction->total_amount, 'transaction_type' => $transaction->transaction_type->value, 'transaction_type_desc' => $transaction->transaction_type->getDescription(), 'created_at' => $transaction->created_at, ]; } return [ 'transactions' => $result, 'total' => $transactions->total(), 'page' => $page, 'page_size' => $pageSize, ]; } /** * 获取用户成交记录 * * @param int $userId 用户ID * @param int $page 页码 * @param int $pageSize 每页数量 * @return array 成交记录列表 */ public static function getUserTransactions(int $userId, int $page = 1, int $pageSize = 20): array { $transactions = MexTransaction::where(function ($query) use ($userId) { $query->where('buyer_id', $userId) ->orWhere('seller_id', $userId); }) ->where('is_admin_operation', false) ->orderBy('created_at', 'desc') ->paginate($pageSize, ['*'], 'page', $page); $result = []; foreach ($transactions->items() as $transaction) { $isUserBuyer = $transaction->buyer_id === $userId; $isUserSeller = $transaction->seller_id === $userId; $result[] = [ 'id' => $transaction->id, 'item_id' => $transaction->item_id, 'quantity' => $transaction->quantity, 'price' => $transaction->price, 'total_amount' => $transaction->total_amount, 'transaction_type' => $transaction->transaction_type->value, 'transaction_type_desc' => $transaction->transaction_type->getDescription(), 'user_role' => $isUserBuyer ? 'buyer' : ($isUserSeller ? 'seller' : 'unknown'), 'user_role_desc' => $isUserBuyer ? '买方' : ($isUserSeller ? '卖方' : '未知'), 'counterparty_id' => $isUserBuyer ? $transaction->seller_id : $transaction->buyer_id, 'created_at' => $transaction->created_at, ]; } return [ 'transactions' => $result, 'total' => $transactions->total(), 'page' => $page, 'page_size' => $pageSize, ]; } /** * 获取商品成交统计 * * @param int $itemId 商品ID * @param int $days 统计天数 * @return array 统计信息 */ public static function getItemTransactionStats(int $itemId, int $days = 7): array { $startDate = now()->subDays($days)->startOfDay(); $stats = MexTransaction::where('item_id', $itemId) ->where('created_at', '>=', $startDate) ->selectRaw(' COUNT(*) as total_transactions, SUM(quantity) as total_quantity, SUM(total_amount) as total_amount, AVG(price) as avg_price, MIN(price) as min_price, MAX(price) as max_price ') ->first(); $latestPrice = self::getLatestPrice($itemId); return [ 'item_id' => $itemId, 'days' => $days, 'total_transactions' => $stats->total_transactions ?? 0, 'total_quantity' => $stats->total_quantity ?? 0, 'total_amount' => $stats->total_amount ?? '0.00000', 'avg_price' => $stats->avg_price ? number_format($stats->avg_price, 5) : '0.00000', 'min_price' => $stats->min_price ?? '0.00000', 'max_price' => $stats->max_price ?? '0.00000', 'latest_price' => $latestPrice, 'start_date' => $startDate, 'end_date' => now(), ]; } /** * 获取市场成交统计 * * @param int $days 统计天数 * @return array 统计信息 */ public static function getMarketStats(int $days = 7): array { $startDate = now()->subDays($days)->startOfDay(); $stats = MexTransaction::where('created_at', '>=', $startDate) ->selectRaw(' COUNT(*) as total_transactions, COUNT(DISTINCT item_id) as active_items, SUM(quantity) as total_quantity, SUM(total_amount) as total_amount, AVG(price) as avg_price ') ->first(); // 按交易类型统计 $typeStats = MexTransaction::where('created_at', '>=', $startDate) ->groupBy('transaction_type') ->selectRaw(' transaction_type, COUNT(*) as count, SUM(quantity) as quantity, SUM(total_amount) as amount ') ->get(); $typeStatsFormatted = []; foreach ($typeStats as $typeStat) { $typeStatsFormatted[$typeStat->transaction_type] = [ 'count' => $typeStat->count, 'quantity' => $typeStat->quantity, 'amount' => $typeStat->amount, ]; } return [ 'days' => $days, 'total_transactions' => $stats->total_transactions ?? 0, 'active_items' => $stats->active_items ?? 0, 'total_quantity' => $stats->total_quantity ?? 0, 'total_amount' => $stats->total_amount ?? '0.00000', 'avg_price' => $stats->avg_price ? number_format($stats->avg_price, 5) : '0.00000', 'type_stats' => $typeStatsFormatted, 'start_date' => $startDate, 'end_date' => now(), ]; } /** * 获取商品最新成交价格 * * @param int $itemId 商品ID * @return string|null 最新价格 */ public static function getLatestPrice(int $itemId): ?string { $transaction = MexTransaction::where('item_id', $itemId) ->orderBy('created_at', 'desc') ->first(); return $transaction ? $transaction->price : null; } /** * 创建成交记录 * * @param array $data 成交数据 * @return MexTransaction|null 成交记录 */ public static function createTransaction(array $data): ?MexTransaction { try { $transaction = MexTransaction::create([ 'buy_order_id' => $data['buy_order_id'] ?? null, 'sell_order_id' => $data['sell_order_id'] ?? null, 'buyer_id' => $data['buyer_id'], 'seller_id' => $data['seller_id'], 'item_id' => $data['item_id'], 'currency_type' => $data['currency_type'] ?? 2, // 默认使用钻石币种 'quantity' => $data['quantity'], 'price' => $data['price'], 'total_amount' => $data['total_amount'], 'transaction_type' => $data['transaction_type'], 'is_admin_operation' => $data['is_admin_operation'] ?? false, 'admin_user_id' => $data['admin_user_id'] ?? null, ]); // 触发成交记录创建事件 if ($transaction) { event(new TransactionCreatedEvent($transaction)); } return $transaction; } catch (\Exception $e) { return null; } } /** * 获取最后撮合时间信息(使用撮合日志) * * @return array 最后撮合时间信息 */ public static function getLastMatchTimes(): array { // 使用撮合日志服务获取最后撮合时间 return \App\Module\Mex\Services\MexMatchLogService::getLastMatchTimes(); } /** * 获取商品价格趋势 * * @param int $itemId 商品ID * @param int $days 统计天数 * @return array 价格趋势数据 */ public static function getItemPriceTrend(int $itemId, int $days = 7): array { $startDate = now()->subDays($days)->startOfDay(); $transactions = MexTransaction::where('item_id', $itemId) ->where('created_at', '>=', $startDate) ->orderBy('created_at', 'asc') ->select('price', 'created_at') ->get(); $trend = []; foreach ($transactions as $transaction) { $date = $transaction->created_at->format('Y-m-d'); if (!isset($trend[$date])) { $trend[$date] = []; } $trend[$date][] = $transaction->price; } // 计算每日平均价格 $result = []; foreach ($trend as $date => $prices) { $avgPrice = array_sum($prices) / count($prices); $result[] = [ 'date' => $date, 'avg_price' => number_format($avgPrice, 5), 'min_price' => min($prices), 'max_price' => max($prices), 'transaction_count' => count($prices), ]; } return $result; } }