天天看點

vue 環信內建

vue 環信內建

(标記)

檢視官方文檔 下載下傳的vue demo 需求不合适自己的 ,是以改吧了改吧

需要寫一個單聊的功能 不需要加好友 隻是單純的聊天

因為公司沒買增值服務 太費錢了 是以隻做個本地存儲 退出就删 因為store一重新整理就沒了 是以就存浏覽器了

  1. 安裝 easemob-websdk

    npm install easemob-websdk --save

  2. 安裝 moment

    npm install moment --save

下載下傳案例

  1. 将案例的 utils 檔案複制到自己的 src下 将WebIMConfig中的appkey改成公司申請的
  2. 修改WebIM中代碼
import Vue from 'vue';
import store from '../store'
import config from "./WebIMConfig";
import websdk from "easemob-websdk";
import { Message } from "element-ui";

// 初始化IM SDK
var WebIM = {};
WebIM = window.WebIM = websdk;
WebIM.config = config;
WebIM.conn = new WebIM.connection({ //建立連接配接
    appKey: WebIM.config.appkey,
    isHttpDNS: WebIM.config.isHttpDNS,
    isMultiLoginSessions: WebIM.config.isMultiLoginSessions,
    https: WebIM.config.https,
    url: WebIM.config.xmppURL,
    apiUrl: WebIM.config.apiURL,
    isAutoLogin: true,
    heartBeatWait: WebIM.config.heartBeatWait,
    autoReconnectNumMax: WebIM.config.autoReconnectNumMax,
    autoReconnectInterval: WebIM.config.autoReconnectInterval,
    isStropheLog: WebIM.config.isStropheLog,
    delivery: WebIM.config.delivery
});
if (!WebIM.conn.apiUrl) {
    WebIM.conn.apiUrl = WebIM.config.apiURL;
}

// 注冊監聽回調
WebIM.conn.listen({
    onOpened: function(message) { // 連接配接成功回調
        console.log('環信登入成功')
    },
    onClosed: function(message) { //連接配接關閉回調
        Vue.$router.push({ path: "/Login" });
    }, // 連接配接關閉回調
    onTextMessage: function(message) { //收到文本消息
        console.log(message)
        const { from, to, type } = message;
        const chatId = type !== "chat" ? to : from;
        store.commit("updateMsgList", {
            headPic: message.ext.headPic,
            nickName: message.ext.nickName,
            chatId: chatId,
            msg: message.data,
            bySelf: false,
            from: message.from,
            mid: message.id
        });
        store.commit("updateUserList", {
            headPic: message.ext.headPic,
            nickName: message.ext.nickName,
            chatId: chatId,
            msg: message.data,
            bySelf: false,
            from: message.from,
            mid: message.id
        });
        type === 'chat' && ack(message);
        if (WebIM && WebIM.call && message && message.ext && message.ext.msg_extension) {
            var msgExtension = message.ext.msg_extension && JSON.parse(message.ext.msg_extension);
            var options = {
                confrId: message.ext.conferenceId,
                password: message.ext.password || "",
                gid: msgExtension.group_id,
                inviter: msgExtension.inviter
            };
            WebIM.call.listener.onInvite(message.from, options);
        }
    },
    onEmojiMessage: function(message) { // 收到表情消息
        console.log("onEmojiMessage", message);

    },
    onPictureMessage: function(message) { //收到圖檔消息
        console.log("onPictureMessage", message);
        const { from, to, type } = message;
        const chatId = type !== "chat" ? to : from;
        store.commit("updateMsgList", {
            nickName: message.ext.nickName,
            headPic: message.ext.headPic,
            chatId: chatId,
            msg: message.url,
            bySelf: false,
            type: "img",
            mid: message.id,
            from: message.from
        });
        store.commit("updateUserList", {
            nickName: message.ext.nickName,
            headPic: message.ext.headPic,
            chatId: chatId,
            msg: message.url,
            bySelf: false,
            type: "img",
            mid: message.id,
            from: message.from
        });
        type === 'chat' && ack(message);
    },
    onCmdMessage: function(message) {
        console.log("onCmdMessage", message);
    },
    onAudioMessage: function(message) { // 收到音頻消息
        console.log("onAudioMessage", message);
    },
    onLocationMessage: function(message) { // 收到位置消息
        console.log("onLocationMessage", message);
    },
    onFileMessage: function(message) { // 收到檔案消息
        console.log("onFileMessage", message);
        const { from, to, type } = message;
        const chatId = type !== "chat" ? to : from;
        store.commit("updateMsgList", {
            headPic: message.ext.headPic,
            nickName: message.ext.nickName,
            chatId: chatId,
            msg: message.url,
            bySelf: false,
            type: "file",
            filename: message.filename,
            file_length: message.file_length,
            from: message.from
        });
        store.commit("updateUserList", {
            headPic: message.ext.headPic,
            nickName: message.ext.nickName,
            chatId: chatId,
            msg: message.url,
            bySelf: false,
            type: "file",
            filename: message.filename,
            file_length: message.file_length,
            from: message.from
        });
        type === 'chat' && ack(message);
    },
    onVideoMessage: function(message) { // 收到視訊消息
        console.log("onVideoMessage", message);
    },
    onPresence: function(message) {
        console.log("onPresence", message);
    }, // 處理“廣播”或“釋出-訂閱”消息,如聯系人訂閱請求、處理群組、聊天室被踢解散等消息
    onRoster: function(message) {
        console.log("onRoster", message);
    }, // 處理好友申請
    onInviteMessage: function(message) {
        console.log("onInviteMessage", message);
    }, // 處理群組邀請
    onOnline: function() {
        console.log("onOnline 網絡已連接配接");
    }, // 本機網絡連接配接成功
    onOffline: function() {
        console.log("onOffline 網絡已斷開");
    }, // 本機網絡掉線
    onError: function(message) {
        console.log(message)
    }, // 失敗回調
    onRecallMessage: message => {
        console.log("撤回消息", message);
    },
    onBlacklistUpdate: function(list) { // 黑名單變動
        // 查詢黑名單,将好友拉黑,将好友從黑名單移除都會回調這個函數,list則是黑名單現有的所有好友資訊
        // 更新好友黑名單
    },
    onReceivedMessage: function(message) {
        console.log("onReceivedMessage", message);
    }, // 收到消息送達伺服器回執

    onDeliveredMessage: function(message) {}, // 收到消息送達用戶端回執

    onReadMessage: function(message) {
        console.log("onReadMessage", message);
        // store.commit("updateMessageStatus", message);
    }, // 收到消息已讀回執

    onCreateGroup: function(message) {}, // 建立群組成功回執(需調用createGroupNew)
    onMutedMessage: function(message) {} // 如果使用者在A群組被禁言,在A群發消息會走這個回調并且消息不會傳遞給群其它成員
});

