当前位置:   article > 正文

Netty实现websocket聊天程序-前端页面_p2p message

p2p message

效果图

在这里插入图片描述

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'
import vuescroll from "vuescroll"
import "vuescroll/dist/vuescroll.css"
Vue.config.productionTip = false
Vue.use(Antd)
Vue.use(vuescroll)//使用
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

package.json

{
  "name": "cms-pc",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "electron:serve": "vue-cli-service electron:serve",
    "postinstall": "electron-builder install-app-deps",
    "postuninstall": "electron-builder install-app-deps"
  },
  "main": "background.js",
  "dependencies": {
    "ant-design-vue": "^1.7.8",
    "axios": "^0.24.0",
    "core-js": "^3.8.3",
    "vue": "^2.6.14",
    "vue-router": "^3.5.1",
    "vuex": "^3.6.2",
    "electron": "^17.1.2",
    "vuescroll": "^4.17.3"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-router": "~5.0.0",
    "@vue/cli-plugin-vuex": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "vue-template-compiler": "^2.6.14",
    "less": "^3.0.4",
    "less-loader": "^5.0.0",
    "vue-cli-plugin-electron-builder": "^1.3.5"
  }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

vue组件

<template>
    <div class="index">
        <a-row :gutter="[10,10]">
            <a-col :span="24">
                <h2 v-text="'You are talking to: '+message2UserId"/>
                <div class="messagesWrapper">
                    <vue-scroll ref="chatMessagesScroller" :ops="ops" style="width:100%;">
                        <div class="chatMessages">
                            <a-row :gutter="[10,10]">
                                <a-col v-for="(message,index) in chatMessages" :key="index" :span="24">
                                    <div :class="['chatMessageItem',message.fromId === loginUserId ? 'send' : 'receive']">
                                        <div class="messageAuthor">
                                            <a-avatar :size="45" icon="user"/>
                                        </div>
                                        <div class="messageInfo">
                                            <div class="messageTime">2022-03-28</div>
                                            <div :class="['chat-bubble',message.fromId === loginUserId ?
                                                'chat-bubble-right chat-bubble-success':'chat-bubble-left chat-bubble-primary']"
                                                 :id="'chatMessage_'+index">
                                                <span v-text="message.messageInfo"/>
                                            </div>
                                        </div>
                                    </div>
                                </a-col>
                            </a-row>
                        </div>
                    </vue-scroll>
                </div>
                <a-textarea v-model="messageInfo" placeholder="input message" rows="4"/>
                <a-button type="primary" v-on:click="sendMessage" icon="enter" style="float: right;margin-top:10px">send</a-button>
            </a-col>
            <a-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
                <span>
                    当前状态:<span :style="isLogined ? 'color:green;':'color: red;'" v-text="isLogined ? '已登录': '未登录'"/>
                </span>
                <a-input-search v-model="loginUserId" placeholder="your id" @search="imLogin">
                    <a-button type="primary" slot="enterButton">
                        login
                    </a-button>
                </a-input-search>
            </a-col>
            <a-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
                <label>chat to user:</label>
                <a-input v-model="message2UserId" placeholder="chat target user id" style="width:100%"/>
            </a-col>
        </a-row>
    </div>
</template>

