Appearance
消息系统
MineShop 内置完整的消息系统,支持多渠道推送、消息模板、用户偏好设置等功能。
🎯 系统架构
┌─────────────────────────────────────────────────────────────┐
│ 消息服务 (MessageService) │
├─────────────────────────────────────────────────────────────┤
│ 创建消息 │ 发送消息 │ 定时发送 │ 批量发送 │ 统计分析 │
├─────────────────────────────────────────────────────────────┤
│ 通知服务 (NotificationService) │
├─────────────────────────────────────────────────────────────┤
│ 站内信 │ 邮件 │ 短信 │ 推送 │ 小程序 │ WebSocket │
└─────────────────────────────────────────────────────────────┘✨ 核心特性
1. 多渠道支持
| 渠道 | 说明 | 状态 |
|---|---|---|
database | 站内信 | ✅ 已实现 |
email | 邮件通知 | 🔧 需配置 |
sms | 短信通知 | 🔧 需配置 |
push | APP 推送 | 🔧 需配置 |
miniapp | 小程序订阅消息 | 🔧 需配置 |
websocket | 实时推送 | 🔧 需配置 |
2. 消息类型
php
enum MessageType: string
{
case SYSTEM = 'system'; // 系统通知
case ANNOUNCEMENT = 'announcement'; // 公告
case ALERT = 'alert'; // 警告
case REMINDER = 'reminder'; // 提醒
case MARKETING = 'marketing'; // 营销
}3. 消息服务
php
// MessageService.php
class MessageService
{
// 创建消息
public function create(array $data): Message
{
$this->validateMessageData($data);
$data = $this->setDefaultValues($data);
return $this->repository->create($data);
}
// 发送消息
public function send(int $messageId): bool
{
$message = $this->repository->findById($messageId);
$recipients = $message->getRecipients();
Db::transaction(function () use ($message, $recipients) {
$message->markAsSending();
$this->createUserMessages($message, $recipients);
$message->markAsSent();
});
// 异步推送到各渠道
$this->queueNotifications($message, $recipients);
return true;
}
// 定时发送
public function schedule(int $messageId, Carbon $scheduledAt): bool
{
return $message->update([
'scheduled_at' => $scheduledAt,
'status' => MessageStatus::SCHEDULED->value
]);
}
}4. 用户偏好设置
php
// NotificationService.php
public function getDefaultPreferences(): array
{
return [
'channel_preferences' => [
'database' => true,
'email' => false,
'sms' => false,
'push' => false
],
'type_preferences' => [
'system' => true,
'announcement' => true,
'alert' => true,
'reminder' => true,
'marketing' => false
],
'do_not_disturb_enabled' => false,
'do_not_disturb_start' => '22:00:00',
'do_not_disturb_end' => '08:00:00',
'min_priority' => 1,
];
}
// 检查是否应该发送
protected function shouldSendNotification(Message $message, int $userId, string $channel): bool
{
$preference = $this->preferenceRepository->getUserPreference($userId);
// 检查渠道偏好
if (!$preference->getChannelSetting($channel)) {
return false;
}
// 检查消息类型偏好
if (!$preference->getTypeSetting($message->type)) {
return false;
}
// 检查优先级
if ($message->priority < $preference->min_priority) {
return false;
}
return true;
}5. 免打扰时段
php
protected function isInDoNotDisturbTime(int $userId): bool
{
$preference = $this->preferenceRepository->getUserPreference($userId);
if (!$preference->do_not_disturb_enabled) {
return false;
}
$now = Carbon::now();
$startTime = Carbon::createFromTimeString($preference->do_not_disturb_start);
$endTime = Carbon::createFromTimeString($preference->do_not_disturb_end);
// 处理跨天情况
if ($startTime->greaterThan($endTime)) {
return $now->gte($startTime) || $now->lte($endTime);
}
return $now->between($startTime, $endTime);
}🔄 消息状态
┌──────────┐ 发送 ┌──────────┐ 完成 ┌──────────┐
│ draft │ ────────→ │ sending │ ────────→ │ sent │
│ 草稿 │ │ 发送中 │ │ 已发送 │
└──────────┘ └──────────┘ └──────────┘
│ │
│ 定时 │ 失败
↓ ↓
┌──────────┐ ┌──────────┐
│ scheduled│ │ failed │
│ 已定时 │ │ 失败 │
└──────────┘ └──────────┘📦 数据结构
消息表 (messages)
| 字段 | 类型 | 说明 |
|---|---|---|
title | string | 消息标题 |
content | text | 消息内容 |
type | string | 消息类型 |
priority | int | 优先级 (1-5) |
recipient_type | string | 接收者类型 |
channels | json | 推送渠道 |
status | string | 状态 |
scheduled_at | datetime | 定时发送时间 |
用户消息表 (user_messages)
| 字段 | 类型 | 说明 |
|---|---|---|
user_id | int | 用户 ID |
message_id | int | 消息 ID |
is_read | bool | 是否已读 |
read_at | datetime | 阅读时间 |
is_deleted | bool | 是否删除 |
💻 API 接口
后台管理
| 接口 | 方法 | 说明 |
|---|---|---|
/admin/message | GET | 消息列表 |
/admin/message | POST | 创建消息 |
/admin/message/{id} | PUT | 更新消息 |
/admin/message/{id}/send | POST | 发送消息 |
/admin/message/statistics | GET | 统计数据 |
用户端
| 接口 | 方法 | 说明 |
|---|---|---|
/api/message/list | GET | 我的消息 |
/api/message/{id} | GET | 消息详情 |
/api/message/{id}/read | POST | 标记已读 |
/api/message/read-all | POST | 全部已读 |
/api/message/unread-count | GET | 未读数量 |
/api/message/preferences | GET | 偏好设置 |
/api/message/preferences | PUT | 更新偏好 |
🔧 配置说明
php
// config/autoload/system_message.php
return [
'message' => [
'max_title_length' => 255,
'max_content_length' => 10000,
'default_priority' => 1,
'retention_days' => 90, // 消息保留天数
],
'notification' => [
'default_channels' => [
'database' => true,
'email' => false,
'sms' => false,
'push' => false,
],
],
'queue' => [
'channel' => 'default',
],
];📊 统计功能
php
public function getStatistics(): array
{
return [
'total' => Message::count(),
'sent' => Message::where('status', 'sent')->count(),
'pending' => Message::where('status', 'draft')->count(),
'by_type' => Message::groupBy('type')
->selectRaw('type, count(*) as count')
->get(),
];
}⚠️ 注意事项
- 异步发送: 大量消息使用队列异步发送
- 用户偏好: 尊重用户的通知偏好设置
- 免打扰: 非紧急消息遵守免打扰时段
- 消息清理: 定期清理过期消息