export default WebIM;
           
  1. main.js 中

    import WebIM from './utils/WebIM';

new Vue({
    el: '#app',
    router,
    store,
    WebIM,
    components: { App },
    template: '<App/>'
})
           
  1. store 添加 login.js
import { Message } from "element-ui";
const Login = {
    state: {
        // username: ""
        imusername: "" //登入使用者賬号
    },
    mutations: {
        setUserName(state, username) {
            state.imusername = username;
        },
    },
    actions: {
        onLogin: function(context, payload) {
            context.commit("setUserName", payload.username);
            var options = {
                apiUrl: WebIM.config.apiURL,
                user: payload.username,
                pwd: payload.password,
                appKey: WebIM.config.appkey
            };
            WebIM.conn.open(options);
            localStorage.setItem("imuserInfo", JSON.stringify({ userId: payload.username, password: payload.password }));
        },
        onLogout: function(context) {
            context.commit("setUserName", "");
            // localStorage.setItem("userInfo", "");
        },
    },
    getters: {

    }
};
export default Login;
           
  1. store 添加 chat.js

    有些沒用的 也沒删

import Vue from 'vue';
import WebIM from "../utils/WebIM";

// import WebIM from "../utils/WebIM";

// TODO 處理頁面重新整理無法擷取到音頻url
const res = function(response) {
    let objectUrl = WebIM.utils.parseDownloadResponse.call(WebIM.conn, response);
    return objectUrl; //  'blob:http://localhost:8080/536070e2-b3a0-444a-b1cc-f0723cf95588'
};

function test(url, func) {
    let options = {
        url: url,
        headers: {
            Accept: "audio/mp3"
        },
        onFileDownloadComplete: func,
        onFileDownloadError: function() {
            console.log("音頻下載下傳失敗");
        }
    };
    WebIM.utils.download.call(WebIM.conn, options);
}

const Chat = {
    state: {
        userList: {},
        msgList: {},
        currentMsgs: []
    },
    mutations: {
        updateUserList(state, payload) {
            console.log(payload)
            const {
                chatId,
            } = payload;
            var immsgList = JSON.parse(localStorage.getItem("immsgList"));
            var imuserList = JSON.parse(localStorage.getItem("imuserList"));
            if (imuserList !== null && imuserList !== '') { //登入狀态
                state.msgList = immsgList
                state.userList = imuserList
                if (!state.userList[chatId]) {
                    state.userList[chatId] = {
                        name: chatId,
                        nickName: payload.nickName,
                        headPic: payload.headPic,
                        subscription: "to"
                    }
                } else {
                    state.userList[chatId] = {
                        name: chatId,
                        nickName: payload.nickName,
                        headPic: payload.headPic,
                        subscription: "to"
                    }
                    state.userList[chatId] = state.userList[chatId].sort((a, b) => {
                        return b.time - a.time;
                    });
                }
                state.userList = Object.assign({}, state.userList);
                localStorage.setItem("imuserList", JSON.stringify(state.userList))

            } else {
                if (!state.userList[chatId]) {
                    state.userList[chatId] = {
                        name: chatId,
                        nickName: payload.nickName,
                        headPic: payload.headPic,
                        subscription: "to"
                    }
                } else {
                    state.userList[chatId] = {
                        name: chatId,
                        nickName: payload.nickName,
                        headPic: payload.headPic,
                        subscription: "to"
                    }
                    state.userList[chatId] = state.userList[chatId].sort((a, b) => {
                        return a.time - b.time;
                    });
                    console.log(state.userList)
                }
                state.userList = Object.assign({}, state.userList);
                localStorage.setItem("imuserList", JSON.stringify(state.userList))
            }
        },
        updateMsgList(state, payload) { // 消息清單
            const {
                chatId,
                msg,
                bySelf,
                type,
                id
            } = payload;
            var immsgList = JSON.parse(localStorage.getItem("immsgList"));
            if (immsgList !== null && immsgList !== '') { //登入狀态
                state.msgList = immsgList
                if (!state.msgList[chatId]) {
                    state.msgList[chatId] = [{
                        msg,
                        bySelf,
                        type: type || "",
                        mid: id,
                        headPic: payload.headPic,
                        nickName: payload.nickName,
                        ...payload
                    }];

                } else {
                    state.msgList[chatId].push({
                        msg,
                        bySelf,
                        type: type || "",
                        headPic: payload.headPic,
                        nickName: payload.nickName,
                        mid: id,
                        ...payload
                    });
                    state.msgList[chatId] = state.msgList[chatId].sort((a, b) => {
                        return a.time - b.time;
                    });
                }

                state.msgList = Object.assign({}, state.msgList);
                localStorage.setItem("immsgList", JSON.stringify(state.msgList))

            } else { //退出了 在登入

                if (!state.msgList[chatId]) {
                    state.msgList[chatId] = [{
                        msg,
                        bySelf,
                        type: type || "",
                        headPic: payload.headPic,
                        nickName: payload.nickName,
                        mid: id,
                        ...payload
                    }];


                } else {
                    state.msgList[chatId].push({
                        msg,
                        bySelf,
                        type: type || "",
                        mid: id,
                        headPic: payload.headPic,
                        nickName: payload.nickName,
                        ...payload
                    });
                    state.msgList[chatId] = state.msgList[chatId].sort((a, b) => {
                        return a.time - b.time;
                    });


                }

                state.msgList = Object.assign({}, state.msgList);
                localStorage.setItem("immsgList", JSON.stringify(state.msgList))


            }
        },
        updateCurrentMsgList(state, messages) {
            state.currentMsgs = messages;
        },
        updateMessageMid(state, message) {
            const {
                id,
                mid
            } = message;
            const {
                name,
                params
            } = Vue.$route;
            state.currentMsgs.forEach((item) => {
                if (item.mid == id) {
                    item.mid = mid
                }
            })
            Object.keys(state.msgList[name]).forEach((user) => {
                if (state.msgList[name][user].length) {
                    state.msgList[name][user].forEach((msg) => {
                        if (msg.mid == id) {
                            msg.mid = mid;
                        }
                    });
                }
            });
        },
        updateMessageStatus(state, message) {
            const {
                id,
                mid,
                action,
                readUser
            } = message;
            const {
                name,
                params
            } = Vue.$route;
            Object.keys(state.msgList[name]).forEach((user) => {
                // console.log(state.msgList[name][user]);

                if (action == "oneUserReadMsgs") {
                    if (state.msgList[name][readUser]) {
                        state.msgList[name][readUser].forEach((msg) => {
                            if (msg.status != "recall") {
                                msg.status = "read";
                            }
                        });
                    }
                } else if (state.msgList[name][user].length) {
                    state.msgList[name][user].forEach((msg) => {
                        if (action === "readMsgs" && !msg.bySelf) {
                            if (msg.status != "recall") {
                                msg.status = "read";
                            }
                        } else if (msg.mid == id || msg.mid == mid) {
                            msg.status = message.status;
                            if (message.msg) {
                                msg.msg = message.msg;
                            }
                        }
                    });
                }
            });
        },
    },
    actions: {
        onGetContactUserList: function(context, payload) {
            try {
                WebIM.conn.getRoster({ //查詢好友清單
                    success: function(roster) {
                        console.log("roster", roster);
                        const userList = roster.filter(user => ["both", "to"].includes(user.subscription));
                        context.commit("updateUserList", {
                            userList,
                            type: "contactUserList",
                            black: payload
                        });
                    }
                });
            } catch (e) {
                console.log("error", e);
            }
        },
        // 擷取目前聊天對象的記錄 @payload: {key, type}
        onGetCurrentChatObjMsg: function(context, payload) {
            const {
                id,
                type
            } = payload;
            context.commit("updateCurrentMsgList", context.state.msgList[type][id]);
        },
        onSendText: function(context, payload) { //發送文本資訊
            const {
                nickName,
                headPic,
                chatId,
                message
            } = payload;
            const id = WebIM.conn.getUniqueId();
            const time = +new Date();

            const msgObj = new WebIM.message("txt", id);
            msgObj.set({
                msg: message,
                ext: {
                    'headPic': headPic,
                    'nickName': nickName,
                },
                to: chatId,
                success: function() {
                    console.log('fdsf')
                    context.commit("updateMsgList", {
                        headPic: headPic,
                        nickName: nickName,
                        chatId: chatId,
                        msg: message,
                        bySelf: true,
                        time: time,
                        mid: id,
                    });
                    context.commit("updateUserList", {
                        headPic: headPic,
                        nickName: nickName,
                        chatId: chatId,
                        msg: message,
                        bySelf: true,
                        time: time,
                        mid: id,
                    });
                },
                fail: function(e) {
                    console.log("Send private text error", e);
                }
            });
            WebIM.conn.send(msgObj.body);
        },
        sendImgMessage: function(context, payload) { //發送圖檔資訊
            const {
                nickName,
                headPic,
                chatId,
                file,
                callback
            } = payload;
            const id = WebIM.conn.getUniqueId();
            const msgObj = new WebIM.message("img", id);
            msgObj.set({
                apiUrl: WebIM.config.apiURL,
                file: file,
                ext: {
                    'headPic': headPic,
                    'nickName': nickName,
                },
                to: chatId,
                onFileUploadError: function(error) {
                    console.log("圖檔上傳失敗", error);
                    callback();
                },
                onFileUploadComplete: function(data) {
                    let url = data.uri + "/" + data.entities[0].uuid;
                    context.commit("updateMsgList", {
                        headPic: headPic,
                        msg: url,
                        nickName: nickName,
                        chatId: chatId,
                        bySelf: true,
                        type: "img",
                        time: data.timestamp,
                        mid: id,
                    });
                    context.commit("updateUserList", {
                        headPic: headPic,
                        msg: url,
                        nickName: nickName,
                        chatId: chatId,
                        bySelf: true,
                        type: "img",
                        time: data.timestamp,
                        mid: id,
                    });
                    callback();
                },
                success: function() {
                    console.log("圖檔發送成功");
                }
            });
            WebIM.conn.send(msgObj.body);
        },
        sendFileMessage: function(context, payload) {
            const {
                nickName,
                headPic,
                chatId,
                file,
                callback
            } = payload;
            const id = WebIM.conn.getUniqueId();
            const msgObj = new WebIM.message("file", id);
            msgObj.set({
                apiUrl: WebIM.config.apiURL,
                file: file,
                ext: {
                    'headPic': headPic,
                    'nickName': nickName,
                },
                ext: {
                    file_length: file.data.size
                },
                to: 19956,
                onFileUploadError: function(error) {
                    console.log("檔案上傳失敗", error);
                    callback();
                },
                onFileUploadComplete: function(data) {
                    let url = data.uri + "/" + data.entities[0].uuid;
                    context.commit("updateMsgList", {
                        headPic: headPic,
                        msg: url,
                        nickName: nickName,
                        chatId: chatId,
                        bySelf: true,
                        type: "file",
                        filename: file.data.name,
                        file_length: file.data.size,
                        time: data.timestamp,
                        mid: id,
                        // status: "sending"
                    });
                    context.commit("updateUserList", {
                        headPic: headPic,
                        msg: url,
                        nickName: nickName,
                        chatId: chatId,
                        bySelf: true,
                        type: "file",
                        filename: file.data.name,
                        file_length: file.data.size,
                        time: data.timestamp,
                        mid: id,
                        // status: "sending"
                    });
                    callback();
                },
                success: function() {
                    console.log("檔案發送成功");
                }
            });
            WebIM.conn.send(msgObj.body);
        },
        getHistoryMessage: function(context, payload) {
            const options = {
                queue: payload.name,
                isGroup: payload.isGroup,
                count: 10, // 每次擷取消息條數
                success: function(msgs) {
                    try {
                        payload.success && payload.success(msgs);
                        if (msgs.length) {
                            const userInfo = JSON.parse(localStorage.getItem("userInfo"));
                            const userId = userInfo && userInfo.userId;
                            msgs.forEach((item) => {
                                let time = Number(item.time);
                                let msg = {};
                                const bySelf = item.from == userId;
                                if (!item.filename) {
                                    msg = {
                                        chatType: payload.isGroup ? "group" : "contact",
                                        chatId: bySelf ? item.to : item.from,
                                        msg: item.data,
                                        bySelf: bySelf,
                                        time: time,
                                        mid: item.id,
                                        status: "read"
                                    };
                                    if (payload.isGroup) {
                                        msg.chatId = item.to;
                                    } else {
                                        msg.chatId = bySelf ? item.to : item.from;
                                    }
                                } else if (!item.ext.file_length && item.filename !== "audio" && item.filename.substring(item.filename.length - 3) !== "mp4") { // 為圖檔的情況
                                    msg = {
                                        msg: item.url,
                                        chatType: payload.isGroup ? "group" : "contact",
                                        chatId: bySelf ? item.to : item.from,
                                        bySelf: bySelf,
                                        type: "img",
                                        time: time,
                                        mid: item.id,
                                        status: "read"
                                    };
                                    if (payload.isGroup) {
                                        msg.chatId = item.to;
                                    } else {
                                        msg.chatId = bySelf ? item.to : item.from;
                                    }
                                } else if (item.filename === "audio") {
                                    msg = {
                                        msg: item.url,
                                        chatType: payload.isGroup ? "group" : "contact",
                                        chatId: bySelf ? item.to : item.from,
                                        bySelf: bySelf,
                                        type: "audio"
                                    };
                                    if (payload.isGroup) {
                                        msg.chatId = item.to;
                                    } else {
                                        msg.chatId = bySelf ? item.to : item.from;
                                    }
                                } else if (item.filename.substring(item.filename.length - 3) === "mp4") {
                                    msg = {
                                        msg: item.url,
                                        chatType: payload.isGroup ? "group" : "contact",
                                        chatId: bySelf ? item.to : item.from,
                                        bySelf: bySelf,
                                        type: "video"
                                    };
                                    if (payload.isGroup) {
                                        msg.chatId = item.to;
                                    } else {
                                        msg.chatId = bySelf ? item.to : item.from;
                                    }
                                } else {
                                    msg = {
                                        msg: item.url,
                                        chatType: payload.isGroup ? "group" : "contact",
                                        chatId: bySelf ? item.to : item.from,
                                        bySelf: bySelf,
                                        type: "file",
                                        filename: item.filename,
                                        file_length: item.file_length,
                                        time: time,
                                        mid: item.id,
                                        status: "read"
                                    };
                                    if (payload.isGroup) {
                                        msg.chatId = item.to;
                                    } else {
                                        msg.chatId = bySelf ? item.to : item.from;
                                    }
                                }
                                msg.isHistory = true;
                                context.commit("updateMsgList", msg);
                                context.commit("updateUserList", msg);
                            });
                            context.commit("updateMessageStatus", {
                                action: "readMsgs"
                            });
                        }
                    } catch (e) {
                        console.log("error", e);
                    }
                },
                fail: function() {}
            };
            WebIM.conn.fetchHistoryMessages(options);
        },
        recallMessage: function(context, payload) {
            const {
                chatType,
                mid
            } = payload.message;
            const to = payload.to;
            const me = this;
            const chatTypeObj = {
                contact: "chat",
                group: "groupchat",
                chatroom: "chatroom"
            };
            const option = {
                mid,
                to,
                type: chatTypeObj[chatType],
                success: function() {
                    payload.message.status = "recall";
                    payload.message.msg = "消息已撤回";
                    Vue.$store.commit("updateMessageStatus", payload.message);
                },
                fail: function() {
                    // me.$message('消息撤回失敗');
                },
            };
            WebIM.conn.recallMessage(option);
        }
    },
    getters: {
        onGetContactUserList(state) {
            return state.userList.contactUserList;
        },
        onGetCurrentChatObjMsg(state) {
            return state.currentMsgs;
        },
        fetchHistoryMessages(state) {
            return state.currentMsgs;
        }
    }

};
export default Chat;
           
  1. 複制 chartEmoji upLoadFile upLoadImage 檔案到 compnents

    upLoadGile

