CustomerService.vue 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. <template>
  2. <div class="autoBox box">
  3. <div class="crumbs">
  4. <el-breadcrumb separator="/">
  5. <el-breadcrumb-item :to="{ path: 'home' }">{{$t('common.Home')}}</el-breadcrumb-item>
  6. <el-breadcrumb-item>{{$t('common.Online')}}</el-breadcrumb-item>
  7. </el-breadcrumb>
  8. </div>
  9. <div class="service">
  10. <div class="serviceBox">
  11. <div style="height: 68px;width: 68px;display: inline-block;position: relative;top: 20px;left: 20px;">
  12. <img src="@/assets/img/helpCenter/CusTitle.png" alt="" style="width: 100%;">
  13. </div>
  14. <div class="onlineTile">{{$t('common.customer')}}</div>
  15. </div>
  16. <div style="width: 100%;">
  17. <!-- 聊天框 -->
  18. <div style="width:66%;height:100%;float:left;border-right:1px solid #bfbfbf;position: relative;">
  19. <!-- 聊天界面 -->
  20. <div id="messageList" style="width: 95%;padding: 20px;color: #666666;height: 500px;overflow-y: auto;">
  21. <div v-for="(item,index) in oldMessageList" style="position: relative;margin: 30px 0">
  22. <div v-if="item.messageType=='2'">
  23. <div style="width:32px;height:32px;display: inline-block;;position: absolute;top: 25px;left: 0;">
  24. <img src="@/assets/img/helpCenter/customerHead.png" alt="" style="width: 100%;">
  25. </div>
  26. <div style="display: inline-block;margin-left: 50px;font-size: 12px;">
  27. <span style="float: left;">{{item.senderName}}</span>
  28. <div style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;">
  29. {{item.sendContent}}
  30. </div>
  31. </div>
  32. <div style="clear: both;"></div>
  33. </div>
  34. <div v-if="item.messageType=='1'">
  35. <div style="width:32px;height:32px;display: inline-block;;position: absolute;top: 25px;right: 0;">
  36. <img src="@/assets/img/helpCenter/customerHead.png" alt="" style="width: 100%;">
  37. </div>
  38. <div style="display: inline-block;margin-right: 50px;font-size: 12px;float: right;">
  39. <span style="float: right;">{{item.senderName}}</span>
  40. <div style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;">
  41. {{item.sendContent}}
  42. </div>
  43. </div>
  44. <div style="clear: both;"></div>
  45. </div>
  46. <div v-if="item.messageType=='3'">
  47. <div style="width:32px;height:32px;display: inline-block;;position: absolute;top: 25px;left: 0;">
  48. <img src="@/assets/img/helpCenter/customerHead.png" alt="" style="width: 100%;">
  49. </div>
  50. <div style="display: inline-block;margin-left: 50px;font-size: 12px;">
  51. <span style="float: left;">{{item.senderName}}</span>
  52. <div style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;">
  53. {{item.sendContent}}
  54. </div>
  55. </div>
  56. <div style="clear: both;"></div>
  57. </div>
  58. </div>
  59. <!-- <div v-if="this.oldMessageList.size == 0">
  60. <div style="width:100%;text-align: center;" >没有更多聊天记录了</div>
  61. </div>
  62. <div v-if="this.oldMessageList.size > 0"></div>
  63. <div style="width:100%;margin: 20px auto;text-align: center;">
  64. <div style="width: 90px;height: 1px;background-color: #666666;display: inline-block;"></div>
  65. 上次聊到这里
  66. <div style="width: 90px;height: 1px;background-color: #666666;display: inline-block;"></div>
  67. </div>
  68. <div style="text-align: center;">
  69. {{date}}
  70. </div>
  71. </div> -->
  72. <!-- 平台客服 -->
  73. <!-- <div v-for="(item,index) in chatList" style="position: relative;margin: 30px 0">-->
  74. <!-- <div style="width:32px;height:32px;display: inline-block;;position: absolute;top: 25px;left: 0;">-->
  75. <!-- <img src="@/assets/img/helpCenter/Customer.png" alt="" style="width: 100%;">-->
  76. <!-- </div>-->
  77. <!-- <div v-if="item.text == ''" style="display: inline-block;margin-left: 50px;font-size: 12px;">-->
  78. <!-- <span style="float: left;">{{item.nickName}}</span>-->
  79. <!-- <div style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;">-->
  80. <!-- {{item.content}}-->
  81. <!-- </div>-->
  82. <!-- </div>-->
  83. <!-- <div v-if="item.text != ''" style="display: inline-block;margin-left: 50px;font-size: 12px;">-->
  84. <!-- <span style="float: left;">{{item.nickName}}</span>-->
  85. <!-- <div style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;">-->
  86. <!-- {{item.content}}-->
  87. <!-- </div>-->
  88. <!-- <div class="quickAnswer">-->
  89. <!-- <ul v-for="(i,to) in item.text">-->
  90. <!-- <li>-->
  91. <!-- {{to + 1}}、{{i.menuName}}-->
  92. <!-- </li>-->
  93. <!-- </ul>-->
  94. <!-- </div>-->
  95. <!-- </div>-->
  96. <!-- <div v-for="(j,to) in item.list" style="position: relative;margin: 30px 0">-->
  97. <!-- <div style="width:32px;height:32px;display: inline-block;;position: absolute;top: 25px;right: 0;">-->
  98. <!-- <img src="@/assets/img/helpCenter/user.png" alt="" style="width: 100%;">-->
  99. <!-- </div>-->
  100. <!-- <div style="display: inline-block;margin-right: 50px;font-size: 12px;float: right;">-->
  101. <!-- <span style="float: right;">{{j.questionerName}}</span>-->
  102. <!-- <div style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;">-->
  103. <!-- {{j.questionerContext}}-->
  104. <!-- </div>-->
  105. <!-- -->
  106. <!-- </div>-->
  107. <!-- -->
  108. <!-- </div>-->
  109. <!-- </div>-->
  110. <!-- <div style="position: relative;margin: 30px 0;">
  111. <div style="width:32px;height:32px;display: inline-block;position: absolute;top: 25px;left: 0;">
  112. <img src="@/assets/img/helpCenter/Customer.png" alt="" style="width: 100%;">
  113. </div>
  114. <div style="display: inline-block;margin-left: 50px;font-size: 12px;">
  115. <span style="float: left;">平台智能在线客服</span>
  116. <div style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;">
  117. 您是想问以下问题吗?快读点选可以获取答案,如果不是,请在输入框提问
  118. </div>
  119. <div class="quickAnswer">
  120. <ul>
  121. <li>
  122. 1、如何修改实名认证手机
  123. </li>
  124. <li>
  125. 2、个人如何实名认证
  126. </li>
  127. <li>
  128. 3、企业如何实名认证
  129. </li>
  130. <li>
  131. 4、注册时选择个人,可以申请成为企业用户吗?
  132. </li>
  133. </ul>
  134. </div>
  135. </div>
  136. </div> -->
  137. <!-- 转人工客服 -->
  138. <div v-if="flag == '0'" style="text-align: center;font-size:12px;line-height: 20px;">
  139. <div @click="toConnect()" style="height: 22px;background-color: #25C4BA;border-radius: 10px;padding: 0 10px;display: inline-block;color: #fff;" class="cursor">
  140. {{$t('common.TransferService')}}
  141. </div>
  142. <div style="height: 22px;background-color: #dff8f2;border-radius: 10px;padding: 0 10px;display: inline-block;color: #44d6b5;">
  143. {{$t('common.CustomerStatus')}}:<span>{{$t(status)}}</span>
  144. </div>
  145. </div>
  146. <!-- 在线客服 -->
  147. <div v-if="flag == '0'" v-for="(item,index) in messageList" style="position: relative;margin: 30px 0">
  148. <!-- <div v-if="item.messageType=='2'">
  149. <div style="width:32px;height:32px;display: inline-block;;position: absolute;top: 25px;left: 0;">
  150. <img src="@/assets/img/helpCenter/userHead.png" alt="" style="width: 100%;">
  151. </div>
  152. <div style="display: inline-block;margin-left: 50px;font-size: 12px;">
  153. <span style="float: left;">{{item.senderName}}</span>
  154. <div style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;">
  155. {{item.sendContent}}
  156. </div>
  157. </div>
  158. <div style="clear: both;"></div>
  159. </div> -->
  160. <div v-if="item.messageType=='1'">
  161. <div style="width:32px;height:32px;display: inline-block;;position: absolute;top: 25px;right: 0;">
  162. <img src="@/assets/img/helpCenter/userHead.png" alt="" style="width: 100%;">
  163. </div>
  164. <div style="display: inline-block;margin-right: 50px;font-size: 12px;float: right;">
  165. <span style="float: right;">{{item.senderName}}</span>
  166. <div style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;">
  167. {{item.sendContent}}
  168. </div>
  169. </div>
  170. <div style="clear: both;"></div>
  171. </div>
  172. <div v-if="item.messageType=='3'">
  173. <div style="width:32px;height:32px;display: inline-block;;position: absolute;top: 25px;left: 0;">
  174. <img src="@/assets/img/helpCenter/userHead.png" alt="" style="width: 100%;">
  175. </div>
  176. <div style="display: inline-block;margin-left: 50px;font-size: 12px;">
  177. <span style="float: left;">{{$t('common.customer')}}</span>
  178. <div style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;" v-html="item.sendContent">
  179. </div>
  180. </div>
  181. <div class="quickAnswer">
  182. <ul v-for="(i,to) in item.umsUserOnlineServiceMenus">
  183. <li style="border-bottom:1px doshed #333333" class="cursor">
  184. <span @click="seek(i,to)">{{to + 1}}.{{i}}</span>
  185. </li>
  186. </ul>
  187. </div>
  188. <div style="clear: both;"></div>
  189. </div>
  190. </div>
  191. <!-- &lt;!&ndash; 用户 &ndash;&gt;-->
  192. <!-- <div v-for="(item,index) in custmerList" style="position: relative;margin: 30px 0">-->
  193. <!-- <div style="width:32px;height:32px;display: inline-block;;position: absolute;top: 25px;right: 0;">-->
  194. <!-- <img src="@/assets/img/helpCenter/user.png" alt="" style="width: 100%;">-->
  195. <!-- </div>-->
  196. <!-- <div style="display: inline-block;margin-right: 50px;font-size: 12px;float: right;">-->
  197. <!-- <span v-if="item.replyingPersonName == null" style="float: right;">{{item.questionerName}}</span>-->
  198. <!-- <div v-if="item.replyingPersonName == null" style="background:#F3F3F3;padding: 0 10px;line-height: 20px;margin-top: 25px;line-height: 38px;border-radius: 5px;">-->
  199. <!-- {{item.questionerContext}}-->
  200. <!-- </div>-->
  201. <!-- </div>-->
  202. <!-- </div>-->
  203. </div>
  204. <div class="down" style="width:100%;position: relative;border-top: 1px solid #bfbfbf;">
  205. <el-input
  206. ref="sendMsg"
  207. type="textarea"
  208. :placeholder="$t('common.EnterContent')"
  209. v-model="contentText"
  210. style="width: 92%;border: none;"
  211. >
  212. </el-input>
  213. <el-button ref="btn"
  214. @click="sendText"
  215. style="position: absolute;right: 10px;top: 45px;text-align:center"
  216. >{{$t('common.Send')}}
  217. </el-button>
  218. </div>
  219. </div>
  220. <!-- 常见问题 -->
  221. <div style="float: right;width: 33.8%;height: 100%;">
  222. <div style="margin: 0 20px;height: 20px;margin-top: 20px;">
  223. <span style="float: left;">
  224. <div style="width: 14px;height: 14px;float: left">
  225. <img src="@/assets/img/helpCenter/question.png" alt="" style="width:100%;">
  226. </div>
  227. <div style="float:left;margin-left:5px;font-size: 18px;color:#0091FF;font-size:14px;font-weight: 600;">
  228. {{$t('common.commonProblem')}}
  229. </div>
  230. </span>
  231. <!-- <span style="float: right;">
  232. <div style="width: 12px;height: 12px;float: left;">
  233. <img src="@/assets/img/helpCenter/change.png" alt="" style="width:100%;">
  234. </div>
  235. <div style="float:left;margin-left:5px;font-size:14px;color:#25C4BA">
  236. 换一批
  237. </div>
  238. </span> -->
  239. </div>
  240. <div style="width: 100%;margin: 40px 0;font-size: 12px;color: #0091FF;">
  241. <ul v-for="(item,index) in menu" style="list-style: disc;margin-left: 40px;">
  242. <li @click="toView('helpCenter',item.id)" style="margin-top: 20px;" >
  243. {{item.name}}
  244. </li>
  245. </ul>
  246. </div>
  247. </div>
  248. <div style="clear: both;"></div>
  249. </div>
  250. </div>
  251. <el-dialog
  252. :title="$i18n.locale=='zh'?'提示':'Reminder'"
  253. :visible.sync="toViewLogin"
  254. :width="$i18n.locale=='zh'?'500px':'750px'"
  255. :height="$i18n.locale=='zh'?'300px':'386px'"
  256. :before-close="toViewLoginChange"
  257. >
  258. <div style="width: 100%;height: 100%;">
  259. <img src="@/assets/img/loginTips.png" alt="" style="width: 180px;height: 180px;margin-left: 20px;">
  260. <div style="float: right;margin-right: 20px;" :style="$i18n.locale=='zh'?'width: 49%;margin-top: 10px;':'width: 453px;margin-top: -25px;'">
  261. <div style="font-size: 20px;font-weight: normal;color: #333333;
  262. font-family: HiraginoSansGB-W3, HiraginoSansGB;
  263. line-height: 40px;">
  264. {{$t('common.ReminderFirst')}}
  265. </div>
  266. <div style="font-size: 16px;font-family: HiraginoSansGB-W3, HiraginoSansGB;
  267. font-weight: normal;color: #666666;line-height: 30px;">
  268. {{$t('common.ReminderSecond')}} <span style="color: #0091FF;font-size: 18px;">{{num}}</span> {{$t('common.ReminderThird')}}
  269. </div>
  270. <div style="font-size: 14px;font-family: HiraginoSansGB-W3, HiraginoSansGB;
  271. font-weight: normal;color: #666666;line-height: 30px;">
  272. {{$t('common.ReminderForth')}}
  273. </div>
  274. <div style="font-size: 14px;font-family: HiraginoSansGB-W3, HiraginoSansGB;
  275. height:33px;line-height:60px;font-weight: normal;color: #0091FF;">
  276. <span style="margin-left: 40px;" class="cursor" @click="toView('login')">
  277. {{$t('common.ReminderFifth')}}
  278. </span>
  279. <span style="margin-left: 10px;" class="cursor" @click="toView('Register')">
  280. {{$t('common.ReminderSixth')}}
  281. </span>
  282. </div>
  283. </div>
  284. </div>
  285. </el-dialog>
  286. </div>
  287. </template>
  288. <script>
  289. import { getDicts } from "@/api/dict";
  290. import { getLevelMenu, saveOrUpdate , addUmsUserOnlineServiceExchangeInformation,getUmsUserOnlineServiceExchangeInformations, } from "@/api/customer/umsUserOnlineServiceExchangeInformation";
  291. import {getOldMessage, getMessage, getAllInformationByCustomer} from "@/api/customer/baseCustomerMessage"
  292. import Base from "@/views/base/Base";
  293. import { getToken, resetToken } from "@/utils/auth";
  294. import {getHelpColumnTree,getHelpColumnContent} from '@/api/operation/help/helpCenterEntity'
  295. export default {
  296. extends: Base,
  297. data () {
  298. return {
  299. num:5,
  300. toViewLogin:false,
  301. customerServiceId: "",
  302. status: "common.Offline",
  303. menu: [],
  304. data:0,
  305. timeout: 30 * 1000,//30秒一次心跳
  306. timeoutObj: null,//心跳心跳倒计时
  307. serverTimeoutObj: null,//心跳倒计时
  308. timeoutnum: null,//断开 重连倒计时
  309. websocket: null,
  310. timestamp: "",
  311. //历史聊天信息
  312. oldMessageList:[],
  313. //当前聊天记录
  314. messageList:[],
  315. flag: "0",
  316. date: new Date(),
  317. params:{
  318. language: this.$i18n.locale.toUpperCase(),
  319. firstLevelStatus: "y",
  320. },
  321. ws: null,
  322. count: 0,
  323. userId: null,
  324. custmerList: [],
  325. chatList:[{
  326. img:'',
  327. nickName:'机器人小智',
  328. content:'下午好,我是机器人小智',
  329. text:[],
  330. list: [],
  331. },
  332. {
  333. img:'',
  334. nickName:'机器人小智',
  335. content:'很高兴为您服务!您是想问以下问题吗?快读点选可以获取答案,如果不是,请输入问题序号',
  336. text:[],
  337. list: [],
  338. }],
  339. contentText: '',// input输入的值
  340. management:[],
  341. userSendMessage: {
  342. id: null,
  343. senderId: '',
  344. senderName: '',
  345. sendContent: '',
  346. receiverId: '',
  347. receiverName: '',
  348. sendingStatus: '',
  349. receivingStatus: '',
  350. messageType: '',
  351. status: '',
  352. createBy: ''
  353. },
  354. }
  355. },
  356. // created () {
  357. // this.getUserId()
  358. // },
  359. mounted () {
  360. //this.timer = setInterval(this.setTimeout, 5000);
  361. this.initWebsocket()
  362. this.$refs.sendMsg.focus()
  363. this.toInitData()
  364. },
  365. beforeDestroy() {
  366. clearInterval(this.timer);
  367. },
  368. updated () {
  369. },
  370. methods: {
  371. // 未登录跳转
  372. loginTipsChange(){
  373. const that=this;
  374. this.num =5;
  375. // clearInterval(timer_interval);
  376. this.timer = setInterval(function() {
  377. if (that.num > 0) {
  378. that.num--;
  379. } else {
  380. if(that.toViewLogin==true){
  381. clearInterval(that.timer);
  382. that.toViewStart('login');
  383. }else {
  384. clearInterval(that.timer);
  385. }
  386. }
  387. }, 1000)
  388. },
  389. // 判断未登录跳转是否关闭
  390. toViewLoginChange(done){
  391. this.toViewLogin=false;
  392. this.num=5;
  393. clearInterval(this.timer);
  394. },
  395. toInitData() {
  396. var language = this.$i18n.locale.toUpperCase();
  397. getHelpColumnTree(language).then((result) => {
  398. this.menu = [];
  399. if (result.data[0].children != null) {
  400. result.data[0].children.forEach(element => {
  401. this.menu.push(element)
  402. });
  403. }
  404. if (result.data[1].children != null) {
  405. result.data[1].children.forEach(element => {
  406. this.menu.push(element)
  407. });
  408. }
  409. if (result.data[2].children != null) {
  410. result.data[2].children.forEach(element => {
  411. this.menu.push(element)
  412. });
  413. }
  414. return;
  415. })
  416. },
  417. seek(i,to){
  418. let user = window.localStorage.getItem("user");
  419. var users = JSON.parse(user);
  420. var userSendMessage = {}
  421. if (users == null) {
  422. userSendMessage.senderId = "0";
  423. if (this.$i18n.locale.toUpperCase() == "ZH") {
  424. userSendMessage.senderName = "游客";
  425. } else {
  426. userSendMessage.senderName = "Visitor";
  427. }
  428. userSendMessage.sendContent = i;
  429. userSendMessage.messageType = '1';
  430. userSendMessage.toMessageType = '3';
  431. this.messageList.push(userSendMessage);
  432. this.websocket.send(JSON.stringify(userSendMessage)) // 调用WebSocket send()发送信息的方法
  433. } else {
  434. userSendMessage.senderId = users.userId;
  435. userSendMessage.senderName = users.username;
  436. userSendMessage.sendContent = i;
  437. userSendMessage.messageType = '1';
  438. userSendMessage.toMessageType = '3';
  439. this.messageList.push(userSendMessage);
  440. this.websocket.send(JSON.stringify(userSendMessage)) // 调用WebSocket send()发送信息的方法
  441. }
  442. },
  443. toViewStart(router, json) {
  444. clearInterval(this.timer);
  445. this.$router.push({ name: router, params: {key:json} });
  446. },
  447. toView(router,id){
  448. this.$store.commit('modify', router);
  449. window.localStorage.setItem('router', router);
  450. const { href } = this.$router.resolve({
  451. name: router,
  452. query: {
  453. key: id
  454. }
  455. });
  456. window.open(href, '_blank');
  457. },
  458. //初始化数据,建立连接
  459. initWebsocket() {
  460. this.timestamp = Date.parse(new Date());
  461. let user = window.localStorage.getItem("user");
  462. if (user != null) {
  463. var users = JSON.parse(user);
  464. var userId = users.userId;
  465. //语言版本
  466. var language = this.$i18n.locale.toUpperCase();
  467. var params = users.userId+",customer,"+users.username+","+language;
  468. } else {
  469. var language = this.$i18n.locale.toUpperCase();
  470. var params = "0"+",customer,"+"游客,"+language;
  471. }
  472. // 判断页面有没有存在websocket连接
  473. if (window.WebSocket) {
  474. this.messageList = [];
  475. var ishttps = 'https:' == document.location.protocol ? true: false;
  476. if(ishttps){
  477. this.websocket = new WebSocket("wss://www.geidcp.com/robot/websocket/"+params)
  478. }else{
  479. this.websocket = new WebSocket("ws://localhost:7028/robot/websocket/"+params)
  480. }
  481. // 连接成功
  482. this.websocket.onopen = this.setOnopenMessage;
  483. // 连接关闭的回调
  484. this.websocket.onclose = this.setOncloseMessage;
  485. // 连接错误
  486. this.websocket.onerror = this.setErrorMessage;
  487. // 收到消息的回调
  488. this.websocket.onmessage = this.clickUserList;
  489. // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
  490. window.onbeforeunload = this.onbeforeunload
  491. }
  492. },
  493. reconnect () { // 重新连接
  494. let self = this;
  495. if(self.lockReconnect) return;
  496. self.lockReconnect = true;
  497. //没连接上会一直重连,设置延迟避免请求过多
  498. self.timeoutnum && clearTimeout(self.timeoutnum);
  499. self.timeoutnum = setTimeout(() => {
  500. //新连接
  501. self.initWebSocket();
  502. self.lockReconnect = false;
  503. }, 5000);
  504. },
  505. reset () { // 重置心跳
  506. var self = this;
  507. // 清除时间
  508. clearTimeout(self.timeoutObj);
  509. clearTimeout(self.serverTimeoutObj);
  510. // 重启心跳
  511. self.start();
  512. },
  513. start () { // 开启心跳
  514. var self = this;
  515. self.timeoutObj && clearTimeout(self.timeoutObj);
  516. self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj);
  517. self.timeoutObj = setTimeout(function(){
  518. //这里发送一个心跳,后端收到后,返回一个心跳消息,
  519. if (self.websocket.readyState == 1) {//如果连接正常
  520. var userSendMessage = {}
  521. userSendMessage.messageType = '1';
  522. userSendMessage.sendContent = "heartBeat";
  523. self.websocketsend(JSON.stringify(userSendMessage));
  524. } else { // 否则重连
  525. self.reconnect();
  526. }
  527. self.serverTimeoutObj = setTimeout(() => {
  528. //超时关闭
  529. self.closeWebSocket();
  530. }, self.timeout);
  531. }, self.timeout)
  532. },
  533. setOnmessageMessage (event) {
  534. },
  535. setErrorMessage () {
  536. var self = this;
  537. //重连
  538. self.reconnect();
  539. console.log("WebSocket连接发生错误" + ' 状态码:' + this.websocket.readyState)
  540. },
  541. setOnopenMessage () {
  542. var self = this;
  543. //开启心跳
  544. // this.getNoReadRecords();
  545. self.start();
  546. console.log("WebSocket连接成功" + ' 状态码:' + this.websocket.readyState)
  547. },
  548. setOncloseMessage () {
  549. var self = this;
  550. //重连
  551. self.reconnect();
  552. console.log( "WebSocket连接关闭" + ' 状态码:' + this.websocket.readyState)
  553. },
  554. onbeforeunload () {
  555. this.closeWebSocket();
  556. },
  557. //websocket发送消息
  558. websocketsend(messsage) {
  559. var self = this;
  560. self.websocket.send(messsage)
  561. },
  562. closeWebSocket() { // 关闭websocket
  563. var self = this;
  564. self.websocket.close()
  565. },
  566. //与客服建立连接
  567. toConnect() {
  568. let user = window.localStorage.getItem("user");
  569. var users = JSON.parse(user);
  570. if (users == null) {
  571. this.toViewLogin = true;
  572. return;
  573. }
  574. this.flag = "1";
  575. var userSendMessage = {}
  576. userSendMessage.senderId = users.userId;
  577. userSendMessage.senderName = users.username;
  578. userSendMessage.sendContent = "联系人工客服";
  579. userSendMessage.messageType = '1';
  580. this.messageList.push(userSendMessage);
  581. this.websocket.send(JSON.stringify(userSendMessage)) // 调用WebSocket send()发送信息的方法
  582. },
  583. //设置滚动条最底
  584. scrollToBottom() {
  585. this.$nextTick(() => {
  586. let div = document.getElementById('messageList');
  587. div.scrollTop = div.scrollHeight;
  588. });
  589. },
  590. //获取之前的聊天记录
  591. getOldUserMessage(){
  592. let user = window.localStorage.getItem('user');
  593. if (user != null) {
  594. var users = JSON.parse(user);
  595. var userId = users.userId;
  596. getOldMessage(userId).then(result => {
  597. if (result.data.baseCustomerMessages != null) {
  598. this.oldMessageList = result.data.baseCustomerMessages;
  599. this.scrollToBottom()
  600. } else {
  601. this.oldMessageList = [];
  602. }
  603. })
  604. }
  605. },
  606. clickUserList:function(e){
  607. let resData = e.data
  608. var send = JSON.parse(resData);
  609. if (send.umsUserOnlineServiceMenus == "null" && send.levelId == "null") {
  610. this.customerServiceId = send.sendContent.replace(/\[|]/g,'').split(",")[0];
  611. }
  612. if (send.sendContent == "心跳机制") {
  613. if (send.umsUserOnlineServiceMenus != "[]") {
  614. this.status = "common.Online"
  615. } else {
  616. this.status = "common.Offline"
  617. }
  618. if (this.flag == "1") {
  619. let user = window.localStorage.getItem("user");
  620. var users = JSON.parse(user);
  621. if (users == null) {
  622. this.toViewLogin = true;
  623. return;
  624. }
  625. if (this.customerServiceId != null) {
  626. getAllInformationByCustomer(users.userId,this.customerServiceId).then(result => {
  627. this.oldMessageList = result.data.allInformationByCustomer;
  628. })
  629. }
  630. }
  631. console.log(send.sendContent)
  632. this.reset();
  633. return
  634. }
  635. if (send.umsUserOnlineServiceMenus != "null") {
  636. send.umsUserOnlineServiceMenus = send.umsUserOnlineServiceMenus.replace(/\[|]/g,'').split(",");
  637. send.umsUserOnlineServiceMenus[0] = " "+send.umsUserOnlineServiceMenus[0]
  638. this.messageList.push(send);
  639. }
  640. if (send.levelId != "null") {
  641. this.toView('helpCenter',send.levelId)
  642. }
  643. if (send.sendContent == "当前没有客服在线!") {
  644. send.umsUserOnlineServiceMenus = null
  645. this.messageList.push(send);
  646. }
  647. if (send.sendContent == "There is no customer service online at present!") {
  648. send.umsUserOnlineServiceMenus = null
  649. this.messageList.push(send);
  650. }
  651. if (send.sendContent == "这个问题我暂时还不会呢,小E还在学习中~如您需要人工服务,请点击上方转人工按钮, 小E帮您转接至客户服务中心提供人工在线客服服务") {
  652. send.sendContent = "这个问题我暂时还不会呢,小E还在学习中~</br>如您需要人工服务,请点击上方转人工按钮, 小E帮您转接至客户服务中心提供人工在线客服服务"
  653. send.umsUserOnlineServiceMenus = null
  654. this.messageList.push(send);
  655. }
  656. if (send.sendContent == "I don't know about this problem for the time being. Xiao E is still learning ~ if you need manual service, please click the switch to manual button at the top, and small e will help you transfer to the customer service center to provide manual online customer service") {
  657. send.sendContent = "I don't know about this problem for the time being. Xiao E is still learning ~ </br>if you need manual service, please click the switch to manual button at the top, and small e will help you transfer to the customer service center to provide manual online customer service"
  658. send.umsUserOnlineServiceMenus = null
  659. this.messageList.push(send);
  660. }
  661. this.scrollToBottom();
  662. this.reset();
  663. },
  664. connectOnlineCustomer() {
  665. // window.open("http://localhost:8080/#/customerOnlineService");
  666. this.$store.commit('modify', 'customerOnlineService');
  667. window.localStorage.setItem('router', 'customerOnlineService');
  668. const { href } = this.$router.resolve({
  669. name: router,
  670. });
  671. window.open(href, '_blank');
  672. },
  673. // getUserId () {
  674. // let time = new Date().getTime()
  675. // let user = window.localStorage.getItem('user');
  676. // var users = JSON.parse(user);
  677. // this.userId = users.userId;
  678. // },
  679. // 发送聊天消息
  680. sendText () {
  681. var userSendMessage = {}
  682. let user = window.localStorage.getItem("user");
  683. let _this = this
  684. // _this.$refs.sendMsg.focus()
  685. // if (!_this.contentText) {
  686. // return false
  687. // }
  688. if (this.flag == "0") {
  689. if (user == null) {
  690. userSendMessage.senderId = "0";
  691. if (this.$i18n.locale.toUpperCase() == "ZH") {
  692. userSendMessage.senderName = "游客";
  693. } else {
  694. userSendMessage.senderName = "Visitor";
  695. }
  696. userSendMessage.sendContent = _this.contentText;
  697. userSendMessage.messageType = '1';
  698. userSendMessage.toMessageType = '3';
  699. this.messageList.push(userSendMessage);
  700. } else {
  701. var users = JSON.parse(user);
  702. userSendMessage.senderId = users.userId;
  703. userSendMessage.senderName = users.username;
  704. userSendMessage.sendContent = _this.contentText;
  705. userSendMessage.messageType = '1';
  706. userSendMessage.toMessageType = '3';
  707. this.messageList.push(userSendMessage);
  708. }
  709. }
  710. if (this.flag == "1") {
  711. var users = JSON.parse(user);
  712. if (user == null) {
  713. this.toViewLogin = true;
  714. return;
  715. }
  716. userSendMessage.senderId = users.userId;
  717. userSendMessage.senderName = users.username;
  718. userSendMessage.sendContent = _this.contentText;
  719. userSendMessage.messageType = '1';
  720. userSendMessage.toMessageType = '2';
  721. this.getOldUserMessage();
  722. }
  723. // this.userSendMessage.receiverId = this.management.questionerId;
  724. // this.userSendMessage.receiverName = this.management.questionerName;
  725. this.websocket.send(JSON.stringify(userSendMessage)) // 调用WebSocket send()发送信息的方法
  726. _this.contentText = ''
  727. this.reset();
  728. },
  729. },
  730. watch: {
  731. '$i18n.locale'(){
  732. this.toInitData();
  733. this.closeWebSocket();
  734. this.initWebsocket();
  735. },
  736. "toViewLogin"(){
  737. if(this.toViewLogin==true){
  738. this.loginTipsChange()
  739. }
  740. }
  741. }
  742. }
  743. </script>
  744. <style scoped>
  745. .message {
  746. padding-top: 60px;
  747. margin-bottom: 60px;
  748. height: 100%;
  749. overflow: hidden;
  750. }
  751. .crumbs {
  752. margin-left: 20px;
  753. margin-bottom: 20px;
  754. }
  755. .box .service>>>.el-textarea__inner {
  756. min-height: 130px !important;
  757. max-height: 130px !important;
  758. border-color: transparent;
  759. resize:none
  760. }
  761. .box {
  762. background: #fff;
  763. padding: 20px 0 50px 0;
  764. }
  765. .service {
  766. width: 95%;
  767. box-shadow: 0 5px 15px #ccc8c8;
  768. border-radius: 5px 5px 0 0;
  769. margin: auto;
  770. }
  771. .service input {
  772. flex: 1;
  773. height: 40px;
  774. font-display: 18px;
  775. }
  776. .service button {
  777. border: 1px solid #bfbfbf;
  778. width: 70px;
  779. height: 40px;
  780. background: #fff;
  781. color: #bfbfbf;
  782. text-align: center;
  783. border-radius: 5px;
  784. margin-left: 10px;
  785. }
  786. .serviceBox{
  787. width: 100%;
  788. height: 60px;
  789. border-bottom: 1px solid #bfbfbf;
  790. background-image: linear-gradient(to right, #8deade, #0be0c4 ,rgb(12, 184, 201));
  791. position:relative;
  792. border-radius: 5px 5px 0 0;
  793. }
  794. .avtive {
  795. display: inline-block;
  796. background: blue;
  797. color: #fff;
  798. padding: 10px;
  799. font-size: 16px;
  800. border-radius: 6px;
  801. margin-right: 10px;
  802. flex-wrap: wrap;
  803. word-break: break-all;
  804. max-width: 220px;
  805. }
  806. .onlineTile{
  807. display: inline-block;
  808. font-size: 16px;
  809. color: rgb(255, 255, 255);
  810. font-weight: 700;
  811. position: relative;
  812. bottom: 30px;
  813. left: 30px;
  814. width: 50%;
  815. }
  816. .management div{
  817. line-height: 50px;
  818. /* text-indent: 30px; */
  819. font-size: 14px;
  820. }
  821. .management div:hover {
  822. color: #ff0000;
  823. cursor: pointer;
  824. }
  825. .quickAnswer{
  826. margin-top: 20px;
  827. width:651px;
  828. }
  829. .quickAnswer ul li {
  830. border-bottom: 1px dashed #bfbfbf;
  831. height: 40px;
  832. line-height: 40px;
  833. padding-left: 20px;
  834. color: #38b5f1;
  835. }
  836. .send{
  837. width:57px;
  838. height:28px;
  839. border:1px solid #bfbfbf;
  840. color: #bfbfbf;
  841. position: absolute;
  842. top: 30px;
  843. right: 20px;
  844. text-align: center;
  845. line-height: 25px;
  846. border-radius: 5px;
  847. }
  848. </style>