优化代码,去除MQ

main
gzydong 2021-07-08 19:09:06 +08:00
parent 5579b16548
commit a3b5033cab
35 changed files with 389 additions and 866 deletions

View File

@ -41,10 +41,3 @@ MAIL_PASSWORD=xxxx
MAIL_FROM_ADDRESS=xxxx@163.com MAIL_FROM_ADDRESS=xxxx@163.com
MAIL_FROM_NAME="xxxxx" MAIL_FROM_NAME="xxxxx"
MAIL_ENCRYPTION=ssl MAIL_ENCRYPTION=ssl
# ---- Rabbit MQ 配置 ----
AMQP_HOST=127.0.0.1
AMQP_PORT=5672
AMQP_USER=guest
AMQP_PASSWORD=guest
AMQP_VHOST=/im

View File

@ -24,7 +24,6 @@ Lumen-IM 是一个网页版在线即时聊天项目,前端使用 Element-ui +
- JSON - JSON
- PDO - PDO
- Redis >= 5.0.0 - Redis >= 5.0.0
- AMQP
## 4、相关文档 ## 4、相关文档
[Hyperf 框架](https://hyperf.wiki/2.0/#/README) [Hyperf 框架](https://hyperf.wiki/2.0/#/README)
@ -32,11 +31,11 @@ Lumen-IM 是一个网页版在线即时聊天项目,前端使用 Element-ui +
## 5、项目安装 ## 5、项目安装
1. 下载源码包 1. 下载源码包
2. 安装框架依赖包执行 `compsoer install` 命令 [项目根目录下执行] 2. 安装框架依赖包执行 `compsoer install` 命令 [项目根目录下执行]
2. 拷贝项目根目录下 .env.example 文件为 .env 并正确配置相关参数mysql、redis、rabbitmq 2. 拷贝项目根目录下 .env.example 文件为 .env 并正确配置相关参数mysql、redis
3. 执行数据库迁移文件命令生成相关数据表 `php bin/hyperf.php migrate` 3. 执行数据库迁移文件命令生成相关数据表 `php bin/hyperf.php migrate`
4. 启动运行项目 `php bin/hyperf.php start` 4. 启动运行项目 `php bin/hyperf.php start`
[项目运行之前请确保 Mysql、Redis、RabbitMQ 及 Nginx 服务] [项目运行之前请确保 Mysql、Redis 及 Nginx 服务]
## Nginx 相关配置(代理 swoole 服务) ## Nginx 相关配置(代理 swoole 服务)
##### 配置 Http 服务 ##### 配置 Http 服务
@ -129,7 +128,7 @@ server {
``` ```
### 注意事项 ### 注意事项
1. 请确保 PHP 安装 openssl、redis、amqp 扩展 1. 请确保 PHP 安装 openssl、redis 扩展
2. 请确保 Swoole 扩展开启 openssl 扩展 2. 请确保 Swoole 扩展开启 openssl 扩展
``` ```
[root@iZuf6cs69fbc86cwpu9iv3Z vhost]# php --ri swoole [root@iZuf6cs69fbc86cwpu9iv3Z vhost]# php --ri swoole

View File

@ -1,62 +0,0 @@
<?php
declare(strict_types=1);
/**
* This is my open source code, please do not use it for commercial applications.
* For the full copyright and license information,
* please view the LICENSE file that was distributed with this source code
*
* @author Yuandong<837215079@qq.com>
* @link https://github.com/gzydong/hyperf-chat
*/
namespace App\Amqp\Producer;
use App\Constants\SocketConstants;
use Hyperf\Amqp\Message\ProducerMessage;
use Hyperf\Amqp\Message\Type;
/**
* 消息生产者
*
* @package App\Amqp\Producer
*/
class ChatMessageProducer extends ProducerMessage
{
/**
* 交换机类型
*
* @var string
*/
public $type = Type::FANOUT;
/**
* 交换机名称
*
* @var string
*/
public $exchange = SocketConstants::CONSUMER_MESSAGE_EXCHANGE;
/**
* 实例化处理
*
* @param string $event 事件名
* @param array $data 数据
* @param array $options 其它参数
*/
public function __construct(string $event, array $data, array $options = [])
{
$message = [
'uuid' => uniqid((strval(mt_rand(0, 1000)))),
'event' => $event,
'data' => $data,
'options' => $options
];
$this->payload = $message;
}
public function getPayload()
{
return $this->payload;
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace App\Constants;
class RedisSubscribeChan
{
const WEBSOCKET_CHAN = 'websocket';
}

View File

@ -9,6 +9,7 @@ use App\Constants\SocketConstants;
use App\Model\UsersFriendsApply; use App\Model\UsersFriendsApply;
use App\Service\SocketClientService; use App\Service\SocketClientService;
use App\Service\UserService; use App\Service\UserService;
use App\Support\MessageProducer;
use Hyperf\HttpServer\Annotation\Controller; use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware; use Hyperf\HttpServer\Annotation\Middleware;
use App\Middleware\JWTAuthMiddleware; use App\Middleware\JWTAuthMiddleware;
@ -70,10 +71,12 @@ class ContactsApplyController extends CController
// 判断对方是否在线。如果在线发送消息通知 // 判断对方是否在线。如果在线发送消息通知
if ($this->socketClientService->isOnlineAll($params['friend_id'])) { if ($this->socketClientService->isOnlineAll($params['friend_id'])) {
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_FRIEND_APPLY, [ MessageProducer::publish(
MessageProducer::create(SocketConstants::EVENT_FRIEND_APPLY, [
'apply_id' => $result->id, 'apply_id' => $result->id,
'type' => 1, 'type' => 1,
])); ])
);
} }
return $this->response->success([], '发送好友申请成功...'); return $this->response->success([], '发送好友申请成功...');
@ -101,10 +104,12 @@ class ContactsApplyController extends CController
// 判断对方是否在线。如果在线发送消息通知 // 判断对方是否在线。如果在线发送消息通知
if ($this->socketClientService->isOnlineAll($friend_id)) { if ($this->socketClientService->isOnlineAll($friend_id)) {
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_FRIEND_APPLY, [ MessageProducer::publish(
MessageProducer::create(SocketConstants::EVENT_FRIEND_APPLY, [
'apply_id' => (int)$params['apply_id'], 'apply_id' => (int)$params['apply_id'],
'type' => 2, 'type' => 2,
])); ])
);
} }
return $this->response->success([], '处理成功...'); return $this->response->success([], '处理成功...');

View File

@ -13,6 +13,7 @@ namespace App\Controller\Api\V1;
use App\Cache\SocketRoom; use App\Cache\SocketRoom;
use App\Constants\TalkType; use App\Constants\TalkType;
use App\Service\UserService; use App\Service\UserService;
use App\Support\MessageProducer;
use Hyperf\Di\Annotation\Inject; use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller; use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping; use Hyperf\HttpServer\Annotation\RequestMapping;
@ -76,13 +77,14 @@ class GroupController extends CController
SocketRoom::getInstance()->addRoomMember(strval($data['group_id']), $uid); SocketRoom::getInstance()->addRoomMember(strval($data['group_id']), $uid);
} }
// ... 消息推送队列 MessageProducer::publish(
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ MessageProducer::create(SocketConstants::EVENT_TALK, [
'sender_id' => $user_id, 'sender_id' => $user_id,
'receiver_id' => (int)$data['group_id'], 'receiver_id' => (int)$data['group_id'],
'talk_type' => TalkType::GROUP_CHAT, 'talk_type' => TalkType::GROUP_CHAT,
'record_id' => (int)$data['record_id'] 'record_id' => (int)$data['record_id']
])); ])
);
return $this->response->success([ return $this->response->success([
'group_id' => $data['group_id'] 'group_id' => $data['group_id']
@ -141,13 +143,14 @@ class GroupController extends CController
SocketRoom::getInstance()->addRoomMember($params['group_id'], $uid); SocketRoom::getInstance()->addRoomMember($params['group_id'], $uid);
} }
// 消息推送队列 MessageProducer::publish(
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ MessageProducer::create(SocketConstants::EVENT_TALK, [
'sender_id' => $user_id, 'sender_id' => $user_id,
'receiver_id' => (int)$params['group_id'], 'receiver_id' => (int)$params['group_id'],
'talk_type' => TalkType::GROUP_CHAT, 'talk_type' => TalkType::GROUP_CHAT,
'record_id' => $record_id 'record_id' => $record_id
])); ])
);
return $this->response->success([], '好友已成功加入群聊...'); return $this->response->success([], '好友已成功加入群聊...');
} }
@ -174,13 +177,14 @@ class GroupController extends CController
// 移出聊天室 // 移出聊天室
SocketRoom::getInstance()->delRoomMember($params['group_id'], $user_id); SocketRoom::getInstance()->delRoomMember($params['group_id'], $user_id);
// 消息推送队列 MessageProducer::publish(
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ MessageProducer::create(SocketConstants::EVENT_TALK, [
'sender_id' => $user_id, 'sender_id' => $user_id,
'receiver_id' => (int)$params['group_id'], 'receiver_id' => (int)$params['group_id'],
'talk_type' => TalkType::GROUP_CHAT, 'talk_type' => TalkType::GROUP_CHAT,
'record_id' => $record_id 'record_id' => $record_id
])); ])
);
return $this->response->success([], '已成功退出群组...'); return $this->response->success([], '已成功退出群组...');
} }
@ -245,13 +249,14 @@ class GroupController extends CController
SocketRoom::getInstance()->delRoomMember($params['group_id'], strval($uid)); SocketRoom::getInstance()->delRoomMember($params['group_id'], strval($uid));
} }
// 消息推送队列 MessageProducer::publish(
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ MessageProducer::create(SocketConstants::EVENT_TALK, [
'sender_id' => $user_id, 'sender_id' => $user_id,
'receiver_id' => (int)$params['group_id'], 'receiver_id' => (int)$params['group_id'],
'talk_type' => TalkType::GROUP_CHAT, 'talk_type' => TalkType::GROUP_CHAT,
'record_id' => $record_id 'record_id' => $record_id
])); ])
);
return $this->response->success([], '已成功退出群组...'); return $this->response->success([], '已成功退出群组...');
} }

