当我未能捕捉到耳语事件时,在 laravel 8 / beyondcode/laravel-websockets 1.12 / laravel-echo 1.11.1 / pusher-js 7.0.3 应用程序中进行聊天。在这里阅读https://laravel.com/docs/8.x/broadcasting#receiving-broadcasts 我在我的 vue 文件中:
<template>
<div class="container">
<div class="row" v-if="currentRoom">
<h4>{{ currentRoom.name }}</h4>
<div class="col-sm-12">
<div class="table-responsive" v-if="is_page_loaded && messages.length">
<table class="table table-striped text-primary">
<tbody>
<tr v-for="nextMessage, index in messages">
<td class="integer_cell">{{ index }}</td>
<td>
{{ nextMessage.id }}=>
<span class="pre-formatted" v-html="nextMessage.message"></span>
</td>
<td>
<span v-if="nextMessage.user.id === loggedUserId">
You,
</span>
<span v-if="nextMessage.user.id !== loggedUserId">
{{ nextMessage.user.name }},
</span>
<span>{{ timeInAgoFormat(nextMessage.created_at) }} ago</span>
</td>
<td>
<span v-if="nextMessage.user.id === loggedUserId">
<a class="btn btn-sm btn-danger btn-icon m-1" title="Delete message" @click.prevent="deleteMessage(nextMessage.id, index)">
<i class="fas fa-trash-alt icon-nm"></i>
</a>
</span>
</td>
</tr>
</tbody>
</table>
</div>
<input type="text" class="form-control" v-model="textMessage" @keyup.enter="sendMessage" @keydown="actionUser()">
<span v-show="isWhispering">Whispering...</span>
<div class="col-sm-4">
<ul>
<li v-for="nextUser in onlineUsers ">{{ nextUser.name}}</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<script>
import {bus} from "/../resources/js/app";
export default {
name: "RoomChat",
components: {
},
props: {
loggedUserEmail : {
type: String,
required: true,
},
loggedUserId : {
type: Number,
required: true,
},
loggedUserName : {
type: String,
required: true,
},
}, // props: {
data() {
return {
currentRoom:null,
messages: [],
textMessage: '',
is_page_loaded:false,
isWhispering:false,
showUserEvents:true,
onlineUsers: [],
};
},
created() {
},
mounted() {
bus.$on('userRoomChanged', (currentRoom) => {
this.currentRoom= currentRoom
this.echoServerInit(true)
})
}, // mounted() {
methods: {
echoServerInit(callLoadRoomMessages) {
Echo.private('room.' + this.currentRoom.id )
.listen('NewMessage', (message) => {
console.log('message::'); // I Catch this event on new message by other user
console.log(message);
if (this.showUserEvents) {
this.$toaster.success(message.user.name + ' sent message');
}
this.messages.push(message)
})
.listenForWhisper('typing', (e) => { // I DO NOT Catch this event
alert( 'listenForWhisper typing e::::' )
console.log('listenForWhisper typing e::')
console.log(id)
this.isWhispering = true
})
Echo.join('room.' + this.currentRoom.id) // ALL events below work ok
.here((users) => {
if (this.showUserEvents) {
this.$toaster.success(users.length + ' user(s) in "'+ this.currentRoom.name +'" room now');
}
this.onlineUsers= users
})
.joining((user) => {
if (this.showUserEvents) {
this.$toaster.success(user.name + ' joined "'+ this.currentRoom.name +'" room');
}
this.onlineUsers.push(user)
})
.leaving((user) => {
this.onlineUsers.splice(this.onlineUsers.indexOf(user), 1 )
if (this.showUserEvents) {
this.$toaster.success(user.name + ' left "'+ this.currentRoom.name +'" room');
}
})
.error((error) => {
console.error(error);
if (error.status === 403) {
this.$toaster.error("You have no access to this room !");
}
});
if (callLoadRoomMessages) {
this.loadRoomMessages()
}
this.is_page_loaded= true
}, // echoServerInit(callLoadRoomMessages) {
async sendMessage() {
const result = await this.callApi(
"post",
window.api_path + '/sendMessage',
{body: this.textMessage, 'room_id':this.currentRoom.id}
);
if (result.status != 200) {
this.$toaster.error(result.data.message);
this.messages = [];
return;
}
this.$toaster.success(result.data.message);
this.messages.push(result.data.message);
this.textMessage = ''
this.isWhispering= false
}, // async sendMessage() {
async loadRoomMessages() {
console.log('loadRoomMessages ::')
const result = await this.callApi(
"get",
window.api_path + '/getMessages/' + this.currentRoom.id,
{}
);
if (result.status != 200) {
this.$toaster.error(result.data.message);
this.messages = [];
return;
}
this.messages = result.data.messages;
}, // async loadRoomMessages() {
async deleteMessage(message_id, index) {
const result = await this.callApi(
"delete",
window.api_path + '/deleteMessage/' + message_id,
{}
);
if (result.status != 204) {
this.$toaster.error(result.data.message);
return;
}
this.message.splice(index, 1 )
this.$toaster.success('Message was successfully deleted !');
}, // async deleteMessage() {
actionUser() {
console.log('actionUser() room. + this.currentRoom.id::') // I see these messages
console.log('room.' + this.currentRoom.id)
Echo.private('room.' + this.currentRoom.id )
.whisper('typing', { // broadcasting client event with
name: this.loggedUserName
})
}
} // methods: {
};
</script>
我有相同的房间名称和“打字”触发和捕捉耳语:
Echo.private('room.' + this.currentRoom.id )
.listen('NewMessage', (message) => {
console.log('message::'); // I Catch this event on new message by other user
console.log(message);
if (this.showUserEvents) {
this.$toaster.success(message.user.name + ' sent message');
}
this.messages.push(message)
})
.listenForWhisper('typing', (e) => { // I DO NOT Catch this event
...
Echo.private('room.' + this.currentRoom.id )
.whisper('typing'
echo 的所有其他事件都可以正常工作,
在 app/Events/NewMessage.php 中:
class NewMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $id;
public $room_id;
public $user;
public $message;
public $userTo;
public $read;
public function __construct($id, $room_id, $user, $message, $userTo, $read)
{
$this->dontBroadcastToCurrentUser();
$this->id= $id;
$this->room_id= $room_id;
$this->user= $user;
$this->message= $message;
$this->userTo= $userTo;
$this->read= $read;
\Log::info( varDump($this, ' -1 __construct NewMessage $this::') );
}
public function broadcastOn()
{
return new PrivateChannel('room.'.$this->room_id); // THAT is PUBLIC channel TODO
}
}
在 routes/channels.php 中:
Broadcast::channel('room.{room_id}', function ($user, $room_id) {
$roomUsersCount= RoomUser
::getByRoomId($room_id)
->getByUserId($user->id)
->count();
return $roomUsersCount ? $user : false; // if returned true - user can join this channel
});
出了什么问题以及如何解决?
修改: 当用户输入文本并发送消息时检查日志输出我看到:
myId: connection id 766711505.830162191 received message: {"event":"client-typing","data":{"name":"john"},"channel":"private-room.2"}.
myId: connection id 766711505.830162191 received message: {"event":"client-typing","data":{"name":"john"},"channel":"private-room.2"}.
myId: connection id 766711505.830162191 received message: {"event":"client-typing","data":{"name":"john"},"channel":"private-room.2"}.
myId: connection id 766711505.830162191 received message: {"event":"pusher:ping","data":{}}.
Connection id 766711505.830162191 sending message {"event":"pusher:pong"}
myId: connection id 166472497.321004191 received message: {"event":"pusher:ping","data":{}}.
Connection id 166472497.321004191 sending message {"event":"pusher:pong"}
myId: connection id 766711505.830162191 received message: {"event":"client-typing","data":{"name":"john"},"channel":"private-room.2"}.
Connection id 166472497.321004191 sending message {"channel":"private-room.2","event":"App\\Events\\NewMessage","data":"{\"id\":8,\"room_id\":2,\"user\":{\"id\":2,\"name\":\"JohnDoe\",\"email\":\"john_doe@site.com\",\"status\":1,\"email_verified_at\":null,\"created_at\":null,\"updated_at\":null},\"message\":\"AAAAA\",\"userTo\":{\"id\":2,\"name\":\"JohnDoe\",\"email\":\"john_doe@site.com\",\"status\":1,\"email_verified_at\":null,\"created_at\":null,\"updated_at\":null},\"read\":false}"}
其中 john_doe 是键入 room.2 的用户 - john_doe 输入的房间名称 但是频道名称中的“private-”前缀在哪里?为什么事件名称是“client-typing” - 为什么我有“client”-prefix 阅读文档我没有看到任何频道前缀规则。为什么只有耳语不能正常工作?我想使用私人频道...
谢谢!