<template>
  <label for="uploadFile">
    <i class="el-icon-folder" color="rgba(0, 0, 0, 0.65)" />
    <input id="uploadFile" type="file" accept="video/mp4,audio/mp4" capture="camcorder" class="hide" ref="imgDom" @change="fileChange" />
  </label>
</template>

<script>
import WebIM from "../../utils/WebIM";
import Config from "../../config/index";

import { mapActions } from "vuex";
 export  default {
	data(){
		return {
			file: null
		};
	},
	methods: {
		...mapActions(["sendFileMessage"]),
		// TODO 目前username、及type不是從pams裡取
		fileChange(e){
			let file = WebIM.utils.getFileUrl(e.target);
			if(!file.filename){
				this.$refs.imgDom.value = null;
				return false;
			}

			let obj = {
				chatId: this.chatId.name, // TODO 這裡在群裡面應該取的是ID,後期跟進
        file: file,
        headPic:this.chatId.url,
         nickName:this.chatId.nickname,
				callback: () => {
					this.$refs.imgDom.value = null;
				}
			};
			this.sendFileMessage(obj);
		}
	},
	props: [
		"type", // 聊天類型 contact, group, chatroom
		"chatId" // 選中的聊天對象
  ],
  created(){
  }
};
</script>
<style scoped>
.hide {
  position: absolute;
  top: 0;
  right: 0;
  min-width: 100%;
  min-height: 100%;
  filter: alpha(opacity=0);
  opacity: 0;
  cursor: inherit;
  display: none;
}
i{
  font-size:20px;
  margin-left: 8px;
  cursor: pointer
}
</style>

           