<script>
    export default {
        name: "index",
        data() {
            return {
                loginUserId: '',
                socket: undefined,
                message2UserId: '',
                messageInfo: '',
                chatMessages: [],
                isLogined: false,
                ops: {
                    vuescroll: {},
                    scrollPanel: {
                        scrollingX: false
                    },
                    rail: {
                        keepShow: true
                    },
                    bar: {
                        hoverStyle: true,
                        onlyShowBarOnScroll: false, //是否只有滚动的时候才显示滚动条
                        background: "#929292",//滚动条颜色
                        opacity: 0.5,//滚动条透明度
                        'overflow-x': "hidden"
                    }
                },
                isSending: false,
            }
        },
        methods: {
            initSocketConnect() {
                let that = this;
                if (window.WebSocket || window.MozWebSocket) {
                    that.socket = new WebSocket("ws://localhost:7777/ws");
                    that.socket.onmessage = function (event) {
                        let messagePacket = JSON.parse(event.data);
                        let msgCommand = messagePacket.command;
                        if (msgCommand !== 'HEARTBEAT_RESPONSE') {
                            that.processMessage(messagePacket);
                        }
                    };

                    that.socket.onopen = function (event) {
                        console.log("websocket connected");
                        that.startHeartBeat();
                    };

                    that.socket.onclose = function (event) {
                        console.log("websocket disConnected");
                    };
                } else {
                    console.log("your browser does not support websocket");
                }
            },
            startHeartBeat() {
                let that = this;
                setInterval(function () {
                    let packet = {};
                    packet.command = "3";
                    that.socket.send(JSON.stringify(packet));
                }, 5000);
            },
            imLogin() {
                let that = this;
                if (that.loginUserId) {
                    let loginPacket = {};
                    loginPacket.dataInfo = {
                        userId: that.loginUserId,
                        password: "123456",
                        clientType: "web",
                        clientVersion: "1",
                    };
                    loginPacket.command = "1";
                    that.socket.send(JSON.stringify(loginPacket));
                    that.isLogined = true;
                } else {
                    that.$notification['info']({
                        message: 'please input your loginId',
                    });
                }
            },
            processMessage(messagePacket) {
                let that = this;
                let msgCommand = messagePacket.command;
                switch (msgCommand) {
                    case "SYS_NOTIFY_REQUEST":
                        that.processSysNotifyPacket(messagePacket);
                        break;
                    case "P2P_MESSAGE_REQUEST":
                        that.processP2pMessagePacket(messagePacket);
                        break;
                    default:
                        console.log("msg type to do...");
                }

            },
            processSysNotifyPacket(notifyPacket) {
                let that = this;
                let notifyType = notifyPacket.notifyType;
                switch (notifyType) {
                    case "CLIENT_ONLINE":
                        that.processUserOnline(notifyPacket.jsonNotifyInfo);
                        break;
                    case "CLIENT_OFFLINE":
                        that.processUserOffline(notifyPacket.jsonNotifyInfo);
                        break;
                    default:
                        console.log("process sys notify...");
                }
            },
            processUserOnline(onlineInfo) {
                let that = this;
                let userObj = JSON.parse(onlineInfo);
                let onlineUser = userObj.onlineUser;
                if (that.loginUserId !== onlineUser) {
                    if (window.Notification) {
                        Notification.requestPermission(function (status) {
                            var n = new Notification('上线通知', {body: '用户:' + userObj.onlineUser + "上线了!"});
                        });
                    }
                }
            },
            processUserOffline(offlineInfo) {
                let that = this;
                let userObj = JSON.parse(offlineInfo);
                let userId = userObj.offlineUser;
                if (that.loginUserId !== onlineUser) {
                    if (window.Notification) {
                        Notification.requestPermission(function (status) {
                            var n = new Notification('下线通知', {body: '用户:' + userId + "下线了!"});
                        });
                    }
                }
            },
            sendMessage() {
                let that = this;
                if (!window.WebSocket && !window.MozWebSocket) {
                    alert("your browser does not support websocket");
                    return;
                }
                if (that.socket.readyState === WebSocket.OPEN) {
                    if (that.message2UserId) {
                        if (that.isLogined) {
                            if (that.messageInfo) {
                                if (that.message2UserId !== that.loginUserId) {
                                    that.isSending = true;
                                    let p2pMessagePacket = {};
                                    p2pMessagePacket.dataInfo = {
                                        fromId: that.loginUserId,
                                        toId: that.message2UserId,
                                        messageInfo: that.messageInfo,
                                    };
                                    p2pMessagePacket.command = "5";
                                    that.chatMessages.push(p2pMessagePacket.dataInfo);
                                    that.socket.send(JSON.stringify(p2pMessagePacket));
                                    that.messageInfo = '';
                                    that.scrollMessages2Bottom();
                                    that.isSending = false;
                                } else {
                                    that.$notification['info']({
                                        message: 'you can not chat with yourself',
                                    });
                                }
                            } else {
                                that.$notification['info']({
                                    message: 'chat message can not be empty!',
                                });
                            }
                        } else {
                            that.$notification['info']({
                                message: 'please login before chat to someone!',
                            });
                        }
                    } else {
                        that.$notification['info']({
                            message: 'please input userId which you wanna to chat',
                        });
                    }
                } else {
                    console.log("WebSocket connect failed");
                }
            },
            processP2pMessagePacket(messagePacket) {
                let that = this;
                that.chatMessages.push(messagePacket);
                that.scrollMessages2Bottom();
            },
            scrollMessages2Bottom() {
                let that = this;
                let targetEleId = "#chatMessage_" + (that.chatMessages.length - 1);
                console.log("targetEle:" + targetEleId);
                setTimeout(function () {
                    that.$refs.chatMessagesScroller.scrollIntoView(targetEleId, 100);
                }, 100);
            }
        },
        mounted() {
            let that = this;
            that.initSocketConnect();
        }
    }