View File

@ -10,6 +10,7 @@ use App\Constants\TalkMsgType;
use App\Constants\TalkType; use App\Constants\TalkType;
use App\Model\EmoticonItem; use App\Model\EmoticonItem;
use App\Model\FileSplitUpload; use App\Model\FileSplitUpload;
use App\Support\MessageProducer;
use App\Support\UserRelation; use App\Support\UserRelation;
use App\Service\EmoticonService; use App\Service\EmoticonService;
use App\Service\TalkService; use App\Service\TalkService;
@ -67,13 +68,14 @@ class TalkMessageController extends CController
if (!$record_id) return $this->response->fail('消息发送失败!'); if (!$record_id) return $this->response->fail('消息发送失败!');
// 消息推送队列 MessageProducer::publish(
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ MessageProducer::create(SocketConstants::EVENT_TALK, [
'sender_id' => $user_id, 'sender_id' => $user_id,
'receiver_id' => (int)$params['receiver_id'], 'receiver_id' => (int)$params['receiver_id'],
'talk_type' => (int)$params['talk_type'], 'talk_type' => (int)$params['talk_type'],
'record_id' => $record_id 'record_id' => $record_id
])); ])
);
LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [ LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [
'text' => '[代码消息]', 'text' => '[代码消息]',
@ -133,13 +135,14 @@ class TalkMessageController extends CController
if (!$record_id) return $this->response->fail('图片上传失败!'); if (!$record_id) return $this->response->fail('图片上传失败!');
// 消息推送队列 MessageProducer::publish(
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ MessageProducer::create(SocketConstants::EVENT_TALK, [
'sender_id' => $user_id, 'sender_id' => $user_id,
'receiver_id' => (int)$params['receiver_id'], 'receiver_id' => (int)$params['receiver_id'],
'talk_type' => (int)$params['talk_type'], 'talk_type' => (int)$params['talk_type'],
'record_id' => $record_id, 'record_id' => $record_id,
])); ])
);
LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [ LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [
'text' => '[图片消息]', 'text' => '[图片消息]',
@ -195,13 +198,14 @@ class TalkMessageController extends CController
if (!$record_id) return $this->response->fail('表情发送失败!'); if (!$record_id) return $this->response->fail('表情发送失败!');
// 消息推送队列 MessageProducer::publish(
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ MessageProducer::create(SocketConstants::EVENT_TALK, [
'sender_id' => $user_id, 'sender_id' => $user_id,
'receiver_id' => (int)$params['receiver_id'], 'receiver_id' => (int)$params['receiver_id'],
'talk_type' => (int)$params['talk_type'], 'talk_type' => (int)$params['talk_type'],
'record_id' => $record_id 'record_id' => $record_id
])); ])
);
LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [ LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [
'text' => '[文件消息]', 'text' => '[文件消息]',
@ -259,13 +263,14 @@ class TalkMessageController extends CController
if (!$record_id) return $this->response->fail('表情发送失败!'); if (!$record_id) return $this->response->fail('表情发送失败!');
// 消息推送队列 MessageProducer::publish(
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ MessageProducer::create(SocketConstants::EVENT_TALK, [
'sender_id' => $user_id, 'sender_id' => $user_id,
'receiver_id' => (int)$params['receiver_id'], 'receiver_id' => (int)$params['receiver_id'],
'talk_type' => (int)$params['talk_type'], 'talk_type' => (int)$params['talk_type'],
'record_id' => $record_id 'record_id' => $record_id
])); ])
);
LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [ LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [
'text' => '[表情包消息]', 'text' => '[表情包消息]',
@ -321,12 +326,14 @@ class TalkMessageController extends CController
// 消息推送队列 // 消息推送队列
foreach ($ids as $value) { foreach ($ids as $value) {
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ MessageProducer::publish(
MessageProducer::create(SocketConstants::EVENT_TALK, [
'sender_id' => $user_id, 'sender_id' => $user_id,
'receiver_id' => $value['receiver_id'], 'receiver_id' => $value['receiver_id'],
'talk_type' => $value['talk_type'], 'talk_type' => $value['talk_type'],
'record_id' => $value['record_id'], 'record_id' => $value['record_id'],
])); ])
);
} }
return $this->response->success([], '转发成功...'); return $this->response->success([], '转发成功...');
@ -366,9 +373,11 @@ class TalkMessageController extends CController
[$isTrue, $message,] = $this->talkService->revokeRecord($this->uid(), $params['record_id']); [$isTrue, $message,] = $this->talkService->revokeRecord($this->uid(), $params['record_id']);
if (!$isTrue) return $this->response->fail($message); if (!$isTrue) return $this->response->fail($message);
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_REVOKE_TALK, [ MessageProducer::publish(
MessageProducer::create(SocketConstants::EVENT_REVOKE_TALK, [
'record_id' => $params['record_id'] 'record_id' => $params['record_id']
])); ])
);
return $this->response->success([], $message); return $this->response->success([], $message);
} }

View File

