From 5bbed98cf0c9abd81a9ab6fd93812cbbb9790260 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 28 Feb 2026 18:47:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E8=B0=83=E8=AF=95=E6=B6=88=E6=81=AF=E8=B5=B0?= =?UTF-8?q?=E5=90=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增功能: 1. 创建 feishu_message_log 表,记录消息发送和更新操作 2. FeishuMessageLog 模型:管理消息日志 3. DebugController:提供调试接口查看日志 使用方式: - GET /debug/message-logs?limit=50 - 查看最近50条日志 - GET /debug/message-logs?order_id=123 - 查看指定订单的日志 - POST /debug/clear-logs - 清空日志 Co-Authored-By: Claude Opus 4.6 --- backend/app/controller/DebugController.php | 64 +++++++++++ backend/app/model/FeishuMessageLog.php | 81 ++++++++++++++ .../app/service/FeishuNotificationService.php | 101 +++++++++++++++++- backend/config/route.php | 6 ++ 4 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 backend/app/controller/DebugController.php create mode 100644 backend/app/model/FeishuMessageLog.php diff --git a/backend/app/controller/DebugController.php b/backend/app/controller/DebugController.php new file mode 100644 index 0000000..574e9c0 --- /dev/null +++ b/backend/app/controller/DebugController.php @@ -0,0 +1,64 @@ +get('debug')) { + return json(['code' => 403, 'msg' => 'Forbidden']); + } + + $limit = (int) $request->get('limit', 50); + $orderId = $request->get('order_id'); + + $query = FeishuMessageLog::orderBy('created_at', 'desc'); + + if ($orderId) { + $query->where('order_id', $orderId); + } + + $logs = $query->limit($limit)->get()->toArray(); + + // 解析 JSON 字段 + foreach ($logs as &$log) { + $log['request_data'] = $log['request_data'] ? json_decode($log['request_data'], true) : null; + $log['response_data'] = $log['response_data'] ? json_decode($log['response_data'], true) : null; + } + + return json([ + 'code' => 0, + 'msg' => 'success', + 'data' => $logs, + ]); + } + + /** + * 清空消息日志 + */ + public function clearLogs(Request $request): Response + { + if (config('app.app_env') !== 'dev' && !$request->get('debug')) { + return json(['code' => 403, 'msg' => 'Forbidden']); + } + + FeishuMessageLog::query()->delete(); + + return json([ + 'code' => 0, + 'msg' => 'Logs cleared', + ]); + } +} diff --git a/backend/app/model/FeishuMessageLog.php b/backend/app/model/FeishuMessageLog.php new file mode 100644 index 0000000..7ee86cf --- /dev/null +++ b/backend/app/model/FeishuMessageLog.php @@ -0,0 +1,81 @@ + $action, + 'order_id' => $orderId, + 'node_id' => $nodeId, + 'user_id' => $userId, + 'message_id' => $messageId, + 'status' => $status, + 'request_data' => $requestData ? json_encode($requestData, JSON_UNESCAPED_UNICODE) : null, + 'response_data' => $responseData ? json_encode($responseData, JSON_UNESCAPED_UNICODE) : null, + 'error_message' => $errorMessage, + ]); + } + + /** + * 获取最近的日志 + */ + public static function getRecentLogs(int $limit = 50): array + { + return self::orderBy('created_at', 'desc') + ->limit($limit) + ->get() + ->toArray(); + } + + /** + * 根据订单获取日志 + */ + public static function getLogsByOrder(int $orderId): array + { + return self::where('order_id', $orderId) + ->orderBy('created_at', 'desc') + ->get() + ->toArray(); + } +} diff --git a/backend/app/service/FeishuNotificationService.php b/backend/app/service/FeishuNotificationService.php index ac22c5f..96223c2 100644 --- a/backend/app/service/FeishuNotificationService.php +++ b/backend/app/service/FeishuNotificationService.php @@ -160,7 +160,7 @@ class FeishuNotificationService error_log("📨 发送卡片消息: 不是自审批"); $card = $this->buildApprovalCard($params, $user->company_id); - $messageId = $this->sendMessage($feishuUserId, $card); + $messageId = $this->sendMessage($feishuUserId, $card, $orderId, $nodeId, $userId); if ($messageId && $orderId && $nodeId) { // 保存消息映射 @@ -552,8 +552,13 @@ class FeishuNotificationService * 发送消息到飞书 * @return string|false 返回 message_id 或 false */ - private function sendMessage(string $feishuUserId, array $card) + private function sendMessage(string $feishuUserId, array $card, ?int $orderId = null, ?int $nodeId = null, ?int $userId = null) { + $requestData = [ + 'feishu_user_id' => $feishuUserId, + 'card' => $card, + ]; + try { $app = $this->getAppConfig(); $token = $this->getAccessToken(); @@ -580,18 +585,65 @@ class FeishuNotificationService if ($code !== 0) { error_log('❌ 飞书消息发送失败: ' . json_encode($response)); + + // 记录失败日志 + if ($orderId) { + \app\model\FeishuMessageLog::log( + \app\model\FeishuMessageLog::ACTION_SEND, + $orderId, + $nodeId, + $userId, + null, + \app\model\FeishuMessageLog::STATUS_FAILED, + $requestData, + $response, + $response['msg'] ?? 'Unknown error' + ); + } + return false; } $messageId = $response['data']['message_id'] ?? null; if ($messageId) { error_log('✅ 飞书消息发送成功, message_id=' . $messageId); + + // 记录成功日志 + if ($orderId) { + \app\model\FeishuMessageLog::log( + \app\model\FeishuMessageLog::ACTION_SEND, + $orderId, + $nodeId, + $userId, + $messageId, + \app\model\FeishuMessageLog::STATUS_SUCCESS, + $requestData, + $response + ); + } + return $messageId; } return false; } catch (Exception $e) { error_log('❌ sendMessage 异常: ' . $e->getMessage()); + + // 记录异常日志 + if ($orderId) { + \app\model\FeishuMessageLog::log( + \app\model\FeishuMessageLog::ACTION_SEND, + $orderId, + $nodeId, + $userId, + null, + \app\model\FeishuMessageLog::STATUS_FAILED, + $requestData, + null, + $e->getMessage() + ); + } + return false; } } @@ -650,6 +702,13 @@ class FeishuNotificationService ], ]; + $requestData = [ + 'message_id' => $message->message_id, + 'card' => $updatedCard, + 'status' => $status, + 'operator' => $operatorName, + ]; + $response = HttpClient::httpPost( "https://open.feishu.cn/open-apis/im/v1/messages/{$message->message_id}/update", [ @@ -667,11 +726,49 @@ class FeishuNotificationService // 标记消息为已更新 $message->status = \app\model\FeishuMessage::STATUS_UPDATED; $message->save(); + + // 记录成功日志 + \app\model\FeishuMessageLog::log( + \app\model\FeishuMessageLog::ACTION_UPDATE_CARD, + $orderId, + $nodeId, + $message->user_id, + $message->message_id, + \app\model\FeishuMessageLog::STATUS_SUCCESS, + $requestData, + $response + ); } else { error_log("❌ 消息卡片更新失败: message_id={$message->message_id}, error=" . json_encode($response)); + + // 记录失败日志 + \app\model\FeishuMessageLog::log( + \app\model\FeishuMessageLog::ACTION_UPDATE_CARD, + $orderId, + $nodeId, + $message->user_id, + $message->message_id, + \app\model\FeishuMessageLog::STATUS_FAILED, + $requestData, + $response, + $response['msg'] ?? 'Unknown error' + ); } } catch (Exception $e) { error_log("❌ 更新消息卡片异常: message_id={$message->message_id}, error=" . $e->getMessage()); + + // 记录异常日志 + \app\model\FeishuMessageLog::log( + \app\model\FeishuMessageLog::ACTION_UPDATE_CARD, + $orderId, + $nodeId, + $message->user_id, + $message->message_id, + \app\model\FeishuMessageLog::STATUS_FAILED, + null, + null, + $e->getMessage() + ); } } diff --git a/backend/config/route.php b/backend/config/route.php index 593397c..ad9643a 100644 --- a/backend/config/route.php +++ b/backend/config/route.php @@ -24,6 +24,12 @@ Route::get('/login/callback', [app\controller\AuthController::class, 'qrcodeLogi // 飞书卡片回调(不需要认证,飞书服务器直接调用) Route::post('/feishu/card/callback', [app\controller\FeishuCardController::class, 'callback']); +// 调试接口(开发环境使用) +Route::group('/debug', function () { + Route::get('/message-logs', [app\controller\DebugController::class, 'messageLogs']); + Route::post('/clear-logs', [app\controller\DebugController::class, 'clearLogs']); +}); + // 用户路由(需要认证) Route::group('/api/v1/user', function () { Route::get('/info', [app\controller\UserController::class, 'info']);