hookManager = $hookManager; } /** * 发送通知 * * @param array $data * @return bool */ public function send(array $data): bool { try { // 验证数据 $this->validateData($data); // 获取模板 $template = $this->getTemplate($data['template_id']); if (!$template) { throw new \Exception('通知模板不存在'); } // 获取用户信息 $data['user'] = $this->getUserInfo($data['user_id']); $data['template'] = $template; // 执行发送前钩子 $data = $this->hookManager->executeBeforeSend($data); // 如果没有可用渠道,直接返回 if (empty($data['channels'])) { Log::warning('没有可用的通知渠道', [ 'user_id' => $data['user_id'], 'template_id' => $data['template_id'] ]); return false; } // 创建通知记录 $notification = $this->createNotificationLog($template, $data); // 发送到队列 SendNotificationQueue::dispatch($notification); // 执行发送后钩子 $this->hookManager->executeAfterSend($data, true); return true; } catch (\Exception $e) { // 执行错误钩子 $this->hookManager->executeOnError($data ?? [], $e); Log::error('发送通知失败', [ 'error' => $e->getMessage(), 'data' => $data ?? [] ]); return false; } } /** * 批量发送通知 * * @param array $data * @return bool */ public function sendBatch(array $data): bool { try { foreach ($data as $item) { $this->send($item); } return true; } catch (\Exception $e) { Log::error('批量发送通知失败', [ 'error' => $e->getMessage(), 'data' => $data ]); return false; } } /** * 获取模板 * * @param int $id * @return NotificationTemplate|null */ public function getTemplate(int $id): ?NotificationTemplate { return NotificationTemplate::find($id); } /** * 创建模板 * * @param array $data * @return NotificationTemplate */ public function createTemplate(array $data): NotificationTemplate { return NotificationTemplate::create($data); } /** * 更新模板 * * @param int $id * @param array $data * @return bool */ public function updateTemplate(int $id, array $data): bool { $template = $this->getTemplate($id); if (!$template) { return false; } return $template->update($data); } /** * 删除模板 * * @param int $id * @return bool */ public function deleteTemplate(int $id): bool { $template = $this->getTemplate($id); if (!$template) { return false; } return $template->delete(); } /** * 验证数据 * * @param array $data * @throws \Exception */ protected function validateData(array $data): void { if (empty($data['template_id'])) { throw new \Exception('模板ID不能为空'); } if (empty($data['user_id'])) { throw new \Exception('用户ID不能为空'); } if (empty($data['channels'])) { throw new \Exception('通知渠道不能为空'); } if (!is_array($data['channels'])) { throw new \Exception('通知渠道必须是数组'); } foreach ($data['channels'] as $channel) { if (!in_array($channel, NOTIFICATION_CHANNEL::values())) { throw new \Exception('无效的通知渠道'); } } } /** * 获取用户信息 * * @param int $userId * @return array */ protected function getUserInfo(int $userId): array { // TODO: 实现用户信息获取 return [ 'id' => $userId, 'phone' => '', 'email' => '', 'device_token' => '' ]; } /** * 创建通知记录 * * @param NotificationTemplate $template * @param array $data * @return NotificationLog */ protected function createNotificationLog(NotificationTemplate $template, array $data): NotificationLog { return NotificationLog::create([ 'template_id' => $template->id, 'user_id' => $data['user_id'], 'channels' => $data['channels'], 'title' => $template->title, 'content' => $template->content, 'data' => $data['data'] ?? [], 'status' => NOTIFICATION_STATUS::PENDING ]); } /** * 处理通知发送 * * @param NotificationLog $notification * @return void */ public function handleNotification(NotificationLog $notification): void { try { $notification->update(['status' => NOTIFICATION_STATUS::SENDING]); // 获取用户信息 $data = [ 'user' => $this->getUserInfo($notification->user_id), 'template' => $this->getTemplate($notification->template_id), 'channels' => $notification->channels, 'data' => $notification->data ]; // 执行发送前钩子 $data = $this->hookManager->executeBeforeSend($data); foreach ($data['channels'] as $channel) { $this->sendByChannel($notification, $channel, $data); } $notification->update([ 'status' => NOTIFICATION_STATUS::SENT, 'sent_at' => now() ]); // 执行发送后钩子 $this->hookManager->executeAfterSend($data, true); } catch (\Exception $e) { $notification->update([ 'status' => NOTIFICATION_STATUS::FAILED, 'message' => $e->getMessage() ]); // 执行错误钩子 $this->hookManager->executeOnError($data ?? [], $e); Log::error('处理通知发送失败', [ 'notification_id' => $notification->id, 'error' => $e->getMessage() ]); } } /** * 通过指定渠道发送通知 * * @param NotificationLog $notification * @param string $channel * @param array $data * @return void */ protected function sendByChannel(NotificationLog $notification, string $channel, array $data): void { // 具体的发送逻辑由各个模块的Hook处理 // 这里只需要调用Hook的beforeSend方法即可 } }