@ -12,6 +12,8 @@ declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
use App\Cache\SocketRoom; use App\Cache\SocketRoom;
use App\Service\Message\ReceiveHandleService;
use App\Support\MessageProducer;
use Hyperf\Di\Annotation\Inject; use Hyperf\Di\Annotation\Inject;
use App\Constants\SocketConstants; use App\Constants\SocketConstants;
use Hyperf\Contract\OnCloseInterface; use Hyperf\Contract\OnCloseInterface;
@ -22,9 +24,7 @@ use Swoole\Websocket\Frame;
use Swoole\Http\Response; use Swoole\Http\Response;
use Swoole\WebSocket\Server; use Swoole\WebSocket\Server;
use App\Service\SocketClientService; use App\Service\SocketClientService;
use App\Service\MessageHandleService;
use App\Model\Group\GroupMember; use App\Model\Group\GroupMember;
use App\Amqp\Producer\ChatMessageProducer;
/** /**
* Class WebSocketController * Class WebSocketController
@ -41,9 +41,9 @@ class WebSocketController implements OnMessageInterface, OnOpenInterface, OnClos
/** /**
* @inject * @inject
* @var MessageHandleService * @var ReceiveHandleService
*/ */
private $messageHandleService; private $receiveHandleService;
/** /**
* 消息事件绑定 * 消息事件绑定
@ -84,11 +84,12 @@ class WebSocketController implements OnMessageInterface, OnOpenInterface, OnClos
} }
if (!$isOnline) { if (!$isOnline) {
// 推送消息至队列 MessageProducer::publish(
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_ONLINE_STATUS, [ MessageProducer::create(SocketConstants::EVENT_ONLINE_STATUS, [
'user_id' => $user_id, 'user_id' => $user_id,
'status' => 1, 'status' => 1,
])); ])
);
} }
} }
@ -108,7 +109,7 @@ class WebSocketController implements OnMessageInterface, OnOpenInterface, OnClos
// 回调事件处理函数 // 回调事件处理函数
call_user_func_array([ call_user_func_array([
$this->messageHandleService, $this->receiveHandleService,
self::EVENTS[$result['event']] self::EVENTS[$result['event']]
], [$server, $frame, $result['data']]); ], [$server, $frame, $result['data']]);
} }
@ -132,11 +133,12 @@ class WebSocketController implements OnMessageInterface, OnOpenInterface, OnClos
// 判断是否存在异地登录 // 判断是否存在异地登录
$isOnline = $this->socketClientService->isOnlineAll($user_id); $isOnline = $this->socketClientService->isOnlineAll($user_id);
if (!$isOnline) { if (!$isOnline) {
// 推送消息至队列 MessageProducer::publish(
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_ONLINE_STATUS, [ MessageProducer::create(SocketConstants::EVENT_ONLINE_STATUS, [
'user_id' => $user_id, 'user_id' => $user_id,
'status' => 0, 'status' => 0,
])); ])
);
} }
} }
} }

View File

@ -4,21 +4,7 @@ declare(strict_types=1);
namespace App\Process; namespace App\Process;
use App\Cache\SocketRoom; use App\Service\Message\SubscribeHandleService;
use App\Constants\SocketConstants;
use App\Constants\TalkMsgType;
use App\Constants\TalkType;
use App\Model\Chat\TalkRecords;
use App\Model\Chat\TalkRecordsCode;
use App\Model\Chat\TalkRecordsFile;
use App\Model\Chat\TalkRecordsForward;
use App\Model\Chat\TalkRecordsInvite;
use App\Model\Group\Group;
use App\Model\User;
use App\Model\UsersFriendsApply;
use App\Service\SocketClientService;
use App\Service\UserService;
use Hyperf\Amqp\Result;
use Hyperf\Process\AbstractProcess; use Hyperf\Process\AbstractProcess;
use Hyperf\Process\Annotation\Process; use Hyperf\Process\Annotation\Process;
@ -35,35 +21,13 @@ class RedisWebsocketSubscribe extends AbstractProcess
private $chans = ['websocket']; private $chans = ['websocket'];
/** /**
* 消息事件与回调事件绑定 * @var SubscribeHandleService
*
* @var array
*/ */
const EVENTS = [ private $handleService;
// 聊天消息事件
SocketConstants::EVENT_TALK => 'onConsumeTalk',
// 键盘输入事件
SocketConstants::EVENT_KEYBOARD => 'onConsumeKeyboard',
// 用户在线状态事件
SocketConstants::EVENT_ONLINE_STATUS => 'onConsumeOnlineStatus',
// 聊天消息推送事件
SocketConstants::EVENT_REVOKE_TALK => 'onConsumeRevokeTalk',
// 好友申请相关事件
SocketConstants::EVENT_FRIEND_APPLY => 'onConsumeFriendApply'
];
/**
* @var SocketClientService
*/
private $socketClientService;
public function handle(): void public function handle(): void
{ {
$this->socketClientService = container()->get(SocketClientService::class); $this->handleService = container()->get(SubscribeHandleService::class);
redis()->subscribe($this->chans, [$this, 'subscribe']); redis()->subscribe($this->chans, [$this, 'subscribe']);
} }
@ -80,306 +44,13 @@ class RedisWebsocketSubscribe extends AbstractProcess
//echo PHP_EOL . "chan : $chan , msg : $message"; //echo PHP_EOL . "chan : $chan , msg : $message";
$data = json_decode($message, true); $data = json_decode($message, true);
$this->{self::EVENTS[$data['event']]}($data); if (!isset(SubscribeHandleService::EVENTS[$data['event']])) return;
$this->handleService->{SubscribeHandleService::EVENTS[$data['event']]}($data);
} }
public function isEnable($server): bool public function isEnable($server): bool
{ {
return true; return true;
} }
/**
* 对话聊天消息
*
* @param array $data 队列消息
* @return string
*/
public function onConsumeTalk(array $data): string
{
$talk_type = $data['data']['talk_type'];
$sender_id = $data['data']['sender_id'];
$receiver_id = $data['data']['receiver_id'];
$record_id = $data['data']['record_id'];
$fds = [];
$groupInfo = null;
if ($talk_type == TalkType::PRIVATE_CHAT) {
$fds = array_merge(
$this->socketClientService->findUserFds($sender_id),
$this->socketClientService->findUserFds($receiver_id)
);
} else if ($talk_type == TalkType::GROUP_CHAT) {
foreach (SocketRoom::getInstance()->getRoomMembers(strval($receiver_id)) as $uid) {
$fds = array_merge($fds, $this->socketClientService->findUserFds(intval($uid)));
}
$groupInfo = Group::where('id', $receiver_id)->first(['group_name', 'avatar']);
}
// 客户端ID去重
if (!$fds = array_unique($fds)) {
return Result::ACK;
}
$result = TalkRecords::leftJoin('users', 'users.id', '=', 'talk_records.user_id')
->where('talk_records.id', $record_id)
->first([
'talk_records.id',
'talk_records.talk_type',
'talk_records.msg_type',
'talk_records.user_id',
'talk_records.receiver_id',
'talk_records.content',
'talk_records.is_revoke',
'talk_records.created_at',
'users.nickname',
'users.avatar',
]);
if (!$result) return Result::ACK;
$file = $code_block = $forward = $invite = [];
switch ($result->msg_type) {
case TalkMsgType::FILE_MESSAGE:
$file = TalkRecordsFile::where('record_id', $result->id)->first([
'id', 'record_id', 'user_id', 'file_source', 'file_type',
'save_type', 'original_name', 'file_suffix', 'file_size', 'save_dir'
]);
$file = $file ? $file->toArray() : [];
$file && $file['file_url'] = get_media_url($file['save_dir']);
break;
case TalkMsgType::FORWARD_MESSAGE:
$forward = ['num' => 0, 'list' => []];
$forwardInfo = TalkRecordsForward::where('record_id', $result->id)->first(['records_id', 'text']);
if ($forwardInfo) {
$forward = [
'num' => count(parse_ids($forwardInfo->records_id)),
'list' => json_decode($forwardInfo->text, true) ?? []
];
}
break;
case TalkMsgType::CODE_MESSAGE:
$code_block = TalkRecordsCode::where('record_id', $result->id)->first(['record_id', 'code_lang', 'code']);
$code_block = $code_block ? $code_block->toArray() : [];
break;
case TalkMsgType::GROUP_INVITE_MESSAGE:
$notifyInfo = TalkRecordsInvite::where('record_id', $result->id)->first([
'record_id', 'type', 'operate_user_id', 'user_ids'
]);
$userInfo = User::where('id', $notifyInfo->operate_user_id)->first(['nickname', 'id']);
$invite = [
'type' => $notifyInfo->type,
'operate_user' => ['id' => $userInfo->id, 'nickname' => $userInfo->nickname],
'users' => User::whereIn('id', parse_ids($notifyInfo->user_ids))->get(['id', 'nickname'])->toArray()
];
unset($notifyInfo, $userInfo);
break;
}
$notify = [
'sender_id' => $sender_id,
'receiver_id' => $receiver_id,
'talk_type' => $talk_type,
'data' => $this->formatTalkMessage([
'id' => $result->id,
'talk_type' => $result->talk_type,
'msg_type' => $result->msg_type,
"user_id" => $result->user_id,
"receiver_id" => $result->receiver_id,
'avatar' => $result->avatar,
'nickname' => $result->nickname,
'group_name' => $groupInfo ? $groupInfo->group_name : '',
'group_avatar' => $groupInfo ? $groupInfo->avatar : '',
"created_at" => $result->created_at,
"content" => $result->content,
"file" => $file,
"code_block" => $code_block,
'forward' => $forward,
'invite' => $invite
])
];
$this->socketPushNotify($fds, json_encode([SocketConstants::EVENT_TALK, $notify]));
return Result::ACK;
}
/**
* 键盘输入事件消息
*
* @param array $data 队列消息
* @return string
*/
public function onConsumeKeyboard(array $data): string
{
$fds = $this->socketClientService->findUserFds($data['data']['receiver_id']);
$this->socketPushNotify($fds, json_encode([SocketConstants::EVENT_KEYBOARD, $data['data']]));
return Result::ACK;
}
/**
* 用户上线或下线消息
*
* @param array $data 队列消息
* @return string
*/
public function onConsumeOnlineStatus(array $data): string
{
$user_id = (int)$data['data']['user_id'];
$status = (int)$data['data']['status'];
$fds = [];
$ids = container()->get(UserService::class)->getFriendIds($user_id);
foreach ($ids as $friend_id) {
$fds = array_merge($fds, $this->socketClientService->findUserFds(intval($friend_id)));
}
$this->socketPushNotify(array_unique($fds), json_encode([
SocketConstants::EVENT_ONLINE_STATUS, [
'user_id' => $user_id,
'status' => $status
]
]));
return Result::ACK;
}
/**
* 撤销聊天消息
*
* @param array $data 队列消息
* @return string
*/
public function onConsumeRevokeTalk(array $data): string
{
$record = TalkRecords::where('id', $data['data']['record_id'])->first(['id', 'talk_type', 'user_id', 'receiver_id']);
$fds = [];
if ($record->talk_type == TalkType::PRIVATE_CHAT) {
$fds = array_merge($fds, $this->socketClientService->findUserFds($record->user_id));
$fds = array_merge($fds, $this->socketClientService->findUserFds($record->receiver_id));
} else if ($record->talk_type == TalkType::GROUP_CHAT) {
$userIds = SocketRoom::getInstance()->getRoomMembers(strval($record->receiver_id));
foreach ($userIds as $uid) {
$fds = array_merge($fds, $this->socketClientService->findUserFds((int)$uid));
}
}
$fds = array_unique($fds);
$this->socketPushNotify($fds, json_encode([SocketConstants::EVENT_REVOKE_TALK, [
'talk_type' => $record->talk_type,
'sender_id' => $record->user_id,
'receiver_id' => $record->receiver_id,
'record_id' => $record->id,
]]));
return Result::ACK;
}
/**
* 好友申请消息
*
* @param array $data 队列消息
* @return string
*/
public function onConsumeFriendApply(array $data): string
{
$data = $data['data'];
$applyInfo = UsersFriendsApply::where('id', $data['apply_id'])->first();
if (!$applyInfo) return Result::ACK;
$fds = $this->socketClientService->findUserFds($data['type'] == 1 ? $applyInfo->friend_id : $applyInfo->user_id);
if ($data['type'] == 1) {
$msg = [
'sender_id' => $applyInfo->user_id,
'receiver_id' => $applyInfo->friend_id,
'remark' => $applyInfo->remark,
];
} else {
$msg = [
'sender_id' => $applyInfo->friend_id,
'receiver_id' => $applyInfo->user_id,
'status' => $applyInfo->status,
'remark' => $applyInfo->remark,
];
}
$friendInfo = User::select(['id', 'avatar', 'nickname', 'mobile', 'motto'])->find($data['type'] == 1 ? $applyInfo->user_id : $applyInfo->friend_id);
$msg['friend'] = [
'user_id' => $friendInfo->id,
'avatar' => $friendInfo->avatar,
'nickname' => $friendInfo->nickname,
'mobile' => $friendInfo->mobile,
];
$this->socketPushNotify(array_unique($fds), json_encode([SocketConstants::EVENT_FRIEND_APPLY, $msg]));
return Result::ACK;
}
/**
* WebSocket 消息推送
*
* @param $fds
* @param $message
*/
private function socketPushNotify($fds, $message)
{
$server = server();
foreach ($fds as $fd) {
$server->exist(intval($fd)) && $server->push(intval($fd), $message);
}
}
/**
* 格式化对话的消息体
*
* @param array $data 对话的消息
* @return array
*/
private function formatTalkMessage(array $data): array
{
$message = [
"id" => 0, // 消息记录ID
"talk_type" => 1, // 消息来源[1:好友私信;2:群聊]
"msg_type" => 1, // 消息类型
"user_id" => 0, // 发送者用户ID
"receiver_id" => 0, // 接收者ID[好友ID或群ID]
// 发送消息人的信息
"nickname" => "",// 用户昵称
"avatar" => "",// 用户头像
"group_name" => "",// 群组名称
"group_avatar" => "",// 群组头像
// 不同的消息类型
"file" => [],
"code_block" => [],
"forward" => [],
"invite" => [],
// 消息创建时间
"content" => '',// 文本消息
"created_at" => "",
// 消息属性
"is_revoke" => 0, // 消息是否撤销
];
return array_merge($message, array_intersect_key($data, $message));
}
} }