</script>

<style scoped>
    .index {
        width: 60%;
        margin: 0 auto;
        height: 100%;
        margin-top: 60px;
    }

    .messagesWrapper {
        height: 60vh;
        background-color: rgba(255,255,255,.6);
        border-radius: 4px;
        margin-bottom: 20px;
    }
    .chatMessages{
        padding: 20px;
    }
    .chatMessageItem{
        width: 100%;
        display: flex;
        align-items: flex-start;
    }
    .chatMessageItem .messageInfo{
        width: 0;
        flex: 1;
    }
    .chatMessageItem.send{
        flex-direction: row-reverse;
        justify-content: flex-end;
    }
    .chatMessageItem.send .messageAuthor{
        margin-left: 10px;
    }
    .chatMessageItem.send .messageInfo{
        text-align: right;
    }
    .chatMessageItem.receive{
        flex-direction: row;
        justify-content: flex-start;
    }

    .chatMessageItem.receive .messageAuthor{
        margin-right: 10px;
    }
    .chatMessageItem.receive .messageInfo{
        text-align: left;
    }
    .chat-bubble {
        color: #333;
        box-shadow: 3px 5px 15px rgba(0, 0, 0, .2);
        padding: 5px 10px;
        width: auto;
        max-width: 50%;
        text-align: left;
        display: inline-block !important;
        position: relative;
        word-break: break-all;
        background-color: #ffffff;
        transition: all .2s;
        cursor: pointer;
        margin-bottom: 10px;
    }

    .chat-bubble:hover {
        transform: scale(1.03);
    }

    .chat-bubble-left {
        float: left;
        border-radius: 0 5px 5px 5px;
    }

    .chat-bubble-left:before {
        content: '';
        width: 6px;
        height: 6px;
        left: -6px;
        top: 0;
        position: absolute;
        border-left: 3px solid transparent;
        border-bottom: 3px solid transparent;
        border-top: 3px solid #ffffff;
        border-right: 3px solid #ffffff;
    }

    .chat-bubble-right {
        float: right;
        border-radius: 5px 0 5px 5px;
    }

    .chat-bubble-right:after {
        content: '';
        width: 6px;
        height: 6px;
        right: -6px;
        top: 0;
        position: absolute;
        border-left: 3px solid #ffffff;
        border-bottom: 3px solid transparent;
        border-top: 3px solid #ffffff;
        border-right: 3px solid transparent;
    }

    /**
       chat-bubble-primary
     */
    .chat-bubble-left.chat-bubble-primary {
        background: linear-gradient(90deg, #2b92e4, #30a1dc) !important;
        color: #ffffff !important;
    }

    .chat-bubble-left.chat-bubble-primary:before {
        border-right: 3px solid #2b92e4 !important;
        border-top: 3px solid #2b92e4 !important;
    }

    .chat-bubble-right.chat-bubble-primary {
        background: linear-gradient(90deg, #30a1dc, #2b92e4) !important;
        color: #ffffff !important;
    }

    .chat-bubble-right.chat-bubble-primary:after {
        border-left: 3px solid #2b92e4 !important;
        border-top: 3px solid #2b92e4 !important;
    }

    /**
       chat-bubble-success
     */
    .chat-bubble-left.chat-bubble-success {
        background: linear-gradient(90deg, #4caf50, #66b869) !important;
        color: #ffffff !important;
    }

    .chat-bubble-left.chat-bubble-success:before {
        border-right: 3px solid #4caf50 !important;
        border-top: 3px solid #4caf50 !important;
    }

    .chat-bubble-right.chat-bubble-success {
        background: linear-gradient(90deg, #66b869, #4caf50) !important;
        color: #ffffff !important;
    }

    .chat-bubble-right.chat-bubble-success:after {
        border-left: 3px solid #4caf50 !important;
        border-top: 3px solid #4caf50 !important;
    }
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/404255
推荐阅读
相关标签
  

闽ICP备14008679号