Commit 03f0fcd0 authored by 罗超's avatar 罗超

实现消息显示

parent b139fbe4
......@@ -11,7 +11,8 @@ const BabiliWebpackPlugin = require('babili-webpack-plugin')
let mainConfig = {
entry: {
main: path.join(__dirname, '../src/main/index.js'),
sdk: path.join(__dirname, '../src/sdk/NIM_Web_SDK_v5.0.0')
sdk1: path.join(__dirname, '../src/sdk/NIM_Web_SDK_v6.1.0.js'),
sdk2: path.join(__dirname, '../src/sdk/NIM_Web_SDK_v5.8.0.js')
},
externals: [
...Object.keys(dependencies || {})
......
......@@ -24,7 +24,8 @@ let rendererConfig = {
devtool: '#cheap-module-eval-source-map',
entry: {
renderer: path.join(__dirname, '../src/renderer/main.js'),
sdk: path.join(__dirname, '../src/sdk/NIM_Web_SDK_v5.0.0')
sdk1: path.join(__dirname, '../src/sdk/NIM_Web_SDK_v6.1.0.js'),
sdk2: path.join(__dirname, '../src/sdk/NIM_Web_SDK_v5.8.0.js')
},
externals: [
...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d))
......
......@@ -42,6 +42,7 @@
"js-md5": "^0.6.0",
"moment": "^2.18.1",
"vue": "^2.3.3",
"vue-draggable-resizable": "^2.0.0-rc1",
"vue-electron": "^1.0.6",
"vue-qart": "^2.1.0",
"vue-router": "^2.5.3",
......
res/im/icons.png

10.6 KB | W: | H:

res/im/icons.png

17.9 KB | W: | H:

res/im/icons.png
res/im/icons.png
res/im/icons.png
res/im/icons.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -4,8 +4,8 @@ import config from './index'
let emojiBaseUrl = `http://yx-web.nosdn.127.net/webdoc/h5/emoji`
let emojiList = {
'emoji': {
'[大笑]': {file: 'emoji_0.png'}, '[可爱]': {file: 'emoji_01.png'}, '[色]': {file: 'emoji_02.png'}, '[嘘]': {file: 'emoji_03.png'}, '[亲]': {file: 'emoji_04.png'}, '[呆]': {file: 'emoji_05.png'}, '[口水]': {file: 'emoji_06.png'}, '[汗]': {file: 'emoji_145.png'}, '[呲牙]': {file: 'emoji_07.png'}, '[鬼脸]': {file: 'emoji_08.png'}, '[害羞]': {file: 'emoji_09.png'}, '[偷笑]': {file: 'emoji_10.png'}, '[调皮]': {file: 'emoji_11.png'}, '[可怜]': {file: 'emoji_12.png'}, '[敲]': {file: 'emoji_13.png'}, '[惊讶]': {file: 'emoji_14.png'}, '[流感]': {file: 'emoji_15.png'}, '[委屈]': {file: 'emoji_16.png'}, '[流泪]': {file: 'emoji_17.png'}, '[嚎哭]': {file: 'emoji_18.png'}, '[惊恐]': {file: 'emoji_19.png'}, '[怒]': {file: 'emoji_20.png'}, '[酷]': {file: 'emoji_21.png'}, '[不说]': {file: 'emoji_22.png'}, '[鄙视]': {file: 'emoji_23.png'}, '[阿弥陀佛]': {file: 'emoji_24.png'}, '[奸笑]': {file: 'emoji_25.png'}, '[睡着]': {file: 'emoji_26.png'}, '[口罩]': {file: 'emoji_27.png'}, '[努力]': {file: 'emoji_28.png'}, '[抠鼻孔]': {file: 'emoji_29.png'}, '[疑问]': {file: 'emoji_30.png'}, '[怒骂]': {file: 'emoji_31.png'}, '[晕]': {file: 'emoji_32.png'}, '[呕吐]': {file: 'emoji_33.png'}, '[拜一拜]': {file: 'emoji_160.png'}, '[惊喜]': {file: 'emoji_161.png'}, '[流汗]': {file: 'emoji_162.png'}, '[卖萌]': {file: 'emoji_163.png'}, '[默契眨眼]': {file: 'emoji_164.png'}, '[烧香拜佛]': {file: 'emoji_165.png'}, '[晚安]': {file: 'emoji_166.png'}, '[强]': {file: 'emoji_34.png'}, '[弱]': {file: 'emoji_35.png'}, '[OK]': {file: 'emoji_36.png'}, '[拳头]': {file: 'emoji_37.png'}, '[胜利]': {file: 'emoji_38.png'}, '[鼓掌]': {file: 'emoji_39.png'}, '[握手]': {file: 'emoji_200.png'}, '[发怒]': {file: 'emoji_40.png'}, '[骷髅]': {file: 'emoji_41.png'}, '[便便]': {file: 'emoji_42.png'}, '[火]': {file: 'emoji_43.png'}, '[溜]': {file: 'emoji_44.png'}, '[爱心]': {file: 'emoji_45.png'}, '[心碎]': {file: 'emoji_46.png'}, '[钟情]': {file: 'emoji_47.png'}, '[唇]': {file: 'emoji_48.png'}, '[戒指]': {file: 'emoji_49.png'}, '[钻石]': {file: 'emoji_50.png'}, '[太阳]': {file: 'emoji_51.png'}, '[有时晴]': {file: 'emoji_52.png'}, '[多云]': {file: 'emoji_53.png'}, '[雷]': {file: 'emoji_54.png'}, '[雨]': {file: 'emoji_55.png'}, '[雪花]': {file: 'emoji_56.png'}, '[爱人]': {file: 'emoji_57.png'}, '[帽子]': {file: 'emoji_58.png'}, '[皇冠]': {file: 'emoji_59.png'}, '[篮球]': {file: 'emoji_60.png'}, '[足球]': {file: 'emoji_61.png'}, '[垒球]': {file: 'emoji_62.png'}, '[网球]': {file: 'emoji_63.png'}, '[台球]': {file: 'emoji_64.png'}, '[咖啡]': {file: 'emoji_65.png'}, '[啤酒]': {file: 'emoji_66.png'}, '[干杯]': {file: 'emoji_67.png'}, '[柠檬汁]': {file: 'emoji_68.png'}, '[餐具]': {file: 'emoji_69.png'}, '[汉堡]': {file: 'emoji_70.png'}, '[鸡腿]': {file: 'emoji_71.png'}, '[面条]': {file: 'emoji_72.png'}, '[冰淇淋]': {file: 'emoji_73.png'}, '[沙冰]': {file: 'emoji_74.png'}, '[生日蛋糕]': {file: 'emoji_75.png'}, '[蛋糕]': {file: 'emoji_76.png'}, '[糖果]': {file: 'emoji_77.png'}, '[葡萄]': {file: 'emoji_78.png'}, '[西瓜]': {file: 'emoji_79.png'}, '[光碟]': {file: 'emoji_80.png'}, '[手机]': {file: 'emoji_81.png'}, '[电话]': {file: 'emoji_82.png'}, '[电视]': {file: 'emoji_83.png'}, '[声音开启]': {file: 'emoji_84.png'}, '[声音关闭]': {file: 'emoji_85.png'}, '[铃铛]': {file: 'emoji_86.png'}, '[锁头]': {file: 'emoji_87.png'}, '[放大镜]': {file: 'emoji_88.png'}, '[灯泡]': {file: 'emoji_89.png'}, '[锤头]': {file: 'emoji_90.png'}, '[烟]': {file: 'emoji_91.png'}, '[炸弹]': {file: 'emoji_92.png'}, '[枪]': {file: 'emoji_93.png'}, '[刀]': {file: 'emoji_94.png'}, '[药]': {file: 'emoji_95.png'}, '[打针]': {file: 'emoji_96.png'}, '[钱袋]': {file: 'emoji_97.png'}, '[钞票]': {file: 'emoji_98.png'}, '[银行卡]': {file: 'emoji_99.png'}, '[手柄]': {file: 'emoji_100.png'}, '[麻将]': {file: 'emoji_101.png'}, '[调色板]': {file: 'emoji_102.png'}, '[电影]': {file: 'emoji_103.png'}, '[麦克风]': {file: 'emoji_104.png'}, '[耳机]': {file: 'emoji_105.png'}, '[音乐]': {file: 'emoji_106.png'}, '[吉他]': {file: 'emoji_107.png'}, '[火箭]': {file: 'emoji_108.png'}, '[飞机]': {file: 'emoji_109.png'}, '[火车]': {file: 'emoji_110.png'}, '[公交]': {file: 'emoji_111.png'}, '[轿车]': {file: 'emoji_112.png'}, '[出租车]': {file: 'emoji_113.png'}, '[警车]': {file: 'emoji_114.png'}, '[自行车]': {file: 'emoji_115.png'}
"emoji": {
"[大笑]":{file:"emoji_0.png"},"[可爱]":{file:"emoji_01.png"},"[色]":{file:"emoji_02.png"},"[嘘]":{file:"emoji_03.png"},"[亲]":{file:"emoji_04.png"},"[呆]":{file:"emoji_05.png"},"[口水]":{file:"emoji_06.png"},"[汗]":{file:"emoji_145.png"},"[呲牙]":{file:"emoji_07.png"},"[鬼脸]":{file:"emoji_08.png"},"[害羞]":{file:"emoji_09.png"},"[偷笑]":{file:"emoji_10.png"},"[调皮]":{file:"emoji_11.png"},"[可怜]":{file:"emoji_12.png"},"[敲]":{file:"emoji_13.png"},"[惊讶]":{file:"emoji_14.png"},"[流感]":{file:"emoji_15.png"},"[委屈]":{file:"emoji_16.png"},"[流泪]":{file:"emoji_17.png"},"[嚎哭]":{file:"emoji_18.png"},"[惊恐]":{file:"emoji_19.png"},"[怒]":{file:"emoji_20.png"},"[酷]":{file:"emoji_21.png"},"[不说]":{file:"emoji_22.png"},"[鄙视]":{file:"emoji_23.png"},"[阿弥陀佛]":{file:"emoji_24.png"},"[奸笑]":{file:"emoji_25.png"},"[睡着]":{file:"emoji_26.png"},"[口罩]":{file:"emoji_27.png"},"[努力]":{file:"emoji_28.png"},"[抠鼻孔]":{file:"emoji_29.png"},"[疑问]":{file:"emoji_30.png"},"[怒骂]":{file:"emoji_31.png"},"[晕]":{file:"emoji_32.png"},"[呕吐]":{file:"emoji_33.png"},"[拜一拜]":{file:"emoji_160.png"},"[惊喜]":{file:"emoji_161.png"},"[流汗]":{file:"emoji_162.png"},"[卖萌]":{file:"emoji_163.png"},"[默契眨眼]":{file:"emoji_164.png"},"[烧香拜佛]":{file:"emoji_165.png"},"[晚安]":{file:"emoji_166.png"},"[强]":{file:"emoji_34.png"},"[弱]":{file:"emoji_35.png"},"[OK]":{file:"emoji_36.png"},"[拳头]":{file:"emoji_37.png"},"[胜利]":{file:"emoji_38.png"},"[鼓掌]":{file:"emoji_39.png"},"[握手]":{file:"emoji_200.png"},"[发怒]":{file:"emoji_40.png"},"[骷髅]":{file:"emoji_41.png"},"[便便]":{file:"emoji_42.png"},"[火]":{file:"emoji_43.png"},"[溜]":{file:"emoji_44.png"},"[爱心]":{file:"emoji_45.png"},"[心碎]":{file:"emoji_46.png"},"[钟情]":{file:"emoji_47.png"},"[唇]":{file:"emoji_48.png"},"[戒指]":{file:"emoji_49.png"},"[钻石]":{file:"emoji_50.png"},"[太阳]":{file:"emoji_51.png"},"[有时晴]":{file:"emoji_52.png"},"[多云]":{file:"emoji_53.png"},"[雷]":{file:"emoji_54.png"},"[雨]":{file:"emoji_55.png"},"[雪花]":{file:"emoji_56.png"},"[爱人]":{file:"emoji_57.png"},"[帽子]":{file:"emoji_58.png"},"[皇冠]":{file:"emoji_59.png"},"[篮球]":{file:"emoji_60.png"},"[足球]":{file:"emoji_61.png"},"[垒球]":{file:"emoji_62.png"},"[网球]":{file:"emoji_63.png"},"[台球]":{file:"emoji_64.png"},"[咖啡]":{file:"emoji_65.png"},"[啤酒]":{file:"emoji_66.png"},"[干杯]":{file:"emoji_67.png"},"[柠檬汁]":{file:"emoji_68.png"},"[餐具]":{file:"emoji_69.png"},"[汉堡]":{file:"emoji_70.png"},"[鸡腿]":{file:"emoji_71.png"},"[面条]":{file:"emoji_72.png"},"[冰淇淋]":{file:"emoji_73.png"},"[沙冰]":{file:"emoji_74.png"},"[生日蛋糕]":{file:"emoji_75.png"},"[蛋糕]":{file:"emoji_76.png"},"[糖果]":{file:"emoji_77.png"},"[葡萄]":{file:"emoji_78.png"},"[西瓜]":{file:"emoji_79.png"},"[光碟]":{file:"emoji_80.png"},"[手机]":{file:"emoji_81.png"},"[电话]":{file:"emoji_82.png"},"[电视]":{file:"emoji_83.png"},"[声音开启]":{file:"emoji_84.png"},"[声音关闭]":{file:"emoji_85.png"},"[铃铛]":{file:"emoji_86.png"},"[锁头]":{file:"emoji_87.png"},"[放大镜]":{file:"emoji_88.png"},"[灯泡]":{file:"emoji_89.png"},"[锤头]":{file:"emoji_90.png"},"[烟]":{file:"emoji_91.png"},"[炸弹]":{file:"emoji_92.png"},"[枪]":{file:"emoji_93.png"},"[刀]":{file:"emoji_94.png"},"[药]":{file:"emoji_95.png"},"[打针]":{file:"emoji_96.png"},"[钱袋]":{file:"emoji_97.png"},"[钞票]":{file:"emoji_98.png"},"[银行卡]":{file:"emoji_99.png"},"[手柄]":{file:"emoji_100.png"},"[麻将]":{file:"emoji_101.png"},"[调色板]":{file:"emoji_102.png"},"[电影]":{file:"emoji_103.png"},"[麦克风]":{file:"emoji_104.png"},"[耳机]":{file:"emoji_105.png"},"[音乐]":{file:"emoji_106.png"},"[吉他]":{file:"emoji_107.png"},"[火箭]":{file:"emoji_108.png"},"[飞机]":{file:"emoji_109.png"},"[火车]":{file:"emoji_110.png"},"[公交]":{file:"emoji_111.png"},"[轿车]":{file:"emoji_112.png"},"[出租车]":{file:"emoji_113.png"},"[警车]":{file:"emoji_114.png"},"[自行车]":{file:"emoji_115.png"}
}
}
......@@ -18,21 +18,21 @@ for (let emoji in emojiList) {
}
let pinupList = {
'ajmd': {},
'ajmd':{},
'xxy': {},
'lt': {}
}
for (let i = 1; i <= 48; i++) {
let key = 'ajmd0' + (i >= 10 ? i : '0' + i)
let key = 'ajmd0'+ (i >= 10 ? i: '0' + i)
pinupList['ajmd'][key] = {file: key + '.png'}
}
for (let i = 1; i <= 40; i++) {
let key = 'xxy0' + (i >= 10 ? i : '0' + i)
let key = 'xxy0'+ (i >= 10 ? i: '0' + i)
pinupList['xxy'][key] = {file: key + '.png'}
}
for (let i = 1; i <= 20; i++) {
let key = 'lt0' + (i >= 10 ? i : '0' + i)
let key = 'lt0'+ (i >= 10 ? i: '0' + i)
pinupList['lt'][key] = {file: key + '.png'}
}
......@@ -47,4 +47,4 @@ for (let emoji in pinupList) {
export default {
emojiList,
pinupList
}
}
\ No newline at end of file
let config = {
sdk: 'NIM_Web_SDK_v5.0.0',
sdk: 'NIM_Web_SDK_v6.1.0',
// 用户自定义的登录注册地址
loginUrl: '/webdemo/h5/login.html',
registUrl: '/webdemo/h5/regist.html',
......@@ -11,12 +11,17 @@ let config = {
logo: 'http://yx-web.nos.netease.com/webdoc/h5/im/logo.png',
// 默认用户头像
defaultUserIcon: 'http://yx-web.nos.netease.com/webdoc/h5/im/default-icon.png',
// 默认普通群头像
defaultGroupIcon: 'http://yx-web.nos.netease.com/webdoc/h5/im/default-group.png',
// 默认高级群头像
defaultAdvancedIcon: 'http://yx-web.nos.netease.com/webdoc/h5/im/default-advanced.png',
// 系统通知图标
noticeIcon: 'http://yx-web.nos.netease.com/webdoc/h5/im/notice-icon.png',
// 我的手机图标
myPhoneIcon: 'http://yx-web.nos.netease.com/webdoc/h5/im/my-phone.png',
// 本地消息显示数量,会影响性能
localMsglimit: 36
localMsglimit: 36,
useDb: false
}
const env = 'online'
......
......@@ -26,6 +26,7 @@ global.ISCUSTOM = false
let updateTimer
let loginWindow
let mainWindow
let hideWindow
let appIcon = null
let isLogin = false
let timeout = null
......@@ -134,6 +135,10 @@ function createWindow () {
}
getLoginWindow()
getMainWinodw(1)
mainWindow.onbeforeunload = (e) => {
mainWindow.hide()
e.returnValue = false
}
mainWindow.webContents.session.on('will-download', (event, item, webContents) => {
const totalBytes = item.getTotalBytes()
let pathAll = folderpath + `\\` + downloadname
......@@ -243,11 +248,11 @@ function createWindow () {
}
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
// app.on('window-all-closed', () => {
// if (process.platform !== 'darwin') {
// app.quit()
// }
// })
app.on('activate', () => {
if (loginWindow === null) {
createWindow()
......@@ -586,11 +591,31 @@ let getMainWinodw=function(isLoad){
minWidth:800,
minHeight:580
})
mainWindow.on('close', (e) => {
mainWindow.hide()
e.preventDefault()
})
}
if(isLoad==0){
mainWindow.loadURL(mainUrl)
mainWindow.once('ready-to-show', () => {
mainWindow.show()
})
}
}
//加载隐藏窗口防止用户关闭
if(!hideWindow || hideWindow.isDestroyed()){
hideWindow = new BrowserWindow({
transparent: true,
frame: false,
maximizable: false,
resizable: true,
show: false,
height: 1,
width: 1,
icon: windowIcon
})
hideWindow.setSkipTaskbar(true)
hideWindow.webContents.closeDevTools()
}
}
var WORKER_ENABLED = !!(global === global.window && global.URL && global.Blob && global.Worker);
function InlineWorker(func, self) {
var _this = this;
var functionBody;
self = self || {};
if (WORKER_ENABLED) {
functionBody = func.toString().trim().match(
/^function\s*\w*\s*\([\w\s,]*\)\s*{([\w\W]*?)}$/
)[1];
return new global.Worker(global.URL.createObjectURL(
new global.Blob([ functionBody ], { type: "text/javascript" })
));
}
function postMessage(data) {
setTimeout(function() {
_this.onmessage({ data: data });
}, 0);
}
this.self = self;
this.self.postMessage = postMessage;
setTimeout(func.bind(self, self), 0);
}
InlineWorker.prototype.postMessage = function postMessage(data) {
var _this = this;
setTimeout(function() {
_this.self.onmessage({ data: data });
}, 0);
};
module.exports = InlineWorker;
This diff is collapsed.
import { ToastPlugin } from 'vux'
const MyToastPlugin = Object.create(null)
MyToastPlugin.install = function (Vue) {
Vue.use(ToastPlugin)
// 此方法基于vux的ToastPlugin,需确保注册ToastPlugin插件,否则以alert进行提示。
Vue.prototype.$toast = function (msg) {
if (this.$vux.toast) {
this.$vux.toast.show({
type: 'text',
text: msg,
position: 'middle'
})
} else {
alert(msg)
}
}
}
export default MyToastPlugin
\ No newline at end of file
/* 此插件的设计仅是因为vue-touch官方还不支持vue 2.0 所做的过渡方案 */
/*
* 使用方法:
* 1. 注册插件
* - import VueTouch from './plugins/touchEvent'
* - Vue.use(VueTouch)
* 2. 侦听事件
* - <span v-touch:hold="func"></span>
* - 触摸方法: hold(长按) tap(短按) swiperight(右划) swipeleft(左划) swipetop swipedown
* - 绑定参数: dom节点的data-set属性
*/
import Vue from 'vue'
const TouchEventPlugin = Object.create(null)
TouchEventPlugin.install = function (Vue) {
// 添加全局资源
Vue.directive('touch', {
//传入的模式 hold swiperight swipeleft swipetop swipedown tap
bind: function (el, binding, vnode) {
// Vue 编译生成的虚拟节点
// vnode = (vnode && vnode.data && vnode.data.attrs) || {}
vnode = vnode || {}
// 传给指令的参数。例如 v-touch:swipeRight, arg 的值是 "swipeRight"
let touchType = binding.arg.toLowerCase()
var timeOutEvent = 0
var direction = ''
//滑动处理
var startX = null
var startY = null
//返回角度
function GetSlideAngle(dx, dy) {
return Math.atan2(dy, dx) * 180 / Math.PI
}
//根据起点和终点返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑动
function GetSlideDirection (startX, startY, endX, endY) {
let dy = startY - endY
let dx = endX - startX
let result = 0
//如果滑动距离太短
if (Math.abs(dx) < 2 && Math.abs(dy) < 2) {
return result
}
let angle = GetSlideAngle(dx, dy)
if (angle >= -45 && angle < 45) {
result = 'swiperight'
} else if (angle >= 45 && angle < 135) {
result = 'swipeup'
} else if (angle >= -135 && angle < -45) {
result = 'swipedown'
} else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
result = 'swipeleft'
}
return result
}
el.addEventListener('touchstart', function (ev) {
startX = ev.touches[0].pageX
startY = ev.touches[0].pageY
//判断长按
timeOutEvent = setTimeout(() => {
timeOutEvent = 0
if (touchType === 'hold'){
binding.value(vnode)
}
} , 800)
}, false)
el.addEventListener('touchmove' , function (ev) {
if (timeOutEvent) {
clearTimeout(timeOutEvent)
timeOutEvent = 0
}
})
el.addEventListener('touchend', function (ev) {
if (timeOutEvent) {
clearTimeout(timeOutEvent)
timeOutEvent = 0
}
let endX = ev.changedTouches[0].pageX
let endY = ev.changedTouches[0].pageY
direction = GetSlideDirection(startX, startY, endX, endY)
switch (direction) {
case 0:
if (touchType === 'tap'){
binding.value(vnode)
}
break
case 'swipeup':
if (touchType === 'swipeup'){
binding.value(vnode)
}
break
case 'swipedown':
if (touchType === 'swipedown'){
binding.value(vnode)
}
break
case 'swipeleft':
if (touchType === 'swipeleft'){
binding.value(vnode)
}
break
case 'swiperight':
if (touchType === 'swiperight'){
binding.value(vnode)
}
break
default:
break
}
}, false)
}
})
}
export default TouchEventPlugin
\ No newline at end of file
<style>
@import url('./assets/css/font.css');
@import url('./assets/css/global.css');
@import url('//at.alicdn.com/t/font_1062339_sosklwlszu.css');
@import url('//at.alicdn.com/t/font_1062339_xxfkedot0lp.css');
</style>
......
......@@ -49,4 +49,23 @@ button{
}
.cursor-pointer{
cursor: pointer;
}
\ No newline at end of file
}
*::-webkit-scrollbar{
width: 4px;
height: 4px;
}
*::-webkit-scrollbar-track{
background-color: #F5F5F5;
}
*::-webkit-scrollbar-thumb{
border-radius: 20px;
background-color: rgba(0,0,0,0);
margin-bottom: 24px;
}
*:hover::-webkit-scrollbar-thumb{
background-color: rgba(0,0,0,.2);
}
/* *:hover::-webkit-scrollbar{
width: 4px;
height: 4px;
} */
......@@ -40,12 +40,19 @@
</div>
</div>
</div>
<div class="contentarea">
<msg :user=user></msg>
</div>
</div>
</div>
</transition>
</template>
<script>
import msg from './msssage/index'
export default {
components: {
msg
},
data() {
return {
user: {},
......@@ -54,6 +61,7 @@ export default {
val: 0,
name: "消息"
},
noticeObj:{},
isMaxed: false
};
},
......@@ -170,12 +178,12 @@ export default {
bottom: 0px;
top: 0px;
right: 0px;
background: #f1f1f1;
background: #f9f9f9;
box-sizing: border-box;
}
.homebox .rightPannel .navtool {
height: 40px;
box-shadow: 1px 2px 8px 0px rgba(0, 0, 0, 0.08);
box-shadow: 1px 2px 8px 0px rgba(0, 0, 0, .1);
display: flex;
-webkit-app-region: drag !important;
}
......@@ -222,4 +230,12 @@ export default {
.opera__item.min:hover {
background: rgba(0, 0, 0, 0.1);
}
.homebox .rightPannel .contentarea{
position:absolute;
top: 40px;
z-index: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>
<template>
<div>
<div class="messagehead">
<span class="objname">{{sessionName}}</span>
<div class="rightOperabox">
<i class="iconfont icongengduo"></i>
</div>
</div>
<div class="messagecontent" :style="{'bottom':(consoleinfo.currenth+1)+'px'}">
<div class="invalidHint" v-if="scene==='team' && teamInvalid">
<span>{{`您已退出该${teamInfo && teamInfo.type==='normal' ? '讨论组':'群'}`}}</span>
</div>
<chat-list
type="session"
:msglist="msglist"
:userInfos="userInfos"
:myInfo="myInfo"
:isRobot="isRobot"
@msgs-loaded="msgsLoaded"
></chat-list>
</div>
<VueDraggableResizable
class-name="sendconsole"
:draggable="false"
:min-height="consoleinfo.minh"
:max-height="consoleinfo.maxh"
:handles="['tm']"
@resizing="onResizing"
:h="consoleinfo.currenth"
:resizable="true"
:active="true"
></VueDraggableResizable>
</div>
</template>
<script>
import util from "../../../utils";
import pageUtil from "../../../utils/page";
import VueDraggableResizable from "vue-draggable-resizable";
import "vue-draggable-resizable/dist/VueDraggableResizable.css";
import chatList from './chatlist'
export default {
props: {
id: {
type: String,
default: ""
}
},
components: {
VueDraggableResizable,
chatList
},
data() {
return {
consoleinfo: {
minh: 130,
maxh: 350,
currenth: 130
}
};
},
updated() {
pageUtil.scrollChatListDown();
},
destroyed() {
this.$store.dispatch("resetCurrSession");
},
mounted() {
//获取记录的操作区域高度
if (localStorage.consoleh && localStorage.consoleh != "") {
this.consoleinfo.currenth = parseInt(localStorage.consoleh);
}
setTimeout(() => {
this.$store.dispatch("hideLoading");
}, 1000);
},
computed: {
sessionId() {
let sessionId = this.id;
this.$store.dispatch("showLoading");
// 此时设置当前会话
this.$store.dispatch("setCurrSession", sessionId);
pageUtil.scrollChatListDown();
return sessionId;
},
sessionName() {
let sessionId = this.sessionId;
let user = null;
if (/^p2p-/.test(sessionId)) {
user = sessionId.replace(/^p2p-/, "");
if (user === this.$store.state.userUID) {
return "我的手机";
} else if (this.isRobot) {
return this.robotInfos[user].nick;
} else {
let userInfo = this.userInfos[user] || {};
return util.getFriendAlias(userInfo);
}
} else if (/^team-/.test(sessionId)) {
var teamMembers = this.$store.state.teamMembers[this.to];
if (
teamMembers === undefined ||
teamMembers.length < this.teamInfo.memberNum
) {
this.$store.dispatch("getTeamMembers", this.to);
}
if (this.teamInfo) {
// teamInfo中的人数为初始获取的值,在人员增减后不会及时更新,而teamMembers在人员增减后同步维护的人员信息
var members =
this.$store.state.teamMembers &&
this.$store.state.teamMembers[this.teamInfo.teamId];
var memberCount = members && members.length;
return this.teamInfo.name + (memberCount ? `(${memberCount})` : "");
} else {
return "群";
}
}
},
scene() {
return util.parseSession(this.sessionId).scene;
},
to() {
return util.parseSession(this.sessionId).to;
},
// 判断是否是机器人
isRobot() {
let sessionId = this.sessionId;
let user = null;
if (/^p2p-/.test(sessionId)) {
user = sessionId.replace(/^p2p-/, "");
if (this.robotInfos[user]) {
return true;
}
}
return false;
},
myInfo() {
return this.$store.state.myInfo;
},
userInfos() {
return this.$store.state.userInfos;
},
robotInfos() {
return this.$store.state.robotInfos;
},
msglist() {
let msgs = this.$store.state.currSessionMsgs;
return msgs;
},
teamInfo() {
if (this.scene === "team") {
var teamId = this.sessionId.replace("team-", "");
return this.$store.state.teamlist.find(team => {
return team.teamId === teamId;
});
}
return undefined;
},
muteInTeam() {
if (this.scene !== "team") return false;
var teamMembers = this.$store.state.teamMembers;
var Members = teamMembers && teamMembers[this.teamInfo.teamId];
var selfInTeam =
Members &&
Members.find(item => {
return item.account === this.$store.state.userUID;
});
return (selfInTeam && selfInTeam.mute) || false;
},
teamInvalid() {
if (this.scene === "team") {
return !(this.teamInfo && this.teamInfo.validToCurrentUser);
}
return false;
},
sendInvalidHint() {
if (this.scene === "team" && this.teamInvalid) {
return `您已不在该${
this.teamInfo && this.teamInfo.type === "normal" ? "讨论组" : "群"
},不能发送消息`;
} else if (this.muteInTeam) {
return "您已被禁言";
}
return "无权限发送消息";
}
},
methods: {
onResizing(x, y, w, h) {
localStorage.consoleh = h;
this.consoleinfo.currenth = h;
},
onClickBack () {
// location.href = '#/contacts'
window.stopPlayAudio && window.stopPlayAudio()
window.history.go(-1)
},
msgsLoaded () {
pageUtil.scrollChatListDown()
},
enterNameCard () {
if (/^p2p-/.test(this.sessionId)) {
let account = this.sessionId.replace(/^p2p-/, '')
if (account === this.$store.state.userUID) {
location.href = `#/general`
return
}
location.href = `#/namecard/${account}`
}
},
onTeamManageClick() {
if (this.teamInfo && this.teamInfo.validToCurrentUser) {
location.href = `#/teammanage/${this.teamInfo.teamId}`
} else {
this.$toast('您已退出该群')
}
},
onHistoryClick() {
if (this.scene!=='team' || (this.teamInfo && this.teamInfo.validToCurrentUser)) {
location.href = `#/chathistory/${this.sessionId}`
} else {
this.$toast('您已退出该群')
}
}
}
};
</script>
<style>
.msgbox .messagebox .messagehead {
height: 46px;
line-height: 46px;
padding-left: 20px;
border-bottom: 1px solid #ddd;
position: relative;
}
.msgbox .messagebox .messagehead .objname {
font-size: 24px;
color: #333;
}
.msgbox .messagebox .messagehead .rightOperabox {
height: 46px;
line-height: 46px;
width: 46px;
text-align: center;
position: absolute;
right: 0;
top: 0;
cursor: pointer;
}
.msgbox .messagebox .messagehead .rightOperabox i {
font-size: 4px;
color: #aaa;
}
.msgbox .messagebox .sendconsole {
position: absolute;
bottom: 0;
min-height: 130px;
left: 0;
right: 0;
border-top: 1px solid #ddd;
top: unset !important;
width: 100% !important;
}
.msgbox .messagebox .messagecontent {
position: absolute;
top: 47px;
left: 0;
right: 0;
overflow: auto;
background: #f1f1f1;
padding: 20px;
box-sizing: border-box;
}
.msgbox .messagebox .messagecontent .invalidHint {
text-align: center;
}
.msgbox .messagebox .messagecontent .invalidHint span {
height: 22px;
background: rgba(0, 0, 0, 0.15);
border-radius: 6px;
line-height: 22px;
color: #fff;
font-size: 12px;
display: inline-block;
margin: 0 auto;
padding: 0 6px;
}
.handle-tm {
top: -5px;
left: 0;
/* margin-left: -5px; */
cursor: n-resize;
width: 100%;
background: transparent;
border: none;
}
</style>
This diff is collapsed.
<template>
<ul id="chat-list" class="chat__list">
<li class="u-msg item-time more" v-if="canLoadMore">
<i class="iconfont icon3lishi"></i>点击加载更多
</li>
<chat-item
v-for="(msg, index) in msglist"
:type="type"
:rawMsg="msg"
:isRobot="isRobot"
:userInfos="userInfos"
:myInfo="myInfo"
:key="(msg.idClient || index)"
:isHistory="isHistory"
@msg-loaded="msgLoaded"
></chat-item>
<!-- <li class="u-msg item-time none" v-else>已无更多记录</li> -->
</ul>
</template>
<script>
import util from "../../../utils";
import config from "../../../configs";
import emojiObj from "../../../configs/emoji";
import chatItem from "./chatitem";
export default {
components: {
chatItem
},
data() {
return {
msgLoadedTimer: null
};
},
props: {
type: String,
canLoadMore: [String, Boolean],
isRobot: {
type: Boolean,
default() {
return false;
}
},
msglist: {
type: Array,
default() {
return [];
}
},
userInfos: {
type: Object,
default() {
return {};
}
},
myInfo: {
type: Object,
default() {
return {};
}
},
isHistory: {
type: Boolean,
default() {
return false;
}
}
// robotInfos: {
// type: Object,
// default () {
// return {}
// }
// }
},
methods: {
msgLoaded() {
clearTimeout(this.msgLoadedTimer);
this.msgLoadedTimer = setTimeout(() => {
this.$emit("msgs-loaded");
}, 20);
}
}
};
</script>
<style>
.chat__list {
width: 100%;
box-sizing: border-box;
margin: 0;
padding: 0;
}
.chat__list li {
list-style: none;
margin: 0;
padding: 0;
margin-bottom: 12px;
}
.chat__list .u-msg {
margin-bottom: 12px;
}
.chat__list .u-msg.item-time {
color: #2d98da;
font-size: 12px;
text-align: center;
}
.chat__list .u-msg.item-time i {
margin-right: 5px;
font-size: 13px;
}
.chat__list .u-msg.item-time.more {
cursor: pointer;
}
</style>
This diff is collapsed.
......@@ -3,7 +3,7 @@ import axios from 'axios'
import App from './App'
import router from './router'
// import store from './store'
import store from '../store'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
......@@ -26,6 +26,6 @@ Vue.prototype.$encrypt = encrypt
new Vue({
components: { App },
router,
// store,
store,
template: '<App/>'
}).$mount('#app')
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* 黑名单及静音列表
*/
import store from '../'
// 完成添加/删除黑名单,初始化获取黑名单列表,都会触发此函数
export function onBlacklist (blacks) {
blacks = blacks.map(item => {
if (typeof item.isBlack !== 'boolean') {
item.isBlack = true
}
return item
})
// 更新黑名单列表
store.commit('updateBlacklist', blacks)
// 在好友身上打上标记
store.commit('updateFriends', blacks)
// 更新好友信息字典
store.commit('updateUserInfo', blacks)
}
export function onMarkInBlacklist (obj) {
obj = obj || obj2
let account = obj.account
// 说明是自己,被别人加入黑名单
if (account === store.state.userUID) {
} else {
// 说明是别人的帐号,黑名单通知
if (typeof obj.isAdd === 'boolean') {
onBlacklist([{
account,
isBlack: obj.isAdd
}])
}
}
}
export function updateBlack ({state}, {account, isBlack}) {
const nim = state.nim
if (account && (typeof isBlack === 'boolean')) {
nim.markInBlacklist({
account,
// `true`表示加入黑名单, `false`表示从黑名单移除
isAdd: isBlack,
done: function (error, obj) {
if (error) {
alert(error)
return
}
onMarkInBlacklist(obj)
}
})
}
}
\ No newline at end of file
import store from '../'
import config from '../../configs'
// 用于demo记录封面
export function initChatroomInfos ({state, commit}, obj) {
commit('initChatroomInfos', obj)
}
export function getChatroomInfo ({state, commit, dispatch}) {
const chatroom = state.currChatroom
if (chatroom) {
chatroom.getChatroom({
done: function getChatroomDone (error, info) {
if (error) {
alert(error.message)
return
}
info = info.chatroom || {creator: ''}
let creator = info.creator
chatroom.getChatroomMembersInfo({
accounts: [creator],
done: function getChatroomMembersInfoDone (error, user) {
if (error) {
alert(error.message)
return
}
commit('getChatroomInfo', Object.assign(info, {actor: user.members[0]}))
}
})
}
})
}
}
export function getChatroomMembers ({state, commit, dispatch}) {
// 先拉管理员
getChatroomMembersLocal (false, function (obj) {
commit('updateChatroomMembers', Object.assign(obj, {type: 'put'}))
// 再拉成员列表
getChatroomMembersLocal (true, function (obj) {
commit('updateChatroomMembers', Object.assign(obj, {type: 'put'}))
})
})
}
function getChatroomMembersLocal (isGuest, callback) {
const chatroom = store.state.currChatroom
if (chatroom) {
chatroom.getChatroomMembers({
guest: isGuest,
limit: 100,
done: function getChatroomMembersDone (error, obj) {
if (error) {
alert(error.message)
return
}
callback(obj)
}
})
}
}
export function clearChatroomMembers ({state, commit}) {
commit('updateChatroomMembers', {type: 'destroy'})
}
\ No newline at end of file
import store from '../'
import config from '../../configs'
import util from '../../utils'
import {formatMsg} from './msgs'
export function onChatroomMsgs (msgs) {
if (!Array.isArray(msgs)) {
msgs = [msgs]
}
msgs = msgs.map(msg => {
return formatMsg(msg)
})
if (store.state.currChatroomId) {
store.commit('updateCurrChatroomMsgs', {
type: 'put',
msgs
})
}
}
function onSendMsgDone (error, msg) {
store.dispatch('hideLoading')
if (error) {
alert(error.message)
return
}
onChatroomMsgs([msg])
}
export function sendChatroomMsg ({state, commit}, obj) {
const chatroom = state.currChatroom
obj = obj || {}
let type = obj.type || ''
store.dispatch('showLoading')
switch (type) {
case 'text':
chatroom.sendText({
text: obj.text,
done: onSendMsgDone
})
break
case 'custom':
chatroom.sendCustomMsg({
content: JSON.stringify(obj.content),
pushContent: obj.pushContent,
done: onSendMsgDone
})
}
}
export function sendChatroomRobotMsg ({state, commit}, obj) {
const chatroom = state.currChatroom
let {type, robotAccid, content, params, target, body} = obj
if (type === 'text') {
chatroom.sendRobotMsg({
robotAccid,
content: {
type: 'text',
content,
},
body,
done: onSendMsgDone
})
} else if (type === 'welcome') {
chatroom.sendRobotMsg({
robotAccid,
content: {
type: 'welcome',
},
body,
done: onSendMsgDone
})
} else if (type === 'link') {
chatroom.sendRobotMsg({
robotAccid,
content: {
type: 'link',
params,
target
},
body,
done: onSendMsgDone
})
}
}
export function sendChatroomFileMsg ({state, commit}, obj) {
const chatroom = state.currChatroom
let {fileInput} = Object.assign({}, obj)
let type = 'file'
if (/\.(png|jpg|bmp|jpeg|gif)$/i.test(fileInput.value)) {
type = 'image'
} else if (/\.(mov|mp4|ogg|webm)$/i.test(fileInput.value)) {
type = 'video'
}
store.dispatch('showLoading')
chatroom.sendFile({
type,
fileInput,
uploadprogress: function (data) {
// console.log(data.percentageText)
},
uploaderror: function () {
fileInput.value = ''
console && console.log('上传失败')
},
uploaddone: function(error, file) {
fileInput.value = ''
// console.log(error);
// console.log(file);
},
beforesend: function (msg) {
// console && console.log('正在发送消息, id=', msg);
},
done: function (error, msg) {
onSendMsgDone (error, msg)
}
})
}
export function getChatroomHistoryMsgs ({state, commit}, obj) {
const chatroom = state.currChatroom
if (chatroom) {
let {timetag} = Object.assign({}, obj)
let options = {
timetag,
limit: config.localMsglimit || 20,
done: function getChatroomHistoryMsgsDone (error, obj) {
if (obj.msgs) {
if (obj.msgs.length === 0) {
commit('setNoMoreHistoryMsgs')
} else {
let msgs = obj.msgs.map(msg => {
return formatMsg(msg)
})
commit('updateCurrChatroomMsgs', {
type: 'concat',
msgs
})
}
}
store.dispatch('hideLoading')
}
}
store.dispatch('showLoading')
nim.getHistoryMsgs(options)
}
}
/*
* 用户关系及好友关系托管
*/
import store from '../'
import { formatUserInfo } from './userInfo'
// 好友关系,回调
export function onFriends (friends) {
friends = friends.map(item => {
if (typeof item.isFriend !== 'boolean') {
item.isFriend = true
}
return item
})
store.commit('updateFriends', friends)
// 更新好友信息字典,诸如昵称
store.commit('updateUserInfo', friends)
}
// 更新好友资料,添加好友成功
export function onUpdateFriend(error, friends) {
if (error) {
alert(error)
return
}
if (!Array.isArray(friends)) {
friends = [friends]
}
friends = friends.map(item => {
if (typeof item.isFriend !== 'boolean') {
item.isFriend = true
}
return item
})
// 补充好友资料
store.dispatch('searchUsers', {
accounts: friends.map(item => {
return item.account
}),
done: (users) => {
const nim = store.state.nim
friends = nim.mergeFriends(friends, users).map(formatUserInfo)
// 更新好友列表
store.commit('updateFriends', friends)
// 更新好友资料
store.commit('updateUserInfo', friends)
}
})
}
// 删除好友,这里使用标记删除
export function onDeleteFriend(error, friends) {
if (error) {
alert(error)
return
}
if (!Array.isArray(friends)) {
friends = [friends]
}
friends = friends.map(item => {
item.isFriend = false
return item
})
// 更新好友列表
store.commit('updateFriends', [], friends)
// 更新好友资料
store.commit('updateUserInfo', friends)
}
export function onSyncFriendAction(obj) {
switch (obj.type) {
case 'addFriend':
// alert('你在其它端直接加了一个好友' + obj.account + ', 附言' + obj.ps);
onUpdateFriend(null, obj.friend);
break;
case 'applyFriend':
// alert('你在其它端申请加了一个好友' + obj.account + ', 附言' + obj.ps);
break;
case 'passFriendApply':
alert('你在其它端通过了一个好友申请' + obj.account + ', 附言' + obj.ps);
onUpdateFriend(null, obj.friend);
break;
case 'rejectFriendApply':
// alert('你在其它端拒绝了一个好友申请' + obj.account + ', 附言' + obj.ps);
break;
case 'deleteFriend':
// alert('你在其它端删了一个好友' + obj.account);
onDeleteFriend(null, {
account: obj.account
});
break;
case 'updateFriend':
// alert('你在其它端更新了一个好友', obj.friend);
onUpdateFriend(null, obj.friend);
break;
}
}
// 更新好友昵称
export function updateFriend ({state, commit}, friend) {
const nim = state.nim
nim.updateFriend({
account: friend.account,
alias: friend.alias,
done: onUpdateFriend
})
}
export function addFriend ({state, commit}, account) {
const nim = state.nim
nim.addFriend({
account,
ps: '',
done: onUpdateFriend
})
}
export function deleteFriend ({state, commit}, account) {
const nim = state.nim
nim.deleteFriend({
account,
done: onDeleteFriend
})
}
// Action 提交的是 mutation,而不是直接变更状态。
// Action 可以包含任意异步操作。
import cookie from '../../utils/cookie'
import pageUtil from '../../utils/page'
/* 导出actions方法 */
import {showLoading, hideLoading, showFullscreenImg, hideFullscreenImg} from './widgetUi'
import {initNimSDK} from './initNimSDK'
import {initChatroomSDK, resetChatroomSDK} from './initChatroomSDK'
import {updateBlack} from './blacks'
import {updateFriend, addFriend, deleteFriend} from './friends'
import {resetSearchResult, searchUsers, searchTeam} from './search'
import {deleteSession, setCurrSession, resetCurrSession} from './session'
import {sendMsg, sendFileMsg, sendMsgReceipt, sendRobotMsg, revocateMsg, updateLocalMsg, getHistoryMsgs, resetNoMoreHistoryMsgs, continueRobotMsg} from './msgs'
import {markSysMsgRead, resetSysMsgs, deleteSysMsgs, markCustomSysMsgRead} from './sysMsgs'
import {sendChatroomMsg, sendChatroomRobotMsg, sendChatroomFileMsg, getChatroomHistoryMsgs} from './chatroomMsgs'
import {initChatroomInfos, getChatroomInfo, getChatroomMembers, clearChatroomMembers} from './chatroomInfos'
import { delegateTeamFunction, onTeamNotificationMsg, enterSettingPage, getTeamMembers, checkTeamMsgReceipt, getTeamMsgReads} from './team'
function connectNim ({state, commit, dispatch}, obj) {
let {force} = Object.assign({}, obj)
// 操作为内容页刷新页面,此时无nim实例
//
if (!state.nim || force) {
let loginuser= require('electron').remote.getGlobal("LOGINUSER");
let loginInfo = {
uid: loginuser.ImAccount,
sdktoken:loginuser.ImToken,
}
if (!loginInfo.uid) {
// 无cookie,直接跳转登录页
// pageUtil.turnPage('无历史登录记录,请重新登录', 'login')
} else {
// 有cookie,重新登录
dispatch('initNimSDK', loginInfo)
}
}
}
function connectChatroom ({state, commit, dispatch}, obj) {
let {chatroomId} = Object.assign({}, obj)
const nim = state.nim
if (nim) {
dispatch('showLoading')
nim.getChatroomAddress({
chatroomId,
done: function getChatroomAddressDone (error, obj) {
if (error) {
alert(error.message)
location.href = '#/room'
return
}
dispatch('initChatroomSDK', obj)
}
})
}
}
export default {
updateRefreshState ({commit}) {
commit('updateRefreshState')
},
// UI 及页面状态变更
showLoading,
hideLoading,
showFullscreenImg,
hideFullscreenImg,
continueRobotMsg,
// 连接sdk请求,false表示强制重连
connect (store, obj) {
let {type} = Object.assign({}, obj)
// type 可为 nim chatroom
type = type || 'nim'
switch (type) {
case 'nim':
connectNim(store, obj)
break
case 'chatroom':
connectChatroom(store, obj)
break
}
},
// 用户触发的登出逻辑
logout ({ state, commit }) {
cookie.delCookie('uid')
cookie.delCookie('sdktoken')
if (state.nim) {
state.nim.disconnect()
}
pageUtil.turnPage('', 'login')
},
// 初始化 重新连接SDK
initNimSDK,
// 清空所有搜索历史纪录
resetSearchResult,
// 搜索用户信息
searchUsers,
// 更新黑名单
updateBlack,
// 更新好友
addFriend,
deleteFriend,
updateFriend,
// 删除会话
deleteSession,
// 设置当前会话
setCurrSession,
// 重置当前会话
resetCurrSession,
// 发送消息
sendMsg,
sendFileMsg,
sendRobotMsg,
// 发送消息已读回执
sendMsgReceipt,
// 消息撤回
revocateMsg,
// 更新本地消息
updateLocalMsg,
getHistoryMsgs,
// 重置历史消息状态
resetNoMoreHistoryMsgs,
// 标记系统消息已读
markSysMsgRead,
markCustomSysMsgRead,
resetSysMsgs,
deleteSysMsgs,
initChatroomSDK,
initChatroomInfos,
resetChatroomSDK,
sendChatroomMsg,
sendChatroomRobotMsg,
sendChatroomFileMsg,
getChatroomHistoryMsgs,
getChatroomInfo,
getChatroomMembers,
clearChatroomMembers,
// 搜索群
searchTeam,
// 代理sdk中的群方法
delegateTeamFunction,
// 处理群消息回调
onTeamNotificationMsg,
// 进入群信息设置页
enterSettingPage,
// 获取群成员
getTeamMembers,
// 群消息回执检查
checkTeamMsgReceipt,
// 查询群消息回执已读列表
getTeamMsgReads,
}
/*
* 聊天室SDK,依赖于nim sdk
*/
import config from '../../configs'
import pageUtil from '../../utils/page'
import util from '../../utils'
import store from '../'
import {onChatroomMsgs} from './chatroomMsgs'
const SDK = require('../../sdk/NIM_Web_SDK_v6.1.0')
// 切换聊天室之前需要断开连接,原因是移动端不断累积连接实例,消息并发较大时会有性能问题
// 重新初始化 NIM SDK
export function initChatroomSDK ({ state, commit, dispatch }, obj) {
let {chatroomId, address} = obj
if (chatroomId && address) {
if (state.chatroomInsts[chatroomId]) {
state.chatroomInsts[chatroomId].connect()
} else {
state.chatroomInsts[chatroomId] = SDK.Chatroom.getInstance({
appKey: config.appkey,
account: state.userUID,
token: state.sdktoken,
transports: ['websocket'],
chatroomId,
chatroomAddresses: address,
onconnect: function onChatroomConnect (chatroom) {
dispatch('hideLoading')
commit('setCurrChatroom', chatroomId)
},
onerror: function onChatroomError (error, obj) {
dispatch('hideLoading')
if (error) {
alert('网络连接状态异常')
location.href='#/room'
}
},
onwillreconnect: function onChatroomWillReconnect (obj) {
// 此时说明 `SDK` 已经断开连接, 请开发者在界面上提示用户连接已断开, 而且正在重新建立连接
console.log('即将重连', obj)
},
ondisconnect: function onChatroomDisconnect (error) {
// 此时说明 `SDK` 处于断开状态, 切换聊天室也会触发次回调
dispatch('hideLoading')
if (error) {
switch (error.code) {
// 账号或者密码错误, 请跳转到登录页面并提示错误
case 302:
// 此逻辑与nim sdk错误逻辑相同,复用nim sdk的
// 如果单用聊天室功能需要在此做处理
break;
case 13003:
alert('抱歉,你已被主播拉入了黑名单')
location.href='#/room'
break
// 被踢, 请提示错误后跳转到登录页面
case 'kicked':
if (error.reason === 'managerKick') {
alert('你已被管理员移出聊天室')
location.href='#/room'
} else if (error.reason === 'blacked') {
alert('你已被管理员拉入黑名单,不能再进入')
location.href='#/room'
}
break;
default:
console.log(error.message);
break
}
}
},
// 聊天室消息
onmsgs: onChatroomMsgs
})
}
} else {
alert('没有聊天室地址')
}
}
export function resetChatroomSDK ({state, commit, dispatch}, chatroomId) {
if (chatroomId) {
state.chatroomInsts[chatroomId].disconnect()
} else {
for (let tempRoomId in state.chatroomInsts) {
state.chatroomInsts[tempRoomId].disconnect()
}
}
commit('resetCurrChatroom')
}
/*
* SDK连接相关
*/
import config from '../../configs/index'
import pageUtil from '../../utils/page'
import util from '../../utils/index'
import store from '../'
import {onFriends, onSyncFriendAction} from './friends'
import {onRobots} from './robots'
import {onBlacklist, onMarkInBlacklist} from './blacks'
import {onMyInfo, onUserInfo} from './userInfo'
import {onSessions, onUpdateSession} from './session'
import {onRoamingMsgs, onOfflineMsgs, onMsg} from './msgs'
import {onSysMsgs, onSysMsg, onSysMsgUnread, onCustomSysMsgs} from './sysMsgs'
import { onTeams, onSynCreateTeam, onCreateTeam, onUpdateTeam, onTeamMembers, onUpdateTeamMember, onAddTeamMembers, onRemoveTeamMembers, onUpdateTeamManagers, onDismissTeam, onUpdateTeamMembersMute, onTeamMsgReceipt} from './team'
const SDK = require('../../sdk/NIM_Web_SDK_v6.1.0')
// 重新初始化 NIM SDK
export function initNimSDK ({ state, commit, dispatch }, loginInfo) {
if (state.nim) {
state.nim.disconnect()
}
dispatch('showLoading')
// 初始化SDK
window.nim = state.nim = SDK.NIM.getInstance({
debug: false,
appKey: config.appkey,
account: loginInfo.uid,
token: loginInfo.sdktoken,
transports: ['websocket'],
db: config.useDb,
// logFunc: new SDK.NIM.LoggerPlugin({
// url: '/webdemo/h5/getlogger',
// level: 'info'
// }),
syncSessionUnread: true,
syncRobots: true,
autoMarkRead: true, // 默认为true
onconnect: function onConnect (event) {
if (loginInfo) {
// 连接上以后更新uid
commit('updateUserUID', loginInfo)
}
},
onerror: function onError (event) {
// alert(JSON.stringify(event))
debugger
alert('网络连接状态异常')
location.href = config.loginUrl
},
onwillreconnect: function onWillReconnect () {
console.log(event)
},
ondisconnect: function onDisconnect (error) {
switch (error.code) {
// 账号或者密码错误, 请跳转到登录页面并提示错误
case 302:
pageUtil.turnPage('帐号或密码错误', 'login')
break
// 被踢, 请提示错误后跳转到登录页面
case 'kicked':
let map = {
PC: '电脑版',
Web: '网页版',
Android: '手机版',
iOS: '手机版',
WindowsPhone: '手机版'
}
let str = error.from
let errorMsg = `你的帐号于${util.formatDate(new Date())}${(map[str] || '其他端')}踢出下线,请确定帐号信息安全!`
pageUtil.turnPage(errorMsg, 'login')
break
default:
break
}
},
// // 多端登录
// onloginportschange: onLoginPortsChange,
// 用户关系及好友关系
onblacklist: onBlacklist,
onsyncmarkinblacklist: onMarkInBlacklist,
// onmutelist: onMutelist,
// onsyncmarkinmutelist: onMarkInMutelist,
onfriends: onFriends,
onsyncfriendaction: onSyncFriendAction,
// 机器人
onrobots: onRobots,
// 用户名片 - actions/userInfo
onmyinfo: onMyInfo,
onupdatemyinfo: onMyInfo,
onusers: onUserInfo,
onupdateuser: onUserInfo,
// // 群组
onteams: onTeams,
onsynccreateteam: onSynCreateTeam,
syncTeams: true,
onteammembers: onTeamMembers,
onCreateTeam: onCreateTeam,
onDismissTeam: onDismissTeam,
onUpdateTeam: onUpdateTeam,
onAddTeamMembers: onAddTeamMembers,
onRemoveTeamMembers: onRemoveTeamMembers,
onUpdateTeamManagers: onUpdateTeamManagers,
onupdateteammember: onUpdateTeamMember,
onUpdateTeamMembersMute: onUpdateTeamMembersMute,
onTeamMsgReceipt: onTeamMsgReceipt,
// // 会话
onsessions: onSessions,
onupdatesession: onUpdateSession,
// // 消息
onroamingmsgs: onRoamingMsgs,
onofflinemsgs: onOfflineMsgs,
onmsg: onMsg,
// // 系统通知
onsysmsg: onSysMsg,
onofflinesysmsgs: onSysMsgs,
onupdatesysmsg: onSysMsg, // 通过、拒绝好友申请会收到此回调
onsysmsgunread: onSysMsgUnread,
onupdatesysmsgunread: onSysMsgUnread,
onofflinecustomsysmsgs: onCustomSysMsgs,
oncustomsysmsg: onCustomSysMsgs,
// // 同步完成
onsyncdone: function onSyncDone () {
dispatch('hideLoading')
// 说明在聊天列表页
if (store.state.currSessionId) {
dispatch('setCurrSession', store.state.currSessionId)
}
}
})
window.nim.useDb = config.useDb
}
import store from '../'
import config from '../../configs'
import util from '../../utils'
export function formatMsg (msg) {
const nim = store.state.nim
if (msg.type === 'robot') {
if (msg.content && msg.content.flag === 'bot') {
if (msg.content.message) {
msg.content.message = msg.content.message.map(item => {
switch (item.type) {
case 'template':
item.content = nim.parseRobotTemplate(item.content)
break
case 'text':
case 'image':
case 'answer':
break
}
return item
})
}
}
}
return msg
}
export function onRoamingMsgs (obj) {
let msgs = obj.msgs.map(msg => {
return formatMsg(msg)
})
store.commit('updateMsgs', msgs)
}
export function onOfflineMsgs (obj) {
let msgs = obj.msgs.map(msg => {
return formatMsg(msg)
})
store.commit('updateMsgs', msgs)
}
export function onMsg (msg) {
msg = formatMsg(msg)
store.commit('putMsg', msg)
if (msg.sessionId === store.state.currSessionId) {
store.commit('updateCurrSessionMsgs', {
type: 'put',
msg
})
// 发送已读回执
store.dispatch('sendMsgReceipt')
}
if (msg.scene === 'team' && msg.type ==='notification') {
store.dispatch('onTeamNotificationMsg', msg)
}
}
function onSendMsgDone (error, msg) {
store.dispatch('hideLoading')
if (error) {
// 被拉黑
if (error.code === 7101) {
msg.status = 'success'
alert(error.message)
} else {
alert(error.message)
}
}
onMsg(msg)
}
// 消息撤回
export function onRevocateMsg (error, msg) {
const nim = store.state.nim
if (error) {
if (error.code === 508) {
alert('发送时间超过2分钟的消息,不能被撤回')
} else {
alert(error)
}
return
}
let tip = ''
if (msg.from === store.state.userUID) {
tip = '你撤回了一条消息'
} else {
let userInfo = store.state.userInfos[msg.from]
if (userInfo) {
tip = `${util.getFriendAlias(userInfo)}撤回了一条消息`
} else {
tip = '对方撤回了一条消息'
}
}
nim.sendTipMsg({
isLocal: true,
scene: msg.scene,
to: msg.to,
tip,
time: msg.time,
done: function sendTipMsgDone (error, tipMsg) {
let idClient = msg.deletedIdClient || msg.idClient
store.commit('replaceMsg', {
sessionId: msg.sessionId,
idClient,
msg: tipMsg
})
if (msg.sessionId === store.state.currSessionId) {
store.commit('updateCurrSessionMsgs', {
type: 'replace',
idClient,
msg: tipMsg
})
}
}
})
}
export function revocateMsg ({state, commit}, msg) {
const nim = state.nim
let {idClient} = msg
msg = Object.assign(msg, state.msgsMap[idClient])
nim.deleteMsg({
msg,
done: function deleteMsgDone (error) {
onRevocateMsg(error, msg)
}
})
}
export function updateLocalMsg ({state, commit}, msg) {
store.commit('updateCurrSessionMsgs', {
type: 'replace',
idClient: msg.idClient,
msg: msg
})
state.nim.updateLocalMsg({
idClient: msg.idClient,
localCustom: msg.localCustom
})
store.commit('replaceMsg', {
sessionId: msg.sessionId,
idClient: msg.idClient,
msg: msg
})
}
// 发送普通消息
export function sendMsg ({state, commit}, obj) {
const nim = state.nim
obj = obj || {}
let type = obj.type || ''
store.dispatch('showLoading')
switch (type) {
case 'text':
nim.sendText({
scene: obj.scene,
to: obj.to,
text: obj.text,
done: onSendMsgDone,
needMsgReceipt: obj.needMsgReceipt || false
})
break
case 'custom':
nim.sendCustomMsg({
scene: obj.scene,
to: obj.to,
pushContent: obj.pushContent,
content: JSON.stringify(obj.content),
done: onSendMsgDone
})
}
}
// 发送文件消息
export function sendFileMsg ({state, commit}, obj) {
const nim = state.nim
let { type } = obj
if (!type) {
type = 'file'
if (/\.(png|jpg|bmp|jpeg|gif)$/i.test(fileInput.value)) {
type = 'image'
} else if (/\.(mov|mp4|ogg|webm)$/i.test(fileInput.value)) {
type = 'video'
}
}
store.dispatch('showLoading')
const data = Object.assign({
type,
uploadprogress: function (data) {
// console.log(data.percentageText)
},
uploaderror: function () {
fileInput.value = ''
console && console.log('上传失败')
},
uploaddone: function(error, file) {
fileInput.value = ''
// console.log(error);
// console.log(file);
},
beforesend: function (msg) {
// console && console.log('正在发送消息, id=', msg);
},
done: function (error, msg) {
onSendMsgDone (error, msg)
}
}, obj)
nim.sendFile(data)
}
// 发送机器人消息
export function sendRobotMsg ({state, commit}, obj) {
const nim = state.nim
let {type, scene, to, robotAccid, content, params, target, body} = obj
scene = scene || 'p2p'
if (type === 'text') {
nim.sendRobotMsg({
scene,
to,
robotAccid: robotAccid || to,
content: {
type: 'text',
content,
},
body,
done: onSendMsgDone
})
} else if (type === 'welcome') {
nim.sendRobotMsg({
scene,
to,
robotAccid: robotAccid || to,
content: {
type: 'welcome',
},
body,
done: onSendMsgDone
})
} else if (type === 'link') {
nim.sendRobotMsg({
scene,
to,
robotAccid: robotAccid || to,
content: {
type: 'link',
params,
target
},
body,
done: onSendMsgDone
})
}
}
// 发送消息已读回执
export function sendMsgReceipt ({state, commit}) {
// 如果有当前会话
let currSessionId = store.state.currSessionId
if (currSessionId) {
// 只有点对点消息才发已读回执
if (util.parseSession(currSessionId).scene === 'p2p') {
let msgs = store.state.currSessionMsgs
const nim = state.nim
if (state.sessionMap[currSessionId]) {
nim.sendMsgReceipt({
msg: state.sessionMap[currSessionId].lastMsg,
done: function sendMsgReceiptDone (error, obj) {
// do something
}
})
}
}
}
}
function sendMsgReceiptDone(error, obj) {
console.log('发送消息已读回执' + (!error?'成功':'失败'), error, obj);
}
export function getHistoryMsgs ({state, commit}, obj) {
const nim = state.nim
if (nim) {
let {scene, to} = obj
let options = {
scene,
to,
reverse: false,
asc: true,
limit: config.localMsglimit || 20,
done: function getHistoryMsgsDone (error, obj) {
if (obj.msgs) {
if (obj.msgs.length === 0) {
commit('setNoMoreHistoryMsgs')
} else {
let msgs = obj.msgs.map(msg => {
return formatMsg(msg)
})
commit('updateCurrSessionMsgs', {
type: 'concat',
msgs: msgs
})
}
}
store.dispatch('hideLoading')
}
}
if (state.currSessionLastMsg) {
options = Object.assign(options, {
lastMsgId: state.currSessionLastMsg.idServer,
endTime: state.currSessionLastMsg.time,
})
}
store.dispatch('showLoading')
nim.getHistoryMsgs(options)
}
}
export function resetNoMoreHistoryMsgs ({commit}) {
commit('resetNoMoreHistoryMsgs')
}
// 继续与机器人会话交互
export function continueRobotMsg ({commit}, robotAccid) {
commit('continueRobotMsg', robotAccid)
}
import store from '../'
export function onRobots (robots) {
store.commit('updateRobots', robots)
}
import {formatUserInfo} from './userInfo'
export function resetSearchResult ({state, commit}) {
commit('updateSearchlist', {
type: 'user',
list: []
})
commit('updateSearchlist', {
type: 'team',
list: []
})
}
export function searchUsers ({state, commit}, obj) {
let {accounts, done} = obj
const nim = state.nim
if (!Array.isArray(accounts)) {
accounts = [accounts]
}
nim.getUsers({
accounts,
done: function searchUsersDone (error, users) {
if (error) {
alert(error)
return
}
commit('updateSearchlist', {
type: 'user',
list: users
})
let updateUsers = users.filter(item => {
let account = item.account
if (item.account === state.userUID) {
return false
}
let userInfo = state.userInfos[account] || {}
if (userInfo.isFriend) {
return false
}
return true
})
updateUsers = updateUsers.map(item => {
return formatUserInfo(item)
})
commit('updateUserInfo', updateUsers)
if (done instanceof Function) {
done(users)
}
}
})
}
export function searchTeam ({ state, commit }, obj) {
let { teamId, done } = obj
const nim = state.nim
nim.getTeam({
teamId: teamId,
done: function searchTeamDone (error, teams) {
if (error) {
if (error.code === 803) {
// 群不存在或未发生变化
teams = []
} else {
alert(error)
return
}
}
if (!Array.isArray(teams)) {
teams = [teams]
}
teams.forEach(team => {
if (team.avatar && team.avatar.indexOf('nim.nosdn.127') > 0 && team.avatar.indexOf('?imageView') === -1) {
team.avatar = team.avatar + '?imageView&thumbnail=300y300'
}
})
commit('updateSearchlist', {
type: 'team',
list: teams
})
if (done instanceof Function) {
done(teams)
}
}
})
}
/*
* 会话列表
*/
import store from '../'
// 如果会话对象不是好友,需要更新好友名片
function updateSessionAccount (sessions) {
let accountsNeedSearch = []
sessions.forEach(item => {
if (item.scene === 'p2p') {
// 如果不存在缓存资料
if (!store.state.userInfos[item.to]) {
accountsNeedSearch.push(item.to)
}
}
})
if (accountsNeedSearch.length > 0) {
store.dispatch('searchUsers', {
accounts: accountsNeedSearch
})
}
}
// onSessions只在初始化完成后回调
export function onSessions (sessions) {
updateSessionAccount(sessions)
store.commit('updateSessions', sessions)
}
export function onUpdateSession (session) {
let sessions = [session]
updateSessionAccount(sessions)
store.commit('updateSessions', sessions)
}
export function deleteSession ({state, commit}, sessionId) {
const nim = state.nim
sessionId = sessionId || ''
let scene = null
let account = null
if (/^p2p-/.test(sessionId)) {
scene = 'p2p'
account = sessionId.replace(/^p2p-/, '')
} else if (/^team-/.test(sessionId)) {
scene = 'team'
account = sessionId.replace(/^team-/, '')
}
if (account && scene) {
nim.deleteSession({
scene,
to: account,
done: function deleteServerSessionDone (error, obj) {
if (error) {
alert(error)
return
}
nim.deleteLocalSession({
id: sessionId,
done: function deleteLocalSessionDone (error, obj) {
if (error) {
alert(error)
return
}
commit('deleteSessions', [sessionId])
}
})
}
})
}
}
export function setCurrSession ({state, commit, dispatch}, sessionId) {
const nim = state.nim
if (sessionId) {
commit('updateCurrSessionId', {
type: 'init',
sessionId
})
if (nim) {
// 如果在聊天页面刷新,此时还没有nim实例,需要在onSessions里同步
nim.setCurrSession(sessionId)
commit('updateCurrSessionMsgs', {
type: 'init',
sessionId
})
// 发送已读回执
dispatch('sendMsgReceipt')
}
}
}
export function resetCurrSession ({state, commit}) {
const nim = state.nim
nim.resetCurrSession()
commit('updateCurrSessionMsgs', {
type: 'destroy'
})
}
import store from '../'
import {onUpdateFriend, onDeleteFriend} from './friends'
import {onRevocateMsg} from './msgs'
export function onSysMsgs (sysMsgs) {
store.commit('updateSysMsgs', sysMsgs)
}
export function onSysMsg (sysMsg) {
switch (sysMsg.type) {
// 在其他端添加或删除好友
case 'addFriend':
onUpdateFriend(null, {
account: sysMsg.from
})
store.commit('updateSysMsgs', [sysMsg])
break
case 'deleteFriend':
onDeleteFriend(null, {
account: sysMsg.from
})
break
// 对方消息撤回
case 'deleteMsg':
if(sysMsg.scene === 'p2p') {
sysMsg.sessionId = `p2p-${sysMsg.from}`
} else {
sysMsg.sessionId = `team-${sysMsg.to}`
}
onRevocateMsg(null, sysMsg)
break
case 'teamInvite': //被邀请入群
case 'applyTeam': // 申请入群
case 'rejectTeamApply': // 申请入群被拒绝
case 'rejectTeamInvite': // 拒绝入群邀请
store.commit('updateSysMsgs', [sysMsg])
break
}
store.commit('updateSysMsgState', sysMsg)
}
export function onSysMsgUnread (obj) {
store.commit('updateSysMsgUnread', obj)
}
export function onCustomSysMsgs (customSysMsgs) {
console.log(customSysMsgs)
if (!Array.isArray(customSysMsgs)) {
customSysMsgs = [customSysMsgs]
}
customSysMsgs = customSysMsgs.filter(msg => {
if (msg.type === 'custom') {
if (msg.content) {
try {
let content = JSON.parse(msg.content)
// 消息正在输入中
if ((content.id + '') === '1') {
return false
}
} catch (e) {}
}
}
return true
})
if (customSysMsgs.length > 0) {
store.commit('updateCustomSysMsgs', customSysMsgs)
}
}
// 不传obj则全部重置
export function markSysMsgRead ({state, commit}, obj) {
const nim = state.nim
let sysMsgs = []
if (obj && obj.sysMsgs) {
sysMsgs = obj.sysMsgs
} else {
sysMsgs = state.sysMsgs
}
if (Array.isArray(sysMsgs) && sysMsgs.length > 0) {
nim.markSysMsgRead({
sysMsgs,
done: function (error, obj) {
}
})
}
}
export function markCustomSysMsgRead ({state, commit}) {
commit('updateCustomSysMsgUnread', {
type: 'reset'
})
}
export function resetSysMsgs ({state, commit}, obj) {
commit('resetSysMsgs', obj)
}
export function deleteSysMsgs({commit}, obj) {
commit('deleteSysMsgs', obj)
}
\ No newline at end of file
import store from '../'
// 收到群列表及更新群列表接口
export function onTeams(teams) {
if (!Array.isArray(teams)) {
teams = [teams]
}
teams = teams.filter(item => !!item)
teams.forEach(team=>{
if (team.validToCurrentUser === undefined) {
team.validToCurrentUser = true
}
if (team.avatar && team.avatar.indexOf('nim.nosdn.127') >0 && team.avatar.indexOf('?imageView')===-1) {
team.avatar = team.avatar + '?imageView&thumbnail=300y300'
}
})
store.commit('updateTeamList', teams)
}
// 收到群成员及更新群成员接口
export function onTeamMembers(obj) {
store.commit('updateTeamMembers', obj)
}
export function onCreateTeam(team) {
onTeams(team)
onTeamMembers({
teamId: team.teamId,
members: []
// members: [team.owner]
})
}
export function onSynCreateTeam(team){
onTeams(team)
}
export function onDismissTeam(obj) {
store.commit('updateTeamList', {
invalid: { teamId: obj.teamId }
})
}
export function onUpdateTeam(team) {
onTeams(team)
}
export function onTeamNotificationMsg({state, commit}, msg) {
if (msg.attach.type === 'updateTeam' && msg.attach.team) {
store.commit('updateTeamInfo', msg.attach.team)
}
if (msg.attach.type === 'transferTeam') {
onTeamMembers({
teamId: msg.attach.team.teamId,
members: msg.attach.members
})
}
}
export function onAddTeamMembers(obj) {
obj.accounts.forEach(account=>{
// 自己被拉入群时更新群列表
if (account === store.state.userUID) {
let team = [obj.team]
onTeams(team)
}
})
onTeamMembers({
teamId: obj.team.teamId,
members: obj.members
})
}
export function onRemoveTeamMembers(obj) {
obj.accounts.forEach(account => {
// 自己被移出群时,更新群列表
if (account === store.state.userUID) {
obj.team.validToCurrentUser = false
let team = [obj.team]
onTeams(team)
}
})
store.commit('removeTeamMembersByAccounts', {
teamId: obj.team.teamId,
accounts: obj.accounts
})
}
export function onUpdateTeamMember(teamMember) {
onTeamMembers({
teamId: teamMember.teamId,
members: teamMember
})
}
export function onUpdateTeamMembersMute(obj) {
onTeamMembers({
teamId: obj.team.teamId,
members: obj.members
})
}
export function onUpdateTeamManagers(obj) {
onTeamMembers({
teamId: obj.team.teamId,
members: obj.members
})
}
export function onTeamMsgReceipt(obj) {
obj.teamMsgReceipts.forEach(item => {
if (item.teamId === store.state.currReceiptQueryTeamId) {
store.commit('updateSingleTeamMsgReads', item)
}
})
console.log('群消息回执通知' + obj)
}
// 进入可配置的群信息设置页,进入前改变state中的配置信息,进入页面后读取配置信息更新视图
export function enterSettingPage({commit}, obj) {
commit('updateTeamSettingConfig', obj)
setTimeout(() => {
location.href = `#/teamsetting`
}, 20)
}
/*
* 代理nim sdk中对群组的操作方法
* @functionName nim sdk中的方法名
* @options 传递给sdk方法的参数
*/
export function delegateTeamFunction({state}, {functionName, options}) {
const nim = state.nim
if (functionName && nim[functionName] && typeof nim[functionName] === 'function') {
nim[functionName](options)
} else {
throw(`There is not property of '${functionName}' in nim or '${functionName}' is not a function`)
}
}
export function getTeamMembers({ state }, teamId) {
const nim = state.nim
if (!nim) {
// 防止nim未初始化
setTimeout(() => {
getTeamMembers(store, teamId)
}, 200);
return
}
nim.getTeamMembers({
teamId: teamId,
done: (err, obj) => {
if (obj.members) {
onTeamMembers({
teamId: obj.teamId,
members: obj.members
})
} else {
setTimeout(() => {
getTeamMembers(store, teamId)
}, 200);
}
}
})
}
export function checkTeamMsgReceipt({state}, msgs) {
var result = /team-(\d+)/.exec(state.currSessionId)
if (!result) {
return null
}
var teamId = result[1]
var needToPeceiptList= getMsgNeedToReceipt(state, teamId, msgs)
if (needToPeceiptList && needToPeceiptList.length>0) {
nim.sendTeamMsgReceipt({
teamMsgReceipts: needToPeceiptList,
done: (err, obj, content) => {
console.log('标记群组消息已读' + (!err ? '成功' : '失败'));
if (!err) {
store.commit('updateSentReceipedMap', needToPeceiptList)
}
}
})
}
store.commit('updateReceiptQueryList', {
teamId: teamId,
msgs: msgs
})
}
// 查询需要发送回执的消息
function getMsgNeedToReceipt(state, teamId, msgs) {
var sentReceipedList = state.sentReceipedMap[teamId] || []
var needToReceipt = msgs.filter(msg => {
// 需要回执,且未发送过
return msg.needMsgReceipt && msg.from !== state.myInfo.account && !sentReceipedList.find(id => id === msg.idServer)
}).map(msg => {
return {
teamId: teamId,
idServer: msg.idServer
}
})
return needToReceipt
}
export function getTeamMsgReads({ state }, needQuery) {
nim.getTeamMsgReads({
teamMsgReceipts: needQuery,
done: (error, obj, content) => {
if (error) {
console.log('获取群组消息已读' + error)
}else {
console.log('获取群组消息已读:', content)
store.commit('updateTeamMsgReads', content)
}
}
})
}
/*
* 用户账号信息
*/
import store from '../'
import config from '../../configs'
import util from '../../utils'
export function formatUserInfo (obj) {
const nim = store.state.nim
let gender = ''
switch (obj.gender) {
case 'male':
gender = '男'
break
case 'female':
gender = '女'
break
case 'unknown':
gender = ''
break
}
let custom = obj.custom || ''
try {
custom = JSON.parse(custom)
} catch (e) {
custom = {
data: custom
}
}
if (obj.avatar) {
obj.avatar = nim.viewImageSync({
url: obj.avatar, // 必填
thumbnail: { // 生成缩略图, 可选填
width: 40,
height: 40,
mode: 'cover'
}
})
// obj.avatar += '?imageView&thumbnail=40x40&quality=85'
} else {
obj.avatar = config.defaultUserIcon
}
let result = Object.assign(obj, {
account: obj.account,
nick: obj.nick || '',
avatar: obj.avatar || config.defaultUserIcon,
birth: obj.birth || '',
email: obj.email || '',
tel: obj.tel || '',
gender,
sign: obj.sign || '',
custom,
createTime: obj.createTime || (new Date()).getTime(),
updateTime: obj.updateTime || (new Date()).getTime()
})
return result
}
export function onMyInfo (obj) {
obj = util.mergeObject(store.state.myInfo, obj);
let myInfo = formatUserInfo(obj)
store.commit('updateMyInfo', myInfo)
}
export function onUserInfo (users) {
if (!Array.isArray(users)) {
users = [users]
}
users = users.map(formatUserInfo)
store.commit('updateUserInfo', users)
}
import pageUtil from '../../utils/page'
// 显示加载中进度条
export function showLoading ({state, commit}) {
commit('updateLoading', true)
}
// 隐藏加载中进度条
export function hideLoading ({state, commit}) {
commit('updateLoading', false)
}
// 显示原图片
export function showFullscreenImg ({state, commit}, obj) {
if (obj) {
obj.type = 'show'
commit('updateFullscreenImage', obj)
}
}
// 隐藏原图片
export function hideFullscreenImg ({state, commit}) {
commit('updateFullscreenImage', {
type: 'hide'
})
}
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import mutations from './mutations'
import actions from './actions'
import state from './state'
const store = new Vuex.Store({
// 内存数据状态,UI可通过this.$store.state.* 获得数据
state,
// 唯一拥有更改内存数据的接口,不可进行异步操作
mutations,
// 与mutation通讯,ui层写入内存数据的接口,可异步操作
actions,
plugins: []
})
export default store
This diff is collapsed.
/* 内存数据状态 */
export default {
// 正在加载中
isLoading: true,
// 操作是否是刷新页面,刷新初始没有nim实例,会导致时序问题
isRefresh: true,
// 全屏显示的原图
isFullscreenImgShow: false,
fullscreenImgSrc: '',
// 切页动画 forward,backward
transitionName: 'forward',
// IM相关
// NIM SDK 实例
nim: null,
// 登录账户ID
userUID: null,
// 用户名片
myInfo: {},
// 好友/黑名单/陌生人名片, 数据结构如:{cid: {attr: ...}, ...}
userInfos: {},
// 用户订阅的事件同步, 数据结构如:{cid: {typeid: {...}, ...}, ...}
userSubscribes: {},
// 好友列表
friendslist: [],
// 机器人列表
robotslist: [],
// 用于判定帐号是否是robots
robotInfos: {},
robotInfosByNick: {},
// 黑名单列表
blacklist: [],
// 禁言列表
// mutelist: [],
teamlist: [],
// 群自身的属性,数据结构如:{tid: {attr: ...}, ...}
// teamAttrs: {},
// 群对象的成员列表,数据结构如:{tid: {members: [...], ...}, ...}
teamMembers: {},
// 关闭群提醒的群id列表
muteTeamIds: [],
// 群设置传递数据
teamSettingConfig: {},
// 已发送群消息回执Map,key为群Id
sentReceipedMap: {},
// 当前群消息回执查询的群id
currReceiptQueryTeamId: null,
// 群消息回执查询的消息列表
receiptQueryList: [],
// 群消息回执查询结果列表
teamMsgReads: [],
// 群消息已读未读账号列表
teamMsgReadsDetail: {
readAccounts: [],
unreadAccounts: []
},
// 消息列表
msgs: {}, // 以sessionId作为key
msgsMap: {}, // 以idClient作为key,诸如消息撤回等的消息查找
// 会话列表
sessionlist: [],
sessionMap: {},
// 当前会话ID(即当前聊天列表,只有单聊群聊采用,可用于判别)
currSessionId: null,
currSessionMsgs: [],
// 是否有更多历史消息,用于上拉加载更多
noMoreHistoryMsgs: false,
// 继续对话的机器人id
continueRobotAccid: '',
// 系统消息
sysMsgs: [],
customSysMsgs: [],
sysMsgUnread: {
total: 0
},
customSysMsgUnread: 0,
// 临时变量
// 缓存需要获取的用户信息账号,如searchUser
searchedUsers: [],
// 缓存需要获取的群组账号
searchedTeams: [],
// 聊天室相关
// 聊天室sdk实例
chatroomInsts: {},
chatroomInfos: {},
// 聊天室分房间消息集合
chatroomMsgs: {},
// 当前聊天室实例及id
currChatroom: null,
currChatroomId: null,
currChatroomMsgs: [],
currChatroomInfo: {},
// 聊天室成员列表
currChatroomMembers: [],
}
const cookie = {
// 写cookies
setCookie: function (name, value) {
//写cookies
setCookie: function(name, value) {
let days = 1
let exp = new Date()
exp.setTime(exp.getTime() + days * 24 * 60 * 60 * 1000)
document.cookie = name + '=' + escape(value) + ';expires=' + exp.toGMTString()
exp.setTime(exp.getTime() + days*24*60*60*1000)
document.cookie = name + '=' + escape (value) + ';expires=' + exp.toGMTString()
},
// 读取cookies
//读取cookies
readCookie: function (name) {
let arr = null
let reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
let reg = new RegExp('(^| )'+name+'=([^;]*)(;|$)')
if (document.cookie && (arr = document.cookie.match(reg))) {
return unescape(arr[2])
} else {
return null
}
},
// 删除cookies
delCookie: function (name) {
return null;
}
},
//删除cookies
delCookie: function (name) {
let cval = this.readCookie(name)
if (cval != null) {
if (cval!=null) {
document.cookie = name + '=' + cval + ';expires=' + (new Date(0)).toGMTString()
}
}
}
}
export default cookie
import Vue from 'vue'
import store from '../store'
if (!Function.prototype.bind) {
Function.prototype.bind = function () {
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift()
return function () {
return fn.apply(object, args.concat(Array.prototype.slice.call(arguments)))
if(!Function.prototype.bind){
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
return function(){
return fn.apply(object, args.concat(Array.prototype.slice.call(arguments)));
}
}
}
......@@ -14,32 +15,32 @@ let Utils = Object.create(null)
Utils.encode = function (_map, _content) {
_content = '' + _content
if (!_map || !_content) {
return _content || ''
return _content||''
}
return _content.replace(_map.r, function ($1) {
var _result = _map[!_map.i ? $1.toLowerCase() : $1]
return _result != null ? _result : $1
})
}
});
};
Utils.escape = (function () {
let _reg = /<br\/?>$/
let _map = {
r: /\<|\>|\&|\r|\n|\s|\'|\"/g,
'<': '&lt;',
'>': '&gt;',
'&': '&amp;',
' ': '&nbsp;',
'"': '&quot;',
"'": '&#39;',
'\n': '<br/>',
'\r': ''
r:/\<|\>|\&|\r|\n|\s|\'|\"/g,
'<':'&lt;',
'>':'&gt;',
'&':'&amp;',
' ':'&nbsp;',
'"':'&quot;',
"'":'&#39;',
'\n':'<br/>',
'\r':''
}
return function (_content) {
return function(_content){
_content = Utils.encode(_map, _content)
return _content.replace(_reg, '<br/>')
}
})()
return _content.replace(_reg, '<br/>');
};
})();
Utils.object2query = function (obj) {
let keys = Object.keys(obj)
......@@ -198,26 +199,26 @@ Utils.generateChatroomSysMsg = function (data) {
text = `${(data.attach.toNick[0] || data.attach.to[0])}被管理员拉入黑名单`
break
case 'unblackMember':
text = `${(data.attach.toNick[0] || data.attach.to[0])}被管理员解除拉黑`
text = `${(data.attach.toNick[0]||data.attach.to[0])}被管理员解除拉黑`
break
case 'gagMember':
text = `${(data.attach.toNick[0] || data.attach.to[0])}被管理员禁言`
text = `${(data.attach.toNick[0]||data.attach.to[0])}被管理员禁言`
break
case 'ungagMember':
text = `${(data.attach.toNick[0] || data.attach.to[0])}被管理员解除禁言`
text = `${(data.attach.toNick[0]||data.attach.to[0])}被管理员解除禁言`
break
case 'addManager':
text = `${(data.attach.toNick[0] || data.attach.to[0])}被任命管理员身份`
text = `${(data.attach.toNick[0]||data.attach.to[0])}被任命管理员身份`
break
case 'removeManager':
text = `${(data.attach.toNick[0] || data.attach.to[0])}被解除管理员身份`
break
text = `${(data.attach.toNick[0]||data.attach.to[0])}被解除管理员身份`
break;
case 'addTempMute':
text = `${(data.attach.toNick[0] || data.attach.to[0])}被管理员临时禁言`
break
text = `${(data.attach.toNick[0]||data.attach.to[0])}被管理员临时禁言`
break;
case 'removeTempMute':
text = `${(data.attach.toNick[0] || data.attach.to[0])}被管理员解除临时禁言`
break
text = `${(data.attach.toNick[0]||data.attach.to[0])}被管理员解除临时禁言`
break;
case 'addCommon':
text = `管理员添加普通成员`
break
......@@ -226,7 +227,7 @@ Utils.generateChatroomSysMsg = function (data) {
break
case 'kickMember':
text = `${data.attach.toNick[0]}被管理员踢出房间`
break
break;
// case 'xxx':
// 直播公告已更新
// break;
......@@ -237,4 +238,131 @@ Utils.generateChatroomSysMsg = function (data) {
return text
}
Utils.generateTeamSysmMsg = function (data) {
var text, nicks = this.getNickNames(data.attach.users)
switch (data.attach.type) {
case 'updateTeam':
text = this.getTeamUpdateInfo(data)
break;
case 'addTeamMembers': {
let op = nicks.pop()
text = `${op}邀请${nicks.join()}加入群`
break;
}
case 'removeTeamMembers': {
let op = nicks.pop()
text = `${nicks.join()}${op}移出群`
break;
}
case 'acceptTeamInvite': {
let op = nicks.pop()
text = `${nicks.join()}接受了${op}入群邀请`
break;
}
case 'passTeamApply': {
let op = nicks.shift()
if (nicks.length===1 && op===nicks[0]) {
// 此情况为高级群设置不需要验证,用户申请入群后,收到的群消息提示
text = `${op}加入群`
} else {
text = `${op}通过了${nicks}入群邀请`
}
break;
}
case 'addTeamManagers': {
// todo test
let op = nicks.pop()
text = `${op}新增了${nicks}为管理员`
break;
}
case 'removeTeamManagers': {
// todo test
let op = nicks.pop()
text = `${op}移除了${nicks}的管理员权限`
break;
}
case 'leaveTeam': {
text = `${nicks.join()}退出了群`
break;
}
case 'dismissTeam': {
text = `${nicks.join()}解散了群`
break;
}
case 'transferTeam': {
// todo test
let nicks = this.getNickNames(data.attach.users)
let op = nicks.shift()
text = `${op}转让群主给${nicks}`
break;
}
case 'updateTeamMute':{
let nicks = this.getNickNames(data.attach.users)
let op = nicks.shift()
text = `${nicks}被管理员${data.attach.mute ? '禁言' : '解除禁言'}`
break;
}
default:
break;
}
return text
}
// todo 写成私有成员方法
Utils.getNickNames = function(users) {
return users.map(user => {
return user.account === store.state.userUID? '你' : user.nick
})
}
// todo 写成私有成员方法
Utils.getTeamUpdateInfo = function(msg) {
let text, team = msg.attach.team, op = this.getNickNames(msg.attach.users).pop()
if (team['name']) {
text = `${op}修改群名为${team['name']}`
} else if (team['intro']) {
text = `${op}修改群介绍为${team['intro']}`
}
// 由于群公告的交互与 Android iOS 不一致,现版本不适配群公告
// else if (team['announcement']) {
// text = `${op}修改群公告为${team['announcement']}`
// }
else if (team['joinMode']) {
text = `群身份验证模式更新为${team.joinMode === 'noVerify' ? '不需要验证' : team.joinMode === 'needVerify' ? '需要验证' : '禁止任何人加入'}`
} else if (team['inviteMode']) {
text = `邀请他人权限为${team['inviteMode'] === 'all' ? '所有人' : '管理员'}`
} else if (team['updateTeamMode']) {
text = `群资料修改权限为${team['updateTeamMode'] === 'all' ? '所有人' : '管理员'}`
} else if (team['beInviteMode']) {
text = `被邀请人身份${team['beInviteMode'] === 'noVerify' ? '不需要验证' : '需要验证'}`
} else {
text = '更新群信息'
}
return text
}
Utils.teamConfigMap = {
joinMode: {
'noVerify': '不需要验证',
'needVerify': '需要验证',
'rejectAll': '禁止任何人加入'
},
beInviteMode: {
'needVerify': '需要验证',
'noVerify': '不需要验证'
},
inviteMode: {
'manager': '管理员邀请',
'all': '所有人邀请'
},
updateTeamMode: {
'manager': '管理员修改',
'all': '所有人修改'
},
memberType: {
'manager': '管理员',
'normal': '普通成员'
}
}
export default Utils
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment