TheCurrentSession.vue 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715
  1. <template>
  2. <div class="row allAlignment">
  3. <leftNav/>
  4. <div>
  5. <hader/>
  6. <messageCenter></messageCenter>
  7. <div class="row">
  8. <!-- 聊天列表模块 -->
  9. <div class="sessionList">
  10. <el-collapse>
  11. <el-collapse-item>
  12. <template slot="title">
  13. <span>会话中 <span>({{sessionList.length }})</span></span>
  14. <!-- <span class="sessionList_span">排队人数(10)</span> -->
  15. </template>
  16. <div :class="{session_choose:dataIndex ==index && sessionType ==1}"
  17. class="user session_style" @click="chooseDialogue(1,index)"
  18. v-for="(item,index) in sessionList">
  19. <div class="row allAlignment item-center">
  20. <span style="font-weight:bold;color:#666;font-size:14px;">{{item.name}}</span>
  21. <span style="color:#999;font-size:.12px;">{{item.intime}}</span>
  22. </div>
  23. <div class="row allAlignment item-center">
  24. <div style="width:90%;font-size:.12px;" class="ellipsis">
  25. <span v-html="item.text"></span>
  26. </div>
  27. <span v-if="item.num > 0" class="markNumber">{{item.num}}</span>
  28. </div>
  29. </div>
  30. </el-collapse-item>
  31. <el-collapse-item>
  32. <template slot="title">
  33. <span>已离线<span>({{offlineList.length }})</span></span>
  34. </template>
  35. <div :class="{session_choose:dataIndex == index && sessionType ==2}"
  36. class="user session_style" @click="chooseDialogue(2,index)"
  37. v-for="(item,index) in offlineList">
  38. <div class="row allAlignment item-center">
  39. <span style="font-weight:bold;color:#999;font-size:14px;">{{item.name}}</span>
  40. <span style="color:#999;font-size:12px;">{{item.intime}}</span>
  41. </div>
  42. <div class="row allAlignment item-center">
  43. <div style="width:90%;color:#999;font-size:12px;" class="ellipsis">
  44. <span v-html="item.text"></span>
  45. </div>
  46. </div>
  47. </div>
  48. </el-collapse-item>
  49. <!-- <el-collapse-item>
  50. <template slot="title">
  51. <span>排队中<span>({{lineUp.length}})</span></span>
  52. </template>
  53. <div class="user" v-for="item in lineUp">
  54. <div class="row allAlignment item-center">
  55. <span style="font-weight:bold;color:#666;font-size:14px;">{{item}}</span>
  56. <span style="color:#999;font-size:12px;">{{item}}</span>
  57. </div>
  58. </div>
  59. </el-collapse-item> -->
  60. </el-collapse>
  61. </div>
  62. <!-- 聊天模块 -->
  63. <div class="chat">
  64. <div class="chatTop row item-center allAlignment" style="padding:0 10px;">
  65. <p class="ellipsis"
  66. style="width:40%;font-size:14px;font-weight:bold;color:#666;"
  67. >{{sessionName}}</p>
  68. <div class="row item-center rightAlignment"
  69. style="width:50%;height:100%;color:#999;font-size:12px;">
  70. <p class="row item-center" @click="getServiceList()">
  71. <!-- 转接 -->
  72. <el-popover placement="right" width="400" trigger="click">
  73. <el-table :data="transferList">
  74. <el-table-column width="150" property="groupname" label="组名"></el-table-column>
  75. <el-table-column width="100" property="kfname" label="姓名"></el-table-column>
  76. <el-table-column label="操作">
  77. <template slot-scope="scope">
  78. <el-button size="mini" @click="transfer(scope.$index, scope.row)">转入
  79. </el-button>
  80. </template>
  81. </el-table-column>
  82. </el-table>
  83. <el-button slot="reference"><i style="font-size:14px" class="el-icon-refresh"></i>
  84. 转接
  85. </el-button>
  86. </el-popover>
  87. </p>
  88. <p class="row item-center" style="margin-left:10px;">
  89. <el-button size="mini" type="text" @click="open">
  90. <i style="font-size:15px" class="el-icon-close"></i>结束服务
  91. </el-button>
  92. </p>
  93. </div>
  94. </div>
  95. <div class="chat-box scroll" id='chat_box'>
  96. <!-- 转接 历史信息-->
  97. <div v-if="showHistoryList">
  98. <div v-for="(item,index) in historyList" :key="index">
  99. <!-- 客服消息 -->
  100. <div style="padding:0 10px;margin-top:20px;" class="rightAlignment" v-if="item.from_id.startsWith('KF')" >
  101. <div style="height:37px;font-size:12px;color:#bbb;" class="row item-center rightAlignment">
  102. {{item.time_line | formatDate}}
  103. </div>
  104. <div class="row item-center rightAlignment">
  105. <p v-if="item.content.text != ''" class="chatMsg message_box" v-html="item.content.text"></p>
  106. <div v-if="item.content.img !=''">
  107. <!-- :fit="contain" style="background:#F5F5F5; border-radius: 10px 0 10px 10px;"-->
  108. <el-image style="width: 200px; height: 100px"
  109. @click="handlePictureCardPreview(img_http+item.content.img)"
  110. :src="img_http + item.content.img" :fit="fit"></el-image>
  111. </div>
  112. </div>
  113. </div>
  114. <!-- 用户消息 -->
  115. <div style="padding:0 10px;margin-top:20px;" v-else>
  116. <div style="height:37px;font-size:.12px;color:#bbb;" class="row item-center">
  117. {{item.time_line | formatDate}}
  118. </div>
  119. <div class="row">
  120. <p v-if="item.content.text != ''" class="chatMsg user_box" v-html="item.content.text"></p>
  121. <div v-if="item.content.img != ''">
  122. <el-image style="width: 200px; height: 100px"
  123. @click="handlePictureCardPreview(img_http+item.content.img)"
  124. :src="img_http + item.content.img"
  125. :fit="fit">
  126. </el-image>
  127. </div>
  128. </div>
  129. </div>
  130. </div>
  131. </div>
  132. <div v-for="(item,index) in data" :key="index">
  133. <!-- 系统转接 -->
  134. <!-- <div class="row center" v-if="item.type == 'system'">
  135. <p style="font-size:12px;color:#bbb;">09.30.45 由问答机器人转接</p>
  136. </div> -->
  137. <!-- 用户消息 -->
  138. <div style="padding:0 10px;margin-top:20px;" v-if="item.type == 'user'">
  139. <div style="height:37px;font-size:.12px;color:#bbb;"
  140. class="row item-center"
  141. >{{item.time}}
  142. </div>
  143. <div class="row">
  144. <div v-if="item.content.img != ''">
  145. <!-- :fit="contain " style="width: 100%; height: 100px"-->
  146. <el-image style="width: 200px; height: 100px"
  147. @click="handlePictureCardPreview(img_http+item.content.img)"
  148. :src="img_http + item.content.img" :fit="fit"></el-image>
  149. </div>
  150. <p v-else class="chatMsg user_box" v-html="item.content.text"></p>
  151. </div>
  152. </div>
  153. <!-- 客服消息 -->
  154. <div style="padding:0 10px;margin-top:20px;" class="rightAlignment"
  155. v-if="item.type == 'service'">
  156. <div style="height:37px;font-size:12px;color:#bbb;"
  157. class="row item-center rightAlignment">{{item.time}}
  158. </div>
  159. <div class="row item-center rightAlignment">
  160. <div v-if="item.content.img !=''">
  161. <!-- :fit="contain" style="background:#F5F5F5; border-radius: 10px 0 10px 10px;"-->
  162. <el-image style="width: 200px; height: 100px"
  163. @click="handlePictureCardPreview(img_http+item.content.img)"
  164. :src="img_http + item.content.img" :fit="fit"></el-image>
  165. </div>
  166. <p v-else class="chatMsg message_box" v-html="item.content.text"></p>
  167. </div>
  168. </div>
  169. <!-- 点击图片放大 -->
  170. <el-dialog :visible.sync="dialogVisible">
  171. <img width="100%" :src="dialogImageUrl" alt="">
  172. </el-dialog>
  173. </div>
  174. </div>
  175. <div class="key column allAlignment">
  176. <div class="frce row item-center allAlignment">
  177. <div class="row ">
  178. <!-- <img class="hover"
  179. :src="isFrce?require('@/assets/img/frcea.png'):require('@/assets/img/frce.png')"
  180. @click="frceClick" style="margin-right:16px;"/> -->
  181. <el-popover id="pop" placement="top-start" width="400" trigger="hover">
  182. <ul>
  183. <li class="emoticon" v-for="(item,index) in frceArr" :key="item.id">
  184. <img class="pointer" :src="require(`@/assets/img/${index}.gif`)"
  185. @click="frceCenterClick(item)" alt="">
  186. </li>
  187. </ul>
  188. <el-button class="expression" slot="reference"></el-button>
  189. </el-popover>
  190. <input type="file" id="file" style="display:none;" @change="uploadIMG"/>
  191. <label for="file" class="row item-center" style="height:100%">
  192. <img class="hover" src="@/assets/img/img.png"/>
  193. </label>
  194. </div>
  195. <div>
  196. <i :class="{disable : is_eva_btn}" @click="evaluation()"
  197. class="el-icon-postcard hover evaluation"></i>
  198. </div>
  199. </div>
  200. <textarea draggable="false" class="input scroll" id="input" v-model="inputValue"
  201. @keyup.enter="listenEnter($event)" @keyup.ctrl.enter="lineFeed()"></textarea>
  202. <div class="row rightAlignment" style="width: 100%;">
  203. <div @click="sendMessage()" class="msgInputBtn row center">发送</div>
  204. </div>
  205. </div>
  206. <!-- 发送消息音频提示 -->
  207. <!-- <audio id="send" src="@/assets/audio/send.wav"></audio> -->
  208. </div>
  209. <!-- 快捷回复模块 -->
  210. <div class="FastReply">
  211. <div class="FastReplyHader row item-center">快捷回复</div>
  212. <div class="FastReplySwitch row item-center average">
  213. <p :class="FastReplySwitch=='one'?'active':''" class="hover"
  214. @click="FastReplySwitchClick('one')">公有库</p>
  215. <span style="width:1px;height:18px;background:#ccc;display: block;"></span>
  216. <p :class="FastReplySwitch=='tow'?'active':''"
  217. class="hover"
  218. @click="FastReplySwitchClick('tow')"
  219. >私有库</p>
  220. </div>
  221. <!-- <div class="serch row center">
  222. <div class="serchBox">
  223. <input placeholder="搜索快捷回复" v-model="serch" type="text" />
  224. <img src="@/assets/img/serch.png" />
  225. </div>
  226. </div> -->
  227. <!-- <div> -->
  228. <!-- <el-collapse>
  229. <el-collapse-item>
  230. <template slot="title" name="el-icon-caret-bottom">
  231. <span>常用语</span>
  232. </template> -->
  233. <div class="FastReplyBox">
  234. <!-- <ul class="FastReplyList"> -->
  235. <!-- <li @click="getLanguage(item.content)" class="row cursor_text" v-for="item in FastReply.sysWords" :key="item.id"> -->
  236. <div @click="getLanguage(item.content)" class="row cursor_text item-center"
  237. v-for="item in FastReply.sysWords" :key="item.id" v-if="FastReplySwitch == 'one'">
  238. <el-tooltip class="title_span" effect="light" placement="bottom-start">
  239. <div slot="content">{{item.content}}</div>
  240. <span class="title_span" style=" width: 100%">#{{item.title}}</span>
  241. </el-tooltip>
  242. <!-- <div class="ellipsis" style=" width: 70%">
  243. <span class="content_span">{{item.content}}</span>
  244. </div> -->
  245. </div>
  246. <!-- </li> -->
  247. <div @click="getLanguage(item.content)" class="row cursor_text item-center"
  248. v-for="item in FastReply.userWords" :key="item.id" v-if="FastReplySwitch == 'tow'">
  249. <el-tooltip class="title_span" effect="light" placement="bottom-start">
  250. <div slot="content">{{item.content}}</div>
  251. <span class="title_span" style=" width: 100%">#{{item.title}}</span>
  252. </el-tooltip>
  253. <!-- <div class="ellipsis" style=" width: 70%">
  254. <span class="content_span">{{item.content}}</span>
  255. </div> -->
  256. </div>
  257. <!-- <li class="row cursor_text" v-for="item in FastReply.userWords" :key="item.id">
  258. <div v-if="FastReplySwitch == 'tow'" class="row item-center">
  259. <p style="margin-right:10px;color:#666;font-size:14px;font-weight: bold;"
  260. >#{{item.title}}</p>
  261. <p class="ellipsis" style="width: 60%; color:#999;font-size:14px;">{{item.content}}</p>
  262. </div>
  263. </li> -->
  264. <!-- </ul> -->
  265. </div>
  266. <!-- </el-collapse-item>
  267. </el-collapse> -->
  268. <!-- </div> -->
  269. </div>
  270. <!-- 用户信息模块 -->
  271. <div class="userinfo">
  272. <div style="color:#666;font-weight:bold;font-size:14px;">访问信息</div>
  273. <div style="margin-top:10px;color:#999;font-size:14px;" class="userData wrap">
  274. <!-- <p>来源:{{session_user_info.website}}</p> -->
  275. <p @dblclick="get_ip_Info" class="get_ip" :data-clipboard-text="terminal_IP.ip">
  276. IP地址:{{terminal_IP.ip}}</p>
  277. <p>来源终端:{{terminal_IP.system}}</p>
  278. </div>
  279. <div style="color:#666;font-weight:bold;font-size:14px; margin-top:30px;">用户信息</div>
  280. <div id="user_info_box" style="margin-top:10px;color:#999;font-size:14px;" class="userData wrap">
  281. <div class="user_info_box">
  282. <span>账号:</span>
  283. <input class="user_text" style="background: #ECF4FF;"
  284. v-model="session_user_info.account_name" readonly type="text">
  285. </div>
  286. <div class="user_info_box">
  287. <span>标签:</span>
  288. <el-select style="width:70%;" v-model="value" @focus='focusFun' @change='labelChange'
  289. placeholder="请选择">
  290. <el-option
  291. v-for="item in options"
  292. :key="item.id"
  293. :label="item.name"
  294. :value="item.id">
  295. </el-option>
  296. </el-select>
  297. </div>
  298. <div class="user_info_box">
  299. <span>昵称:</span>
  300. <el-input style="width:70%;" v-model="session_user_info.nick_name"
  301. placeholder="请输入内容"></el-input>
  302. </div>
  303. <div class="user_info_box">
  304. <span>手机:</span>
  305. <el-input @blur='validation_user_info(1)' style="width:70%;"
  306. v-model="session_user_info.account_phone"
  307. placeholder="请输入内容"></el-input>
  308. </div>
  309. <div class="user_info_box">
  310. <span>邮箱:</span>
  311. <el-input @blur='validation_user_info(2)' style="width:70%;"
  312. v-model="session_user_info.account_email"
  313. placeholder="请输入内容"></el-input>
  314. </div>
  315. <div class="user_info_box">
  316. <span>地址:</span>
  317. <el-input style="width:70%;" v-model="session_user_info.address"
  318. placeholder="请输入内容"></el-input>
  319. </div>
  320. <div class="user_info_box">
  321. <span>备注:</span>
  322. <el-input style="width:70%;" v-model="session_user_info.remark"
  323. placeholder="请输入内容"></el-input>
  324. </div>
  325. </div>
  326. <div class=" row rightAlignment">
  327. <div class="userBtn row center" @click="bt_update()">保存</div>
  328. </div>
  329. </div>
  330. </div>
  331. <!-- 截图粘贴 -->
  332. <el-dialog
  333. :close-on-click-modal="true"
  334. :close-on-press-escape="true"
  335. title="是否发送图片"
  336. :visible.sync="dialogPaste"
  337. width="35%">
  338. <!-- :before-close="handleClose" -->
  339. <!-- <span>这是一段信息</span> -->
  340. <el-image
  341. :src="pasteUrl" :fit="fit"></el-image>
  342. <span slot="footer" class="dialog-footer">
  343. <el-button @click="dialogPaste = false">取 消</el-button>
  344. <el-button type="primary" @click="handleClose()">确 定</el-button>
  345. </span>
  346. </el-dialog>
  347. </div>
  348. </div>
  349. </template>
  350. <script>
  351. import "@/css/index.css";
  352. import Clipboard from 'clipboard';
  353. import {mapState, mapGetters} from 'vuex'; //先要引入
  354. import leftNav from "@/components/leftNav";
  355. import hader from "@/components/hader";
  356. import messageCenter from "@/components/messageCenter";
  357. export default {
  358. name: "TheCurrentSession",
  359. data() {
  360. return {
  361. /***********************************/
  362. inputValue: "", //输入框内容
  363. isFrce: false, //表情包开关
  364. frceArr: [], //表情包数组
  365. FastReply: "", //快捷回复
  366. FastReplySwitch: "one", //快捷回复开关
  367. user_info: '',//用户信息
  368. token: "",
  369. time: "",
  370. transferList: [],//转接列表
  371. lineUp: [],//排队列表
  372. conversationId: '',//会话工单
  373. session_user_info: {},//当前会话用户信息
  374. img_http: 'http://kfadmin.bocai186.com',//图片路径域
  375. // img_http: 'http://192.168.2.187:8090',//图片路径域
  376. fit: 'scale-down',//图片渲染样式
  377. is_eva_btn: true,//
  378. trigger_condition: 0,//评价触发条件
  379. webTime: '',//客服会话时间
  380. session_marked: '',//客服当前会话标记
  381. sensitive: [],//客服敏感词数据
  382. userSensitiveWords: [],//用户敏感词
  383. sensitiveNumber: 0,//关键词次数
  384. isTrue: true,//编辑用户信息按钮开关
  385. options: [],
  386. label_id: '',
  387. value: '请选择',
  388. dialogPaste: false,
  389. dialogVisible: false, //图片放大
  390. dialogImageUrl: '', // 放大的图片
  391. dialogUrl: false,
  392. pasteUrl: '',//截屏图片
  393. userSwitching: true,//是否切换完成
  394. terminal_IP: {},//访客设备信息
  395. showHistoryList: false,
  396. historyList: [],
  397. historyTime:'',
  398. }
  399. },
  400. filters: {
  401. /**
  402. * 时间戳转日期自定义时间格式
  403. * timeStamp:时间戳
  404. * custom:转换日期时定义年月日用是什么符号隔开
  405. * isDtae:0=月份、1=日期、3=时间
  406. */
  407. formatDate: function (value, custom = '', isDtae = 3) {
  408. let timeStamp = value;
  409. var date = new Date();
  410. date.setTime(timeStamp * 1000);
  411. var y = date.getFullYear();
  412. var m = date.getMonth() + 1;
  413. m = m < 10 ? ('0' + m) : m;
  414. var d = date.getDate();
  415. d = d < 10 ? ('0' + d) : d;
  416. var h = date.getHours();
  417. h = h < 10 ? ('0' + h) : h;
  418. var minute = date.getMinutes();
  419. var second = date.getSeconds();
  420. minute = minute < 10 ? ('0' + minute) : minute;
  421. second = second < 10 ? ('0' + second) : second;
  422. if (isDtae == 0) {
  423. return y + custom + m //+'student';
  424. } else if (isDtae == 1) {
  425. return y + custom + m + custom + d;
  426. } else if (isDtae == 3) {
  427. return h + ':' + minute;
  428. } else {
  429. return y + '-' + m + '-' + d + ' ' + h + ':' + minute //+ ':' + second;
  430. }
  431. }
  432. },
  433. methods: {
  434. /****************************/
  435. validation_user_info(type) {
  436. if (type == 1 && this.session_user_info.account_phone) {
  437. if (!/^1[34578]\d{9}$/.test(this.session_user_info.account_phone)) {
  438. this.session_user_info.account_phone = '';
  439. this.$message({
  440. message: '这不是一个手机号哦!...',
  441. type: 'warning'
  442. });
  443. }
  444. } else if (type == 2 && this.session_user_info.account_email) {
  445. if (!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.session_user_info.account_email)) {
  446. this.session_user_info.account_email = ''
  447. this.$message({
  448. message: '这不是一个邮箱哦!...',
  449. type: 'warning'
  450. });
  451. }
  452. }
  453. },
  454. /***************图片放大*************** */
  455. handlePictureCardPreview(url) {
  456. this.dialogImageUrl = url;
  457. this.dialogVisible = true;
  458. },
  459. /************回车提交************/
  460. listenEnter(event) {
  461. if (event.keyCode === 13) {
  462. this.inputValue = this.inputValue.replace(/\s/g, '')
  463. // this.inputValue = this.inputValue.replace(/\n /g,'')
  464. this.sendMessage(); // 发送文本
  465. }
  466. },
  467. /************ctrl+center 换行***********/
  468. lineFeed() {
  469. this.inputValue = this.inputValue + '\n'
  470. },
  471. /********************发送获取标签数据指令*******************/
  472. focusFun() {
  473. // console.log('haha');
  474. this.$websocket.send(JSON.stringify({type: 'userlabeall'}));
  475. },
  476. /**************************获取选择标签ID****************/
  477. labelChange(e) {
  478. this.label_id = e;
  479. },
  480. /******************消息数据接收********************/
  481. chatMessage(redata) {
  482. console.log(this.historyList,'historyList');
  483. //console.log(this.data,'data');
  484. //用户离线后会话窗口切换
  485. if (redata.message_type == "userClose") {
  486. console.log(redata)
  487. return false
  488. }
  489. // //用户会话结束窗口切换
  490. if (redata.message_type == "delUser") {
  491. redata.data;
  492. console.log(redata.data, this.session_user_info)
  493. if (redata.data.id == this.session_user_info.id) {
  494. this.session_user_info = {};
  495. this.value = '请选择';
  496. }
  497. return false
  498. }
  499. //获取标签数据信息
  500. if (redata.message_type == "userlabeall") {
  501. if (Object.values(redata.data).length > 0) {
  502. this.options = [];
  503. this.options = Object.values(redata.data);
  504. // this.value = this.options[0].name;
  505. }
  506. return false
  507. }
  508. //接收系统操作信息状态在线客服列表
  509. if (redata.message_type == "onlinekfs") {
  510. this.transferList = [];
  511. this.transferList = this.transferList.concat(redata.data);
  512. return false
  513. }
  514. //接收会话时间
  515. if (redata.message_type == "webTime") {
  516. let data = this.data;
  517. // console.log(data, '接收会话时间');
  518. data[data.length - 1].time = redata.data.webTime
  519. this.$store.dispatch("SET_CURRENT", data);
  520. if(this.historyList.length > 0){
  521. let historyTime = this.historyTime;
  522. this.$set(this.historyList[this.historyTime], 'time', redata.data.webTime);
  523. }
  524. return false
  525. }
  526. //客服手动转接用户成功
  527. if (redata.message_type == "trunconnect") {
  528. this.sessionList.splice(this.dataIndex, 1);
  529. this.$message({
  530. message: '转接用户成功...',
  531. type: 'success'
  532. });
  533. if (this.sessionList.length > 1) {
  534. this.$store.dispatch("SET_NUM", 0);
  535. // this.data = []
  536. } else {
  537. // this.data = [];
  538. this.$store.dispatch("SET_CURRENT", []);//当前会话数据
  539. this.$store.dispatch("SET_SESSION_NAME", '');
  540. }
  541. return false
  542. }
  543. if (redata.message_type == 'chatMessage') {
  544. this.automaticRolling();
  545. }
  546. // 转接历史信息
  547. if (redata.message_type == "connect") {
  548. if (redata.data.history.length > 0) {
  549. console.log(redata, '转接历史消息');
  550. this.showHistoryList = true;
  551. redata.data.history.forEach(res => {
  552. let content = JSON.parse(res.content)
  553. res.content = content;
  554. if (content.text) {
  555. content.text = this.$public.turnFace(content.text,this.$frce)
  556. res.content = content
  557. }
  558. this.historyList.push(res)
  559. })
  560. }
  561. }
  562. },
  563. /*********************图片发送*********************/
  564. uploadIMG(e) {
  565. //console.log(e);
  566. let self = this;
  567. let files = e.target.files || e.dataTransfer.files;
  568. if (!files.length) return;
  569. const isJPG = files.type == 'image/jpeg' || 'image/jpg' || 'image/png' || 'image/svg';
  570. const isLt2M = file.size / 1024 / 1024 < 2;
  571. if (!isJPG) {
  572. this.$message.error('上传只能是图片格式!');
  573. return false;
  574. }
  575. if (!isLt2M) {
  576. this.$message.error('上传图片大小不能超过 2MB!');
  577. return false;
  578. }
  579. let picavalue = files[0];
  580. //console.log(picavalue);
  581. if (picavalue.size / 1000 > 20000) {
  582. this.$message({
  583. message: "图片过大不支持上传",
  584. type: "warning"
  585. });
  586. } else {
  587. this.$public.imgPreview(picavalue, function (imgSrc, formData) {
  588. self.upImg(formData)
  589. });
  590. }
  591. },
  592. /**********************图片上传***********************/
  593. upImg(formData) {
  594. let self = this;
  595. // 数据结构请求
  596. self.post('api/' + self.$ports.uploadImg, formData).then(res => {
  597. //console.log(res.data.data.src)
  598. if (res.data.code == 1) {
  599. let isFirst = true;
  600. //判断客服是否发送的第一句话
  601. if (self.data.length > 0) {
  602. for (let i = 0; i < self.data.length; i++) {
  603. if (self.data[i].type == 'service') {
  604. isFirst = false;
  605. break;
  606. }
  607. }
  608. }
  609. let obj = {
  610. text: '',
  611. img: res.data.data.src,
  612. type: false,
  613. };
  614. let chatList = self.sessionList[self.dataIndex];
  615. // console.log(self.webTime);
  616. //本地存储
  617. chatList.data.push({type: 'service', content: obj, time: self.webTime});
  618. // self.data = [];
  619. // self.data = chatList.data;
  620. // self.$store.dispatch("SET_CURRENT", []);
  621. self.$store.dispatch("SET_CURRENT", chatList.data);
  622. let type = 'chatMessage';
  623. let data = {
  624. from_name: self.user_info.user_name,//发送者
  625. from_avatar: self.user_info.avatar,//发送者头像
  626. from_id: "KF" + self.user_info.id,//发送者id
  627. content: JSON.stringify(obj),
  628. to_id: self.sessionList[self.dataIndex].id,
  629. to_name: self.sessionList[self.dataIndex].name,
  630. conversationId: self.sessionList[self.dataIndex].conversationId,
  631. isFirst: isFirst,//是否是第一句话
  632. sensitiveNumber: 0,//敏感词次数
  633. }
  634. self.websocketsend(JSON.stringify({type, data}))
  635. }
  636. })
  637. },
  638. /*****************转接会话用户确认******************/
  639. transfer(e) {
  640. if (this.sessionList.length > 0) {
  641. this.$confirm('此操作将当前用户转出, 是否继续?', '温馨提示!', {
  642. confirmButtonText: '确定',
  643. cancelButtonText: '取消',
  644. type: 'warning'
  645. }).then(() => {
  646. let type = "changeOtherhKeFu";
  647. let data = {
  648. conversationId: this.sessionType == 1 ? this.sessionList[this.dataIndex].conversationId : this.offlineList[this.dataIndex].conversationId,
  649. togroup: this.transferList[e].groupid,
  650. fromgroup: this.user_info.group_id,
  651. toukfuid: this.transferList[e].kfuid,
  652. fromkfuid: "KF" + this.user_info.id,
  653. uid: this.sessionType == 1 ? this.sessionList[this.dataIndex].id : this.offlineList[this.dataIndex].id,
  654. word: '',
  655. }
  656. //console.log({type,data});
  657. this.websocketsend(JSON.stringify({type, data}))
  658. }).catch(() => {
  659. })
  660. } else {
  661. this.$message({
  662. message: '亲!您没有和用户会话怎么能转接呢。',
  663. type: 'warning'
  664. });
  665. }
  666. },
  667. /******************获取客服人员列表*****************/
  668. getServiceList() {
  669. //console.log(12313);
  670. this.websocketsend(JSON.stringify({"type": "getkfonlines"}))
  671. },
  672. /*****************切换用户会话对象******************/
  673. chooseDialogue(type, index) {
  674. console.log(this.sessionList);
  675. if (this.userSwitching) {
  676. let data = [];
  677. let order_id = '';
  678. this.$store.dispatch("SET_TYPE", type);
  679. this.$store.dispatch("SET_NUM", index);
  680. if (type == 1) {
  681. data = this.sessionList[index].data;
  682. order_id = this.sessionList[index].id;
  683. this.$set(this.sessionList[index], 'num', 0);
  684. this.$store.dispatch("SET_SESSION_NAME", this.sessionList[index].name);
  685. } else if (type == 2) {
  686. data = this.offlineList[index].data;
  687. this.$store.dispatch("SET_SESSION_NAME", this.offlineList[index].name);
  688. order_id = this.offlineList[index].id;
  689. }
  690. this.$store.dispatch("SET_CURRENT", data);//当前会话数据
  691. this.userSwitching = false;
  692. this.get_user(order_id)
  693. } else {
  694. this.$message({
  695. message: '警告!,操作太频繁',
  696. type: 'warning'
  697. });
  698. }
  699. },
  700. /***************关闭当前和用户聊天对话***************/
  701. open() {
  702. let _this = this;
  703. if (this.sessionType == 1) {
  704. if (this.sessionList.length < 1) return
  705. } else {
  706. if (this.offlineList.length < 1) return
  707. }
  708. this.$confirm('此操作将关闭和当前用户通话, 是否继续?', '温馨提示!', {
  709. confirmButtonText: '确定',
  710. cancelButtonText: '取消',
  711. type: 'warning'
  712. }).then(() => {
  713. let to_id = this.sessionType == 1 ? this.sessionList[this.dataIndex].id : this.offlineList[this.dataIndex].id;
  714. let conversationId = this.sessionType == 1 ? this.sessionList[this.dataIndex].conversationId : this.offlineList[this.dataIndex].conversationId;
  715. let data = {
  716. "type": "kfCloseUser",
  717. data: {
  718. to_id,
  719. kf_id: "KF" + _this.user_info.id,
  720. group_id: _this.user_info.group_id,
  721. conversationId: conversationId,
  722. type: 3,
  723. }
  724. }
  725. if (this.sessionType == 1) {
  726. let sessionList = this.sessionList;
  727. sessionList.splice(this.dataIndex, 1);
  728. if (sessionList.length > 0) {
  729. this.$store.dispatch("SET_CURRENT", sessionList[0]);//当前会话数据
  730. this.$store.dispatch("SET_SESSION_NAME", sessionList[0].name);
  731. } else {
  732. this.$store.dispatch("SET_CURRENT", []);//当前会话数据
  733. this.$store.dispatch("SET_SESSION_NAME", '');
  734. }
  735. } else {
  736. let offlineList = this.offlineList;
  737. offlineList.splice(this.dataIndex, 1);
  738. this.$store.dispatch("SET_CURRENT", []);//当前会话数据
  739. this.$store.dispatch("SET_SESSION_NAME", '');
  740. }
  741. this.websocketsend(JSON.stringify(data))
  742. }).catch(() => {
  743. // this.$message({
  744. // type: 'info',
  745. // message: '已取消删除'
  746. // });
  747. });
  748. },
  749. /*****************数据发送方法调用******************/
  750. websocketsend(Data) {
  751. this.$websocket.send(Data);
  752. this.automaticRolling();
  753. },
  754. // 消息发送声音提示
  755. sendAudio() {
  756. let send = new Audio()
  757. send.src = "../../static/audio/send.wav"
  758. send.play()
  759. },
  760. /*********************发送消息*********************/
  761. sendMessage() {
  762. if (!this.inputValue) return;
  763. if (this.sessionType == 2) {
  764. this.$message({
  765. message: '只能给在线用户发送消息哦...',
  766. type: 'warning'
  767. });
  768. return false;
  769. }
  770. // if(this.offlineList.length <= 0 ) return
  771. let isFirst = true, sensitiveNumber = 0;
  772. this.isFrce = false;
  773. //判断客服是否发送的第一句话
  774. if (this.data.length > 0) {
  775. for (let i = 0; i < this.data.length; i++) {
  776. if (this.data[i].type == 'service') {
  777. isFirst = false;
  778. break;
  779. }
  780. }
  781. }
  782. this.historyTime = this.historyList.length - 1;
  783. //检测发送信息是否含有敏感词
  784. let sensitive_data = this.$public.shieldingKeyword(this.$public.turnFace(this.inputValue, this.$frce), this.sensitive);
  785. //组合发送数据
  786. let data = {
  787. from_name: this.user_info.user_name,//发送者
  788. from_avatar: this.user_info.avatar,//发送者头像
  789. from_id: "KF" + this.user_info.id,//发送者id
  790. content: JSON.stringify({
  791. text: this.inputValue,
  792. img: '',
  793. }),
  794. to_id: this.sessionList[this.dataIndex].id,
  795. to_name: this.sessionList[this.dataIndex].name,
  796. conversationId: this.sessionList[this.dataIndex].conversationId,
  797. isFirst: isFirst,//是否是第一句话
  798. sensitiveNumber: this.sensitiveNumber,//敏感词次数
  799. }
  800. let chatList = this.sessionList[this.dataIndex];
  801. //有敏感词提示并且禁止发送
  802. if (sensitive_data.num == 0) {
  803. // 本地储存
  804. chatList.data.push({
  805. type: 'service', content: {
  806. text: this.$public.turnFace(this.inputValue, this.$frce),
  807. img: '',
  808. }, time: this.time[1]
  809. });
  810. //this.data = [];
  811. //标记当前会话位置
  812. this.session_marked = chatList.data.length - 1;
  813. //this.data = chatList.data;
  814. this.$store.dispatch("SET_CURRENT", chatList.data);//当前会话数据
  815. this.websocketsend(JSON.stringify({type: 'chatMessage', data}))
  816. this.sendAudio();
  817. this.inputValue = '';
  818. this.sensitiveNumber = 0;
  819. } else {
  820. this.$message({
  821. message: '敏感词' + sensitive_data.text,
  822. type: 'warning'
  823. });
  824. //计算关键词次数
  825. this.sensitiveNumber = this.sensitiveNumber + sensitive_data.num;
  826. }
  827. },
  828. /******************开启或关闭表情包******************/
  829. frceClick() {
  830. this.isFrce = !this.isFrce;
  831. },
  832. /*******************发送评价指令*******************/
  833. evaluation() {
  834. if (!this.is_eva_btn && this.sessionType == 1) {
  835. this.$message({
  836. message: '评价指令已发送',
  837. type: 'success'
  838. });
  839. let type = 'getEvaluate';
  840. let data = {
  841. conversationId: this.sessionList[this.dataIndex].conversationId,
  842. to_id: this.sessionList[this.dataIndex].id,
  843. }
  844. this.sessionList[this.dataIndex].isEva = 10;
  845. this.$store.dispatch("SET_SESSION", this.sessionList);
  846. this.websocketsend(JSON.stringify({type, data}));
  847. this.is_eva_btn = true;
  848. } else if (this.sessionType == 2) {
  849. this.$message.error('用户已离线指令无法发送');
  850. } else {
  851. this.$message.error('评价指令无法发送');
  852. }
  853. },
  854. /******************查询快捷数据信息*****************/
  855. quickReplyInfo() {
  856. let obj = {
  857. headers: {
  858. apiToken: this.$md5("userwords" + "customer-service" + "index" + "service"),
  859. userToken: this.token
  860. }
  861. };
  862. this.get("api" + this.$ports.FastReply.userWords, obj).then(res => {
  863. if (res.data.code == 1) {
  864. this.FastReply = res.data.data;
  865. }
  866. });
  867. },
  868. /******************获取快捷语文字******************/
  869. getLanguage(e) {
  870. // console.log(e, "公有库");
  871. this.inputValue = this.inputValue + e;
  872. },
  873. /*****************表情包输入框赋值******************/
  874. frceCenterClick(text) {
  875. this.inputValue = this.inputValue + "#" + text + "/";
  876. //console.log(this.inputValue);
  877. },
  878. /******************* 快捷语库开关 ******************/
  879. FastReplySwitchClick(num) {
  880. this.FastReplySwitch = num;
  881. },
  882. /*****************获取当前聊天用户信息****************/
  883. get_user(id) {
  884. let obj = {
  885. headers: {
  886. "apiToken": this.$md5('accountInfo' + "customer-service" + 'service' + 'service'),
  887. 'userToken': this.token
  888. },
  889. account_id: id
  890. };
  891. this.post('api' + this.$ports.userInfo.accountInfo, obj).then(res => {
  892. if (res.data.code == 1) {
  893. this.session_user_info = res.data.data;
  894. this.value = res.data.data.label
  895. this.userSwitching = true;
  896. }
  897. })
  898. },
  899. /********************获取配置信息********************/
  900. get_config_info() {
  901. let obj = {
  902. headers: {
  903. apiToken: this.$md5("minround" + "customer-service" + "evaluate" + "index"),
  904. userToken: this.token
  905. }
  906. };
  907. this.get("api/" + this.$ports.minRound, obj).then(res => {
  908. if (res.data.code == 1) {
  909. this.trigger_condition = res.data.data.systemconfig_data;
  910. }
  911. });
  912. },
  913. /***********发送消息或接收消息后自动滚动高度*************/
  914. automaticRolling() {
  915. this.$nextTick(() => {
  916. let msg = document.getElementById('chat_box') // 获取对象
  917. msg.scrollTop = msg.scrollHeight // 滚动高度
  918. })
  919. },
  920. /**************获取敏感词*****************/
  921. getSensitive() {
  922. let obj = {
  923. headers: {
  924. "apiToken": this.$md5('sensitivewords' + "customer-service" + 'index' + 'index'),
  925. 'userToken': this.token
  926. }
  927. };
  928. this.post('api' + this.$ports.sensitiveWords, '', obj).then(res => {
  929. if (res.data.code == 1) {
  930. res.data.data.serverSensitive.forEach(res => {
  931. this.sensitive.push(res.sensitivewords_word)
  932. })
  933. res.data.data.userSensitive.forEach(res => {
  934. this.userSensitiveWords.push(res.sensitivewords_word)
  935. })
  936. }
  937. })
  938. },
  939. /********************获取vuex数据***********************/
  940. get_vuex_info() {
  941. let getters = this.$store.getters
  942. this.token = getters.get_user_info.token;//token
  943. this.user_info = getters.get_user_info;//用户消息
  944. this.time = JSON.parse(sessionStorage.getItem("time"));
  945. },
  946. /**********************编辑用户信息**********************/
  947. bt_update() {
  948. if (!this.isTrue) return false;
  949. this.isTrue = false;
  950. let obj = {
  951. headers: {
  952. "apiToken": this.$md5('update' + "customer-service" + 'service' + 'service'),
  953. 'userToken': this.token
  954. },
  955. account_id: this.session_user_info.id,
  956. nick_name: this.session_user_info.nick_name,
  957. account_email: this.session_user_info.account_email,
  958. phone: this.session_user_info.account_phone,
  959. address: this.session_user_info.address,
  960. remark: this.session_user_info.remark,
  961. label_id: this.label_id
  962. };
  963. this.post('api' + this.$ports.userInfo.update, obj).then(res => {
  964. if (res.data.code == 1) {
  965. this.$message({
  966. showClose: true,
  967. message: `恭喜你,${res.data.msg}`,
  968. type: 'success'
  969. });
  970. }
  971. this.isTrue = true;
  972. })
  973. },
  974. /******************qq截图粘贴---获取剪切板数据*****************/
  975. getClipboardData(e) {
  976. // 添加到事件对象中的访问系统剪贴板的接口
  977. let clipboardData = e.clipboardData,
  978. i = 0,
  979. items, item, types;
  980. if (clipboardData) {
  981. items = clipboardData.items;
  982. if (!items) {
  983. return;
  984. }
  985. item = items[0];
  986. // 保存在剪贴板中的数据类型
  987. types = clipboardData.types || [];
  988. for (; i < types.length; i++) {
  989. if (types[i] === 'Files') {
  990. item = items[i];
  991. break;
  992. }
  993. }
  994. // 判断是否为图片数据
  995. if (item && item.kind === 'file' && item.type.match(/^image\//i)) {
  996. this.imgReader(item);
  997. }
  998. }
  999. },
  1000. /**********qq截图粘贴---获取剪切板图片信息进行转换blob***********/
  1001. imgReader(item) {
  1002. let _this = this;
  1003. var blob = item.getAsFile(), reader = new FileReader();
  1004. // 读取文件后将其显示在网页中
  1005. reader.onload = function (e) {
  1006. var img = new Image();
  1007. img.src = e.target.result;
  1008. _this.dialogPaste = true;
  1009. _this.pasteUrl = e.target.result;
  1010. // console.log(img.src)
  1011. //document.body.appendChild( img );
  1012. };
  1013. // 读取文件
  1014. reader.readAsDataURL(blob);
  1015. },
  1016. /*******************qq截图粘贴---监听时间捆绑*****************/
  1017. paste() {
  1018. document.getElementById('input').addEventListener('paste', this.getClipboardData);
  1019. },
  1020. /**********************qq截图粘贴---发送截图*****************/
  1021. handleClose(done) {
  1022. this.dialogPaste = false;
  1023. let blob = this.$public.dataURItoBlob(this.pasteUrl)
  1024. let self = this;
  1025. var formData = new FormData();
  1026. formData.append("file", blob);
  1027. self.upImg(formData);
  1028. },
  1029. /****************双击获取ip*******************/
  1030. get_ip_Info() {
  1031. var clipboard = new Clipboard(".get_ip")
  1032. clipboard.on('success', e => {
  1033. // console.log('复制成功')
  1034. this.$message({
  1035. message: '复制成功',
  1036. type: 'success'
  1037. });
  1038. // 释放内存
  1039. clipboard.destroy()
  1040. })
  1041. clipboard.on('error', e => {
  1042. // 不支持复制
  1043. this.$message({
  1044. message: '该浏览器不支持自动复制',
  1045. type: 'warning'
  1046. });
  1047. // 释放内存
  1048. clipboard.destroy()
  1049. })
  1050. },
  1051. /****************访问信息和评价状态***************/
  1052. accessTerminal(data) {
  1053. if (this.sessionType == 1) {
  1054. let List = this.sessionList[this.dataIndex];
  1055. if (data == 'eva') {
  1056. if (!List) return false
  1057. // console.log(List,'对话信息');
  1058. if (List.isEva == 10) {
  1059. this.is_eva_btn = true;
  1060. } else if (List.isEva != 10) {
  1061. if (this.data.length > this.trigger_condition) {
  1062. List.isEva = 100;
  1063. this.is_eva_btn = false;
  1064. } else {
  1065. this.is_eva_btn = true;
  1066. }
  1067. }
  1068. this.sessionList[this.dataIndex] = List
  1069. this.$store.dispatch("SET_SESSION", this.sessionList)
  1070. } else {
  1071. if (List) {
  1072. this.terminal_IP = {
  1073. system: List.system + '-' + List.browse,
  1074. ip: List.ip
  1075. }
  1076. } else {
  1077. this.terminal_IP = {}
  1078. }
  1079. }
  1080. } else if (this.sessionType == 2) {
  1081. let List = this.offlineList[this.dataIndex];
  1082. // if(data == 'eva'){
  1083. // if (this.data.length > this.trigger_condition){
  1084. // List.isEva = 100;
  1085. // }
  1086. // }else{
  1087. if (List) {
  1088. this.terminal_IP = {
  1089. system: List.system + '-' + List.browse,
  1090. ip: List.ip
  1091. }
  1092. } else {
  1093. this.terminal_IP = {}
  1094. }
  1095. // }
  1096. }
  1097. }
  1098. },
  1099. /**
  1100. * 挂载前执行
  1101. */
  1102. mounted() {
  1103. //获取vuex里面数据
  1104. this.get_vuex_info();
  1105. let _this = this;
  1106. this.get_config_info();
  1107. //客服人员登陆会话
  1108. if (this.$store.getters.get_is_init) {
  1109. // this.$websocket.onmessage = this.;
  1110. _this.websocketsend(JSON.stringify({
  1111. type: 'init',
  1112. data: {
  1113. uid: 'KF' + _this.user_info.id,
  1114. group: _this.user_info.group_id,
  1115. token: this.token,
  1116. name: _this.user_info.user_name,
  1117. avatar: _this.user_info.user_avatar,
  1118. }
  1119. }));
  1120. this.$store.dispatch("SET_IS_INIT", false);
  1121. }
  1122. //获取客服快捷语
  1123. this.quickReplyInfo();
  1124. //获取敏感词
  1125. this.getSensitive();
  1126. //获取
  1127. this.frceArr = this.$frce;
  1128. //调用截图粘贴捆绑方法
  1129. this.paste();
  1130. //
  1131. this.accessTerminal();
  1132. //
  1133. if (this.sessionList.length > 0) {
  1134. if (this.sessionList[this.dataIndex].isEva == 100 && this.sessionList[this.dataIndex]) {
  1135. this.is_eva_btn = false;
  1136. }
  1137. }
  1138. },
  1139. beforeDestroy() {
  1140. document.getElementById('input').removeEventListener('paste', this.getClipboardData)
  1141. },
  1142. /**
  1143. * 事件监听
  1144. */
  1145. watch: {
  1146. get_session_message(e) {
  1147. this.chatMessage(e)
  1148. },
  1149. sessionList(e) {
  1150. this.accessTerminal(e)
  1151. },
  1152. offlineList(e) {
  1153. this.accessTerminal(e)
  1154. },
  1155. /*****************评价按钮显示隐藏处理*****************/
  1156. get_is_eva_btn(data) {
  1157. this.accessTerminal('eva')
  1158. }
  1159. },
  1160. /**
  1161. * 计算属性
  1162. */
  1163. computed: {
  1164. ...mapGetters({
  1165. data: 'get_current',
  1166. sessionName: 'get_session_name',
  1167. sessionList: 'get_session',
  1168. offlineList: 'get_offline',
  1169. dataIndex: 'get_num',
  1170. sessionType: 'get_type',
  1171. get_user_info: 'get_session_user',
  1172. // is_eva_btn:'get_is_eva_btn',
  1173. }),
  1174. get_session_message() {
  1175. return this.$store.getters.get_session_message;
  1176. },
  1177. /****************判断是否可以点击评价*****************/
  1178. get_is_eva_btn() {
  1179. return this.data;
  1180. }
  1181. },
  1182. components: {
  1183. leftNav,
  1184. hader,
  1185. messageCenter
  1186. }
  1187. };
  1188. </script>
  1189. <style>
  1190. .el-icon-arrow-right:before {
  1191. content: "\E791";
  1192. color: #ccc;
  1193. }
  1194. .emoticon {
  1195. width: 30px;
  1196. height: 30px;
  1197. display: inline-block;
  1198. }
  1199. #pop .expression {
  1200. display: inline-block;
  1201. width: 20px;
  1202. height: 20px;
  1203. background: url("./../assets/img/frce.png") no-repeat;
  1204. background-size: 100% 100%;
  1205. cursor: pointer;
  1206. margin-right: 10px;
  1207. }
  1208. #pop .expression:hover {
  1209. background: url("./../assets/img/frcea.png") no-repeat;
  1210. background-size: 100% 100%;
  1211. }
  1212. .session_choose {
  1213. background: #F6F8FF;
  1214. }
  1215. .session_style:hover {
  1216. /* background:#F6F8FF; */
  1217. background: #ECF4FF;
  1218. cursor: pointer;
  1219. }
  1220. .sessionList {
  1221. width: 16vw;
  1222. background: #fff;
  1223. }
  1224. .markNumber {
  1225. display: inline-block;
  1226. width: 20px;
  1227. height: 20px;
  1228. border-radius: 50%;
  1229. background: #f60;
  1230. font-size: 12px;
  1231. color: #fff;
  1232. text-align: center;
  1233. line-height: 20px;
  1234. }
  1235. .el-collapse-item__header {
  1236. position: relative;
  1237. font-size: 14px;
  1238. font-weight: bold;
  1239. color: #666;
  1240. font-family: PingFang SC;
  1241. padding-left: 32px;
  1242. height: 49px;
  1243. justify-content: space-between;
  1244. padding-right: 10px;
  1245. }
  1246. .el-collapse-item__header.is-active {
  1247. border-bottom: 1px solid #d5e5ff;
  1248. }
  1249. .el-collapse-item__header {
  1250. border-bottom: 1px solid #d5e5ff;
  1251. }
  1252. .el-icon-arrow-right {
  1253. position: absolute;
  1254. left: 10px;
  1255. top: auto;
  1256. }
  1257. .sessionList_span {
  1258. color: #999;
  1259. }
  1260. .user {
  1261. padding: 10px;
  1262. }
  1263. .evaluation {
  1264. font-size: 24px;
  1265. color: #969696;
  1266. }
  1267. .el-collapse-item__content {
  1268. padding-bottom: 0;
  1269. }
  1270. .chat {
  1271. width: 40vw;
  1272. height: 93vh;
  1273. border: 1px solid #d5e5ff;
  1274. border-top: none;
  1275. background: #fff;
  1276. }
  1277. .user_text {
  1278. border: 1px solid #ECF4FF;
  1279. color: #999;
  1280. line-height: 30px;
  1281. width: 70%;
  1282. }
  1283. .user_text:focus {
  1284. outline: none;
  1285. }
  1286. .chatTop {
  1287. height: 50px;
  1288. border-bottom: 1px solid #d5e5ff;
  1289. }
  1290. .chat-box {
  1291. height: 62vh;
  1292. /* background: red; */
  1293. /* padding: 40px 0; */
  1294. padding-bottom: 10px;
  1295. border-bottom: 1px solid #d5e5ff;
  1296. overflow-x: hidden;
  1297. overflow-y: auto;
  1298. }
  1299. .chatMsg {
  1300. display: inline-block;
  1301. padding: 10px;
  1302. font-size: 14px;
  1303. max-width: 85%;
  1304. word-wrap: break-word;
  1305. }
  1306. p {
  1307. margin-block-start: 0em;
  1308. margin-block-end: 0em;
  1309. margin-inline-start: 0px;
  1310. margin-inline-end: 0px;
  1311. }
  1312. .frce {
  1313. height: 0.38rem;
  1314. width: 100%;
  1315. padding: 16px 10px;
  1316. }
  1317. .input {
  1318. height: 100px;
  1319. background: #fff;
  1320. resize: none;
  1321. font-size: 14px;
  1322. margin: 0 10px;
  1323. border: none;
  1324. /* border: 1px solid #d5e5ff; */
  1325. }
  1326. .input:focus {
  1327. outline: none;
  1328. border: none;
  1329. }
  1330. .user_info_box {
  1331. margin: 10px 0;
  1332. }
  1333. .title_span {
  1334. /* width: 100%; */
  1335. margin: 4px 2px;
  1336. color: #666;
  1337. font-size: 14px;
  1338. font-weight: bold;
  1339. }
  1340. .content_span {
  1341. color: #999;
  1342. font-size: 14px;
  1343. }
  1344. .key {
  1345. /* width: 27.8vw; */
  1346. /* position: absolute; */
  1347. bottom: 22px;
  1348. height: 23vh;
  1349. /* background: #409EFF; */
  1350. }
  1351. .msgInputBtn {
  1352. right: 10px;
  1353. bottom: 10px;
  1354. width: 60px;
  1355. height: 30px;
  1356. /* background:#ECF4FF; */
  1357. background: #5399f5;
  1358. margin-right: 10px;
  1359. border-radius: 5px;
  1360. font-size: 14px;
  1361. color: #fff;
  1362. cursor: pointer;
  1363. }
  1364. /* .msgInputBtn:hover{
  1365. background:#5399f5;
  1366. } */
  1367. .frceBox {
  1368. position: absolute;
  1369. /* top: 25vw; */
  1370. bottom: 25vh;
  1371. left: 31.5vw;
  1372. width: 28vw;
  1373. height: 25vh;
  1374. background: #fff;
  1375. border: 1px solid #d5e5ff;
  1376. overflow-x: hidden;
  1377. overflow-y: auto;
  1378. z-index: 999999;
  1379. }
  1380. .frceBox p {
  1381. width: 50px;
  1382. height: 50px;
  1383. }
  1384. .FastReply {
  1385. width: 18vw;
  1386. height: 92vh;
  1387. border-right: 1px solid #d5e5ff;
  1388. background: #fff;
  1389. }
  1390. .FastReplyBox {
  1391. padding: 0.4rem 0;
  1392. height: 80vh;
  1393. overflow-x: hidden;
  1394. overflow-y: auto;
  1395. }
  1396. .FastReplyHader {
  1397. height: 50px;
  1398. border-bottom: 1px solid #d5e5ff;
  1399. padding: 0 10px;
  1400. font-size: 14px;
  1401. color: #666;
  1402. font-weight: bold;
  1403. }
  1404. .FastReplySwitch {
  1405. height: 50px;
  1406. border-bottom: 1px solid #d5e5ff;
  1407. color: #666;
  1408. font-size: 14px;
  1409. padding: 0 40px;
  1410. }
  1411. .FastReplySwitch p.active {
  1412. position: relative;
  1413. color: #5399f5;
  1414. }
  1415. .FastReplySwitch p.active::after {
  1416. content: "";
  1417. display: inline-block;
  1418. position: absolute;
  1419. width: 42px;
  1420. height: 2px;
  1421. left: 1px;
  1422. bottom: -15px;
  1423. background: #5399f5;
  1424. }
  1425. ul {
  1426. margin-block-start: 0.4em;
  1427. margin-block-end: 0.4em;
  1428. }
  1429. .cursor_text {
  1430. cursor: pointer;
  1431. margin: 10px 20px;
  1432. }
  1433. .cursor_text:hover {
  1434. color: #d5e5ff;
  1435. background: #f6f8ff;
  1436. }
  1437. .serch {
  1438. padding: 20px 10px;
  1439. }
  1440. .disable {
  1441. color: #f0f0f0 !important;
  1442. }
  1443. .serchBox {
  1444. width: 200px;
  1445. height: 40px;
  1446. border: 1px solid #eee;
  1447. position: relative;
  1448. }
  1449. .serchBox img {
  1450. position: absolute;
  1451. right: 10px;
  1452. top: 12px;
  1453. }
  1454. .serchBox input {
  1455. width: 100%;
  1456. height: 100%;
  1457. background: #f5f5f5;
  1458. border: none;
  1459. color: #999;
  1460. padding: 0 10px;
  1461. }
  1462. .serchBox input:focus {
  1463. outline: none;
  1464. color: #666;
  1465. }
  1466. .FastReplyList {
  1467. width: 100%;
  1468. }
  1469. .userinfo {
  1470. width: 16vw;
  1471. padding: 20px;
  1472. background: #ECF4FF;
  1473. }
  1474. .userData p {
  1475. line-height: 30px;
  1476. display: block;
  1477. width: 100%;
  1478. }
  1479. .message_box {
  1480. background: #DFF0FF;
  1481. border-radius: 10px 0 10px 10px;
  1482. }
  1483. .user_box {
  1484. background: #F5F5F5;
  1485. border-radius: 0 10px 10px 10px;
  1486. }
  1487. .userDataInput {
  1488. width: 80%;
  1489. padding: 10px;
  1490. height: 80px;
  1491. resize: none;
  1492. border: 1px solid #d5e5ff;
  1493. background: #fff;
  1494. }
  1495. .userDataInput:focus {
  1496. outline: none;
  1497. }
  1498. .userBtn {
  1499. width: 60px;
  1500. height: 34px;
  1501. border: 1px solid rgba(221, 221, 221, 1);
  1502. background: linear-gradient(
  1503. 180deg,
  1504. rgba(245, 245, 245, 1) 0%,
  1505. rgba(238, 238, 238, 1) 100%
  1506. );
  1507. border-radius: 5px;
  1508. color: #888;
  1509. font-size: 14px;
  1510. margin-top: 10px;
  1511. }
  1512. .userBtn:hover {
  1513. background: #5399f5;
  1514. color: #f0f0f0;
  1515. cursor: pointer;
  1516. }
  1517. .chatmin {
  1518. height: 46.5vh;
  1519. }
  1520. #pop .el-button--primary {
  1521. background: #409EFF !important;
  1522. /* color:#fff !important; */
  1523. border: 1px solid #DCDFE6;
  1524. line-height: 1;
  1525. padding: 4px 8px;
  1526. }
  1527. .cell button {
  1528. line-height: 1;
  1529. -webkit-transition: .1s;
  1530. border-radius: 4px;
  1531. border: 1px solid #DCDFE6;
  1532. padding: 4px 8px;
  1533. }
  1534. #pop .el-button {
  1535. line-height: 0;
  1536. /* width: 0; */
  1537. border: none;
  1538. padding: 0;
  1539. color: #999;
  1540. font-size: 12px;
  1541. font-weight: 400;
  1542. }
  1543. .el-tooltip__popper {
  1544. max-width: 15vw;
  1545. /* line-height: 180%; */
  1546. }
  1547. .rightAlignment .el-button {
  1548. border: none;
  1549. }
  1550. </style>