View File

@ -223,6 +223,7 @@ class GroupService extends BaseService
} }
} }
Db::beginTransaction();
try { try {
if ($updateArr) { if ($updateArr) {
GroupMember::whereIn('id', $updateArr)->update([ GroupMember::whereIn('id', $updateArr)->update([

View File

@ -1,29 +1,33 @@
<?php <?php
namespace App\Service; namespace App\Service\Message;
use App\Cache\LastMessage;
use App\Cache\UnreadTalk;
use App\Constants\SocketConstants; use App\Constants\SocketConstants;
use App\Constants\TalkMsgType; use App\Constants\TalkMsgType;
use App\Constants\TalkType; use App\Constants\TalkType;
use Hyperf\Di\Annotation\Inject;
use Swoole\Http\Response;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
use App\Amqp\Producer\ChatMessageProducer;
use App\Model\Chat\TalkRecords; use App\Model\Chat\TalkRecords;
use App\Model\Group\Group; use App\Model\Group\Group;
use App\Model\UsersFriend; use App\Model\UsersFriend;
use App\Cache\LastMessage; use App\Service\SocketClientService;
use App\Cache\UnreadTalk; use App\Support\MessageProducer;
use Swoole\Http\Response;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
class MessageHandleService class ReceiveHandleService
{ {
/** /**
* @inject
* @var SocketClientService * @var SocketClientService
*/ */
private $socketClientService; private $socketClientService;
public function __construct(SocketClientService $clientService)
{
$this->socketClientService = $clientService;
}
/** /**
* 对话消息 * 对话消息
* *
@ -81,12 +85,14 @@ class MessageHandleService
'created_at' => $result->created_at 'created_at' => $result->created_at
]); ]);
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ MessageProducer::publish(
MessageProducer::create(SocketConstants::EVENT_TALK, [
'sender_id' => $result->user_id, 'sender_id' => $result->user_id,
'receiver_id' => $result->receiver_id, 'receiver_id' => $result->receiver_id,
'talk_type' => $result->talk_type, 'talk_type' => $result->talk_type,
'record_id' => $result->id 'record_id' => $result->id
])); ])
);
} }
/** /**
@ -99,9 +105,11 @@ class MessageHandleService
*/ */
public function onKeyboard($server, Frame $frame, $data) public function onKeyboard($server, Frame $frame, $data)
{ {
push_amqp(new ChatMessageProducer(SocketConstants::EVENT_KEYBOARD, [ MessageProducer::publish(
MessageProducer::create(SocketConstants::EVENT_KEYBOARD, [
'sender_id' => intval($data['sender_id']), 'sender_id' => intval($data['sender_id']),
'receiver_id' => intval($data['receiver_id']), 'receiver_id' => intval($data['receiver_id']),
])); ])
);
} }
} }

View File

@ -1,70 +1,25 @@
<?php <?php
declare(strict_types=1);
/**
* This is my open source code, please do not use it for commercial applications.
* For the full copyright and license information,
* please view the LICENSE file that was distributed with this source code
*
* @author Yuandong<837215079@qq.com>
* @link https://github.com/gzydong/hyperf-chat
*/
namespace App\Amqp\Consumer; namespace App\Service\Message;
use App\Cache\SocketRoom;
use App\Constants\SocketConstants;
use App\Constants\TalkMsgType; use App\Constants\TalkMsgType;
use App\Constants\TalkType; use App\Constants\TalkType;
use App\Model\UsersFriendsApply;
use App\Service\UserService;
use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Result;
use Hyperf\Amqp\Message\ConsumerMessage;
use Hyperf\Amqp\Message\Type;
use Hyperf\Amqp\Builder\QueueBuilder;
use PhpAmqpLib\Message\AMQPMessage;
use App\Model\User;
use App\Model\Chat\TalkRecords; use App\Model\Chat\TalkRecords;
use App\Model\Chat\TalkRecordsCode; use App\Model\Chat\TalkRecordsCode;
use App\Model\Chat\TalkRecordsFile; use App\Model\Chat\TalkRecordsFile;
use App\Model\Chat\TalkRecordsInvite;
use App\Model\Chat\TalkRecordsForward; use App\Model\Chat\TalkRecordsForward;
use App\Model\Chat\TalkRecordsInvite;
use App\Model\Group\Group; use App\Model\Group\Group;
use App\Model\User;
use App\Model\UsersFriendsApply;
use App\Service\SocketClientService; use App\Service\SocketClientService;
use App\Constants\SocketConstants; use App\Service\UserService;
use App\Cache\Repository\LockRedis; use Hyperf\Amqp\Result;
use App\Cache\SocketRoom;
/** class SubscribeHandleService
* 消息推送消费者队列
* @Consumer(name="ConsumerChat",enable=false)
*/
class ChatMessageConsumer extends ConsumerMessage
{ {
/**
* 交换机名称
*
* @var string
*/
public $exchange = SocketConstants::CONSUMER_MESSAGE_EXCHANGE;
/**
* 交换机类型
*
* @var string
*/
public $type = Type::FANOUT;
/**
* 路由key
*
* @var string
*/
public $routingKey = 'consumer:im:message';
/**
* @var SocketClientService
*/
private $socketClientService;
/** /**
* 消息事件与回调事件绑定 * 消息事件与回调事件绑定
* *
@ -88,60 +43,22 @@ class ChatMessageConsumer extends ConsumerMessage
]; ];
/** /**
* ChatMessageConsumer constructor. * @var SocketClientService
*
* @param SocketClientService $socketClientService
*/ */
public function __construct(SocketClientService $socketClientService) private $clientService;
public function __construct(SocketClientService $clientService)
{ {
$this->socketClientService = $socketClientService; $this->clientService = $clientService;
// 动态设置 Rabbit MQ 消费队列名称
$this->setQueue('queue:im_message:' . SERVER_RUN_ID);
}
/**
* 重写创建队列生成类
* 注释:设置自动删除队列
*
* @return QueueBuilder
*/
public function getQueueBuilder(): QueueBuilder
{
return parent::getQueueBuilder()->setAutoDelete(true);
}
/**
* 消费队列消息
*
* @param $data
* @param AMQPMessage $message
* @return string
*/
public function consumeMessage($data, AMQPMessage $message): string
{
if (isset($data['event'])) {
// [加锁]防止消息重复消费
$lockName = sprintf('ws-message:%s-%s', SERVER_RUN_ID, $data['uuid']);
if (!LockRedis::getInstance()->lock($lockName, 60)) {
return Result::ACK;
}
// 调用对应事件绑定的回调方法
return $this->{self::EVENTS[$data['event']]}($data, $message);
}
return Result::ACK;
} }
/** /**
* 对话聊天消息 * 对话聊天消息
* *
* @param array $data 队列消息 * @param array $data 队列消息
* @param AMQPMessage $message
* @return string * @return string
*/ */
public function onConsumeTalk(array $data, AMQPMessage $message): string public function onConsumeTalk(array $data): string
{ {
$talk_type = $data['data']['talk_type']; $talk_type = $data['data']['talk_type'];
$sender_id = $data['data']['sender_id']; $sender_id = $data['data']['sender_id'];
@ -153,12 +70,12 @@ class ChatMessageConsumer extends ConsumerMessage
if ($talk_type == TalkType::PRIVATE_CHAT) { if ($talk_type == TalkType::PRIVATE_CHAT) {
$fds = array_merge( $fds = array_merge(
$this->socketClientService->findUserFds($sender_id), $this->clientService->findUserFds($sender_id),
$this->socketClientService->findUserFds($receiver_id) $this->clientService->findUserFds($receiver_id)
); );
} else if ($talk_type == TalkType::GROUP_CHAT) { } else if ($talk_type == TalkType::GROUP_CHAT) {
foreach (SocketRoom::getInstance()->getRoomMembers(strval($receiver_id)) as $uid) { foreach (SocketRoom::getInstance()->getRoomMembers(strval($receiver_id)) as $uid) {
$fds = array_merge($fds, $this->socketClientService->findUserFds(intval($uid))); $fds = array_merge($fds, $this->clientService->findUserFds(intval($uid)));
} }
$groupInfo = Group::where('id', $receiver_id)->first(['group_name', 'avatar']); $groupInfo = Group::where('id', $receiver_id)->first(['group_name', 'avatar']);
@ -166,7 +83,7 @@ class ChatMessageConsumer extends ConsumerMessage
// 客户端ID去重 // 客户端ID去重
if (!$fds = array_unique($fds)) { if (!$fds = array_unique($fds)) {
return Result::ACK; return true;
} }
$result = TalkRecords::leftJoin('users', 'users.id', '=', 'talk_records.user_id') $result = TalkRecords::leftJoin('users', 'users.id', '=', 'talk_records.user_id')
@ -184,7 +101,7 @@ class ChatMessageConsumer extends ConsumerMessage
'users.avatar', 'users.avatar',
]); ]);
if (!$result) return Result::ACK; if (!$result) return true;
$file = $code_block = $forward = $invite = []; $file = $code_block = $forward = $invite = [];
@ -256,33 +173,31 @@ class ChatMessageConsumer extends ConsumerMessage
$this->socketPushNotify($fds, json_encode([SocketConstants::EVENT_TALK, $notify])); $this->socketPushNotify($fds, json_encode([SocketConstants::EVENT_TALK, $notify]));
return Result::ACK; return true;
} }
/** /**
* 键盘输入事件消息 * 键盘输入事件消息
* *
* @param array $data 队列消息 * @param array $data 队列消息
* @param AMQPMessage $message
* @return string * @return string
*/ */
public function onConsumeKeyboard(array $data, AMQPMessage $message): string public function onConsumeKeyboard(array $data): string
{ {
$fds = $this->socketClientService->findUserFds($data['data']['receiver_id']); $fds = $this->clientService->findUserFds($data['data']['receiver_id']);
$this->socketPushNotify($fds, json_encode([SocketConstants::EVENT_KEYBOARD, $data['data']])); $this->socketPushNotify($fds, json_encode([SocketConstants::EVENT_KEYBOARD, $data['data']]));
return Result::ACK; return true;
} }
/** /**
* 用户上线或下线消息 * 用户上线或下线消息
* *
* @param array $data 队列消息 * @param array $data 队列消息
* @param AMQPMessage $message
* @return string * @return string
*/ */
public function onConsumeOnlineStatus(array $data, AMQPMessage $message): string public function onConsumeOnlineStatus(array $data): string
{ {
$user_id = (int)$data['data']['user_id']; $user_id = (int)$data['data']['user_id'];
$status = (int)$data['data']['status']; $status = (int)$data['data']['status'];
@ -291,7 +206,7 @@ class ChatMessageConsumer extends ConsumerMessage
$ids = container()->get(UserService::class)->getFriendIds($user_id); $ids = container()->get(UserService::class)->getFriendIds($user_id);
foreach ($ids as $friend_id) { foreach ($ids as $friend_id) {
$fds = array_merge($fds, $this->socketClientService->findUserFds(intval($friend_id))); $fds = array_merge($fds, $this->clientService->findUserFds(intval($friend_id)));
} }
$this->socketPushNotify(array_unique($fds), json_encode([ $this->socketPushNotify(array_unique($fds), json_encode([
@ -301,28 +216,27 @@ class ChatMessageConsumer extends ConsumerMessage
] ]
])); ]));
return Result::ACK; return true;
} }
/** /**
* 撤销聊天消息 * 撤销聊天消息
* *
* @param array $data 队列消息 * @param array $data 队列消息
* @param AMQPMessage $message
* @return string * @return string
*/ */
public function onConsumeRevokeTalk(array $data, AMQPMessage $message): string public function onConsumeRevokeTalk(array $data): string
{ {
$record = TalkRecords::where('id', $data['data']['record_id'])->first(['id', 'talk_type', 'user_id', 'receiver_id']); $record = TalkRecords::where('id', $data['data']['record_id'])->first(['id', 'talk_type', 'user_id', 'receiver_id']);
$fds = []; $fds = [];
if ($record->talk_type == TalkType::PRIVATE_CHAT) { if ($record->talk_type == TalkType::PRIVATE_CHAT) {
$fds = array_merge($fds, $this->socketClientService->findUserFds($record->user_id)); $fds = array_merge($fds, $this->clientService->findUserFds($record->user_id));
$fds = array_merge($fds, $this->socketClientService->findUserFds($record->receiver_id)); $fds = array_merge($fds, $this->clientService->findUserFds($record->receiver_id));
} else if ($record->talk_type == TalkType::GROUP_CHAT) { } else if ($record->talk_type == TalkType::GROUP_CHAT) {
$userIds = SocketRoom::getInstance()->getRoomMembers(strval($record->receiver_id)); $userIds = SocketRoom::getInstance()->getRoomMembers(strval($record->receiver_id));
foreach ($userIds as $uid) { foreach ($userIds as $uid) {
$fds = array_merge($fds, $this->socketClientService->findUserFds((int)$uid)); $fds = array_merge($fds, $this->clientService->findUserFds((int)$uid));
} }
} }
@ -334,24 +248,23 @@ class ChatMessageConsumer extends ConsumerMessage
'record_id' => $record->id, 'record_id' => $record->id,
]])); ]]));
return Result::ACK; return true;
} }
/** /**
* 好友申请消息 * 好友申请消息
* *
* @param array $data 队列消息 * @param array $data 队列消息
* @param AMQPMessage $message
* @return string * @return string
*/ */
public function onConsumeFriendApply(array $data, AMQPMessage $message): string public function onConsumeFriendApply(array $data): string
{ {
$data = $data['data']; $data = $data['data'];
$applyInfo = UsersFriendsApply::where('id', $data['apply_id'])->first(); $applyInfo = UsersFriendsApply::where('id', $data['apply_id'])->first();
if (!$applyInfo) return Result::ACK; if (!$applyInfo) return true;
$fds = $this->socketClientService->findUserFds($data['type'] == 1 ? $applyInfo->friend_id : $applyInfo->user_id); $fds = $this->clientService->findUserFds($data['type'] == 1 ? $applyInfo->friend_id : $applyInfo->user_id);
if ($data['type'] == 1) { if ($data['type'] == 1) {
$msg = [ $msg = [
@ -379,7 +292,7 @@ class ChatMessageConsumer extends ConsumerMessage
$this->socketPushNotify(array_unique($fds), json_encode([SocketConstants::EVENT_FRIEND_APPLY, $msg])); $this->socketPushNotify(array_unique($fds), json_encode([SocketConstants::EVENT_FRIEND_APPLY, $msg]));
return Result::ACK; return true;
} }
/** /**

View File

@ -0,0 +1,34 @@
<?php
namespace App\Support;
use App\Constants\RedisSubscribeChan;
class MessageProducer
{
/**
* @param string $event
* @param array $data
* @param array $options
* @return array
*/
public static function create(string $event, array $data, array $options = [])
{
return [
'uuid' => uniqid((strval(mt_rand(0, 1000)))),
'event' => $event,
'data' => $data,
'options' => $options
];
}
/**
* @param array $message
*/
public static function publish(array $message)
{
push_redis_subscribe(RedisSubscribeChan::WEBSOCKET_CHAN, $message);
}
}

View File

@ -251,7 +251,6 @@ function parse_ids($ids)
*/ */
function push_amqp(ProducerMessage $message, bool $confirm = false, int $timeout = 5) function push_amqp(ProducerMessage $message, bool $confirm = false, int $timeout = 5)
{ {
push_redis_subscribe('websocket', $message->getPayload());
return container()->get(Producer::class)->produce($message, $confirm, $timeout); return container()->get(Producer::class)->produce($message, $confirm, $timeout);
} }

View File

@ -27,7 +27,6 @@
"hyperf/redis": "~2.0.0", "hyperf/redis": "~2.0.0",
"hyperf/database": "~2.0.0", "hyperf/database": "~2.0.0",
"hyperf/async-queue": "~2.0.0", "hyperf/async-queue": "~2.0.0",
"hyperf/amqp": "~2.0.0",
"hyperf/websocket-server": "^2.0", "hyperf/websocket-server": "^2.0",
"hyperf/constants": "^2.0", "hyperf/constants": "^2.0",
"hyperf/validation": "^2.0", "hyperf/validation": "^2.0",

View File

@ -1,38 +0,0 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
return [
'default' => [
'host' => env('AMQP_HOST','127.0.0.1'),
'port' => intval(env('AMQP_PORT',5672)),
'user' => env('AMQP_USER','guest'),
'password' => env('AMQP_PASSWORD','guest'),
'vhost' => env('AMQP_VHOST','/'),
'pool' => [
'min_connections' => 1,
'max_connections' => 10,
'connect_timeout' => 10.0,
'wait_timeout' => 3.0,
'heartbeat' => -1,
],
'params' => [
'insist' => false,
'login_method' => 'AMQPLAIN',
'login_response' => null,
'locale' => 'en_US',
'connection_timeout' => 3.0,
'read_write_timeout' => 8.0,
'context' => null,
'keepalive' => false,
'heartbeat' => 3,
],
],
];

View File

@ -17,10 +17,11 @@ class CreateUsersTable extends Migration
$table->string('mobile', 11)->default('')->unique()->comment('手机号'); $table->string('mobile', 11)->default('')->unique()->comment('手机号');
$table->string('nickname', 20)->default('')->comment('用户昵称'); $table->string('nickname', 20)->default('')->comment('用户昵称');
$table->string('avatar', 255)->default('')->comment('用户头像地址'); $table->string('avatar', 255)->default('')->comment('用户头像地址');
$table->unsignedTinyInteger('gender')->default(0)->comment('用户性别[0:未知;1:男;2:女]'); $table->unsignedTinyInteger('gender')->default(0)->comment('用户性别[0:未知;1:男;2:女;]');
$table->string('password', 255)->default('')->comment('用户密码'); $table->string('password', 255)->default('')->comment('用户密码');
$table->string('motto', 100)->default('')->comment('用户座右铭'); $table->string('motto', 100)->default('')->comment('用户座右铭');
$table->string('email', 30)->default('')->comment('用户邮箱'); $table->string('email', 30)->default('')->comment('用户邮箱');
$table->unsignedTinyInteger('is_robot')->default(0)->comment('是否机器人[0:否;1:是;]');
$table->dateTime('created_at')->nullable()->comment('注册时间'); $table->dateTime('created_at')->nullable()->comment('注册时间');
$table->dateTime('updated_at')->nullable()->comment('更新时间'); $table->dateTime('updated_at')->nullable()->comment('更新时间');

View File

@ -17,10 +17,10 @@ class CreateArticleAnnexTable extends Migration
$table->unsignedInteger('user_id')->unsigned()->comment('上传文件的用户ID'); $table->unsignedInteger('user_id')->unsigned()->comment('上传文件的用户ID');
$table->unsignedInteger('article_id')->default(0)->comment('笔记ID'); $table->unsignedInteger('article_id')->default(0)->comment('笔记ID');
$table->string('file_suffix', 10)->default('')->comment('文件后缀名'); $table->string('file_suffix', 10)->default('')->comment('文件后缀名');
$table->bigInteger('file_size')->default(0)->unsigned()->comment('文件大小(单位字节)'); $table->unsignedBigInteger('file_size')->default(0)->comment('文件大小(单位字节)');
$table->string('save_dir', 500)->nullable()->comment('文件保存地址(相对地址)'); $table->string('save_dir', 500)->nullable(false)->default('')->comment('文件保存地址(相对地址)');
$table->string('original_name', 100)->nullable()->comment('原文件名'); $table->string('original_name', 100)->nullable(false)->default('')->comment('原文件名');
$table->tinyInteger('status')->default(1)->unsigned()->comment('附件状态[1:正常;2:已删除]'); $table->unsignedTinyInteger('status')->default(1)->comment('附件状态[1:正常;2:已删除]');
$table->dateTime('created_at')->nullable(true)->comment('附件上传时间'); $table->dateTime('created_at')->nullable(true)->comment('附件上传时间');
$table->dateTime('deleted_at')->nullable(true)->comment('附件删除时间'); $table->dateTime('deleted_at')->nullable(true)->comment('附件删除时间');

View File

@ -22,6 +22,8 @@ class CreateEmoticonTable extends Migration
$table->charset = 'utf8'; $table->charset = 'utf8';
$table->collation = 'utf8_general_ci'; $table->collation = 'utf8_general_ci';
$table->unique(['name'], 'uk_name');
}); });
$prefix = config('databases.default.prefix'); $prefix = config('databases.default.prefix');