upLoadImage中

<template>
  <label for="uploadImage" >
    <i class="el-icon-picture-outline" color="rgba(0, 0, 0, 0.65)" />
    <input id="uploadImage" type="file" accept="image/png, image/jpeg, image/jpg" class="hide" ref="imgDom" @change="pictureChange($event)" />
  </label>
</template>

<script>
import WebIM from "../../utils/WebIM";
import Config from "../../config/index";

import { mapActions } from "vuex";
export default {
  data() {
    return {
      image: null
    };
  },
  methods: {
    ...mapActions(["sendImgMessage"]),
    // TODO 目前username、及type不是從pams裡取
    pictureChange(e) {
       if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
        alert("圖檔類型必須是.jpeg,jpg,png中的一種");
        return false;
      }
      let file = WebIM.utils.getFileUrl(e.target);
      if (!file.filename) {
        this.$refs.imgDom.value = null;
        return false;
      }
      let obj = {
        chatId: this.chatId.name, //TODO 這裡在群裡面應該取的是ID,後期跟進
        file: file,
         nickName:this.chatId.nickname,

        headPic:this.chatId.url,
        callback: () => {
          this.$refs.imgDom.value = null;
        }
      };
      this.sendImgMessage(obj);
    },
  },
  props: [
    "type", // 聊天類型 contact, group, chatroom
    "chatId" // 選中的聊天對象
  ],
  created(){
  }
};
</script>
<style scoped>
.hide {
  position: absolute;
  top: 0;
  right: 0;
  min-width: 100%;
  min-height: 100%;
  filter: alpha(opacity=0);
  opacity: 0;
  cursor: inherit;
  display: none;
}
i{
  font-size:20px;
  margin-left: 8px;
  cursor: pointer
}
</style>

           
  1. store index.js中引入
