1 安裝 vue
npm install easemob-websdk --save 官方安裝 ,這種安裝要在依賴包配置初始化連接,提交代碼時並沒把配置提交
使用 hx-websdk 安裝web
npm install --save hx-websdk
2 .使用 新建一個webim.js 放在聊天窗口組件同一層級,爲了Emoji圖片路徑同步vuex
import store from '@/store/store' // window.Strophe = require('strophe.js').Strophe // let WebIM = require('easemob-websdk') import WebIM from "hx-websdk"; // let WebIM = require('hx-websdk') // require('hx-emedia') // WebIM.WebRTC = require('hx-webrtc') WebIM.config = { /* * XMPP server */ xmppURL: 'im-api.easemob.com', /* * Backend REST API URL */ apiURL: (location.protocol === 'https:' ? 'https:' : 'http:') + '//a1.easemob.com', /* * Application AppKey */ appkey: '1106190328208422#liangzi', /* * Whether to use wss * @parameter {Boolean} true or false */ https: false, /* * isMultiLoginSessions * true: A visitor can sign in to multiple webpages and receive messages at all the webpages. * false: A visitor can sign in to only one webpage and receive messages at the webpage. */ isMultiLoginSessions: false, /* * set presence after login */ isAutoLogin: true, /** * Whether to use window.doQuery() * @parameter {Boolean} true or false */ isWindowSDK: false, /** * isSandBox=true: xmppURL: 'im-api-sandbox.easemob.com', apiURL: '//a1-sdb.easemob.com', * isSandBox=false: xmppURL: 'im-api.easemob.com', apiURL: '//a1.easemob.com', * @parameter {Boolean} true or false */ isSandBox: false, /** * Whether to console.log in strophe.log() * @parameter {Boolean} true or false */ isDebug: true, /** * will auto connect the xmpp server autoReconnectNumMax times in background when client is offline. * won't auto connect if autoReconnectNumMax=0. */ autoReconnectNumMax: 2, /** * the interval seconds between each auto reconnectting. * works only if autoReconnectMaxNum >= 2. */ autoReconnectInterval: 2, /** * webrtc supports WebKit and https only */ isWebRTC: (/Firefox/.test(navigator.userAgent) || /WebKit/.test(navigator.userAgent)) && /^https:$/.test(window.location.protocol), /** * after login, send empty message to xmpp server like heartBeat every 45s, to keep the ws connection alive. */ heartBeatWait: 4500, /** * while http access,use ip directly,instead of ServerName,avoiding DNS problem. */ isHttpDNS: false, /** * Will show the status of messages in single chat * msgStatus: true show * msgStatus: true hide */ msgStatus: true, /** * When a message arrived, the receiver send an ack message to the * sender, in order to tell the sender the message has delivered. * See call back function onReceivedMessage */ delivery: true, /** * When a message read, the receiver send an ack message to the * sender, in order to tell the sender the message has been read. * See call back function onReadMessage */ read: false, /** * Will encrypt text message and emoji message * {type:'none'} no encrypt * {type:'base64'} encrypt with base64 * {type:'aes',mode: 'ebc',key: '123456789easemob',iv: '0000000000000000'} encrypt with aes(ebc) * {type:'aes',mode: 'cbc',key: '123456789easemob',iv: '0000000000000000'} encrypt with aes(cbc) */ encrypt: { type: 'none' } } WebIM.Emoji = { path: './../../../../../assets/images/faces/', map: { '[微笑]': 'ee_1.gif', '[撇嘴]': 'ee_2.gif', '[色]': 'ee_3.gif', '[發呆]': 'ee_4.gif', '[流淚]': 'ee_5.gif', '[害羞]': 'ee_6.gif', '[閉嘴]': 'ee_7.gif', '[睡]': 'ee_8.gif', '[大哭]': 'ee_9.gif', '[尷尬]': 'ee_10.gif', '[發怒]': 'ee_11.gif', '[調皮]': 'ee_12.gif', '[呲牙]': 'ee_13.gif', '[驚訝]': 'ee_14.gif', '[難過]': 'ee_15.gif', '[囧]': 'ee_16.gif', '[抓狂]': 'ee_17.gif', '[吐]': 'ee_18.gif', '[偷笑]': 'ee_19.gif', '[愉快]': 'ee_20.gif', '[白眼]': 'ee_21.gif', '[傲慢]': 'ee_22.gif', '[飢餓]': 'ee_23.gif', '[困]': 'ee_24.gif', '[驚恐]': 'ee_25.gif', '[流汗]': 'ee_26.gif', '[憨笑]': 'ee_27.gif', '[清閒]': 'ee_28.gif', '[奮鬥]': 'ee_29.gif', '[咒罵]': 'ee_30.gif', '[疑問]': 'ee_31.gif', '[噓]': 'ee_32.gif', '[暈]': 'ee_33.gif', '[瘋了]': 'ee_34.gif', '[衰]': 'ee_35.gif', '[敲打]': 'ee_36.gif', '[再見]': 'ee_37.gif', '[擦汗]': 'ee_38.gif', '[摳鼻]': 'ee_39.gif', '[糗大了]': 'ee_40.gif', '[壞笑]': 'ee_41.gif', '[左哼哼]': 'ee_42.gif', '[右哼哼]': 'ee_43.gif', '[哈欠]': 'ee_44.gif', '[鄙視]': 'ee_45.gif', '[委屈]': 'ee_46.gif', '[快哭]': 'ee_47.gif', '[陰險]': 'ee_48.gif', '[親親]': 'ee_49.gif', '[嚇]': 'ee_50.gif', '[可憐]': 'ee_51.gif', '[擁抱]': 'ee_52.gif', '[月亮]': 'ee_53.gif', '[太陽]': 'ee_54.gif', '[炸彈]': 'ee_55.gif', '[骷髏]': 'ee_56.gif', '[菜刀]': 'ee_57.gif', '[豬頭]': 'ee_58.gif', '[西瓜]': 'ee_59.gif', '[咖啡]': 'ee_60.gif', '[飯]': 'ee_61.gif', '[愛心]': 'ee_62.gif', '[強]': 'ee_63.gif', '[弱]': 'ee_64.gif', '[握手]': 'ee_65.gif', '[勝利]': 'ee_66.gif', '[抱拳]': 'ee_67.gif', '[勾引]': 'ee_68.gif', '[OK]': 'ee_69.gif', '[No]': 'ee_70.gif', '[玫瑰]': 'ee_71.gif', '[凋謝]': 'ee_72.gif', '[嘴脣]': 'ee_73.gif', '[愛情]': 'ee_74.gif', '[飛吻]': 'ee_75.gif' } } // WebIM.NewEmoji = { // map: ['😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂', '🙂', '🙃', '😉', '😊', '😇', '😍', '🤩', '😘', '😗', '😚', '😙', '😋', '😛', '😜', '🤪', '😝', '🤑', '🤗', '🤭', '🤫', '🤔', '🤐', '🤨', '😐', '😑', '😶', '😏', '😒', '🙄', '😬', '🤥', '😌', '😔', '😪', '🤤', '😴', '😷', '🤒', '🤕', '🤢', '🤮', '🤧', '😵', '🤯', '🤠', '😎', '🤓', '🧐', '😕', '😟', '🙁', '☹', '😮', '😯', '😲', '😳', '😦', '😧', '😨', '😰', '😥', '😢', '😭', '😱', '😖', '😣', '😞', '😓', '😩', '😫', '😤', '😡', '😠', '🤬', '😈', '👿', '💀', '☠', '💩', '🤡', '👹', '👺', '👻', '👽', '👾', '🤖', '😺', '😸', '😹', '😻', '😼', '😽', '🙀', '😿', '😾', '💋', '👋', '🤚', '🖐', '✋', '🖖', '👌', '✌', '🤞', '🤟', '🤘', '🤙', '👈', '👉', '👆', '🖕', '👇', '☝', '👍', '👎', '✊', '👊', '🤛', '🤜', '👏', '🙌', '👐', '🤲', '🤝', '🙏', '✍', '💅', '🤳', '💪', '👂', '👃', '🧠', '👀', '👁', '👅', '👄', '👶', '🧒', '👦', '👧', '🧑', '👱', '👨', '🧔', '👱', '👨', '👨', '👨', '👨', '👩', '👱', '👩', '👩', '👩', '👩', '🧓', '👴', '👵', '🙍', '🙍', '🙍', '🙎', '🙎', '🙎', '🙅', '🙅', '🙅', '🙆', '🙆', '🙆', '💁', '💁', '💁', '🙋', '🙋', '🙋', '🙇', '🙇', '🙇', '🤦', '🤦', '🤦', '🤷', '🤷', '🤷', '👨⚕️', '👩⚕️', '👨🎓', '👩🎓', '👨🏫', '👩🏫', '👨⚖️', '👩⚖️', '👨🌾', '👩🌾', '👨🍳', '👩🍳', '👨🔧', '👩🔧', '👨🏭', '👩🏭', '👨💼', '👩💼', '👨🔬', '👩🔬', '👨💻', '👩💻', '👨🎤', '👩🎤', '👨🎨', '👩🎨', '👨✈️', '👩✈️', '👨🚀', '👩🚀', '👨🚒', '👩🚒', '👮', '👮♂️', '👮♀️', '🕵Det', '🕵️♂️', '🕵️♀️', '💂', '💂', '💂', '👷', '👷', '👷', '🤴', '👸', '👳', '👳', '👳', '👲', '🧕', '🤵', '👰', '🤰', '🤱', '👼', '🎅', '🤶', '🧙', '🧙', '🧙', '🧚', '🧚', '🧚', '🧛', '🧛', '🧛', '🧜', '🧜', '🧜', '🧝', '🧝', '🧝', '🧞', '🧞', '🧞', '🧟', '🧟', '🧟', '💆', '💆', '💆', '💇', '💇', '💇', '🚶', '🚶', '🚶', '🏃', '🏃', '🏃', '💃', '🕺', '🕴', '👯', '👯', '👯', '🧖', '🧖', '🧖', '🧘', '👭', '👫', '👬', '💏', '👨', '👩', '💑', '👨', '👩', '👪', '👨👩👦', '👨👩👧', '👨👩👧👦', '👨👩👦👦', '👨👩👧👧', '👨👨👦', '👨👨👧', '👨👨👧👦', '👨👨👦👦', '👨👨👧👧', '👩👩👦', '👩👩👧', '👩👩👧👦', '👩👩👦👦', '👩👩👧👧', '👨👦', '👨👦👦', '👨👧', '👨👧👦', '👨👧👧', '👩👦', '👩👦👦', '👩👧', '👩👧👦', '👩👧👧', '🗣', '👤', '👥', '👣', '🌂', '☂', '👓', '🕶', '👔', '👕', '👖', '🧣', '🧤', '🧥', '🧦', '👗', '👘', '👙', '👚', '👛', '👜', '👝', '🎒', '👞', '👟', '👠', '👡', '👢', '👑', '👒', '🎩', '🎓', '🧢', '⛑', '💄', '💍', '💼'] // } /* eslint new-cap: ["error", { "newIsCap": false }] */ const conn = new WebIM.connection({ isMultiLoginSessions: WebIM.config.isMultiLoginSessions, https: typeof WebIM.config.https === 'boolean' ? WebIM.config.https : location.protocol === 'https:', url: WebIM.config.xmppURL, heartBeatWait: WebIM.config.heartBeatWait, autoReconnectNumMax: WebIM.config.autoReconnectNumMax, autoReconnectInterval: WebIM.config.autoReconnectInterval, apiUrl: WebIM.config.apiURL, isAutoLogin: true }) conn.listen({ // 鏈接成功回調 onOpened: function (message) { conn.getRoster({ success: function (roster) { // console.log(roster,'連接'); let rosData = [] for (var i = 0, l = roster.length; i < l; i++) { if (roster[i].subscription === 'both') { rosData.push(roster[i]) // console.log(rosData,'連接成功') // store.dispatch('getFriendsData', rosData) } else { return } } } }) }, // 收到文本消息 onTextMessage: function (message) { console.log(message,'接收新的消息'); let textMessage = { from: message.from, content:message.data, type: 'txt' } store.dispatch('setIMtextMessage', JSON.stringify(textMessage) ); // console.log(store,'全局變量'); }, // 接收圖片 onPictureMessage: (message) => { let textMessage = { from: message.from, url: message.url, type: 'img' } store.dispatch('setIMtextMessage', JSON.stringify(textMessage)); console.log(message,'接收圖片'); }, // 收到表情信息 onEmojiMessage: function (message) { console.log(message, '接收表情'); // 接收到的是數組,循環編譯圖片 let content = ''; message.data.forEach((item, index) => { if (item.type=='emoji') { //require不能轉動態參,先截取圖片名稱再拼接轉 let eeIndex = item.data.indexOf('ee_'); let img = item.data.substring(eeIndex, item.data.length); let path = require(`./../../../../../assets/images/faces/${img}`); content += `<img src="${path}" />` } else { content += item.data } }) let textMessage = { from: message.from, content: content, type: 'txt' } store.dispatch('setIMtextMessage', JSON.stringify(textMessage)); }, // 收到聯繫人訂閱請求、處理羣組、聊天室被踢解散等消息 onPresence: function (message) { }, // 處理好友申請 onRoster: function () { conn.getRoster({ success: function (roster) { let rosData = [] for (var i = 0, l = roster.length; i < l; i++) { if (roster[i].subscription === 'both') { rosData.push(roster[i]) console.log('處理好友申請') console.log(rosData) // store.dispatch('getFriendsData', rosData) } else { return } } } }) }, onAudioMessage: function (message) { console.log('當前關閉') }, // 收到音頻消息 onLocationMessage: function (message) { console.log('當前關閉') }, // 收到位置消息 onFileMessage: function (message) { console.log('當前關閉') }, // 收到文件消息 onVideoMessage: function (message) { console.log('當前關閉') }, // 收到視頻消息 onInviteMessage: function (message) { console.log('當前關閉') }, // 處理羣組邀請 onOnline: function () { console.log('當前關閉') }, // 本機網絡鏈接成功 onOffline: function () { console.log('當前關閉') }, // 本機網絡掉線 // 失敗回調 onError: function (message) { console.log(message) } }) // 須要註冊一個全局的WebIM 在hx-sdk中有須要用到 否則發送接收表情時會拋出異常 window.WebIM = WebIM export default { install: function (Vue, options) { // console.log(WebIM) Object.defineProperty(Vue.prototype, '$imConn', { value: conn }) } }
3.若是須要視頻聊天 安裝 hx-webrtcnpm
npm install --save hx-webrtc // 代碼部分 WebIM.WebRTC = require('hx-webrtc') // 集成 const rtcCall = new WebIM.WebRTC.Call({ connection: conn, mediaStreamConstaints: { audio: true, video: true }, listener: { onAcceptCall: function (from, options) { // console.log('onAcceptCall::', 'from: ', from, 'options: ', options); }, onGotRemoteStream: function (stream, streamType) { // console.log('onGotRemoteStream::', 'stream: ', stream, 'streamType: ', streamType); }, onGotLocalStream: function (stream, streamType) { // console.log('onGotLocalStream::', 'stream:', stream, 'streamType: ', streamType); }, onRinging: function (caller) { let reg = /(?<=_).*(?=@)/ let callerId = (reg.exec(caller))[0] let curUser = [] let friends = store.state.data.friends for (let i in friends) { if (friends[i].username === callerId) { curUser = friends[i] } } console.log(curUser) // router.push({ path: '/calling', query: { user: curUser, curBtn: true } }) }, onTermCall: function (reason) { console.log('onTermCall::') console.log('reason:', reason) }, onIceConnectionStateChange: function (iceState) { if (iceState === 'closed') { // router.push({ path: '/friends' }) } }, onError: function (e) { console.log(e) } } }) Object.defineProperty(Vue.prototype, '$rtcCall', { value: rtcCall })
4 .最終代碼結合後端
import store from '@/store/store' // window.Strophe = require('strophe.js').Strophe // let WebIM = require('easemob-websdk') import WebIM from "hx-websdk"; // let WebIM = require('hx-websdk') // require('hx-emedia') // WebIM.WebRTC = require('hx-webrtc') WebIM.config = { /* * XMPP服務器 對於在console.easemob.com建立的appKey,固定爲該值 */ xmppURL: 'im-api.easemob.com', /* *環信後端REST API URL,固定不變 */ apiURL: (location.protocol === 'https:' ? 'https:' : 'http:') + '//a1.easemob.com', /* *rest Server地址 對於在console.easemob.com建立的appkey,固定爲該值 */ appkey: '1106190328208422#liangzi', /* * 是否使用https * @parameter {Boolean} true or false */ https: false, /* * isMultiLoginSessions * true: 訪問者能夠登陸多個網頁,並在全部網頁上接收消息。. * false: 訪客只能登入一個網頁,並在該網頁接收訊息 */ isMultiLoginSessions: false, /* * set presence after login */ isAutoLogin: true, /** * Whether to use window.doQuery() * @parameter {Boolean} true or false */ isWindowSDK: false, /** * isSandBox=true: xmppURL: 'im-api-sandbox.easemob.com', apiURL: '//a1-sdb.easemob.com', * isSandBox=false: xmppURL: 'im-api.easemob.com', apiURL: '//a1.easemob.com', * @parameter {Boolean} true or false */ isSandBox: false, /** * Whether to console.log in strophe.log() * @parameter {Boolean} true or false */ isDebug: true, /** * 將自動鏈接xmpp服務器,當客戶端離線時,在後臺自動重連次數. *若是autoReconnectNumMax=0,則不會自動鏈接. */ autoReconnectNumMax: 2, /** * 每次自動從新鏈接之間的間隔秒. * 僅當autoReconnectMaxNum >= 2時纔有效。 */ autoReconnectInterval: 2, /** * webrtc只支持WebKit和https */ isWebRTC: (/Firefox/.test(navigator.userAgent) || /WebKit/.test(navigator.userAgent)) && /^https:$/.test(window.location.protocol), /** * 登陸後,每隔45秒向xmpp服務器發送一條空消息(好比heartBeat),以保持ws鏈接處於活動狀態 */ heartBeatWait: 4500, /** * 當http訪問時,直接使用ip而不是ServerName,避免了DNS問題 */ isHttpDNS: false, /** * 會顯示消息的狀態在單一聊天 * msgStatus: true show * msgStatus: true hide */ msgStatus: true, /** * 當消息到達時,接收方將ack消息發送到 * 發送方,以便告訴發送方消息已發送。 * 參見回調函數onReceivedMessage */ delivery: true, /** * 當消息讀取時,接收方將ack消息發送到 * 發送方,以便告訴發送方消息已被讀取。 * 參見回調函數onReadMessage */ read: false, /** *將加密短信和表情信息 * {type:'none'} no encrypt * {type:'base64'} encrypt with base64 * {type:'aes',mode: 'ebc',key: '123456789easemob',iv: '0000000000000000'} encrypt with aes(ebc) * {type:'aes',mode: 'cbc',key: '123456789easemob',iv: '0000000000000000'} encrypt with aes(cbc) */ encrypt: { type: 'none' } } WebIM.Emoji = { path: './../../../../../assets/images/faces/', map: { '[微笑]': 'ee_1.gif', '[撇嘴]': 'ee_2.gif', '[色]': 'ee_3.gif', '[發呆]': 'ee_4.gif', '[流淚]': 'ee_5.gif', '[害羞]': 'ee_6.gif', '[閉嘴]': 'ee_7.gif', '[睡]': 'ee_8.gif', '[大哭]': 'ee_9.gif', '[尷尬]': 'ee_10.gif', '[發怒]': 'ee_11.gif', '[調皮]': 'ee_12.gif', '[呲牙]': 'ee_13.gif', '[驚訝]': 'ee_14.gif', '[難過]': 'ee_15.gif', '[囧]': 'ee_16.gif', '[抓狂]': 'ee_17.gif', '[吐]': 'ee_18.gif', '[偷笑]': 'ee_19.gif', '[愉快]': 'ee_20.gif', '[白眼]': 'ee_21.gif', '[傲慢]': 'ee_22.gif', '[飢餓]': 'ee_23.gif', '[困]': 'ee_24.gif', '[驚恐]': 'ee_25.gif', '[流汗]': 'ee_26.gif', '[憨笑]': 'ee_27.gif', '[清閒]': 'ee_28.gif', '[奮鬥]': 'ee_29.gif', '[咒罵]': 'ee_30.gif', '[疑問]': 'ee_31.gif', '[噓]': 'ee_32.gif', '[暈]': 'ee_33.gif', '[瘋了]': 'ee_34.gif', '[衰]': 'ee_35.gif', '[敲打]': 'ee_36.gif', '[再見]': 'ee_37.gif', '[擦汗]': 'ee_38.gif', '[摳鼻]': 'ee_39.gif', '[糗大了]': 'ee_40.gif', '[壞笑]': 'ee_41.gif', '[左哼哼]': 'ee_42.gif', '[右哼哼]': 'ee_43.gif', '[哈欠]': 'ee_44.gif', '[鄙視]': 'ee_45.gif', '[委屈]': 'ee_46.gif', '[快哭]': 'ee_47.gif', '[陰險]': 'ee_48.gif', '[親親]': 'ee_49.gif', '[嚇]': 'ee_50.gif', '[可憐]': 'ee_51.gif', '[擁抱]': 'ee_52.gif', '[月亮]': 'ee_53.gif', '[太陽]': 'ee_54.gif', '[炸彈]': 'ee_55.gif', '[骷髏]': 'ee_56.gif', '[菜刀]': 'ee_57.gif', '[豬頭]': 'ee_58.gif', '[西瓜]': 'ee_59.gif', '[咖啡]': 'ee_60.gif', '[飯]': 'ee_61.gif', '[愛心]': 'ee_62.gif', '[強]': 'ee_63.gif', '[弱]': 'ee_64.gif', '[握手]': 'ee_65.gif', '[勝利]': 'ee_66.gif', '[抱拳]': 'ee_67.gif', '[勾引]': 'ee_68.gif', '[OK]': 'ee_69.gif', '[No]': 'ee_70.gif', '[玫瑰]': 'ee_71.gif', '[凋謝]': 'ee_72.gif', '[嘴脣]': 'ee_73.gif', '[愛情]': 'ee_74.gif', '[飛吻]': 'ee_75.gif' } } // WebIM.NewEmoji = { // map: ['😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂', '🙂', '🙃', '😉', '😊', '😇', '😍', '🤩', '😘', '😗', '😚', '😙', '😋', '😛', '😜', '🤪', '😝', '🤑', '🤗', '🤭', '🤫', '🤔', '🤐', '🤨', '😐', '😑', '😶', '😏', '😒', '🙄', '😬', '🤥', '😌', '😔', '😪', '🤤', '😴', '😷', '🤒', '🤕', '🤢', '🤮', '🤧', '😵', '🤯', '🤠', '😎', '🤓', '🧐', '😕', '😟', '🙁', '☹', '😮', '😯', '😲', '😳', '😦', '😧', '😨', '😰', '😥', '😢', '😭', '😱', '😖', '😣', '😞', '😓', '😩', '😫', '😤', '😡', '😠', '🤬', '😈', '👿', '💀', '☠', '💩', '🤡', '👹', '👺', '👻', '👽', '👾', '🤖', '😺', '😸', '😹', '😻', '😼', '😽', '🙀', '😿', '😾', '💋', '👋', '🤚', '🖐', '✋', '🖖', '👌', '✌', '🤞', '🤟', '🤘', '🤙', '👈', '👉', '👆', '🖕', '👇', '☝', '👍', '👎', '✊', '👊', '🤛', '🤜', '👏', '🙌', '👐', '🤲', '🤝', '🙏', '✍', '💅', '🤳', '💪', '👂', '👃', '🧠', '👀', '👁', '👅', '👄', '👶', '🧒', '👦', '👧', '🧑', '👱', '👨', '🧔', '👱', '👨', '👨', '👨', '👨', '👩', '👱', '👩', '👩', '👩', '👩', '🧓', '👴', '👵', '🙍', '🙍', '🙍', '🙎', '🙎', '🙎', '🙅', '🙅', '🙅', '🙆', '🙆', '🙆', '💁', '💁', '💁', '🙋', '🙋', '🙋', '🙇', '🙇', '🙇', '🤦', '🤦', '🤦', '🤷', '🤷', '🤷', '👨⚕️', '👩⚕️', '👨🎓', '👩🎓', '👨🏫', '👩🏫', '👨⚖️', '👩⚖️', '👨🌾', '👩🌾', '👨🍳', '👩🍳', '👨🔧', '👩🔧', '👨🏭', '👩🏭', '👨💼', '👩💼', '👨🔬', '👩🔬', '👨💻', '👩💻', '👨🎤', '👩🎤', '👨🎨', '👩🎨', '👨✈️', '👩✈️', '👨🚀', '👩🚀', '👨🚒', '👩🚒', '👮', '👮♂️', '👮♀️', '🕵Det', '🕵️♂️', '🕵️♀️', '💂', '💂', '💂', '👷', '👷', '👷', '🤴', '👸', '👳', '👳', '👳', '👲', '🧕', '🤵', '👰', '🤰', '🤱', '👼', '🎅', '🤶', '🧙', '🧙', '🧙', '🧚', '🧚', '🧚', '🧛', '🧛', '🧛', '🧜', '🧜', '🧜', '🧝', '🧝', '🧝', '🧞', '🧞', '🧞', '🧟', '🧟', '🧟', '💆', '💆', '💆', '💇', '💇', '💇', '🚶', '🚶', '🚶', '🏃', '🏃', '🏃', '💃', '🕺', '🕴', '👯', '👯', '👯', '🧖', '🧖', '🧖', '🧘', '👭', '👫', '👬', '💏', '👨', '👩', '💑', '👨', '👩', '👪', '👨👩👦', '👨👩👧', '👨👩👧👦', '👨👩👦👦', '👨👩👧👧', '👨👨👦', '👨👨👧', '👨👨👧👦', '👨👨👦👦', '👨👨👧👧', '👩👩👦', '👩👩👧', '👩👩👧👦', '👩👩👦👦', '👩👩👧👧', '👨👦', '👨👦👦', '👨👧', '👨👧👦', '👨👧👧', '👩👦', '👩👦👦', '👩👧', '👩👧👦', '👩👧👧', '🗣', '👤', '👥', '👣', '🌂', '☂', '👓', '🕶', '👔', '👕', '👖', '🧣', '🧤', '🧥', '🧦', '👗', '👘', '👙', '👚', '👛', '👜', '👝', '🎒', '👞', '👟', '👠', '👡', '👢', '👑', '👒', '🎩', '🎓', '🧢', '⛑', '💄', '💍', '💼'] // } /* eslint new-cap: ["error", { "newIsCap": false }] */ const conn = new WebIM.connection({ isMultiLoginSessions: WebIM.config.isMultiLoginSessions, https: typeof WebIM.config.https === 'boolean' ? WebIM.config.https : location.protocol === 'https:', url: WebIM.config.xmppURL, heartBeatWait: WebIM.config.heartBeatWait, autoReconnectNumMax: WebIM.config.autoReconnectNumMax, autoReconnectInterval: WebIM.config.autoReconnectInterval, apiUrl: WebIM.config.apiURL, isAutoLogin: true }) conn.listen({ // 鏈接成功回調 onOpened: function (message) { conn.getRoster({ success: function (roster) { // console.log(roster,'連接'); let rosData = [] for (var i = 0, l = roster.length; i < l; i++) { if (roster[i].subscription === 'both') { rosData.push(roster[i]) // console.log(rosData,'連接成功') // store.dispatch('getFriendsData', rosData) } else { return } } } }) }, // 收到文本消息 onTextMessage: function (message) { console.log(message,'接收新的消息'); let textMessage = { from: message.from, content:message.data, type: 'txt' } store.dispatch('setIMtextMessage', JSON.stringify(textMessage) ); // console.log(store,'全局變量'); }, // 接收圖片 onPictureMessage: (message) => { let textMessage = { from: message.from, url: message.url, type: 'img' } store.dispatch('setIMtextMessage', JSON.stringify(textMessage)); console.log(message,'接收圖片'); }, // 收到表情信息 onEmojiMessage: function (message) { console.log(message, '接收表情'); // 接收到的是數組 let content = ''; message.data.forEach((item, index) => { if (item.type=='emoji') { //require不能轉動態參,先截取圖片名稱再拼接轉 let eeIndex = item.data.indexOf('ee_'); let img = item.data.substring(eeIndex, item.data.length); let path = require(`./../../../../../assets/images/faces/${img}`); content += `<img src="${path}" />` } else { content += item.data } }) let textMessage = { from: message.from, content: content, type: 'txt' } store.dispatch('setIMtextMessage', JSON.stringify(textMessage)); }, // 收到聯繫人訂閱請求、處理羣組、聊天室被踢解散等消息 onPresence: function (message) { }, // 處理好友申請 onRoster: function () { conn.getRoster({ success: function (roster) { let rosData = [] for (var i = 0, l = roster.length; i < l; i++) { if (roster[i].subscription === 'both') { rosData.push(roster[i]) console.log('處理好友申請') console.log(rosData) // store.dispatch('getFriendsData', rosData) } else { return } } } }) }, onAudioMessage: function (message) { console.log('當前關閉') }, // 收到音頻消息 onLocationMessage: function (message) { console.log('當前關閉') }, // 收到位置消息 onFileMessage: function (message) { console.log('當前關閉') }, // 收到文件消息 onVideoMessage: function (message) { console.log('當前關閉') }, // 收到視頻消息 onInviteMessage: function (message) { console.log('當前關閉') }, // 處理羣組邀請 onOnline: function () { console.log('當前關閉') }, // 本機網絡鏈接成功 onOffline: function () { console.log('當前關閉') }, // 本機網絡掉線 // 失敗回調 onError: function (message) { console.log(message) } }) /* const rtcCall = new WebIM.WebRTC.Call({ connection: conn, mediaStreamConstaints: { audio: true, video: true }, listener: { onAcceptCall: function (from, options) { // console.log('onAcceptCall::', 'from: ', from, 'options: ', options); }, onGotRemoteStream: function (stream, streamType) { // console.log('onGotRemoteStream::', 'stream: ', stream, 'streamType: ', streamType); }, onGotLocalStream: function (stream, streamType) { // console.log('onGotLocalStream::', 'stream:', stream, 'streamType: ', streamType); }, onRinging: function (caller) { let reg = /(?<=_).*(?=@)/ let callerId = (reg.exec(caller))[0] let curUser = [] let friends = store.state.data.friends for (let i in friends) { if (friends[i].username === callerId) { curUser = friends[i] } } console.log(curUser) // router.push({ path: '/calling', query: { user: curUser, curBtn: true } }) }, onTermCall: function (reason) { console.log('onTermCall::') console.log('reason:', reason) }, onIceConnectionStateChange: function (iceState) { if (iceState === 'closed') { // router.push({ path: '/friends' }) } }, onError: function (e) { console.log(e) } } }) */ // 須要註冊一個全局的WebIM 在hx-sdk中有須要用到 否則發送接收表情時會拋出異常 window.WebIM = WebIM export default { install: function (Vue, options) { // console.log(WebIM) Object.defineProperty(Vue.prototype, '$imConn', { value: conn }) Object.defineProperty(Vue.prototype, '$rtcCall', { value: rtcCall }) } }
5 .組件使用或者全局使用api
// main.js import IM from './utils/plugin/webim' Vue.use(IM)
6. 註冊 數組
根據用戶名/密碼/暱稱註冊環信 Web IM :服務器
webIMregister() { this.$imConn.open({ username: 'username', password: 'password', nickname: 'nickname', appKey: WebIM.config.appkey, apiUrl: WebIM.config.apiURL, success: function () { }, error: function () { }, }) },
7 .登陸網絡
// 登陸環信 webIMlogin () { this.$imConn.open({ apiUrl: WebIM.config.apiURL, user: this.userInfo.uuid, pwd: '123456', appKey: WebIM.config.appkey, success: function (token) { console.log('環信登陸成功'); }, error: function(){ } }) },
8.發送消息,圖片app
// 發送消息與表情圖同樣是發送文本 onSend () { this.ishowEmoji = false; let self = this; let id = this.$imConn.getUniqueId(); // 生成本地消息id let msg = new WebIM.message('txt', id); // 建立文本消息 msg.set({ msg: this.messageValue, // 消息內容 to: this.forumUserData.phone, // 接收消息對象(用戶id) roomType: false, success: function (id, serverMsgId) { self.chatContent.push({ // userLogo: self.userInfo.logoPath, msg: self.messageValue, from: self.userInfo.phoneMobile, msg_type: 'txt', timestamp:new Date().getTime(), isShowTime:self.timestampStatus() }); //處理表情已圖片展現 self.replace_em() //清空發送輸入框內容 self.messageValue = ''; }, // 對成功的相關定義,sdk會將消息id登記到日誌進行備份處理 fail: function(e){ console.log("Send private text error"); } // 對失敗的相關定義,sdk會將消息id登記到日誌進行備份處理 }); this.$imConn.send(msg.body); }, //發送圖片 sendImg (e) { this.ishowEmoji = false; let file = e.target.files[0]; let self = this; if(file) { let type = 'image/gif image/png image/jpeg image/jpg'; if(type.indexOf(file.type) != -1) { let id = this.$imConn.getUniqueId();// 生成本地消息id let msg = new WebIM.message('img', id);// 建立圖片消息 let imgFile = WebIM.utils.getFileUrl(this.$refs.imgFile); // 將圖片轉化爲二進制文件 let imgMsg = {}; let option = { apiUrl: WebIM.config.apiURL, file: imgFile, to: self.forumUserData.phone,// 接收消息對象 roomType: false, timestamp:new Date().getTime(), onFileUploadError: (error) => { // 消息上傳失敗 // console.log(error,'失敗'); }, onFileUploadComplete: img => { // 消息上傳成功 // console.log('onFileUploadComplete', img); imgMsg = { // userLogo: self.userInfo.logoPath, url: `${img.uri}/${img.entities[0].uuid}`, from: self.userInfo.phoneMobile, msg_type: 'img', timestamp:new Date().getTime(), isShowTime:self.timestampStatus() }; }, success: res => { // 消息發送成功 self.chatContent.push(imgMsg); //滾動條置底部 setTimeout(() => { document.getElementById('refresh-box').scrollTop = document.getElementById('refresh-box').scrollHeight + 50;//加50是由於還有發送輸入框 }, 100); // console.log('Success',res); }, flashUpload: WebIM.flashUpload }; msg.set(option); this.$imConn.send(msg.body); }else { alert('圖片上傳僅支持jpg、jpeg、png、gif格式'); return; } } }, //處理表情圖片展現, replace_em () { this.chatContent.forEach(item => { if(item.msg_type == 'txt') { let reg = new RegExp('\\[(.*?)\\]',"g"); item.msg = item.msg.replace(reg, (word) => { let emoji = WebIM.Emoji.map[word]; let img = word // let imgPath = `${WebIM.Emoji.path}${emoji}`; // require if(emoji) { let path = require('./../../../../../assets/images/faces/'+emoji); img = `<img src="${path}" />` } return img }); setTimeout(() => { document.getElementById('refresh-box').scrollTop = document.getElementById('refresh-box').scrollHeight + 50;//加50是由於還有發送輸入框 }, 100); } }) }, //處理是否要顯示時間狀態,返回true,false timestampStatus () { let data = this.chatContent[this.chatContent.length - 1]; //聊天列表的最後的一次數據 let isShowTime = false; if (data) { //判斷是否有上一次的聊天記錄, let startTime = new Date(data.timestamp); //上一次的記錄時間 let endTime = new Date().getTime(); //當前發送的時間 if (endTime-startTime>=180000) { //當前的時間大於上一次的時間3分鐘則顯示時間,不然不顯示 isShowTime = true; }else{ isShowTime = false } }else{ //沒有聊天記錄則是第一條聊天記錄顯示時間 isShowTime = true; } return isShowTime; }
接收消息存儲在vuex所有變量 ,在組件內監聽數據變化自行處理接收數據