inquiry.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. <template>
  2. <view class="">
  3. <view class="navBox">
  4. <view class="status_bar" :style="{height: iStatusBarHeight + 'px'}"></view>
  5. <view class="nav">
  6. <view class="navLeft" >
  7. <!-- <image src="../static/img/nav_icon_back.png" mode="aspectFit" class="backImg" @click="goback"></image> -->
  8. </view>
  9. <view class="title">询价信息</view>
  10. <view class="goVin" @click="vinScanFn">车架号查询</view>
  11. </view>
  12. </view>
  13. <view class="status_bar" :style="{height: iStatusBarHeight + 'px'}"></view>
  14. <view style="height: 44px;"></view>
  15. <scroll-view class="conversations" scroll-y="true">
  16. <view @click="setClipboardData">token:{{token}}</view>
  17. <view v-if="conversations.length > 0">
  18. <view class="scroll-item" v-for="(conversation, key) in conversations" :key="key">
  19. <view class="item-head">
  20. <image :src="conversation.data.avatar" class="head-icon"></image>
  21. <view class="item-head_unread" v-if="conversation.unread">{{ conversation.unread }}</view>
  22. </view>
  23. <view class="scroll-item_info" @click="chat(conversation)">
  24. <view class="item-info-top">
  25. <text class="item-info-top_name">{{ conversation.data.name }}</text>
  26. <view class="item-info-top_time">{{ formatDate(conversation.lastMessage.timestamp) }}</view>
  27. </view>
  28. <view class="item-info-bottom">
  29. <view class="item-info-bottom-item">
  30. <view class="item-info-top_content" v-if="!conversation.lastMessage.recalled">
  31. <text class="unread-text">
  32. {{ conversation.lastMessage.read === false && conversation.lastMessage.senderId === currentUser.id ? '[未读]' : '' }}
  33. </text>
  34. <text v-if="conversation.lastMessage.senderId === currentUser.id">我: </text>
  35. <text v-else>{{ conversation.type === 'group' ? conversation.lastMessage.senderData.name : conversation.data.name }}: </text>
  36. <text v-if="conversation.lastMessage.type === 'text'">{{ conversation.lastMessage.payload.text }}</text>
  37. <text v-else-if="conversation.lastMessage.type === 'video'">[视频消息]</text>
  38. <text v-else-if="conversation.lastMessage.type === 'audio'">[语音消息]</text>
  39. <text v-else-if="conversation.lastMessage.type === 'image'">[图片消息]</text>
  40. <text v-else-if="conversation.lastMessage.type === 'file'">[文件消息]</text>
  41. <text v-else-if="conversation.lastMessage.type === 'order'">[自定义消息:订单]</text>
  42. <text v-else-if="conversation.lastMessage.type === 'pic'">[图片消息]</text>
  43. <text v-else-if="conversation.lastMessage.type === 'car'">[车辆信息]</text>
  44. <text v-else>[[未识别内容]]</text>
  45. </view>
  46. <view class="item-info-top_content" v-else>
  47. <text>
  48. {{conversation.lastMessage.recaller.id === currentUser.id ? '你' : conversation.lastMessage.recaller.data.name}}撤回了一条消息
  49. </text>
  50. </view>
  51. <view class="item-info-bottom_action" @click.stop="showAction(conversation)"></view>
  52. </view>
  53. </view>
  54. </view>
  55. </view>
  56. </view>
  57. <view class="no-conversation" v-else>当前没有会话</view>
  58. <view class="action-container" v-if="actionPopup.visible">
  59. <view class="layer" @click="actionPopup.visible = false"></view>
  60. <view class="action-box">
  61. <view class="action-item" @click="topConversation">
  62. {{ actionPopup.conversation.top ? '取消置顶' : '置顶聊天' }}
  63. </view>
  64. <view class="action-item" @click="deleteConversation">删除聊天</view>
  65. </view>
  66. </view>
  67. </scroll-view>
  68. </view>
  69. </template>
  70. <script>
  71. import {formatDate} from '../lib/utils';
  72. import restApi from '../lib/restapi';
  73. const GoEasy = uni.$GoEasy;
  74. const GRTC = uni.$GRTC;
  75. export default {
  76. name: 'conversation',
  77. data() {
  78. return {
  79. conversations: [],
  80. actionPopup: {
  81. conversation: null,
  82. visible: false
  83. },
  84. currentUser: null,
  85. iStatusBarHeight:'',
  86. token:'',
  87. }
  88. },
  89. onLoad(opt) {
  90. this.token=opt.token
  91. uni.setStorageSync('token', this.token);
  92. this.iStatusBarHeight = uni.getSystemInfoSync().statusBarHeight;
  93. this.imLoginUrl()
  94. },
  95. onShow() {
  96. /* uni.$currentUser = uni.getStorageSync('currentUser');
  97. this.currentUser = uni.$currentUser;
  98. console.log(this.currentUser)
  99. if (!this.currentUser) {
  100. uni.navigateTo({ url: './login' });
  101. return;
  102. }
  103. if (GoEasy.getConnectionStatus() === 'disconnected') {
  104. this.connectGoEasy(); //连接goeasy
  105. this.subscribeGroup(); //建立连接后,就应该订阅群聊消息,避免漏掉
  106. }
  107. this.loadConversations(); //加载会话列表
  108. this.initGoEasyListeners(); */
  109. },
  110. onHide() {
  111. if (GoEasy.getConnectionStatus() === 'disconnected') {
  112. return
  113. }
  114. GoEasy.im.off(GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, this.renderConversations);
  115. },
  116. methods: {
  117. formatDate,
  118. connectGoEasy() {
  119. uni.showLoading();
  120. GoEasy.connect({
  121. id: this.currentUser.id,
  122. data: {
  123. name: this.currentUser.name,
  124. avatar: this.currentUser.avatar
  125. },
  126. onSuccess: () => {
  127. console.log('GoEasy connect successfully.')
  128. },
  129. onFailed: (error) => {
  130. console.log('Failed to connect GoEasy, code:' + error.code + ',error:' + error.content);
  131. },
  132. onProgress: (attempts) => {
  133. console.log('GoEasy is connecting', attempts);
  134. }
  135. });
  136. },
  137. setClipboardData(){
  138. uni.setClipboardData({
  139. data: this.token,
  140. success: () => {
  141. uni.showToast({
  142. title: '复制成功'
  143. });
  144. }
  145. });
  146. },
  147. imLoginUrl(){
  148. this.$http('imSys/imLoginUrl', {
  149. token:this.token,
  150. },'POST').then(res => {
  151. // console.log(res)
  152. var users={
  153. userId:res.data.userId,
  154. name:res.data.users.name,
  155. avatar:'',
  156. id:res.data.userId,
  157. }
  158. this.currentUser=users
  159. // this.connectGoEasy()
  160. uni.setStorageSync('users', users);
  161. console.log(this.currentUser)
  162. if (!this.currentUser) {
  163. uni.navigateTo({ url: './login' });
  164. return;
  165. }
  166. if (GoEasy.getConnectionStatus() === 'disconnected') {
  167. this.connectGoEasy(); //连接goeasy
  168. this.subscribeGroup(); //建立连接后,就应该订阅群聊消息,避免漏掉
  169. }
  170. this.loadConversations(); //加载会话列表
  171. this.initGoEasyListeners();
  172. })
  173. },
  174. goBack(){
  175. //app交互
  176. var standalone = window.navigator.standalone
  177. var userAgent = window.navigator.userAgent.toLowerCase()
  178. var safari = /safari/.test(userAgent)
  179. var ios = /iphone|ipod|ipad|mac/.test(userAgent)
  180. var android = /android/.test(userAgent)
  181. if (ios) {
  182. if ( true) {//!standalone&& !safari
  183. window.webkit.messageHandlers.goMyNav.postMessage(null)
  184. }
  185. } else if (android) {
  186. window.android.postMessage()
  187. }
  188. },
  189. vinScanFn(){
  190. //app交互
  191. var standalone = window.navigator.standalone
  192. var userAgent = window.navigator.userAgent.toLowerCase()
  193. var safari = /safari/.test(userAgent)
  194. var ios = /iphone|ipod|ipad|mac/.test(userAgent)
  195. var android = /android/.test(userAgent)
  196. if (ios) {
  197. if ( true) {//!standalone&& !safari
  198. window.webkit.messageHandlers.goMyNav.vinScan(null)
  199. }
  200. } else if (android) {
  201. window.android.vinScan()
  202. }
  203. },
  204. initGoEasyListeners() {
  205. GoEasy.im.on(GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, this.renderConversations); //监听会话列表变化
  206. GoEasy.im.off(GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, this.setUnreadAmount); // 移除之前的设置角标回调,防止重复回调
  207. GoEasy.im.on(GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, this.setUnreadAmount); // 设置角标
  208. // #ifdef APP-PLUS || H5
  209. GRTC.off(GRTC.EVENT.RING, this.onRing); //移除之前的监听来电事件,防止重复回调
  210. GRTC.on(GRTC.EVENT.RING, this.onRing); //监听来电事件
  211. // #endif
  212. },
  213. onRing() {
  214. const currentCall = GRTC.currentCall();
  215. if (currentCall.groupId) {
  216. uni.navigateTo({
  217. url: `./rtc/group/ring`,
  218. })
  219. } else {
  220. uni.navigateTo({
  221. url: `./rtc/private/ring`,
  222. })
  223. }
  224. },
  225. // 加载最新的会话列表
  226. loadConversations() {
  227. GoEasy.im.latestConversations({
  228. onSuccess: (result) => {
  229. uni.hideLoading();
  230. let content = result.content;
  231. this.renderConversations(content);
  232. this.setUnreadAmount(content);
  233. },
  234. onFailed: (error) => {
  235. uni.hideLoading();
  236. console.log('获取最新会话列表失败, error:', error);
  237. }
  238. });
  239. },
  240. renderConversations(content) {
  241. this.conversations = content.conversations;
  242. console.log("消息列表")
  243. console.log(this.conversations)
  244. },
  245. setUnreadAmount(content) {
  246. const unreadTotal = content.unreadTotal;
  247. if(unreadTotal > 0) {
  248. uni.setTabBarBadge({
  249. index: 0,
  250. text: unreadTotal.toString()
  251. });
  252. }else{
  253. uni.removeTabBarBadge({index: 0});
  254. }
  255. // #ifdef APP-PLUS
  256. GoEasy.setBadge({
  257. badge: unreadTotal,
  258. onSuccess: function () {
  259. console.log("setBadge successfully.")
  260. },
  261. onFailed: function (error) {
  262. console.log("Failed to setBadge,error:" + error);
  263. }
  264. });
  265. // #endif
  266. },
  267. subscribeGroup() {
  268. let groups = restApi.findGroups(this.currentUser);
  269. let groupIds = groups.map(item => item.id);
  270. GoEasy.im.subscribeGroup({
  271. groupIds: groupIds,
  272. onSuccess: function () {
  273. console.log('订阅群消息成功');
  274. },
  275. onFailed: function (error) {
  276. console.log('订阅群消息失败:', error);
  277. }
  278. });
  279. },
  280. topConversation() { //会话置顶
  281. this.actionPopup.visible = false;
  282. let conversation = this.actionPopup.conversation;
  283. let description = conversation.top ? '取消置顶' : '置顶';
  284. GoEasy.im.topConversation({
  285. conversation: conversation,
  286. top: !conversation.top,
  287. onSuccess: function () {
  288. uni.showToast({
  289. title: description + '成功',
  290. icon: 'none'
  291. });
  292. },
  293. onFailed: function (error) {
  294. console.log(description, '失败:', error);
  295. }
  296. });
  297. },
  298. deleteConversation() {
  299. uni.showModal({
  300. content: '确认删除这条会话吗?',
  301. success: (res) => {
  302. if (res.confirm) {
  303. let conversation = this.actionPopup.conversation;
  304. this.actionPopup.visible = false;
  305. GoEasy.im.removeConversation({
  306. conversation: conversation,
  307. onSuccess: function () {
  308. console.log('删除会话成功');
  309. },
  310. onFailed: function (error) {
  311. console.log(error);
  312. },
  313. });
  314. } else {
  315. this.actionPopup.visible = false;
  316. }
  317. },
  318. })
  319. },
  320. chat(conversation) {
  321. let path = conversation.type === GoEasy.IM_SCENE.PRIVATE ?
  322. './privateChat?to=' + conversation.userId :
  323. './groupChat?to=' + conversation.groupId;
  324. var friend={
  325. id:conversation.userId,
  326. supplierName:conversation.data.name,
  327. avatar:conversation.data.avatar,
  328. }
  329. uni.setStorage({
  330. key: 'friend',
  331. data: friend,
  332. success: function () {
  333. /* uni.navigateTo({
  334. url: './privateChat?to=' + friend.ID
  335. }); */
  336. uni.navigateTo({ url: path });
  337. }
  338. });
  339. },
  340. showAction(conversation) {
  341. this.actionPopup.conversation = conversation;
  342. this.actionPopup.visible = true;
  343. }
  344. }
  345. }
  346. </script>
  347. <style>
  348. page {
  349. height: 100%;
  350. }
  351. .conversations {
  352. width: 750rpx;
  353. overflow-x: hidden;
  354. display: flex;
  355. flex-direction: column;
  356. height: 100%;
  357. }
  358. .conversations .scroll-item {
  359. height: 152rpx;
  360. display: flex;
  361. align-items: center;
  362. padding-left: 32rpx;
  363. }
  364. .conversations .scroll-item .head-icon {
  365. width: 100rpx;
  366. height: 100rpx;
  367. margin-right: 28rpx;
  368. }
  369. .conversations .scroll-item_info {
  370. height: 151rpx;
  371. width: 590rpx;
  372. padding-right: 32rpx;
  373. border-bottom: 1px solid #EFEFEF;
  374. }
  375. .conversations .scroll-item_info .item-info-top {
  376. padding-top: 20rpx;
  377. /* height: 60rpx;
  378. line-height: 60rpx; */
  379. display: flex;
  380. align-items: center;
  381. justify-content: space-between;
  382. }
  383. .conversations .item-info-top_name {
  384. font-size: 30rpx;
  385. color: #262628;
  386. }
  387. .conversations .item-info-top_time {
  388. font-size: 34rpx;
  389. color: rgba(179, 179, 179, 0.8);
  390. }
  391. .conversations .item-info-bottom {
  392. height: 40rpx;
  393. line-height: 40rpx;
  394. overflow: hidden;
  395. }
  396. .conversations .item-info-bottom-item {
  397. display: flex;
  398. justify-content: space-between;
  399. }
  400. .item-info-bottom .item-info-top_content {
  401. font-size: 34rpx;
  402. color: #b3b3b3;
  403. overflow: hidden;
  404. text-overflow: ellipsis;
  405. white-space: nowrap;
  406. }
  407. .item-info-bottom .item-info-bottom_action {
  408. width: 50rpx;
  409. height: 50rpx;
  410. font-size: 34rpx;
  411. background: url("../static/images/action.png") no-repeat center;
  412. background-size: 28rpx 30rpx;
  413. }
  414. .no-conversation {
  415. width: 100%;
  416. text-align: center;
  417. height: 80rpx;
  418. line-height: 80rpx;
  419. font-size: 34rpx;
  420. color: #9D9D9D;
  421. }
  422. .item-head {
  423. position: relative;
  424. }
  425. .item-head .item-head_unread {
  426. padding: 6rpx;
  427. background-color: #EE593C;
  428. color: #FFFFFF;
  429. font-size: 34rpx;
  430. line-height: 28rpx;
  431. border-radius: 24rpx;
  432. min-width: 24rpx;
  433. min-height: 24rpx;
  434. text-align: center;
  435. position: absolute;
  436. top: 0;
  437. right: 15rpx;
  438. }
  439. .action-container {
  440. width: 100%;
  441. height: 100%;
  442. position: fixed;
  443. top: 0;
  444. left: 0;
  445. display: flex;
  446. justify-content: center;
  447. align-items: center;
  448. }
  449. .action-container .layer {
  450. position: absolute;
  451. top: 0;
  452. left: 0;
  453. background: rgba(51, 51, 51, 0.5);
  454. width: 100%;
  455. height: 100%;
  456. z-index: 99;
  457. }
  458. .action-box {
  459. width: 400rpx;
  460. height: 240rpx;
  461. background: #ffffff;
  462. position: relative;
  463. z-index: 100;
  464. border-radius: 20rpx;
  465. overflow: hidden;
  466. }
  467. .action-item {
  468. text-align: center;
  469. line-height: 120rpx;
  470. font-size: 34rpx;
  471. color: #262628;
  472. border-bottom: 1px solid #EFEFEF;
  473. }
  474. .unread-text {
  475. color: #d02129;
  476. }
  477. .backImg{
  478. width: 44rpx;
  479. height: 44rpx;
  480. /* margin-left: 10rpx; */
  481. /* margin-right: 20rpx; */
  482. }
  483. .nav{
  484. height: 44px;
  485. display: flex;
  486. justify-content: space-between;
  487. align-items: center;
  488. border-bottom: 1px solid #eaeaea;
  489. }
  490. .goVin{
  491. width: 200rpx;
  492. color: #3F90F7;
  493. text-align: right;
  494. padding-right: 20rpx;
  495. }
  496. .navLeft{
  497. width: 200rpx;
  498. padding-left: 20rpx;
  499. }
  500. .navBox{
  501. position: fixed;
  502. left: 0;
  503. top: 0;
  504. z-index: 11;
  505. width: 100vw;
  506. }
  507. </style>