0

当我未能捕捉到耳语事件时,在 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 阅读文档我没有看到任何频道前缀规则。为什么只有耳语不能正常工作?我想使用私人频道...

谢谢!

4

0 回答 0