基于 Swoole 开发实时在线聊天室(十):用户登录后获取未读消息数
接下来,我们正式开始开发聊天室聊天功能。
在用户每次登录后,需要将未读消息发送给客户端,以便提醒用户有多少条未读消息,今天我们就围绕这个功能来编写前后端代码。
前端入口页面逻辑
首先在前端打开 resources/js/pages/Load.vue
,用户登录之后会跳转到该页面,这个 Vue 组件的 mounted
函数实现如下:
async mounted() {
this.$store.commit("setTab", true);
// 只全局监听一次
if (!this.isLogin) {
// 登录了,发送进入信息。
if (this.userid) {
// 处理未读消息
socket.on("count", userCount => {
this.$store.commit("setUnread", userCount);
console.log(userCount);
});
this.$store.commit("setLoginState", true);
}
}
},
用户首次登录成功后,会监听 Websocket 服务端的 count
事件,并在回调函数中根据服务端返回数据初始化各个聊天室未读消息数。
前端代码比较简单,不用做任何调整,接下来我们到后端实现相应的获取未读消息数代码。
创建相关模型类和数据表
我们创建一个新的 counts
表来存放用户在每个聊天室中的未读消息数。
通过如下 Artisan 命令快速生成 Count
模型类及对应数据库迁移类:
php artisan make:model Count -m
然后修改模型类 app/Count.php
代码如下:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Count extends Model
{
public static $ROOMLIST = [1, 2];
public $timestamps = false;
}
注:这里为了简化逻辑,我们将聊天室房间数据写死。
在 database/migrations
目录下编辑刚刚生成的迁移类 CreateCountsTable
的 up
方法如下:
class CreateCountsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('counts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('user_id');
$table->smallInteger('room_id');
$table->integer('count')->default(0);
});
}
...
我们在 counts
表中定义了四个字段,user_id
表示用户 ID,room_id
表示房间 ID,count
表示该用户在该房间中的未读消息数。
最后运行数据库迁移命令生成 counts
表:
php artisan migrate
编写 Websocket 路由实现代码
打开 Websocket 路由文件 routes/websocket.php
,在 login
路由中编写获取未读消息代码如下:
WebsocketProxy::on('login', function (WebSocket $websocket, $data) {
if (!empty($data['token']) && ($user = \App\User::where('api_token', $data['token'])->first())) {
$websocket->loginUsing($user);
// 获取未读消息
$rooms = [];
foreach (\App\Count::$ROOMLIST as $roomid) {
// 循环所有房间
$result = \App\Count::where('user_id', $user->id)->where('room_id', $roomid)->first();
$roomid = 'room' . $roomid;
if ($result) {
$rooms[$roomid] = $result->count;
} else {
$rooms[$roomid] = 0;
}
}
$websocket->toUser($user)->emit('count', $rooms);
} else {
$websocket->emit('login', '登录后才能进入聊天室');
}
});
我们依次遍历所有房间下用户的未读消息,然后通过 count
管道将其发送给客户端,客户端如果在监听这个管道,就可以读取到这个消息数据并进行处理。
测试未读消息初始化
下面我们在浏览器重新登录用户,可以看到 Websocket 通信信息如下:
在 Vue->Vuex 中可以看到对应的未读消息数:
此时数据表是空的,所以数据都是 0, 我们可以在 counts
表中插入一些测试数据:
然后再次登录测试,就可以看到未读消息数了:
1 Comment
前面文章没有将
token
提交到socket
需要做更改:resources\js\pages\Login.vue
: