messages.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. <template>
  2. <view class="container">
  3. <TabBar :tabIndex="tabIndex" v-if="showTabbar"></TabBar>
  4. <uni-popup ref="popup" @maskClick="closePopup" type="center">
  5. <Popup :content1="popup.content1" :content2="popup.content2" :tip1="popup.tip1" :tip2="popup.tip2" :btntext="popup.btntext" @closePopup="closePopup" @toService="toService" :btnEvent="'toService'"></Popup>
  6. </uni-popup>
  7. <uni-popup ref="paypopup" type="bottom" :safe-area="false" @maskClick="closePayPopup">
  8. <PayPopup :swiperIndex="payPopupIndex" @closePopup="closePayPopup"></PayPopup>
  9. </uni-popup>
  10. <uni-popup ref="vippopup" type="center" @maskClick="closePayPopup">
  11. <VipPopup :swiperIndex="vipPopupIndex" @closePopup="closeVipPopup"></VipPopup>
  12. </uni-popup>
  13. <view id="topnav" class="topnav flex-start" :style="{'height':`${topbarOffsetHeight-statusBarHeight}px`,'padding-top':`${statusBarHeight}px`}" >
  14. <image :src="`${assetsUrl}message-setting.png`" mode="aspectFill" class="nav-img" @click="openSetting"></image>
  15. </view>
  16. <scroll-view class="scroll-view"
  17. v-if="scrollHeight>0"
  18. scroll-y="true"
  19. lower-threshold="200"
  20. :style="{'height':`${scrollHeight}px`,'padding-top':`${topbarOffsetHeight}px`}"
  21. >
  22. <!-- <view class="message-item flex-between">
  23. <image :src="`${assetsUrl}message-system.png`" mode="aspectFill" class="left-img"></image>
  24. <view class="right-info">
  25. <view class="ri-top flex-between">
  26. <view class="rit-title fw600 font32">
  27. 系统通知
  28. </view>
  29. <view class="rit-time font22 fw400">
  30. 2022-8-31 09:57:13
  31. </view>
  32. </view>
  33. <view class="ri-bottom flex-between">
  34. <view class="rib-text font28 fw400">
  35. heihei
  36. </view>
  37. <view class="rib-num font20 fw400">
  38. 99
  39. </view>
  40. </view>
  41. </view>
  42. </view> -->
  43. <view class="message-item flex-between" v-for="(item,index) in messagesList" :key="index" :data-index="index" @longpress="showDelBtn" v-if="item.lastMessage.payload">
  44. <image :src="item.userProfile.avatar"
  45. mode="aspectFill"
  46. class="left-img"
  47. :style="{'width':`${showDelIndex===index?'0rpx':'120rpx'}`}"
  48. @click="toTalk(item.userProfile.userID,index)"
  49. ></image>
  50. <view class="right-info" @click="toTalk(item.userProfile.userID,index)">
  51. <view class="ri-top flex-between">
  52. <view class="rit-title fw600 font28 el">
  53. {{item.userProfile.nick}}
  54. </view>
  55. <view class="rit-time font22 fw400">
  56. {{item.lastMessage.lastTimeStr}}
  57. </view>
  58. </view>
  59. <view class="ri-bottom flex-between">
  60. <view class="rib-text font28 fw400 el">
  61. {{item.lastMessage.payload.text}}
  62. </view>
  63. <view class="rib-num font20 fw400" v-if="item.unreadCount!==0">
  64. {{item.unreadCount}}
  65. </view>
  66. </view>
  67. </view>
  68. <view class="del-box font28 fw400" :style="{'width':`${showDelIndex===index?'120rpx':'0rpx'}`}" @click="delConversation">
  69. 删除
  70. </view>
  71. </view>
  72. <!-- <view class="no-more font24 fw400" v-if="messagesList.length!==0&&messagesList.length>=recommendTotal">没有更多了</view> -->
  73. <Status type="noMsg" text="暂无消息" v-if="showNoMsg"></Status>
  74. </scroll-view>
  75. </view>
  76. </template>
  77. <script>
  78. import TabBar from '@/components/TabBar/TabBar.vue';
  79. import Popup from '@/components/Popup/Popup.vue';
  80. import VipPopup from '@/components/Popup/VipPopup.vue';
  81. import PayPopup from '@/components/Popup/PayPopup.vue';
  82. import Status from '@/components/Status/Status.vue';
  83. /**
  84. * 腾讯位置服务,手机账号:18996226740
  85. */
  86. import wxMap from '@/static/qqmap-wx-jssdk1.2/qqmap-wx-jssdk.min.js';
  87. const wxMapSdk=new wxMap({key:'E5SBZ-T2YC3-CBL3F-YGFQQ-26PP2-ERFII'})
  88. export default {
  89. components:{TabBar,Popup,VipPopup,PayPopup,Status},
  90. data() {
  91. return {
  92. scrollHeight:0,
  93. topNavAlpha:0,
  94. assetsUrl:this.$util.assetsUrl,
  95. startTime:0,
  96. startPosition:0,
  97. endPosition:0,
  98. showDelIndex:-1,
  99. tabIndex:1,
  100. messagesList:[],
  101. popup:{
  102. content1:'',
  103. content2:'',
  104. tip1:'',
  105. tip2:'',
  106. btntext:''
  107. },
  108. payPopupIndex:-1,
  109. vipPopupIndex:-1,
  110. userInfo:null,//会话消息用户信息
  111. showNoMsg:false,
  112. systemMsg:{},
  113. showTabbar:true
  114. };
  115. },
  116. computed: {
  117. statusBarHeight() {
  118. return this.$store.state.statusBarHeight;
  119. },
  120. topbarOffsetHeight() {
  121. return this.$store.state.topbarOffsetHeight;
  122. },
  123. platform(){
  124. return this.$store.state.platform;
  125. },
  126. mineInfo(){
  127. return this.$store.state.userInfo;
  128. }
  129. },
  130. onLoad() {
  131. this.computedScollviewHeight();
  132. if(!uni.getStorageSync('token')){
  133. this.showNoMsg=true;
  134. return;
  135. }
  136. uni.$TUIKit.on(uni.$TUIKitEvent.CONVERSATION_LIST_UPDATED, this.onConversationListUpdated);
  137. },
  138. onShow() {
  139. if(!uni.getStorageSync('token')){
  140. return;
  141. }
  142. this.getSystemMessages();
  143. this.getUserMessages();
  144. },
  145. onShareAppMessage(){
  146. return {
  147. title: '糖果公园',
  148. path: `/pages/login/login?share=${this.userInfo.inviteCode}`,
  149. }
  150. },
  151. methods:{
  152. /**
  153. * 计算scroll高度
  154. */
  155. computedScollviewHeight() {
  156. let query = uni.createSelectorQuery().in(this);
  157. let heightLeaf = this.$store.state.tabbarHeight/2;
  158. query.select('#topnav').boundingClientRect(data => {
  159. heightLeaf += data.height;
  160. }).exec(() => {
  161. let sysInfo = uni.getSystemInfoSync();
  162. this.scrollHeight = sysInfo.windowHeight - heightLeaf;
  163. });
  164. },
  165. toLogin(){
  166. uni.reLaunch({
  167. url:'/pages/login/login'
  168. })
  169. },
  170. closePopup(){
  171. this.$refs.popup.close();
  172. },
  173. closePayPopup(){
  174. this.payPopupIndex=-1;
  175. this.$refs.paypopup.close();
  176. this.showTabbar=true;
  177. },
  178. closeVipPopup(){
  179. this.vipPopupIndex=-1;
  180. this.$refs.vippopup.close();
  181. },
  182. showDelBtn(e){
  183. if(this.showDelIndex===e.currentTarget.dataset.index){
  184. this.showDelIndex=-1;
  185. return;
  186. }
  187. uni.vibrateLong();
  188. this.showDelIndex=e.currentTarget.dataset.index;
  189. },
  190. // touchStart(e){
  191. // this.startTime = Date.now()
  192. // this.startPosition = e.changedTouches[0].clientX;
  193. // },
  194. // touchEnd(e){
  195. // const endTime = Date.now()
  196. // if (endTime - this.startTime <50){
  197. // return;
  198. // }
  199. // if (Math.abs(this.endPosition - this.startPosition) > 50){
  200. // this.endPosition = e.changedTouches[0].clientX;
  201. // let elePosition = this.endPosition - this.startPosition < 0 ? "toLeft": "toRight";
  202. // if(elePosition==='toLeft'){
  203. // this.showDelIndex=e.currentTarget.dataset.index;
  204. // }
  205. // else{
  206. // this.showDelIndex=-1;
  207. // }
  208. // } else {
  209. // return;
  210. // }
  211. // },
  212. onConversationListUpdated(event){
  213. if(event.data.length===0){
  214. this.messagesList=[];
  215. this.showNoMsg=true;
  216. return;
  217. }
  218. else{
  219. this.getUserMessages();
  220. }
  221. },
  222. delConversation(){
  223. // this.messagesList.splice(this.showDelIndex-1,1);
  224. uni.$TUIKit.deleteConversation(this.messagesList[this.showDelIndex].conversationID);
  225. this.showDelIndex=-1;
  226. },
  227. openSetting(){
  228. if(!uni.getStorageSync('token')){
  229. this.popup={
  230. content1:'您还未登录',
  231. content2:'该功能登录后才能使用',
  232. tip1:'',
  233. tip2:'',
  234. btntext:'去登录'
  235. }
  236. this.$refs.popup.open();
  237. return;
  238. }
  239. uni.showActionSheet({
  240. itemList: ['全部已读', '清空消息'],
  241. success: (res)=>{
  242. if(res.tapIndex===0){
  243. uni.$TUIKit.setAllMessageRead({scope:uni.$TUIKitTypes.READ_ALL_MSG});
  244. }
  245. if(res.tapIndex===1){
  246. uni.showModal({
  247. title:'清空消息列表',
  248. content:'清空消息列表后,暂无恢复,请确认是否清空消息列表',
  249. success: (ress) => {
  250. if(ress.confirm){
  251. this.messagesList.forEach(item=>{
  252. uni.$TUIKit.deleteConversation(item.conversationID);
  253. })
  254. }
  255. }
  256. })
  257. }
  258. },
  259. fail: res=>{
  260. console.log(res.errMsg);
  261. }
  262. });
  263. },
  264. getSystemMessages(){
  265. let user=JSON.parse(uni.getStorageSync('user'));
  266. this.$api.public.notifyActive({}).then(res=>{
  267. this.$api.public.loadSystemMsgs({
  268. completeUser:user,
  269. onlineRecent:false,
  270. page:{
  271. index:1,
  272. size:20,
  273. sortValue:null
  274. }
  275. }).then(result=>{
  276. })
  277. })
  278. },
  279. getUserMessages(){
  280. uni.$TUIKit.getConversationList().then(res=>{
  281. console.log(res.data.conversationList)
  282. for(let i=0;i<res.data.conversationList.length;i++){
  283. res.data.conversationList[i].lastMessage.lastTimeStr=this.$moment(res.data.conversationList[i].lastMessage.lastTime*1000).format('YYYY-MM-DD HH:mm:ss');
  284. if(res.data.conversationList[i].lastMessage.type==='TIMImageElem'){
  285. res.data.conversationList[i].lastMessage.payload.text="[图片消息]"
  286. }
  287. if(res.data.conversationList[i].lastMessage.type==='TIMVideoFileElem'){
  288. res.data.conversationList[i].lastMessage.payload.text="[视频消息]"
  289. }
  290. if(res.data.conversationList[i].lastMessage.type==='TIMSoundElem'){
  291. res.data.conversationList[i].lastMessage.payload.text="[音频消息]"
  292. }
  293. if(res.data.conversationList[i].lastMessage.type==='TIMCustomElem'){
  294. let msg=JSON.parse(res.data.conversationList[i].lastMessage.payload.data);
  295. if(msg.custom){//删除自定义消息
  296. res.data.conversationList.splice(i,1);
  297. i--;
  298. }
  299. if(msg.type===99)
  300. {
  301. res.data.conversationList[i].lastMessage.payload.text="[系统消息]"
  302. }
  303. if(msg.type===5)
  304. {
  305. res.data.conversationList[i].lastMessage.payload.text="[图片消息]"
  306. }
  307. if(msg.type===6){
  308. res.data.conversationList[i].lastMessage.payload.text="[视频消息]"
  309. }
  310. if(msg.type===100){
  311. res.data.conversationList.splice(i,1);
  312. i--;
  313. // res.data.conversationList[i].userProfile.nick='社区动态';
  314. // res.data.conversationList[i].userProfile.avatar=`${this.assetsUrl}message-active.png`
  315. // res.data.conversationList[i].lastMessage.payload.text="[有人喜欢你]"
  316. }
  317. }
  318. }
  319. this.messagesList=res.data.conversationList;
  320. if(this.messagesList.length===0){
  321. this.showNoMsg=true;
  322. }
  323. else{
  324. this.showNoMsg=false;
  325. }
  326. })
  327. },
  328. toTalk(id,index){
  329. uni.showLoading({
  330. mask:true,
  331. title:'加载中3'
  332. })
  333. console.log(this.messagesList[index])
  334. uni.vibrateShort();
  335. let user=JSON.parse(uni.getStorageSync('user'));
  336. this.$api.public.userDetail({getAlbum:true,completeUser:user,uponUserId:id}).then(res=>{
  337. console.log(res);
  338. this.userInfo=res.data;
  339. let arr=[],obj={latitude:0,longitude:0};
  340. obj.latitude=this.userInfo.geo.lat;
  341. obj.longitude=this.userInfo.geo.lon;
  342. arr.push(obj);
  343. wxMapSdk.calculateDistance({
  344. mode:'straight',
  345. from:{
  346. latitude: this.$store.state.latitude,
  347. longitude: this.$store.state.longitude
  348. },
  349. to:arr,
  350. success:dists=>{
  351. uni.hideLoading();
  352. if(dists.message==="query ok"){
  353. console.log(dists,this.mineInfo)
  354. for(let j=0;j<dists.result.elements.length;j++){
  355. this.userInfo.distance=(dists.result.elements[j].distance>1000?`${Math.floor(dists.result.elements[j].distance/100)/10}km`:`${dists.result.elements[j].distance}m`)
  356. }
  357. if(this.mineInfo.sex==='Male'&&!this.mineInfo.vip){
  358. if(this.platform==='ios'){
  359. this.vipPopupIndex=0;
  360. this.$refs.vippopup.open();
  361. return;
  362. }
  363. else{
  364. this.payPopupIndex=0;
  365. this.$refs.paypopup.open();
  366. this.showTabbar=false;
  367. return;
  368. }
  369. }
  370. if(this.mineInfo.sex==='Famale'&&!this.mineInfo.realMan){
  371. this.popup={
  372. content1:'认证后才能开启私聊哦',
  373. content2:'给客服回复关键词「真人认证」',
  374. tip1:'',
  375. tip2:'',
  376. btntext:'联系客服去认证'
  377. }
  378. this.$refs.popup.open();
  379. return;
  380. }
  381. uni.navigateTo({
  382. url:`/pagesSub/chatting/chatting?conversationid=C2C${id}`
  383. })
  384. }
  385. else{
  386. uni.showToast({
  387. title:'计算距离失败',
  388. icon:'none'
  389. });
  390. uni.navigateTo({
  391. url:`/pagesSub/chatting/chatting?conversationid=C2C${id}`
  392. })
  393. }
  394. },
  395. fail:err=>{
  396. console.log(err)
  397. }
  398. })
  399. })
  400. },
  401. }
  402. }
  403. </script>
  404. <style lang="scss" scoped>
  405. .container{
  406. width: 100vw;
  407. height: 100vh;
  408. background-color: $bgcolor1;
  409. position: relative;
  410. .topnav {
  411. padding: 0 10rpx;
  412. position: fixed;
  413. top: 0;
  414. left: 0;
  415. width: 100%;
  416. z-index: 100;
  417. backdrop-filter: blur(10px);
  418. .nav-item {
  419. height: 56rpx;
  420. margin-left: 16rpx;
  421. color: #ffffff;
  422. }
  423. .nav-img{
  424. width: 44rpx;
  425. height: 44rpx;
  426. margin: 4rpx 0rpx 0rpx 13rpx;
  427. }
  428. }
  429. .scroll-view{
  430. .message-item{
  431. width: 100vw;
  432. box-sizing: border-box;
  433. padding: 24rpx 28rpx;
  434. .left-img{
  435. width: 120rpx;
  436. height: 120rpx;
  437. margin-right: 24rpx;
  438. border-radius: 44rpx;
  439. transition: all 0.3s;
  440. }
  441. .right-info{
  442. width: 532rpx;
  443. height: 120rpx;
  444. transition: all 0.3s;
  445. .ri-top{
  446. margin-top: 8rpx;
  447. .rit-title{
  448. color: $fontcolor5;
  449. width: 307rpx;
  450. }
  451. .rit-time{
  452. color: $fontcolor2;
  453. }
  454. }
  455. .ri-bottom{
  456. margin-top: 20rpx;
  457. .rib-text{
  458. color: $fontcolor3;
  459. flex: 1;
  460. }
  461. .rib-num{
  462. width:36rpx;
  463. height: 36rpx;
  464. border-radius: 36rpx;
  465. background-color: #FE3B49;
  466. color: #ffffff;
  467. line-height: 36rpx;
  468. text-align: center;
  469. }
  470. }
  471. }
  472. .del-box{
  473. background-color: #FE3B49;
  474. color: #ffffff;
  475. height: 120rpx;
  476. transition: all 0.3s;
  477. overflow: hidden;
  478. line-height: 120rpx;
  479. text-align: center;
  480. margin-left: 16rpx;
  481. }
  482. }
  483. }
  484. }
  485. </style>