index.vue 34KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. <template>
  2. <div class="contact-box" id="contact-box">
  3. <div class="contact-box-item msg-box" >
  4. <div class="box-btn " @click="toggleMsgBox">
  5. <i class="el-icon-service"></i>
  6. <span>在线客服</span>
  7. </div>
  8. <div class="contact-msg-box" v-show="showMsgBox">
  9. <div class="msg-box-panel">
  10. <div class="panel-header">
  11. <i class="el-icon-close kf-close" @click="showMsgBox=false"></i>
  12. <p class="kf-h-line">酷医云在线客服</p>
  13. <div class="clearfix"></div>
  14. </div>
  15. <div class="panel-body">
  16. <ul class="msg-inner scroll-y">
  17. <li v-for="(messageitem, key) in messageBox" :key="key" :id="'id_'+messageitem.id" class="cell clearfix" :class="messageitem.float=='right'?'cell_right':''">
  18. <template v-if="messageitem.float=='right'">
  19. <div class="msg_body fl">
  20. <div class="inner" v-html="messageitem.message"></div>
  21. </div>
  22. <div class="cell_pic fl">
  23. <div class="pic">
  24. <img :src="messageitem.avatar" alt="">
  25. </div>
  26. </div>
  27. </template>
  28. <template v-else>
  29. <div class="cell_pic fl">
  30. <div class="pic">
  31. <img :src="messageitem.avatar" alt="">
  32. </div>
  33. </div>
  34. <div class="msg_body fl">
  35. <div class="inner" v-html="messageitem.message"></div>
  36. </div>
  37. </template>
  38. </li>
  39. </ul>
  40. </div>
  41. <div class="panel-tool">
  42. <i class="icon-face" title="表情" @click="showEmotion"></i>
  43. <el-upload
  44. class="avatar-uploader"
  45. action="https://jsonplaceholder.typicode.com/posts/"
  46. :show-file-list="false"
  47. :http-request='handleIMPicUload'
  48. :on-success="handleIMPicSuccess"
  49. :before-upload="beforeIMPicUpload">
  50. <i class="el-icon-picture" title="图片"></i>
  51. </el-upload>
  52. <div class="face-box" v-show="showFace">
  53. <div class="face-box-title">
  54. <span>表情</span>
  55. <i class="el-icon-close " @click="showFace=false" style="float:right" ></i>
  56. </div>
  57. <ul class="face-box-list clearfix">
  58. <li v-for="(faceitem, index) in facelist" :key="index" @click="selectEmotion(faceitem)" >
  59. <img :src="faceitem[1]" :id="faceitem[0]" alt="">
  60. </li>
  61. </ul>
  62. </div>
  63. </div>
  64. <div class="panel-booter">
  65. <div class="msg-input-box">
  66. <textarea class="textarea scroll-y message-textarea" v-model="message" placeholder="请输入"></textarea>
  67. </div>
  68. <div class="msg-send-btn-box">
  69. <span class="time fl">服务时间:工作时间:9:00-22:00 节假日:9:00-18:00</span>
  70. <el-button type="primary" icon="el-icon-edit" class="fr" size="mini" @click="sendMessage">发送</el-button>
  71. <!-- <button type="submit" id="sendadminkfmsg" class="send_btn fr">发送</button> -->
  72. </div>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. <div class="contact-box-item phone-box">
  78. <div class="box-btn" @click="togglePhoneBox">
  79. <i class="el-icon-phone-outline"></i>
  80. <span>客服电话</span>
  81. </div>
  82. <div class="contact-phone-box" v-show="showPhoneBox">
  83. <i class="el-icon-phone-outline" ></i>
  84. <span>0755-86526342</span>
  85. </div>
  86. </div>
  87. </div>
  88. </template>
  89. <script>
  90. import {getusersig} from "@/api/kefu/tencentim";
  91. import webim from 'webim-tencent';
  92. let selType = webim.SESSION_TYPE.C2C;
  93. let reqMsgCount = 15; //每次请求的历史消息(c2c获取群)条数
  94. var msgList = [];
  95. var getPrePageC2CHistroyMsgInfoMap = {};
  96. export default {
  97. name:'contactBox',
  98. data(){
  99. return{
  100. showMsgBox:false,
  101. showPhoneBox:false,
  102. selToID:'',
  103. loginInfo: {
  104. sdkAppID: '', //用户所属应用id,必填
  105. appIDAt3rd: '',
  106. identifier: '', //当前用户ID,必须是否字符串类型,必填
  107. accountType: '', //用户所属应用帐号类型,必填
  108. userSig: '', //当前用户身份凭证,必须是字符串类型,必填
  109. identifierNick: '', //当前用户昵称,不用填写,登录接口会返回用户的昵称,如果没有设置,则返回用户的id
  110. headurl: '', //当前用户默认头像,选填,如果设置过头像,则可以通过拉取个人资料接口来得到头像信息
  111. },
  112. useradmin:{
  113. usersig: '',
  114. Indentifier: '',
  115. appIDAt3rd:'',
  116. IdentifierNick:'',
  117. HeadURL:'',
  118. },
  119. kefuUrl:'https://images.shengws.com/ico_gjh.png',
  120. userSigFlag:false,
  121. imloginFlag:false,
  122. message:'',
  123. messageBox:[],
  124. facelist:[],
  125. showFace:false,
  126. }
  127. },
  128. created(){
  129. this.getusersig();
  130. },
  131. methods:{
  132. getusersig() {
  133. getusersig().then(response => {
  134. if (response.data.state == 0) {
  135. this.$message.error(response.data.msg);
  136. return false;
  137. } else {
  138. this.useradmin = {
  139. usersig: response.data.data.sig,
  140. Indentifier: response.data.data.Indentifier,
  141. appIDAt3rd:response.data.data.appIDAt3rd,
  142. IdentifierNick:response.data.data.IdentifierNick,
  143. HeadURL:response.data.data.HeadURL,
  144. }
  145. this.loginInfo.appIDAt3rd = this.useradmin.appIDAt3rd
  146. this.loginInfo.identifier = this.useradmin.Indentifier
  147. this.loginInfo.userSig = this.useradmin.usersig
  148. this.loginInfo.identifierNick = this.useradmin.IdentifierNick
  149. this.loginInfo.headurl = this.useradmin.HeadURL
  150. this.loginInfo.sdkAppID = response.data.data.sdkAppID
  151. this.loginInfo.accountType = response.data.data.accountType
  152. this.selToID = response.data.data.selToAdmin;
  153. this.userSigFlag = true;
  154. }
  155. });
  156. },
  157. showEmotion:function(){
  158. this.facelist = [];
  159. for (const index in webim.Emotions) {
  160. this.facelist.push(webim.Emotions[index]);
  161. }
  162. this.showFace = true;
  163. },
  164. selectEmotion:function(face){
  165. this.message += face[0];
  166. this.showFace = false;
  167. },
  168. sendMessage:function(){
  169. var message = this.message.trim();
  170. var msgLen = webim.Tool.getStrBytes(message);
  171. if(message == '') {
  172. this.$message.error('不能发送空消息');
  173. return false;
  174. }
  175. var maxLen, errInfo;
  176. if (selType == webim.SESSION_TYPE.C2C) {
  177. maxLen = webim.MSG_MAX_LENGTH.C2C;
  178. errInfo = "消息长度超出限制(最多" + Math.round(maxLen / 3) + "汉字)";
  179. } else {
  180. maxLen = webim.MSG_MAX_LENGTH.GROUP;
  181. errInfo = "消息长度超出限制(最多" + Math.round(maxLen / 3) + "汉字)";
  182. }
  183. if (msgLen > maxLen) {
  184. this.$message.error(errInfo);
  185. return false;
  186. }
  187. this.handleMsgSend(message);
  188. },
  189. handleMsgSend(msgContent) {
  190. var selSess = new webim.Session(selType, this.selToID, this.selToID, this.kefuUrl, Math.round(new Date().getTime() / 1000));
  191. var isSend = true; //是否为自己发送
  192. var seq = -1; //消息序列,-1表示sdk自动生成,用于去重
  193. var random = Math.round(Math.random() * 4294967296); //消息随机数,用于去重
  194. var msgTime = Math.round(new Date().getTime() / 1000); //消息时间戳
  195. var subType; //消息子类型
  196. if (selType == webim.SESSION_TYPE.C2C) {
  197. subType = webim.C2C_MSG_SUB_TYPE.COMMON;
  198. } else {
  199. subType = webim.GROUP_MSG_SUB_TYPE.COMMON;
  200. }
  201. var msg = new webim.Msg(selSess, isSend, seq, random, msgTime, this.loginInfo.identifier, subType, this.loginInfo.identifierNick);
  202. var text_obj, face_obj, tmsg, emotionIndex, emotion, restMsgIndex;
  203. //解析文本和表情
  204. var expr = /\[[^[\]]{1,3}\]/mg;
  205. var emotions = msgContent.match(expr);
  206. if (!emotions || emotions.length < 1) {
  207. text_obj = new webim.Msg.Elem.Text(msgContent);
  208. msg.addText(text_obj);
  209. } else {
  210. for (var i = 0; i < emotions.length; i++) {
  211. tmsg = msgContent.substring(0, msgContent.indexOf(emotions[i]));
  212. if (tmsg) {
  213. text_obj = new webim.Msg.Elem.Text(tmsg);
  214. msg.addText(text_obj);
  215. }
  216. emotionIndex = webim.EmotionDataIndexs[emotions[i]];
  217. emotion = webim.Emotions[emotionIndex];
  218. if (emotion) {
  219. face_obj = new webim.Msg.Elem.Face(emotionIndex, emotions[i]);
  220. msg.addFace(face_obj);
  221. } else {
  222. text_obj = new webim.Msg.Elem.Text(emotions[i]);
  223. msg.addText(text_obj);
  224. }
  225. restMsgIndex = msgContent.indexOf(emotions[i]) + emotions[i].length;
  226. msgContent = msgContent.substring(restMsgIndex);
  227. }
  228. if (msgContent) {
  229. text_obj = new webim.Msg.Elem.Text(msgContent);
  230. msg.addText(text_obj);
  231. }
  232. }
  233. msg.PushInfo = {
  234. "PushFlag": 0,
  235. "Desc": '测试离线推送内容', //离线推送内容
  236. "Ext": '测试离线推送透传内容', //离线推送透传内容
  237. "AndroidInfo": {
  238. "Sound": "android.mp3" //离线推送声音文件路径。
  239. },
  240. "ApnsInfo": {
  241. "Sound": "apns.mp3", //离线推送声音文件路径。
  242. "BadgeMode": 1
  243. }
  244. };
  245. msg.PushInfoBoolean = true; //是否开启离线推送push同步
  246. msg.sending = 1;
  247. msg.originContent = msgContent;
  248. // turnoffFaces_box();
  249. var _this = this;
  250. webim.sendMsg(msg, function (resp) {
  251. _this.addMsg(msg);
  252. _this.message = '';
  253. }, function (err) {
  254. console.log(err)
  255. });
  256. },
  257. addMsg(msg, prepage) {
  258. var messageitem = {
  259. id:'',
  260. message:'',
  261. avatar:'',
  262. time:'',
  263. float:''
  264. };
  265. var isSelfSend, fromAccount, fromAccountNick, fromAccountImage, sessType, subType;
  266. //webim.SESSION_TYPE.GROUP-群聊,
  267. //webim.SESSION_TYPE.C2C-私聊,
  268. sessType = msg.getSession().type();
  269. isSelfSend = msg.getIsSend();//消息是否为自己发的
  270. fromAccount = msg.getFromAccount();
  271. if (!fromAccount) {
  272. return;
  273. }
  274. if (isSelfSend) {//如果是自己发的消息
  275. messageitem.avatar = this.loginInfo.headurl;
  276. messageitem.float = "right";
  277. } else {
  278. messageitem.avatar = this.kefuUrl;
  279. messageitem.float = "left";
  280. }
  281. messageitem.id = msg.random;
  282. messageitem.time = webim.Tool.formatText2Html(webim.Tool.formatTimeStamp(msg.getTime()));
  283. messageitem.message = this.convertMsgtoHtml(msg)
  284. this.messageBox.push(messageitem);
  285. var msgflow = document.getElementsByClassName("msg-inner")[0];
  286. if (prepage) {
  287. //300ms后,等待图片加载完,滚动条自动滚动到底部
  288. if (msgflow.scrollTop == 0) {
  289. setTimeout(function () {
  290. msgflow.scrollTop = 0;
  291. }, 300);
  292. }
  293. } else {
  294. //300ms后,等待图片加载完,滚动条自动滚动到底部
  295. setTimeout(function () {
  296. msgflow.scrollTop = msgflow.scrollHeight;
  297. }, 300);
  298. }
  299. },
  300. sendPic(images, imgName) {
  301. var _this = this;
  302. if (!this.selToID) {
  303. alert("请先选择对话用户");
  304. return;
  305. }
  306. if (!this.selSess) {
  307. this.selSess = new webim.Session(selType, this.selToID, this.selToID, this.kefuUrl, Math.round(new Date().getTime() / 1000));
  308. }
  309. var msg = new webim.Msg(this.selSess, true, -1, -1, -1, this.loginInfo.identifier, 0, this.loginInfo.identifierNick);
  310. var images_obj = new webim.Msg.Elem.Images(images.File_UUID);
  311. for (var i in images.URL_INFO) {
  312. var img = images.URL_INFO[i];
  313. var newImg;
  314. var type;
  315. switch (img.PIC_TYPE) {
  316. case 1://原图
  317. type = 1;//原图
  318. break;
  319. case 2://小图(缩略图)
  320. type = 3;//小图
  321. break;
  322. case 4://大图
  323. type = 2;//大图
  324. break;
  325. }
  326. newImg = new webim.Msg.Elem.Images.Image(type, img.PIC_Size, img.PIC_Width, img.PIC_Height, img.DownUrl);
  327. images_obj.addImage(newImg);
  328. }
  329. msg.addImage(images_obj);
  330. //if(imgName){
  331. // var data=imgName;//通过自定义消息中的data字段保存图片名称
  332. // var custom_obj = new webim.Msg.Elem.Custom(data, '', '');
  333. // msg.addCustom(custom_obj);
  334. //}
  335. //调用发送图片消息接口
  336. webim.sendMsg(msg, function (resp) {
  337. if (selType == webim.SESSION_TYPE.C2C) {//私聊时,在聊天窗口手动添加一条发的消息,群聊时,长轮询接口会返回自己发的消息
  338. _this.addMsg(msg);
  339. }
  340. }, function (err) {
  341. alert(err.ErrorInfo);
  342. });
  343. },
  344. bindScrollHistoryEvent(axtion){
  345. var msgflow = document.getElementsByClassName("msg-inner")[0];
  346. var _this = this;
  347. if (axtion=='init') {
  348. msgflow.onscroll = function () {
  349. if (msgflow.scrollTop == 0) {
  350. msgflow.scrollTop = 10;
  351. if (selType == webim.SESSION_TYPE.C2C) {
  352. _this.getPrePageC2CHistoryMsgs();
  353. }
  354. }
  355. }
  356. }else {
  357. msgflow.onscroll = null;
  358. }
  359. },
  360. getPrePageC2CHistoryMsgs (cbOk, cbError) {
  361. var _this = this;
  362. if (selType == webim.SESSION_TYPE.GROUP) {
  363. _this.$message.error("当前的聊天类型为群聊天,不能进行拉取好友历史消息操作");
  364. return;
  365. }
  366. var tempInfo = getPrePageC2CHistroyMsgInfoMap[_this.selToID];//获取下一次拉取的c2c消息时间和消息Key
  367. var lastMsgTime;
  368. var msgKey;
  369. if (tempInfo) {
  370. lastMsgTime = tempInfo.LastMsgTime;
  371. msgKey = tempInfo.MsgKey;
  372. } else {
  373. _this.$message.error("获取下一次拉取的c2c消息时间和消息Key为空");
  374. return;
  375. }
  376. var options = {
  377. 'Peer_Account': _this.selToID, //好友帐号
  378. 'MaxCnt': reqMsgCount, //拉取消息条数
  379. 'LastMsgTime': lastMsgTime, //最近的消息时间,即从这个时间点向前拉取历史消息
  380. 'MsgKey': msgKey
  381. };
  382. webim.getC2CHistoryMsgs(
  383. options,
  384. function (resp) {
  385. var complete = resp.Complete;//是否还有历史消息可以拉取,1-表示没有,0-表示有
  386. if (resp.MsgList.length == 0) {
  387. webim.Log.warn("没有历史消息了:data=" + JSON.stringify(options));
  388. return;
  389. }
  390. getPrePageC2CHistroyMsgInfoMap[_this.selToID] = {//保留服务器返回的最近消息时间和消息Key,用于下次向前拉取历史消息
  391. 'LastMsgTime': resp.LastMsgTime,
  392. 'MsgKey': resp.MsgKey
  393. };
  394. if (cbOk) {
  395. cbOk(resp.MsgList);
  396. } else {
  397. _this.getHistoryMsgCallback(resp.MsgList, true);
  398. }
  399. },
  400. cbError
  401. );
  402. },
  403. getLastC2CHistoryMsgs (cbOk, cbError) {
  404. var _this = this;
  405. var lastMsgTime = 0;//第一次拉取好友历史消息时,必须传0
  406. var msgKey = '';
  407. var options = {
  408. 'Peer_Account': this.selToID, //好友帐号
  409. 'MaxCnt': reqMsgCount, //拉取消息条数
  410. 'LastMsgTime': lastMsgTime, //最近的消息时间,即从这个时间点向前拉取历史消息
  411. 'MsgKey': msgKey
  412. };
  413. this.selSess = null;
  414. webim.MsgStore.delSessByTypeId(selType, this.selToID);
  415. webim.getC2CHistoryMsgs(
  416. options,
  417. function (resp) {
  418. var complete = resp.Complete;//是否还有历史消息可以拉取,1-表示没有,0-表示有
  419. if (resp.MsgList.length == 0) {
  420. webim.Log.warn("没有历史消息了:data=" + JSON.stringify(options));
  421. return;
  422. }
  423. getPrePageC2CHistroyMsgInfoMap[_this.selToID] = {//保留服务器返回的最近消息时间和消息Key,用于下次向前拉取历史消息
  424. 'LastMsgTime': resp.LastMsgTime,
  425. 'MsgKey': resp.MsgKey
  426. };
  427. if (cbOk)
  428. cbOk(resp.MsgList);
  429. },
  430. cbError
  431. );
  432. },
  433. getHistoryMsgCallback(msgList, prepage) {
  434. var msg;
  435. var prepage = prepage || false;
  436. //如果是加载前几页的消息,消息体需要prepend,所以先倒排一下
  437. if (prepage) {
  438. msgList.reverse();
  439. }
  440. for (var j in msgList) {//遍历新消息
  441. msg = msgList[j];
  442. if (msg.getSession().id() == this.selToID) {//为当前聊天对象的消息
  443. this.selSess = msg.getSession();
  444. //在聊天窗体中新增一条消息
  445. this.addMsg(msg, prepage);
  446. }
  447. }
  448. //消息已读上报,并将当前会话的消息设置成自动已读
  449. webim.setAutoRead(this.selSess, true, true);
  450. },
  451. convertMsgtoHtml(msg) {
  452. var html = "",
  453. elems, elem, type, content;
  454. elems = msg.getElems(); //获取消息包含的元素数组
  455. var count = elems.length;
  456. for (var i = 0; i < count; i++) {
  457. elem = elems[i];
  458. type = elem.getType();//获取元素类型
  459. content = elem.getContent();//获取元素对象
  460. switch (type) {
  461. case webim.MSG_ELEMENT_TYPE.TEXT:
  462. var eleHtml = this.convertTextMsgToHtml(content);
  463. //转义,防XSS
  464. html += webim.Tool.formatText2Html(eleHtml);
  465. break;
  466. case webim.MSG_ELEMENT_TYPE.FACE:
  467. html += this.convertFaceMsgToHtml(content);
  468. break;
  469. case webim.MSG_ELEMENT_TYPE.IMAGE:
  470. if (i <= count - 2) {
  471. var customMsgElem = elems[i + 1];//获取保存图片名称的自定义消息elem
  472. var imgName = customMsgElem.getContent().getData();//业务可以自定义保存字段,demo中采用data字段保存图片文件名
  473. html += this.convertImageMsgToHtml(content, imgName);
  474. i++;//下标向后移一位
  475. } else {
  476. html += this.convertImageMsgToHtml(content);
  477. }
  478. break;
  479. case webim.MSG_ELEMENT_TYPE.SOUND:
  480. html += this.convertSoundMsgToHtml(content);
  481. break;
  482. case webim.MSG_ELEMENT_TYPE.FILE:
  483. html += this.convertFileMsgToHtml(content);
  484. break;
  485. case webim.MSG_ELEMENT_TYPE.LOCATION:
  486. html += this.convertLocationMsgToHtml(content);
  487. break;
  488. case webim.MSG_ELEMENT_TYPE.CUSTOM:
  489. var eleHtml = this.convertCustomMsgToHtml(content);
  490. //转义,防XSS
  491. html += webim.Tool.formatText2Html(eleHtml);
  492. break;
  493. case webim.MSG_ELEMENT_TYPE.GROUP_TIP:
  494. var eleHtml = this.convertGroupTipMsgToHtml(content);
  495. //转义,防XSS
  496. html += webim.Tool.formatText2Html(eleHtml);
  497. break;
  498. default:
  499. webim.Log.error('未知消息元素类型: elemType=' + type);
  500. break;
  501. }
  502. }
  503. return html;
  504. },
  505. convertTextMsgToHtml(content) {
  506. return content.getText();
  507. },
  508. //解析表情消息元素
  509. convertFaceMsgToHtml(content) {
  510. var faceUrl = null;
  511. var data = content.getData();
  512. var index = webim.EmotionDataIndexs[data];
  513. var emotion = webim.Emotions[index];
  514. if (emotion && emotion[1]) {
  515. faceUrl = emotion[1];
  516. }
  517. if (faceUrl) {
  518. return "<img src='" + faceUrl + "'/>";
  519. } else {
  520. return data;
  521. }
  522. },
  523. //解析图片消息元素
  524. convertImageMsgToHtml(content, imageName) {
  525. var smallImage = content.getImage(webim.IMAGE_TYPE.SMALL);//小图
  526. var bigImage = content.getImage(webim.IMAGE_TYPE.LARGE);//大图
  527. var oriImage = content.getImage(webim.IMAGE_TYPE.ORIGIN);//原图
  528. if (!bigImage) {
  529. bigImage = smallImage;
  530. }
  531. if (!oriImage) {
  532. oriImage = smallImage;
  533. }
  534. return "<img name='" + imageName + "' src='" + smallImage.getUrl() + "#" + bigImage.getUrl() + "#" + oriImage.getUrl() + "' style='CURSOR: hand' id='" + content.getImageId() + "' bigImgUrl='" + bigImage.getUrl() + "'/>";
  535. },
  536. handleIMPicUload:function(fileobj){
  537. var file = fileobj.file
  538. console.log("file", file);
  539. var _this = this;
  540. var businessType;//业务类型,1-发群图片,2-向好友发图片
  541. if (selType != webim.SESSION_TYPE.C2C) {//向好友发图片
  542. this.$message.error('不支持群聊');
  543. return;
  544. }
  545. businessType = webim.UPLOAD_PIC_BUSSINESS_TYPE.C2C_MSG;
  546. //封装上传图片请求
  547. var opt = {
  548. 'file': file, //图片对象
  549. 'onProgressCallBack': this.onProgressCallBack, //上传图片进度条回调函数
  550. //'abortButton': document.getElementById('upd_abort'), //停止上传图片按钮
  551. 'To_Account': this.selToID, //接收者
  552. 'businessType': businessType//业务类型
  553. };
  554. //上传图片
  555. webim.uploadPic(opt,
  556. function (resp) {
  557. //上传成功发送图片
  558. _this.sendPic(resp, file.name);
  559. },
  560. function (err) {
  561. alert(err.ErrorInfo);
  562. }
  563. );
  564. },
  565. handleIMPicSuccess:function(){},
  566. beforeIMPicUpload:function(file){
  567. var fileType = file.type;
  568. const isJPG = fileType.indexOf("image") > -1;
  569. if (!isJPG) {
  570. this.$message.error('只能上传图片');
  571. }
  572. return isJPG;
  573. },
  574. togglePhoneBox:function(){
  575. if (this.showPhoneBox) {
  576. this.showPhoneBox = false;
  577. }else {
  578. this.showPhoneBox = true;
  579. }
  580. this.showMsgBox = false;
  581. },
  582. toggleMsgBox:function(){
  583. if (this.showMsgBox) {
  584. this.showMsgBox = false;
  585. }else {
  586. this.showMsgBox = true;
  587. }
  588. this.showPhoneBox = false;
  589. },
  590. webimlogin(){
  591. let _this = this;
  592. let listeners = {
  593. "onConnNotify": this.onConnNotify //监听连接状态回调变化事件,必填
  594. , "jsonpCallback": this.jsonpCallback //IE9(含)以下浏览器用到的jsonp回调函数,
  595. , "onMsgNotify": this.onMsgNotify //监听新消息(私聊,普通群(非直播聊天室)消息,全员推送消息)事件,必填
  596. , "onProfileSystemNotifys": this.onProfileSystemNotifys //监听资料系统(自己或好友)通知事件,选填
  597. , "onKickedEventCall": this.onKickedEventCall //被其他登录实例踢下线
  598. , "onC2cEventNotifys": this.onC2cEventNotifys //监听C2C系统消息通道
  599. };
  600. webim.login(this.loginInfo, listeners, this.loginOptions,
  601. function(resp){
  602. _this.$message.success('webim登录成功');
  603. _this.imloginFlag = true;
  604. },
  605. function(err) {
  606. _this.$message.error('webim登录错误');
  607. }
  608. );
  609. },
  610. onConnNotify(){},
  611. jsonpCallback(){},
  612. onMsgNotify(newMsgList){
  613. //监听新消息事件
  614. var msgList = [];
  615. var dateStart = null;
  616. var dateEnd = null;
  617. //console.warn(newMsgList);
  618. var sess, newMsg, formId;
  619. //获取所有聊天会话
  620. var sessMap = webim.MsgStore.sessMap();
  621. for (var j in newMsgList) {//遍历新消息
  622. newMsg = newMsgList[j];
  623. formId = newMsg.getSession().id();
  624. if (formId.indexOf("AdminKeFu")>-1) {
  625. if (newMsg.getSession().id() == this.selToID) {//为当前聊天对象的消息
  626. this.addMsg(newMsg);
  627. }
  628. msgList.push(newMsg.elems[0].content.text);
  629. }else if(formId.indexOf("User")>-1){
  630. this.$message.success("有的新的消息,请到客服管理查看")
  631. }
  632. }
  633. },
  634. onProfileSystemNotifys(){},
  635. onKickedEventCall(){},
  636. onC2cEventNotifys(){},
  637. },
  638. watch:{
  639. 'userSigFlag':function(value){
  640. if(this.userSigFlag) {
  641. this.webimlogin();
  642. }
  643. },
  644. 'imloginFlag':function(value) {
  645. var _this = this;
  646. if (this.imloginFlag) {
  647. this.bindScrollHistoryEvent('reset');
  648. this.getLastC2CHistoryMsgs(function (msgList) {
  649. _this.getHistoryMsgCallback(msgList);
  650. _this.bindScrollHistoryEvent('init');
  651. //绑定滚动操作
  652. }, function (err) {
  653. alert(err.ErrorInfo);
  654. });
  655. }
  656. }
  657. },
  658. }
  659. </script>
  660. <style scoped>
  661. .contact-box {
  662. position: fixed;
  663. right: 12px;
  664. bottom: 10%;
  665. margin-top: -100px;
  666. z-index: 9999;
  667. }
  668. .contact-box .contact-box-item{
  669. position: relative;
  670. margin-bottom: 6px;
  671. border: 1px solid #999;
  672. }
  673. .contact-box .contact-box-item .box-btn {
  674. width: 48px;
  675. height: 48px;
  676. text-align: center;
  677. display: block;
  678. position: relative;
  679. background: #fff;
  680. cursor: pointer;
  681. }
  682. .contact-box .contact-box-item .box-btn i{
  683. font-size:30px;
  684. margin: 9px;
  685. color: #59a3ec;
  686. display: inline-block;
  687. }
  688. /* .contact-box .contact-box-item .box-btn:hover {
  689. } */
  690. .contact-box .box-btn span{
  691. display: none;
  692. color:#fff;
  693. padding: 8px;
  694. font-size: 14px;
  695. background: #5aa6f1;
  696. }
  697. .contact-box .box-btn:hover span{
  698. display: block;
  699. }
  700. .contact-box .box-btn:hover i{
  701. display: none;
  702. }
  703. .contact-box .contact-phone-box {
  704. border: 1px solid #999;
  705. position: absolute;
  706. bottom: 0px;
  707. right: 56px;
  708. height: 48px;
  709. display:flex;
  710. background: #fff;
  711. width: 230px;
  712. align-items: center;
  713. }
  714. .contact-box .contact-phone-box i {
  715. color: #59a3ec;
  716. font-size:30px;
  717. margin: 9px;
  718. }
  719. .contact-box .contact-phone-box span {
  720. font-size:20px;
  721. margin-left: 15px;
  722. color: #485b6d;
  723. }
  724. .contact-box .contact-info-box {
  725. border: 1px #e5e5e5 solid;
  726. position: absolute;
  727. bottom: 0px;
  728. right: 56px;
  729. display: none;
  730. background: #fff;
  731. width: 175px;
  732. z-index: 10000;
  733. }
  734. .contact-box .msg-box:hover .contact-info-box{
  735. display:block;
  736. color: #485b6d;
  737. font-size:20px;
  738. padding: 5px;
  739. }
  740. .contact-box .contact-msg-box {
  741. border: 1px #e5e5e5 solid;
  742. position: absolute;
  743. bottom: 0px;
  744. right: 56px;
  745. background: #fff;
  746. }
  747. .contact-box .msg-box-panel {
  748. width: 408px;
  749. background-color: #fff;
  750. position: relative;
  751. }
  752. .contact-box .panel-header {
  753. border-bottom: 1px #e5e5e5 solid;
  754. }
  755. .contact-box .panel-header .kf-close {
  756. width: 30px;
  757. height: 20px;
  758. float: right;
  759. cursor: pointer;
  760. margin: 12px 0 0 0;
  761. }
  762. .contact-box .panel-header .kf-h-line {
  763. float: left;
  764. color: #485b6d;
  765. font-size: 16px;
  766. line-height: 40px;
  767. height: 40px;
  768. padding-left: 10px;
  769. }
  770. .contact-box .panel-body {
  771. overflow-x: visible;
  772. overflow-y: auto;
  773. height: 182px;
  774. }
  775. .contact-box .msg-inner {
  776. overflow-y: auto;
  777. overflow-x: hidden;
  778. height: 100%;
  779. border-bottom: 1px #e5e5e5 solid;
  780. }
  781. .contact-box .scroll-y::-webkit-scrollbar {
  782. width: 6px;
  783. height: 3px;
  784. }
  785. .contact-box .scroll-y::-webkit-scrollbar-thumb {
  786. -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.1);
  787. box-shadow: inset 0 0 6px rgba(0,0,0,.1);
  788. border-radius: 2px;
  789. }
  790. .contact-box .scroll-y::-webkit-scrollbar-track {
  791. border-radius: 2px;
  792. }
  793. .contact-box .msg-inner .cell {
  794. margin-bottom: 15px;
  795. }
  796. .contact-box .cell_right {
  797. float: right;
  798. }
  799. .contact-box .clearfix {
  800. clear: both;
  801. }
  802. .contact-box .msg-inner .msg_body {
  803. border: 1px #e5e5e5 solid;
  804. line-height: 22px;
  805. display: inline-block;
  806. padding: 6px;
  807. max-width: 292px;
  808. }
  809. .contact-box .fl {
  810. float: left;
  811. }
  812. .contact-box .msg-inner .msg_body .inner {
  813. color: #465b6e;
  814. }
  815. .contact-box .msg-inner .cell_pic {
  816. width: 40px;
  817. height: 40px;
  818. display: inline-block;
  819. margin: 0 20px;
  820. }
  821. .contact-box .msg-inner .cell_pic .pic {
  822. width: 40px;
  823. height: 40px;
  824. display: flex;
  825. }
  826. .contact-box .msg-inner .cell_pic .pic img {
  827. width: 40px;
  828. height: 40px;
  829. border-radius: 50%;
  830. object-fit: cover;
  831. object-position: center;
  832. }
  833. .contact-box .msg-box-panel .panel-booter .textarea {
  834. border: 1px #fff solid;
  835. padding: 10px 20px;
  836. color: #465b6e;
  837. height: 100px;
  838. resize: none;
  839. width: 100%;
  840. }
  841. .contact-box .msg-box-panel .panel-booter .msg-send-btn-box {
  842. padding: 0 20px 10px 20px;
  843. float: left;
  844. background: #fff;
  845. width: 408px;
  846. }
  847. .contact-box .msg-box-panel .panel-booter .time {
  848. font-size: 12px;
  849. color: #bebebe;
  850. height: 26px;
  851. line-height: 26px;
  852. }
  853. .contact-box .msg-box-panel .panel-booter .msg-send-btn-box .send_btn {
  854. color: #fff;
  855. padding: 6px 20px;
  856. border-radius: 4px;
  857. font-size: 12px;
  858. background: #58a1ed;
  859. border: none;
  860. }
  861. .contact-box .panel-tool {
  862. color: #465b6e;
  863. height: 30px;
  864. border-bottom: 1px #e5e5e5 solid;
  865. display:flex;
  866. align-items: center;
  867. }
  868. .contact-box .panel-tool i {
  869. font-size: 20px;
  870. padding: 0 5px;
  871. margin: 0 5px;
  872. cursor: pointer;
  873. }
  874. .contact-box .panel-tool .icon-face::before {
  875. content: '\1F642';
  876. font-size: 15px;
  877. }
  878. .contact-box .face-box {
  879. width: 304px;
  880. z-index: 10001;
  881. background: #fff;
  882. position: relative;
  883. bottom: 70px;
  884. left: -100px;
  885. border: 2px #e5e5e5 solid;
  886. }
  887. .contact-box .face-box-list li {
  888. display: inline-block;
  889. border-right: 1px #CCC solid;
  890. border-bottom: 1px #CCC solid;
  891. cursor: pointer;
  892. }
  893. .contact-box .face-box-title {
  894. border-bottom: 1px #e5e5e5 solid;
  895. margin: 2px 0;
  896. }
  897. </style>