View File

@ -15,7 +15,7 @@ class CreateFileSplitUploadTable extends Migration
$table->unsignedInteger('id', true)->comment('临时文件ID'); $table->unsignedInteger('id', true)->comment('临时文件ID');
$table->unsignedTinyInteger('file_type')->default(2)->comment('数据类型[1:合并文件;2:拆分文件]'); $table->unsignedTinyInteger('file_type')->default(2)->comment('数据类型[1:合并文件;2:拆分文件]');
$table->unsignedInteger('user_id')->default(0)->comment('上传的用户ID'); $table->unsignedInteger('user_id')->default(0)->comment('上传的用户ID');
$table->string('hash_name', 30)->default('')->comment('临时文件hash名'); $table->string('hash_name', 32)->default('')->comment('临时文件hash名');
$table->string('original_name', 100)->default('')->comment('原文件名'); $table->string('original_name', 100)->default('')->comment('原文件名');
$table->unsignedTinyInteger('split_index')->default(0)->comment('当前索引块'); $table->unsignedTinyInteger('split_index')->default(0)->comment('当前索引块');
$table->unsignedTinyInteger('split_num')->default(0)->comment('总上传索引块'); $table->unsignedTinyInteger('split_num')->default(0)->comment('总上传索引块');

View File

@ -1,35 +0,0 @@
<?php
use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db;
class CreateUserLoginLogTable extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('user_login_log', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('登录日志ID');
$table->unsignedInteger('user_id')->default(0)->comment('用户ID');
$table->string('ip', 20)->comment('登录地址IP');
$table->dateTime('created_at')->nullable(true)->comment('登录时间');
$table->charset = 'utf8';
$table->collation = 'utf8_general_ci';
});
$prefix = config('databases.default.prefix');
DB::statement("ALTER TABLE `{$prefix}user_login_log` comment '用户登录日志表'");
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('user_login_log');
}
}