import Login from "./login";
import Chat from "./chat";
const store = new Vuex.Store({
    modules: {
        //環信測試
        Login: Login,
        chat: Chat,
        //環信測試
    }
});
清除存儲
 mutations: {
        clearToken(state) {
            //環信測試
            localStorage.removeItem('imuserInfo'); // 登入環信使用者
            localStorage.removeItem('immsgList'); //資訊清單
            localStorage.removeItem('imcurrenu'); //目前聊天對象
            localStorage.removeItem('imuserList'); //聊天對象清單
            Chat.state.msgList = {}
            Chat.state.userList = {}
                //環信測試
        },
        }
           
  1. 添加頁面 webuserlist.vue 使用者清單
<template>
   <div class="" style="width:100%;padding:30px 100px;">
      <ul>
        <li v-for="item in artistlist" :key="item.name" style="padding:20px 0;">
          <img :src="item.url" alt="" style="display:inline-block;width:30px;height:30px;border-radius:50%;">
          <span>{{item.name}}</span>
          <span style="display:inline-block;width:60px;font-size:12px;height:30px;line-height:30px;text-align:center;background:green;color:#fff;cursor: pointer;" @click="tochat(item)">私信</span>
        </li>
      </ul>
      <div>會話清單</div>
      <ul>

      </ul>
   </div>
</template>
<script>
// 點選私信進入私信聊天
export default {
  data () {
    return {
     artistlist:[
       {
      formu: localStorage.getItem("imuserInfo") &&
        JSON.parse(localStorage.getItem("imuserInfo")).userId,//目前使用者
       nickname:'小明',
       name:'使用者登入id',
       subscription:'to',
       url:''
     },
     ],
      userName:
        localStorage.getItem("imuserInfo") &&
        JSON.parse(localStorage.getItem("imuserInfo")).userId,
    }
  },
  created(){
  },
  methods:{
    tochat:function(val){
              //加入好友聊天頁面
       if(this.userName!==val.name){
        //  是否有聊天清單
        localStorage.setItem("imcurrenu", JSON.stringify(val))
        this.$router.push({path:'/webIm',query:{imname:val.name}})
       }
    },

  }
}
</script>
<style>
p{
  cursor: pointer;
}
</style>


           
  1. 添加頁面 webimlist.vue 會話清單
<template>
  <div id="webImPage" :style="{ height: clientHeight - 64 + 'px' }">
    <div class="messbox">
      <el-menu style="width: 100%; border-right: 0;" mode="vertical">
        <div v-if="haslist" style="text-align:left;color:#666;font-size:20px;">無資料</div>
        <div v-if="!haslist">
          <el-menu-item
            style="height: 80px; position: relative; textAlign: left; borderBottom: 1px solid #eee; margin: 0"
             v-for="(item) in userList" :key="getKey(item)"
            @click="tochat(item)"
          >
          <span class="custom-title">{{ item.nickName }}</span>
            <div class="icon-style" v-if="getUnreadNum(item) != 0">
              <span class="unreadNum">{{ getUnreadNum(item) }}</span>
            </div>
            <span class="time-style" style="float:right">{{
              getLastMsg(item).msgTime
            }}</span>
            <div v-html="getLastMsg(item).lastMsg"></div>
          </el-menu-item>
        </div>
      </el-menu>
    </div>
  </div>
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import moment from "moment";
import emoji from "../config/emoji";

export default {
  data() {
    return {
        type:'contact',
        haslist:'',
      clientHeight:'',
        userName:
        localStorage.getItem("imuserInfo") &&
        JSON.parse(localStorage.getItem("imuserInfo")).userId,
    };
  },
  computed: {
    ...mapGetters({
       msgList: "onGetCurrentChatObjMsg"
    }),
    userList() {
      var infol = JSON.parse(localStorage.getItem("imuserList"));
      if (infol !== null && infol !== "") {
        this.$store.state.chat.userList = infol;
        this.haslist=false
        console.log(this.$store.state.chat.userList)
        return this.$store.state.chat.userList;
      } else {
        this.haslist=true
        console.log(this.$store.state.chat.userList)
        return this.$store.state.chat.userList;
      }
    },
    chatList() {
      var infol = JSON.parse(localStorage.getItem("immsgList"));
      if (infol !== null && infol !== "") {
        this.$store.state.chat.msgList = infol;
        return this.$store.state.chat.msgList;
      } else {
        return this.$store.state.chat.msgList;
      }
    },
  },
  methods: {
     tochat:function(val){
              //加入好友聊天頁面
        //  是否有聊天清單
        var data={
                 formu: localStorage.getItem("imuserInfo") &&
        JSON.parse(localStorage.getItem("imuserInfo")).userId,//目前使用者
            nickname:val.nickName,
            name:val.name,
             subscription:'to',
             url:val.headPic
        }
        localStorage.setItem("imcurrenu", JSON.stringify(data))
        this.$router.push({path:'/webIm',query:{imname:val.name}})
    },
    ...mapActions([
      "onGetCurrentChatObjMsg"
    ]),
   
    getUnreadNum(item) {
      const chatList = this.chatList[item.name];
      let userId = "";
      userId = item.name;
      const currentMsgs = chatList || [];
      let unReadNum = 0;
      currentMsgs.forEach(msg => {
        console.log(msg)
      //   if (msg.status !== "read" && msg.status !== "recall" && !msg.bySelf) {
      //     unReadNum++;
      //   }
      });
      return unReadNum;
    },
    getLastMsg(item) {
      const chatList = this.chatList[item.name];
      let userId = "";
      userId = item.name;
      console.log(chatList)
      const currentMsgs = chatList || [];
      let lastMsg = "";
        console.log(currentMsgs[currentMsgs.length - 1])

      let lastType =
        currentMsgs.length && currentMsgs[currentMsgs.length - 1].type;
      if (currentMsgs.length>0) {
        if (lastType === "img") {
          lastMsg = "[image]";
        } else if (lastType === "file") {
          lastMsg = currentMsgs[currentMsgs.length - 1].filename;
        } else if (lastType === "audio") {
          lastMsg = "[audio]";
        } else if (lastType === "vidio") {
          lastMsg = "[vidio]";
        } else {
          lastMsg = currentMsgs[currentMsgs.length - 1].msg;
        }
      }
      let rnTxt = [];
      let match = null;
      const regex = /(\[.*?\])/g;
      let start = 0;
      let index = 0;
      while ((match = regex.exec(lastMsg))) {
        index = match.index;
        if (index > start) {
          rnTxt.push(lastMsg.substring(start, index));
        }
        if (match[1] in emoji.obj) {
          const v = emoji.obj[match[1]];
          rnTxt.push(this.customEmoji(v));
        } else {
          rnTxt.push(match[1]);
        }
        start = index + match[1].length;
      }
      rnTxt.push(lastMsg.substring(start, lastMsg.length));
      rnTxt =  rnTxt.toString().replace(/,/g, "");
     lastMsg= rnTxt
      const msgTime = currentMsgs.length
        ? this.renderTime(currentMsgs[currentMsgs.length - 1].time)
        : "";
      return {
        lastMsg,
        msgTime
      };
    },
     customEmoji(value) {
      return `<img src="../../../static/faces/${value}" style="width:20px"/>`;
    },
    getKey(item) {
      let key = "";
      key = item.name;
    },
      // TODO 可以抽離到utils
    renderTime(time) {
      const nowStr = new Date();
      const localStr = time ? new Date(time) : nowStr;
      const localMoment = moment(localStr);
      const localFormat = localMoment.format("MM-DD hh:mm A");
      return localFormat;
    },
      getHeight: function () {
      this.clientHeight = `${document.documentElement.clientHeight}`;
    },
  },
   created(){
    this.getHeight()
    console.log('fdsf')
  },
};
</script>
<style scoped lang="less">
* {
  margin: 0;
  padding: 0;
}
input[name="sendmess"] {
  height: 100%;
  border: none;
}
#webImPage {
  // height:200px;
  width: 100%;
  height: 100%;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  color: #fff;

  .messbox {
    width: 1152px;
    height: 100%;
    margin: 0 auto;
  }
}
</style>

           
  1. 添加頁面 webIM.vue 聊天界面
