msglist.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. <template>
  2. <view scroll-y="true" :class="view + ' wrap ' + (isIPX?'scroll_view_X': '')" @tap="onTap" upper-threshold="-50"
  3. :scroll-into-view="toView">
  4. <view>
  5. <u-modal v-model="show" title="消息举报" ref="uModal" confirm-text="举报" :async-close="true"
  6. @confirm="reportMsg">
  7. <view class="slot-content">
  8. <u-field v-model="reason" label="举报原因" placeholder="请填写举报原因" type="textarea" :auto-height="false"
  9. :clearable="false" maxlength="100">
  10. </u-field>
  11. </view>
  12. </u-modal>
  13. <u-action-sheet :list="list" @click="onMenuClick" v-model="showRpt"></u-action-sheet>
  14. <u-action-sheet :list="typeList" @click="onReportTypeClick" v-model="showRptType"></u-action-sheet>
  15. </view>
  16. <!-- <view class="tips">本应用仅用于环信产品功能开发测试,请勿用于非法用途。任何涉及转账、汇款、裸聊、网恋、网购退款、投资理财等统统都是诈骗,请勿相信!</view> -->
  17. <view class="chat-top ddflex" v-if="recommendCard&&recommendCard.userType==1">
  18. <view class="li ddflex" v-if="recommendCard.visitingCardDTO.wechat" @click="showWeChatCodePop()">
  19. <image src="../../../static/chat_wx.png">
  20. </image>
  21. <view>加微信</view>
  22. </view>
  23. <view class="li ddflex" @click="callPhone(recommendCard.visitingCardDTO.phone)">
  24. <image src="../../../static/chat_dh.png"></image>
  25. <view>打电话</view>
  26. </view>
  27. <view class="li ddflex" @click="jumpUrl('/card/index/index?cardId='+recommendCard.visitingCardDTO.id)">
  28. <image src="../../../static/chat_wy.png"></image>
  29. <view>进微页</view>
  30. </view>
  31. </view>
  32. <view @longtap="onMsgTap(item)" class="message" v-for="item in chatMsg" :key="item.mid" :id="item.mid">
  33. <view class="main-time">{{handleTime(item)}}</view>
  34. <view class="main" :class="item.style">
  35. <!-- yourname:就是消息的 from -->
  36. <!-- <view class="user">
  37. <text v-if="!item.style"
  38. class="user-text">{{ showMessageListNickname(item) + ' ' + handleTime(item)}}</text>
  39. </view> -->
  40. <image class="avatar" :src="showMessageListAvatar(item)" />
  41. <view class="msg">
  42. <image class="err" :class="(item.style == 'self' && item.isFail) ? 'show' : 'hide'"
  43. src="../../../static/msgerr.png" />
  44. <image v-if="item.style == 'self'" src="../../../static/poprightarrow2x.png"
  45. class="msg_poprightarrow" />
  46. <image v-if="item.style == ''" src="../../../static/popleftarrow2x.png" class="msg_popleftarrow" />
  47. <view v-if="item.msg.type == 'img' || item.msg.type == 'video'">
  48. <image v-if="item.msg.type == 'img'" class="avatar" :src="item.msg.data"
  49. style="width:90px; margin:2px auto;" mode="widthFix" @tap="previewImage"
  50. :data-url="item.msg.data" />
  51. <video v-if="item.msg.type == 'video'" :src="item.msg.data" controls style="width:300rpx;" />
  52. </view>
  53. <audio-msg v-if="item.msg.type == 'audio'" :msg="item"></audio-msg>
  54. <file-msg v-if="item.msg.type == 'file'" :msg="item"></file-msg>
  55. <view v-else-if="item.msg.type == 'txt' || item.msg.type == 'emoji'">
  56. <view class="template" v-for="(d_item, d_index) in item.msg.data" :key="d_index">
  57. <text :data-msg="item" @tap="clickMsg" v-if="d_item.type == 'txt'" class="msg-text"
  58. style="float:left;" selectable="true">{{ d_item.data }}</text>
  59. <image v-if="d_item.type == 'emoji'" class="avatar"
  60. :src="'../../../static/faces/' + d_item.data"
  61. style="width:25px; height:25px; margin:0 0 2px 0; float:left;" />
  62. </view>
  63. </view>
  64. </view>
  65. </view>
  66. </view>
  67. <!-- <view class="lixian ddflex">会话已结束,用时 05:30</view>
  68. <view class="lixian ddflex">当前顾问处于离线状态,<button open-type="contact">点此联系智能客服</button></view>
  69. -->
  70. </view>
  71. <!-- <view style="height: 1px;"></view> -->
  72. </template>
  73. <script>
  74. let req = require('../../../../utils/request');
  75. let msgStorage = require("../msgstorage");
  76. let disp = require("../../../../hxChatSDK/utils/broadcast");
  77. let timeFormats = require("../../../../hxChatSDK/utils/timeFormat");
  78. let LIST_STATUS = {
  79. SHORT: "scroll_view_change",
  80. NORMAL: "scroll_view"
  81. };
  82. let page = 0;
  83. let Index = 0;
  84. let curMsgMid = '';
  85. let isFail = false;
  86. import audioMsg from "./type/audio/audio";
  87. import fileMsg from "./type/file";
  88. let WebIM = require("../../../../hxChatSDK/utils/WebIM")["default"];
  89. export default {
  90. data() {
  91. return {
  92. view: LIST_STATUS.NORMAL,
  93. toView: "",
  94. chatMsg: [],
  95. visibility: false,
  96. isIPX: false,
  97. title: '消息举报',
  98. list: [{
  99. text: '举报'
  100. }],
  101. show: false,
  102. showRpt: false,
  103. showRptType: false,
  104. rptMsgId: '', // 举报消息id
  105. rptType: '', // 举报类型
  106. reason: '',
  107. typeList: [{
  108. text: "涉政"
  109. },
  110. {
  111. text: "涉黄"
  112. },
  113. {
  114. text: "广告"
  115. },
  116. {
  117. text: "辱骂"
  118. },
  119. {
  120. text: "暴恐"
  121. },
  122. {
  123. text: "违禁"
  124. }
  125. ],
  126. defaultAvatar: "../../../static/theme2x.png",
  127. defaultGroupAvatar: "../../..//static/groupTheme.png",
  128. recommendCard: '',
  129. isShowCodePop: false,
  130. };
  131. },
  132. components: {
  133. audioMsg,
  134. fileMsg
  135. },
  136. props: {
  137. username: {
  138. type: Object,
  139. default: () => ({})
  140. }
  141. },
  142. // lifetimes
  143. created() {},
  144. beforeMount() {
  145. this.visibility = true;
  146. page = 0;
  147. Index = 0;
  148. },
  149. moved() {},
  150. destroyed() {
  151. this.visibility = false;
  152. msgStorage.off("newChatMsg", this.dispMsg)
  153. },
  154. mounted(event) {
  155. let me = this;
  156. if (getApp().globalData.isIPX) {
  157. this.setData({
  158. isIPX: true
  159. });
  160. }
  161. this.username = uni.username;
  162. let username = this.username;
  163. let myUsername = uni.getStorageSync("myUsername");
  164. let sessionKey = username.groupId ? username.groupId + myUsername : username.your + myUsername;
  165. let chatMsg = uni.getStorageSync(sessionKey) || [];
  166. this.renderMsg(null, null, chatMsg, sessionKey);
  167. uni.setStorageSync(sessionKey, null);
  168. disp.on('em.error.sendMsgErr', function(err) {
  169. // curMsgMid = err.data.mid;
  170. isFail = true;
  171. // return;
  172. console.log('发送失败了');
  173. return;
  174. let msgList = me.chatMsg;
  175. msgList.map(item => {
  176. if (item.mid.substring(item.mid.length - 10) == curMsgMid.substring(curMsgMid.length -
  177. 10)) {
  178. item.msg.data[0].isFail = true;
  179. item.isFail = true;
  180. me.setData({
  181. chatMsg: msgList
  182. });
  183. }
  184. });
  185. // if (me.curChatMsg[0].mid == curMsgMid) {
  186. // me.curChatMsg[0].msg.data[0].isShow = false;
  187. // me.curChatMsg[0].isShow = false;
  188. // }
  189. uni.setStorageSync("rendered_" + sessionKey, msgList);
  190. });
  191. msgStorage.on("newChatMsg", this.dispMsg);
  192. this.getUserInfo();
  193. },
  194. computed: {
  195. //处理时间显示
  196. handleTime() {
  197. return (item) => {
  198. return timeFormats.timeFormat(item.time, 'mm/dd/hh:MM')
  199. }
  200. }
  201. },
  202. methods: {
  203. jumpUrl(url) {
  204. uni.navigateTo({
  205. url: url
  206. })
  207. },
  208. showWeChatCodePop() {
  209. this.$emit("showWeChatCodePop", true, this.recommendCard);
  210. },
  211. //获取用户数据
  212. getUserInfo() {
  213. // this.username = uni.username;
  214. var id = this.username.your.replace('rs_', '');
  215. req.getRequest('/api/user/userInfoById', {
  216. userId: id
  217. }, data => {
  218. this.recommendCard = data;
  219. });
  220. },
  221. // 拨打电话
  222. callPhone(val) {
  223. if (!val) return false
  224. uni.makePhoneCall({
  225. phoneNumber: val
  226. });
  227. },
  228. normalScroll() {
  229. this.setData({
  230. view: LIST_STATUS.NORMAL
  231. });
  232. },
  233. //消息列表头像展示
  234. showMessageListAvatar(item) {
  235. // console.log('item>>>>>',item);
  236. const imUserInfo = uni.getStorageSync("imUserInfo_" + item.info.from);
  237. if (imUserInfo && imUserInfo.avatar) {
  238. return imUserInfo.avatar;
  239. } else {
  240. return this.defaultAvatar;
  241. }
  242. },
  243. //消息列表昵称显示
  244. showMessageListNickname(item) {
  245. // const friendUserInfoMap = getApp().globalData.friendUserInfoMap;
  246. const imUserInfo = uni.getStorageSync("imUserInfo_" + item.info.from);
  247. if (imUserInfo && imUserInfo.nickName) {
  248. return imUserInfo.nickName;
  249. } else {
  250. return item.yourname;
  251. }
  252. },
  253. dispMsg(renderableMsg, type, curChatMsg, sesskey) {
  254. let me = this;
  255. let username = this.username;
  256. let myUsername = uni.getStorageSync("myUsername");
  257. let sessionKey = username.groupId ? username.groupId + myUsername : username.your + myUsername;
  258. me.curChatMsg = curChatMsg;
  259. if (!me.visibility) return; // 判断是否属于当前会话
  260. if (username.groupId) {
  261. // 群消息的 to 是 id,from 是 name
  262. if (renderableMsg.info.from == username.groupId || renderableMsg.info.to == username.groupId) {
  263. if (sesskey == sessionKey) {
  264. me.renderMsg(renderableMsg, type, curChatMsg, sessionKey, 'newMsg');
  265. }
  266. }
  267. } else if (renderableMsg.info.from == username.your || renderableMsg.info.to == username.your) {
  268. if (sesskey == sessionKey) {
  269. me.renderMsg(renderableMsg, type, curChatMsg, sessionKey, 'newMsg');
  270. }
  271. }
  272. },
  273. onInput(e) {
  274. this.setData({
  275. reason: e.target.value
  276. })
  277. },
  278. shortScroll() {
  279. this.setData({
  280. view: LIST_STATUS.SHORT
  281. });
  282. },
  283. onTap() {
  284. this.$emit("msglistTap", null, {
  285. bubbles: true
  286. });
  287. },
  288. onMsgTap(item) {
  289. // 别人发的消息
  290. if (item.style !== 'self') {
  291. this.setData({
  292. showRpt: true,
  293. rptMsgId: item.id
  294. })
  295. }
  296. },
  297. onMenuClick(idx) {
  298. if (idx === 0) {
  299. this.setData({
  300. showRptType: true
  301. })
  302. }
  303. },
  304. reportMsg() {
  305. let that = this
  306. if (this.reason === '') {
  307. this.$refs.uModal.clearLoading();
  308. uni.showToast({
  309. title: "请填写举报原因",
  310. icon: 'none'
  311. });
  312. return false
  313. }
  314. WebIM.conn
  315. .reportMessage({
  316. reportType: that.rptType, // 举报类型
  317. reportReason: that.reason, // 举报原因。
  318. messageId: that.rptMsgId // 上报消息id
  319. })
  320. .then(() => {
  321. uni.showToast({
  322. title: "举报成功",
  323. icon: 'none'
  324. });
  325. })
  326. .catch((e) => {
  327. uni.showToast({
  328. title: "举报失败",
  329. icon: 'none'
  330. });
  331. }).finally(() => {
  332. that.setData({
  333. reason: '',
  334. rptType: '',
  335. rptMsgId: '',
  336. show: false
  337. })
  338. });
  339. },
  340. onReportTypeClick(idx) {
  341. // 设置举报类型
  342. this.setData({
  343. rptType: this.typeList[idx].text,
  344. show: true
  345. })
  346. },
  347. previewImage(event) {
  348. var url = event.target.dataset.url;
  349. uni.previewImage({
  350. urls: [url] // 需要预览的图片 http 链接列表
  351. });
  352. },
  353. getHistoryMsg() {
  354. let me = this;
  355. let username = this.username;
  356. let myUsername = uni.getStorageSync("myUsername");
  357. let sessionKey = username.groupId ? username.groupId + myUsername : username.your + myUsername;
  358. let historyChatMsgs = uni.getStorageSync("rendered_" + sessionKey) || [];
  359. if (Index < historyChatMsgs.length) {
  360. let timesMsgList = historyChatMsgs.slice(-Index - 10, -Index);
  361. this.setData({
  362. chatMsg: timesMsgList.concat(me.chatMsg),
  363. toView: timesMsgList[timesMsgList.length - 1].mid
  364. });
  365. Index += timesMsgList.length;
  366. if (timesMsgList.length == 10) {
  367. page++;
  368. }
  369. uni.stopPullDownRefresh();
  370. }
  371. },
  372. renderMsg(renderableMsg, type, curChatMsg, sessionKey, isnew) {
  373. let me = this;
  374. var historyChatMsgs = uni.getStorageSync("rendered_" + sessionKey) || [];
  375. historyChatMsgs = historyChatMsgs.concat(curChatMsg);
  376. if (!historyChatMsgs.length) return;
  377. if (isnew == 'newMsg') {
  378. this.setData({
  379. chatMsg: this.chatMsg.concat(curChatMsg),
  380. // 跳到最后一条
  381. toView: historyChatMsgs[historyChatMsgs.length - 1].mid
  382. });
  383. } else {
  384. this.setData({
  385. chatMsg: historyChatMsgs.slice(-10),
  386. // 跳到最后一条
  387. toView: historyChatMsgs[historyChatMsgs.length - 1].mid
  388. });
  389. }
  390. uni.setStorageSync("rendered_" + sessionKey, historyChatMsgs);
  391. let chatMsg = uni.getStorageSync(sessionKey) || [];
  392. chatMsg.map(function(item, index) {
  393. curChatMsg.map(function(item2, index2) {
  394. if (item2.mid == item.mid) {
  395. chatMsg.splice(index, 1);
  396. }
  397. });
  398. });
  399. uni.setStorageSync(sessionKey, chatMsg);
  400. Index = historyChatMsgs.slice(-10).length;
  401. // setTimeout 兼容支付宝小程序
  402. setTimeout(() => {
  403. uni.pageScrollTo({
  404. scrollTop: 5000,
  405. duration: 300,
  406. fail: (e) => {
  407. //console.log('滚失败了', e)
  408. }
  409. });
  410. }, 100)
  411. if (isFail) {
  412. this.renderFail(sessionKey);
  413. }
  414. },
  415. renderFail(sessionKey) {
  416. let me = this;
  417. let msgList = me.chatMsg;
  418. msgList.map(item => {
  419. if (item.mid.substring(item.mid.length - 10) == curMsgMid.substring(curMsgMid.length - 10)) {
  420. item.msg.data[0].isFail = true;
  421. item.isFail = true;
  422. me.setData({
  423. chatMsg: msgList
  424. });
  425. }
  426. });
  427. if (me.curChatMsg[0].mid == curMsgMid) {
  428. me.curChatMsg[0].msg.data[0].isShow = false;
  429. me.curChatMsg[0].isShow = false;
  430. }
  431. uni.setStorageSync("rendered_" + sessionKey, msgList);
  432. isFail = false;
  433. },
  434. clickMsg(event) {
  435. if (typeof(event.target.dataset.msg) == 'object' &&
  436. event.target.dataset.msg.msg.ext &&
  437. event.target.dataset.msg.msg.ext.msg_extension) {
  438. this.$emit("clickMsg", event.target.dataset.msg.msg.ext)
  439. }
  440. }
  441. }
  442. };
  443. </script>
  444. <style>
  445. @import "./msglist.css";
  446. </style>