View File

@ -0,0 +1,45 @@
<?php
use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db;
class CreateTalkListTable extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('talk_list', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('聊天列表ID');
$table->unsignedTinyInteger('talk_type')->default(1)->comment('聊天类型[1:私信;2:群聊;]');
$table->unsignedInteger('user_id')->default(0)->comment('用户ID');
$table->unsignedInteger('receiver_id')->default(0)->comment('接收者ID用户ID 或 群ID');
$table->unsignedTinyInteger('is_top')->default(0)->comment('是否置顶[0:否;1:是]');
$table->unsignedTinyInteger('is_robot')->default(0)->comment('是否机器人[0:否;1:是;]');
$table->unsignedTinyInteger('is_delete')->default(0)->comment('是否删除[0:否;1:是;]');
$table->unsignedTinyInteger('is_disturb')->default(0)->comment('消息免打扰[0:否;1:是;]');
$table->dateTime('created_at')->nullable(true)->comment('创建时间');
$table->dateTime('updated_at')->nullable(true)->comment('更新时间');
$table->charset = 'utf8';
$table->collation = 'utf8_general_ci';
$table->engine = 'InnoDB';
$table->index(['user_id', 'receiver_id', 'talk_type'], 'idx_user_id_receiver_id_talk_type');
});
$prefix = config('databases.default.prefix');
DB::statement("ALTER TABLE `{$prefix}talk_list` comment '用户聊天列表'");
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('talk_list');
}
}

View File

@ -1,44 +0,0 @@
<?php
use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db;
class CreateUsersChatListTable extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users_chat_list', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('聊天列表ID');
$table->unsignedTinyInteger('type')->default(1)->comment('聊天类型[1:好友;2:群聊]');
$table->unsignedInteger('uid')->default(0)->comment('用户ID');
$table->unsignedInteger('friend_id')->default(0)->comment('朋友的用户ID');
$table->unsignedInteger('group_id')->default(0)->comment('聊天分组ID');
$table->unsignedInteger('status')->default(1)->default(1)->comment('状态[0:已删除;1:正常]');
$table->unsignedTinyInteger('is_top')->default(0)->comment('是否置顶[0:否;1:是]');
$table->unsignedTinyInteger('not_disturb')->default(0)->comment('是否消息免打扰[0:否;1:是]');
$table->dateTime('created_at')->nullable(true)->comment('创建时间');
$table->dateTime('updated_at')->nullable(true)->comment('更新时间');
$table->charset = 'utf8';
$table->collation = 'utf8_general_ci';
$table->engine = 'InnoDB';
$table->index(['uid', 'friend_id', 'group_id', 'type'], 'idx_uid_type_friend_id_group_id');
});
$prefix = config('databases.default.prefix');
DB::statement("ALTER TABLE `{$prefix}users_chat_list` comment '用户聊天列表'");
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users_chat_list');
}
}

View File

@ -1,42 +0,0 @@
<?php
use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db;
class CreateChatRecordsTable extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('chat_records', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('聊天记录ID');
$table->tinyInteger('source')->unsigned()->default(1)->comment('消息来源[1:好友消息;2:群聊消息]');
$table->tinyInteger('msg_type')->unsigned()->default(1)->comment('消息类型[1:文本消息;2:文件消息;3:系统提示好友入群消息或系统提示好友退群消息;4:会话记录转发]');
$table->unsignedInteger('user_id')->default(0)->comment('发送消息的用户ID[0:代表系统消息]');
$table->unsignedInteger('receive_id')->default(0)->comment('接收消息的用户ID或群聊ID');
$table->text('content')->nullable(true)->charset('utf8mb4')->comment('文本消息');
$table->tinyInteger('is_revoke')->default(0)->comment('是否撤回消息[0:否;1:是]');
$table->dateTime('created_at')->nullable(true)->comment('发送消息的时间');
$table->charset = 'utf8';
$table->collation = 'utf8_general_ci';
$table->engine = 'InnoDB';
$table->index(['user_id', 'receive_id'], 'idx_userid_receiveid');
});
$prefix = config('databases.default.prefix');
DB::statement("ALTER TABLE `{$prefix}chat_records` comment '用户聊天记录表'");
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('chat_records');
}
}

View File

@ -0,0 +1,48 @@
<?php
use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db;
class CreateTalkRecordsTable extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('talk_records', function (Blueprint $table) {
$table->unsignedBigInteger('id', true)->comment('聊天记录ID');
$table->unsignedTinyInteger('talk_type')->unsigned()->default(1)->comment('对话类型[1:私信;2:群聊;]');
$table->unsignedTinyInteger('msg_type')->unsigned()->default(1)->comment('消息类型[1:文本消息;2:文件消息;3:会话消息;4:代码消息;5:投票消息;6:群公告;7:好友申请;8:登录通知;9:入群消息/退群消息;]');
$table->unsignedInteger('user_id')->default(0)->comment('发送者ID0:代表系统消息 >0: 用户ID');
$table->unsignedInteger('receiver_id')->default(0)->comment('接收者ID用户ID 或 群ID');
$table->tinyInteger('is_revoke')->default(0)->comment('是否撤回消息[0:否;1:是]');
$table->tinyInteger('is_mark')->default(0)->comment('是否重要消息[0:否;1:是;]');
$table->tinyInteger('is_read')->default(0)->comment('是否已读[0:否;1:是;]');
$table->unsignedBigInteger('quote_id')->default(0)->comment('引用消息ID');
$table->text('content')->nullable(true)->charset('utf8mb4')->comment('文本消息 {@nickname@}');
$table->string('warn_users', 200)->default('')->comment('@好友 、 多个用英文逗号 “,” 拼接 (0:代表所有人)');
$table->dateTime('created_at')->nullable(true)->comment('创建时间');
$table->dateTime('updated_at')->nullable(true)->comment('更新时间');
$table->charset = 'utf8';
$table->collation = 'utf8_general_ci';
$table->engine = 'InnoDB';
$table->index(['user_id', 'receiver_id'], 'idx_user_id_receiver_id');
});
$prefix = config('databases.default.prefix');
DB::statement("ALTER TABLE `{$prefix}talk_records` comment '用户聊天记录表'");
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('talk_records');
}
}

View File