<template>
  <div id="webImPage" :style="{ height: clientHeight - 64 + 'px' }">
    <div class="messbox">
      <div class="messagebox-header">
        <span style="color:red;" >本尊{{ userName }}</span>
        <span>其他人{{ hxiteminfo.nickname }}</span>
      </div>
      <div class="messagebox-content" ref="msgContent">
        <div
          v-for="(item, i) in chatList"
          :key="i"
          class="message-group"
          :style="{ float: item.bySelf ? 'right' : 'left' }"
        >
          <h4 style="text-align: left;margin:0">{{ item.from }}</h4>
          <!-- 撤回消息 -->
          <!-- <div v-if="item.status == 'recall'" class="recallMsg">{{item.msg}}</div>
            <div v-if="item.status == 'recall'" class="recallMsg">{{renderTime(item.time)}}</div> -->
          <!-- 撤回消息 end -->
          <div :style="{ float: item.bySelf ? 'right' : 'left' }">
            <span style="user-select: none">
              <img
                :key="item.id"
                :src="item.msg ? item.msg : ''"
                v-if="item.type === 'img'"
                class="img-style"
              />
              <!-- 檔案card -->
              <div
                v-else-if="item.type === 'file'"
                class="file-style"
                :style="{ float: item.bySelf ? 'right' : 'left' }"
              >
                <el-card :body-style="{ padding: '0px' }">
                  <div style="padding: 14px;">
                    <h2>檔案</h2>
                    <span>
                      <h3>{{ item.filename }}</h3>
                    </span>
                    <div class="bottom clearfix">
                      <span>{{ readablizeBytes(item.file_length) }}</span>
                      <a :href="item.msg" :download="item.filename">點選下載下傳</a>
                    </div>
                  </div>
                </el-card>
              </div>
              <!-- 音頻消息 -->
              <div
                v-else-if="item.type === 'audio'"
                :style="{ float: item.bySelf ? 'right' : 'left' }"
              >
                <audio :src="item.msg" controls></audio>
              </div>
              <!-- 視訊消息 -->
              <div v-else-if="item.type === 'video'">
                <video :src="item.msg" width="100%" controls></video>
              </div>
              <!-- 聊天消息 -->
              <p
                v-else
                v-html="renderTxt(item.msg)"
                :class="{ byself: item.bySelf }"
              ></p>
            </span>
          </div>
        </div>
      </div>
      <div class="messagebox-footer">
        <div class="footer-icon">
          <!-- 表情元件 -->
          <ChatEmoji v-on:selectEmoji="selectEmoji" :inpMessage="message" />
          <!-- 上傳圖檔元件 -->
          <UpLoadImage :type="this.type" :chatId="hxiteminfo" v-if="showico" />
          <!-- 上傳檔案元件 -->
          <!-- <UpLoadFile :type="this.type" :chatId="hxiteminfo" v-if="showico" /> -->
        </div>
        <div class="fotter-send">
          <el-input
            v-model="message"
             type="textarea"
             @keyup.enter.native="onSendTextMsg"
            equired
            name="sendmess"
            placeholder="消息"
            class="sengTxt"
            style="resize:none"
            ref="txtDom"
          />
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import ChatEmoji from "../components/chatEmoji/index.vue";
import UpLoadImage from "../components/upLoadImage/index.vue";
import UpLoadFile from "../components/upLoadFile/index.vue";
import WebIM from "../utils/WebIM";
import moment from "moment";
import emoji from "../config/emoji";
export default {
  components: {
    ChatEmoji,
    UpLoadImage,
    UpLoadFile
  },
  data() {
    return {
      type: "contact",
      activeKey: "contact",
      showModal: false,
      activedKey: {
        contact: {
          // name: "lmy999",
          // subscription: "both",
        }
      },
      message: "",
      clientHeight: "",
      userName:
        localStorage.getItem("imuserInfo") &&
        JSON.parse(localStorage.getItem("imuserInfo")).userId,
      hxiteminfo: {},
      showico: false,
      list: ""
    };
  },
  created() {
    this.getHeight();
    if (this.$route.query.imname) {
      if (
        JSON.parse(localStorage.getItem("imcurrenu")).formu === this.userName
      ) {
        this.hxiteminfo = JSON.parse(localStorage.getItem("imcurrenu"));
        console.log(this.hxiteminfo)
        this.showico = true;
      }
    }
  },
  computed: {
    // ...mapGetters({
    //   contact: "onGetContactUserList",
    //   msgList: "onGetCurrentChatObjMsg"
    // }),

    userList() {
      //擷取聊過天的對象清單集合
        return this.$store.state.chat.userList
    },
    chatList() {
      //擷取聊天記錄
      var infol = JSON.parse(localStorage.getItem("immsgList"));
      if (infol !== null && infol !== "") {
        this.$store.state.chat.msgList = infol;
        return this.$store.state.chat.msgList[this.hxiteminfo.name];
      } else {
        return this.$store.state.chat.msgList[this.hxiteminfo.name];
      }
    }
  },
  methods: {
    getKey(item, type) {
      let key = "";
      switch (type) {
        case "contact":
          key = item.name;
          break;
        case "group":
          key = item.groupid;
          break;
        case "chatroom":
          key = item.id;
          break;
        default:
          break;
      }
      return key;
    },
    ...mapActions([
      "onSendText", //發送資訊
      // "onGetCurrentChatObjMsg", //擷取資訊清單
      "onGetContactUserList", //擷取聊過天的對象清單集合
      "getHistoryMessage" //擷取曆史記錄
    ]),
    selectEmoji(v) {
      //添加表情
      this.$data.message = v;
      this.$refs.txtDom.focus(); //給輸入框焦點
    },
    getHeight: function() {
      this.clientHeight = `${document.documentElement.clientHeight}`;
    },

    onSendTextMsg() {
      if (this.$data.message == "" || this.$data.message == "\n") {
        this.$data.message = "";
        return;
      }
       console.log({
        headPic: this.hxiteminfo.url,
        nickName: this.hxiteminfo.nickname,
        chatId: this.hxiteminfo.name,
        message: this.$data.message
      })
      this.onSendText({
        headPic: this.hxiteminfo.url,
        nickName: this.hxiteminfo.nickname,
        chatId: this.hxiteminfo.name,
        message: this.$data.message
      });
      this.$data.message = "";
    },
    // TODO 可以抽離到utils
    renderTime(time) {
      const nowStr = new Date();
      const localStr = time ? new Date(time) : nowStr;
      const localMoment = moment(localStr);
      const localFormat = localMoment.format("MM-DD hh:mm A");
      return localFormat;
    },
    readablizeBytes(value) {
      let s = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
      let e = Math.floor(Math.log(value) / Math.log(1024));
      return (value / Math.pow(1024, Math.floor(e))).toFixed(2) + " " + s[e];
    },
    renderTxt: function(txt) {
      let rnTxt = [];
      let match = null;
      const regex = /(\[.*?\])/g;
      let start = 0;
      let index = 0;
      while ((match = regex.exec(txt))) {
        index = match.index;
        if (index > start) {
          rnTxt.push(txt.substring(start, index));
        }
        if (match[1] in emoji.obj) {
          const v = emoji.obj[match[1]];
          rnTxt.push(this.customEmoji(v));
        } else {
          rnTxt.push(match[1]);
        }
        start = index + match[1].length;
      }
      rnTxt.push(txt.substring(start, txt.length));
      return rnTxt.toString().replace(/,/g, "");
    },
    customEmoji(value) {
      return `<img src="../../../static/faces/${value}" style="width:20px;display:inline-block;"/>`;
    }
  }
};
</script>
<style lang="less">
@import "../assets/css/webImPage.less";
</style>

           
  1. static引入 faces檔案