|
|
@@ -1,316 +0,0 @@
|
|
|
-<?php
|
|
|
-
|
|
|
-namespace App\Module\AppMessage\Services;
|
|
|
-
|
|
|
-use App\Module\AppMessage\Enums\AppMessageStatus;
|
|
|
-use App\Module\AppMessage\Enums\AppMessageType;
|
|
|
-use App\Module\AppMessage\Enums\AppSenderType;
|
|
|
-use App\Module\AppMessage\Models\AppMessage;
|
|
|
-use App\Module\AppMessage\Models\AppMessageRecipient;
|
|
|
-use App\Module\AppMessage\Models\AppMessageTemplate;
|
|
|
-use App\Module\AppMessage\Queues\SendAppMessageQueue;
|
|
|
-use Illuminate\Support\Facades\DB;
|
|
|
-use Illuminate\Support\Facades\Log;
|
|
|
-use Illuminate\Support\Collection;
|
|
|
-use Carbon\Carbon;
|
|
|
-
|
|
|
-/**
|
|
|
- * 应用消息服务类
|
|
|
- *
|
|
|
- * 该服务类提供了消息的发送、模板管理、消息状态管理等功能
|
|
|
- */
|
|
|
-class AppMessageService
|
|
|
-{
|
|
|
- /**
|
|
|
- * 发送消息
|
|
|
- *
|
|
|
- * @param array $data [
|
|
|
- * 'template_id' => int|null, // 模板ID
|
|
|
- * 'template_code' => string|null, // 模板代码
|
|
|
- * 'title' => string, // 消息标题
|
|
|
- * 'content' => string, // 消息内容
|
|
|
- * 'content_type' => string, // 内容类型:text,html,markdown,json
|
|
|
- * 'data' => array|null, // 附加数据
|
|
|
- * 'variables_data' => array|null, // 模板变量数据
|
|
|
- * 'sender_id' => int, // 发送者ID
|
|
|
- * 'sender_type' => string, // 发送者类型:system,user
|
|
|
- * 'receiver_id' => int|null, // 接收者ID,为空表示群发
|
|
|
- * 'receivers' => array|null, // 群发接收者ID数组
|
|
|
- * 'allow_reply' => bool, // 是否允许回复
|
|
|
- * 'parent_id' => int|null, // 父消息ID(回复时使用)
|
|
|
- * ]
|
|
|
- * @return AppMessage
|
|
|
- */
|
|
|
- public function send(array $data): AppMessage
|
|
|
- {
|
|
|
- try {
|
|
|
- DB::beginTransaction();
|
|
|
-
|
|
|
- // 如果提供了模板ID或代码,则获取模板
|
|
|
- if (!empty($data['template_id']) || !empty($data['template_code'])) {
|
|
|
- $template = $this->getTemplate($data['template_id'] ?? null, $data['template_code'] ?? null);
|
|
|
- if ($template) {
|
|
|
- $data = $this->applyTemplate($template, $data);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 创建消息
|
|
|
- $message = new AppMessage();
|
|
|
- $message->type = $data['type'] ?? 'user';
|
|
|
- $message->template_id = $data['template_id'] ?? null;
|
|
|
- $message->template_code = $data['template_code'] ?? null;
|
|
|
- $message->title = $data['title'];
|
|
|
- $message->content = $data['content'];
|
|
|
- $message->content_type = $data['content_type'] ?? 'text';
|
|
|
- $message->data = $data['data'] ?? null;
|
|
|
- $message->variables_data = $data['variables_data'] ?? null;
|
|
|
- $message->sender_id = $data['sender_id'];
|
|
|
- $message->sender_type = $data['sender_type'];
|
|
|
- $message->receiver_id = $data['receiver_id'] ?? null;
|
|
|
- $message->parent_id = $data['parent_id'] ?? null;
|
|
|
- $message->allow_reply = $data['allow_reply'] ?? true;
|
|
|
- $message->save();
|
|
|
-
|
|
|
- // 处理群发
|
|
|
- if (empty($message->receiver_id) && !empty($data['receivers'])) {
|
|
|
- $this->sendToRecipients($message, $data['receivers']);
|
|
|
- }
|
|
|
-
|
|
|
- DB::commit();
|
|
|
- return $message;
|
|
|
- } catch (\Exception $e) {
|
|
|
- DB::rollBack();
|
|
|
- throw $e;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 批量发送消息
|
|
|
- *
|
|
|
- * @param array $messages 消息数组
|
|
|
- * @return Collection
|
|
|
- */
|
|
|
- public function sendBatch(array $messages): Collection
|
|
|
- {
|
|
|
- $results = collect();
|
|
|
- foreach ($messages as $data) {
|
|
|
- $results->push($this->send($data));
|
|
|
- }
|
|
|
- return $results;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取模板
|
|
|
- *
|
|
|
- * @param int|null $id 模板ID
|
|
|
- * @param string|null $code 模板代码
|
|
|
- * @return AppMessageTemplate|null
|
|
|
- */
|
|
|
- public function getTemplate(?int $id = null, ?string $code = null): ?AppMessageTemplate
|
|
|
- {
|
|
|
- if ($id) {
|
|
|
- return AppMessageTemplate::find($id);
|
|
|
- }
|
|
|
- if ($code) {
|
|
|
- return AppMessageTemplate::where('code', $code)->first();
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 应用模板
|
|
|
- *
|
|
|
- * @param AppMessageTemplate $template 模板
|
|
|
- * @param array $data 数据
|
|
|
- * @return array
|
|
|
- */
|
|
|
- protected function applyTemplate(AppMessageTemplate $template, array $data): array
|
|
|
- {
|
|
|
- $variables = $data['variables_data'] ?? [];
|
|
|
- $content = $template->content;
|
|
|
-
|
|
|
- // 替换模板变量
|
|
|
- if (!empty($variables) && !empty($template->variables)) {
|
|
|
- foreach ($template->variables as $key => $info) {
|
|
|
- $value = $variables[$key] ?? '';
|
|
|
- $content = str_replace('{{'.$key.'}}', $value, $content);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return array_merge($data, [
|
|
|
- 'type' => $template->type,
|
|
|
- 'title' => $template->title,
|
|
|
- 'content' => $content,
|
|
|
- 'content_type' => $template->content_type,
|
|
|
- 'allow_reply' => $template->allow_reply,
|
|
|
- ]);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送给多个接收者
|
|
|
- *
|
|
|
- * @param AppMessage $message 消息
|
|
|
- * @param array $receiverIds 接收者ID数组
|
|
|
- * @return void
|
|
|
- */
|
|
|
- protected function sendToRecipients(AppMessage $message, array $receiverIds): void
|
|
|
- {
|
|
|
- $now = Carbon::now();
|
|
|
- $recipients = array_map(function ($userId) use ($message, $now) {
|
|
|
- return [
|
|
|
- 'message_id' => $message->id,
|
|
|
- 'user_id' => $userId,
|
|
|
- 'created_at' => $now,
|
|
|
- 'updated_at' => $now,
|
|
|
- ];
|
|
|
- }, array_unique($receiverIds));
|
|
|
-
|
|
|
- AppMessageRecipient::insert($recipients);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 标记消息为已读
|
|
|
- *
|
|
|
- * @param int $messageId 消息ID
|
|
|
- * @param int $userId 用户ID
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- public function markAsRead(int $messageId, int $userId): bool
|
|
|
- {
|
|
|
- $now = Carbon::now();
|
|
|
-
|
|
|
- // 更新直接接收的消息
|
|
|
- $message = AppMessage::where('id', $messageId)
|
|
|
- ->where('receiver_id', $userId)
|
|
|
- ->first();
|
|
|
-
|
|
|
- if ($message) {
|
|
|
- $message->update([
|
|
|
- 'is_read' => true,
|
|
|
- 'read_at' => $now
|
|
|
- ]);
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- // 更新群发消息接收记录
|
|
|
- $recipient = AppMessageRecipient::where('message_id', $messageId)
|
|
|
- ->where('user_id', $userId)
|
|
|
- ->first();
|
|
|
-
|
|
|
- if ($recipient) {
|
|
|
- $recipient->update([
|
|
|
- 'is_read' => true,
|
|
|
- 'read_at' => $now
|
|
|
- ]);
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取用户未读消息数量
|
|
|
- *
|
|
|
- * @param int $userId 用户ID
|
|
|
- * @return int
|
|
|
- */
|
|
|
- public function getUnreadCount(int $userId): int
|
|
|
- {
|
|
|
- // 直接接收的未读消息
|
|
|
- $directCount = AppMessage::where('receiver_id', $userId)
|
|
|
- ->where('is_read', false)
|
|
|
- ->where('status', 1)
|
|
|
- ->count();
|
|
|
-
|
|
|
- // 群发消息的未读数量
|
|
|
- $recipientCount = AppMessageRecipient::where('user_id', $userId)
|
|
|
- ->where('is_read', false)
|
|
|
- ->where('status', 1)
|
|
|
- ->count();
|
|
|
-
|
|
|
- return $directCount + $recipientCount;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取用户的消息列表
|
|
|
- *
|
|
|
- * @param int $userId 用户ID
|
|
|
- * @param array $filters 过滤条件
|
|
|
- * @param int $perPage 每页数量
|
|
|
- * @return \Illuminate\Pagination\LengthAwarePaginator
|
|
|
- */
|
|
|
- public function getUserMessages(int $userId, array $filters = [], int $perPage = 15)
|
|
|
- {
|
|
|
- $query = AppMessage::where(function ($query) use ($userId) {
|
|
|
- $query->where('receiver_id', $userId)
|
|
|
- ->orWhereExists(function ($query) use ($userId) {
|
|
|
- $query->from('app_message_recipients')
|
|
|
- ->whereColumn('app_message_recipients.message_id', 'app_messages.id')
|
|
|
- ->where('app_message_recipients.user_id', $userId)
|
|
|
- ->where('app_message_recipients.status', 1);
|
|
|
- });
|
|
|
- })->where('status', 1);
|
|
|
-
|
|
|
- // 应用过滤条件
|
|
|
- if (!empty($filters['type'])) {
|
|
|
- $query->where('type', $filters['type']);
|
|
|
- }
|
|
|
- if (!empty($filters['content_type'])) {
|
|
|
- $query->where('content_type', $filters['content_type']);
|
|
|
- }
|
|
|
- if (isset($filters['is_read'])) {
|
|
|
- $query->where('is_read', $filters['is_read']);
|
|
|
- }
|
|
|
-
|
|
|
- return $query->orderBy('created_at', 'desc')->paginate($perPage);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 创建消息模板
|
|
|
- *
|
|
|
- * @param array $data 模板数据,包含以下字段:
|
|
|
- * - name: string 模板名称
|
|
|
- * - code: string 模板代码
|
|
|
- * - type: string 模板类型
|
|
|
- * - title: string 消息标题
|
|
|
- * - content: string 消息内容
|
|
|
- * - variables: array 模板变量
|
|
|
- * - status: bool 模板状态
|
|
|
- * @return AppMessageTemplate 返回创建的模板实例
|
|
|
- */
|
|
|
- public function createTemplate(array $data): AppMessageTemplate
|
|
|
- {
|
|
|
- return AppMessageTemplate::create($data);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 更新消息模板
|
|
|
- *
|
|
|
- * @param int $id 模板ID
|
|
|
- * @param array $data 更新的模板数据,字段同createTemplate方法
|
|
|
- * @return bool 更新成功返回true,失败返回false
|
|
|
- */
|
|
|
- public function updateTemplate(int $id, array $data): bool
|
|
|
- {
|
|
|
- $template = $this->getTemplate($id);
|
|
|
- if (!$template) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- return $template->update($data);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 删除消息模板
|
|
|
- *
|
|
|
- * @param int $id 模板ID
|
|
|
- * @return bool 删除成功返回true,失败返回false
|
|
|
- */
|
|
|
- public function deleteTemplate(int $id): bool
|
|
|
- {
|
|
|
- $template = $this->getTemplate($id);
|
|
|
- if (!$template) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- return $template->delete();
|
|
|
- }
|
|
|
-}
|