@ -4,14 +4,15 @@ use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint; use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration; use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db; use Hyperf\DbConnection\Db;
class CreateChatRecordsFileTable extends Migration
class CreateTalkRecordsFileTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
*/ */
public function up(): void public function up(): void
{ {
Schema::create('chat_records_file', function (Blueprint $table) { Schema::create('talk_records_file', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('文件ID'); $table->unsignedInteger('id', true)->comment('文件ID');
$table->unsignedInteger('record_id')->default(0)->comment('消息记录ID'); $table->unsignedInteger('record_id')->default(0)->comment('消息记录ID');
$table->unsignedInteger('user_id')->default(0)->comment('上传文件的用户ID'); $table->unsignedInteger('user_id')->default(0)->comment('上传文件的用户ID');
@ -33,7 +34,7 @@ class CreateChatRecordsFileTable extends Migration
}); });
$prefix = config('databases.default.prefix'); $prefix = config('databases.default.prefix');
DB::statement("ALTER TABLE `{$prefix}chat_records_file` comment '用户聊天记录_文件消息表'"); DB::statement("ALTER TABLE `{$prefix}talk_records_file` comment '用户聊天记录_文件消息表'");
} }
/** /**
@ -41,6 +42,6 @@ class CreateChatRecordsFileTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
Schema::dropIfExists('chat_records_file'); Schema::dropIfExists('talk_records_file');
} }
} }

View File

@ -5,14 +5,14 @@ use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration; use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db; use Hyperf\DbConnection\Db;
class CreateChatRecordsDeleteTable extends Migration class CreateTalkRecordsDeleteTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
*/ */
public function up(): void public function up(): void
{ {
Schema::create('chat_records_delete', function (Blueprint $table) { Schema::create('talk_records_delete', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('聊天删除记录ID'); $table->unsignedInteger('id', true)->comment('聊天删除记录ID');
$table->unsignedInteger('record_id')->default(0)->comment('聊天记录ID'); $table->unsignedInteger('record_id')->default(0)->comment('聊天记录ID');
$table->unsignedInteger('user_id')->default(0)->comment('用户ID'); $table->unsignedInteger('user_id')->default(0)->comment('用户ID');
@ -26,7 +26,7 @@ class CreateChatRecordsDeleteTable extends Migration
}); });
$prefix = config('databases.default.prefix'); $prefix = config('databases.default.prefix');
DB::statement("ALTER TABLE `{$prefix}chat_records_delete` comment '用户聊天记录_删除记录表'"); DB::statement("ALTER TABLE `{$prefix}talk_records_delete` comment '用户聊天记录_删除记录表'");
} }
/** /**
@ -34,6 +34,6 @@ class CreateChatRecordsDeleteTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
Schema::dropIfExists('chat_records_delete_file'); Schema::dropIfExists('talk_records_delete');
} }
} }

View File

@ -4,14 +4,14 @@ use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint; use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration; use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db; use Hyperf\DbConnection\Db;
class CreateChatRecordsForwardTable extends Migration class CreateTalkRecordsForwardTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
*/ */
public function up(): void public function up(): void
{ {
Schema::create('chat_records_forward', function (Blueprint $table) { Schema::create('talk_records_forward', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('合并转发ID'); $table->unsignedInteger('id', true)->comment('合并转发ID');
$table->unsignedInteger('record_id')->default(0)->comment('消息记录ID'); $table->unsignedInteger('record_id')->default(0)->comment('消息记录ID');
$table->unsignedInteger('user_id')->default(0)->comment('转发用户ID'); $table->unsignedInteger('user_id')->default(0)->comment('转发用户ID');
@ -27,7 +27,7 @@ class CreateChatRecordsForwardTable extends Migration
}); });
$prefix = config('databases.default.prefix'); $prefix = config('databases.default.prefix');
DB::statement("ALTER TABLE `{$prefix}chat_records_forward` comment '用户聊天记录_转发信息表'"); DB::statement("ALTER TABLE `{$prefix}talk_records_forward` comment '用户聊天记录_转发信息表'");
} }
/** /**
@ -35,6 +35,6 @@ class CreateChatRecordsForwardTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
Schema::dropIfExists('chat_records_forward'); Schema::dropIfExists('talk_records_forward');
} }
} }

View File

@ -4,14 +4,15 @@ use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint; use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration; use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db; use Hyperf\DbConnection\Db;
class CreateChatRecordsInviteTable extends Migration
class CreateTalkRecordsInviteTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
*/ */
public function up(): void public function up(): void
{ {
Schema::create('chat_records_invite', function (Blueprint $table) { Schema::create('talk_records_invite', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('入群或退群通知ID'); $table->unsignedInteger('id', true)->comment('入群或退群通知ID');
$table->unsignedInteger('record_id')->default(0)->comment('消息记录ID'); $table->unsignedInteger('record_id')->default(0)->comment('消息记录ID');
$table->tinyInteger('type')->default(1)->comment('通知类型[1:入群通知;2:自动退群;3:管理员踢群]'); $table->tinyInteger('type')->default(1)->comment('通知类型[1:入群通知;2:自动退群;3:管理员踢群]');
@ -26,7 +27,7 @@ class CreateChatRecordsInviteTable extends Migration
}); });
$prefix = config('databases.default.prefix'); $prefix = config('databases.default.prefix');
DB::statement("ALTER TABLE `{$prefix}chat_records_invite` comment '用户聊天记录_入群或退群消息表'"); DB::statement("ALTER TABLE `{$prefix}talk_records_invite` comment '用户聊天记录_入群或退群消息表'");
} }
/** /**
@ -34,6 +35,6 @@ class CreateChatRecordsInviteTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
Schema::dropIfExists('chat_records_invite'); Schema::dropIfExists('talk_records_invite');
} }
} }

View File

@ -4,14 +4,15 @@ use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint; use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration; use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db; use Hyperf\DbConnection\Db;
class CreateChatRecordsCodeTable extends Migration
class CreateTalkRecordsCodeTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
*/ */
public function up(): void public function up(): void
{ {
Schema::create('chat_records_code', function (Blueprint $table) { Schema::create('talk_records_code', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('入群或退群通知ID'); $table->unsignedInteger('id', true)->comment('入群或退群通知ID');
$table->unsignedInteger('record_id')->default(0)->comment('消息记录ID'); $table->unsignedInteger('record_id')->default(0)->comment('消息记录ID');
$table->unsignedInteger('user_id')->default(0)->comment('上传文件的用户ID'); $table->unsignedInteger('user_id')->default(0)->comment('上传文件的用户ID');
@ -27,7 +28,7 @@ class CreateChatRecordsCodeTable extends Migration
}); });
$prefix = config('databases.default.prefix'); $prefix = config('databases.default.prefix');
DB::statement("ALTER TABLE `{$prefix}chat_records_code` comment '用户聊天记录_代码块消息表'"); DB::statement("ALTER TABLE `{$prefix}talk_records_code` comment '用户聊天记录_代码块消息表'");
} }
/** /**
@ -35,6 +36,6 @@ class CreateChatRecordsCodeTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
Schema::dropIfExists('chat_records_code'); Schema::dropIfExists('talk_records_code');
} }
} }

View File

@ -14,21 +14,18 @@ class CreateUsersFriendsTable extends Migration
{ {
Schema::create('users_friends', function (Blueprint $table) { Schema::create('users_friends', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('关系ID'); $table->unsignedInteger('id', true)->comment('关系ID');
$table->unsignedInteger('user1')->default(0)->comment('用户1(user1 一定比 user2 小)'); $table->unsignedInteger('user_id')->default(0)->comment('用户ID');
$table->unsignedInteger('user2')->default(0)->comment('用户2(user1 一定比 user2 小)'); $table->unsignedInteger('friend_id')->default(0)->comment('好友ID');
$table->string('user1_remark', 20)->default('')->comment('好友备注'); $table->string('remark', 30)->default('')->comment('好友备注');
$table->string('user2_remark', 20)->default('')->comment('好友备注'); $table->unsignedTinyInteger('status')->default(0)->comment('好友状态[0:否;1:是;]');
$table->unsignedTinyInteger('active')->default(1)->default(1)->comment('主动邀请方[1:user1;2:user2]');
$table->unsignedTinyInteger('status')->default(1)->comment('好友状态[0:已解除好友关系;1:好友状态]');
$table->dateTime('agree_time')->comment('成为好友时间');
$table->dateTime('created_at')->nullable(true)->comment('创建时间'); $table->dateTime('created_at')->nullable(true)->comment('创建时间');
$table->dateTime('updated_at')->nullable(true)->comment('更新时间');
$table->charset = 'utf8'; $table->charset = 'utf8';
$table->collation = 'utf8_general_ci'; $table->collation = 'utf8_general_ci';
$table->engine = 'InnoDB'; $table->engine = 'InnoDB';
$table->index(['user1', 'user2'], 'idx_user1_user2'); $table->index(['user_id', 'friend_id'], 'idx_user_id_friend_id');
$table->index(['user2', 'user1'], 'idx_user2_user1');
}); });
$prefix = config('databases.default.prefix'); $prefix = config('databases.default.prefix');

View File

@ -4,6 +4,7 @@ use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint; use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration; use Hyperf\Database\Migrations\Migration;
use Hyperf\DbConnection\Db; use Hyperf\DbConnection\Db;
class CreateUsersFriendsApplyTable extends Migration class CreateUsersFriendsApplyTable extends Migration
{ {
/** /**
@ -14,11 +15,12 @@ class CreateUsersFriendsApplyTable extends Migration
Schema::create('users_friends_apply', function (Blueprint $table) { Schema::create('users_friends_apply', function (Blueprint $table) {
$table->unsignedInteger('id', true)->comment('申请ID'); $table->unsignedInteger('id', true)->comment('申请ID');
$table->unsignedInteger('user_id')->default(0)->comment('申请人ID'); $table->unsignedInteger('user_id')->default(0)->comment('申请人ID');
$table->unsignedInteger('friend_id')->default(0)->comment('被申请人'); $table->unsignedInteger('friend_id')->default(0)->comment('好友ID');
$table->unsignedTinyInteger('status')->default(0)->comment('申请状态[0:等待处理;1:已同意]'); $table->unsignedTinyInteger('status')->default(0)->comment('申请状态[0:等待处理;1:已同意;2:已拒绝;]');
$table->string('remarks', 50)->default('')->comment('申请人备注信息'); $table->string('remark', 50)->default('')->comment('备注信息');
$table->string('reason', 50)->default('')->comment('拒绝的原因');
$table->dateTime('created_at')->nullable()->comment('申请时间'); $table->dateTime('created_at')->nullable()->comment('申请时间');
$table->dateTime('updated_at')->nullable()->comment('处理时间'); $table->dateTime('updated_at')->nullable()->comment('更新时间');
$table->charset = 'utf8'; $table->charset = 'utf8';
$table->collation = 'utf8_general_ci'; $table->collation = 'utf8_general_ci';

View File

@ -28,7 +28,7 @@ class CreateGroupMemberTable extends Migration
$table->engine = 'InnoDB'; $table->engine = 'InnoDB';
$table->unique(['group_id', 'user_id'], 'uk_group_id_user_id'); $table->unique(['group_id', 'user_id'], 'uk_group_id_user_id');
$table->index(['user_id', 'group_id'], 'idx_user_id_group_id'); $table->index(['user_id'], 'idx_user_id');
}); });
$prefix = config('databases.default.prefix'); $prefix = config('databases.default.prefix');