123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763 |
- <template>
- <view class="container">
- <view id="topnav" class="topnav flex-start" :style="{'height':`${topbarOffsetHeight-statusBarHeight}px`,'padding-top':`${statusBarHeight}px`}">
- <view class="nav-item flex-center" @click="back">
- <image :src="`${assetsUrl}back.png`" mode="widthFix" class="nav-img"></image>
- </view>
- <view class="nav-center flex-center">
- <view class="nav-text font32 fw600">
- {{userInfo.nick}}
- </view>
- <view class="nav-tip font20 fw400" >
- {{onlineState}} · {{userInfo.distance}}
- </view>
- </view>
-
- <view class="nav-item"></view>
- </view>
- <scroll-view
- class="scroll-view"
- scroll-y="true"
- :style="{'height': `${scrollHeight}px`,'margin-top':`${topbarOffsetHeight}px`}"
- v-if="scrollHeight>0"
- lower-threshold="200"
- :scroll-into-view="scrollTo"
- refresher-enabled="true"
- :refresher-triggered="scrollTriggered"
- :refresher-threshold="45"
- refresher-default-style="white"
- refresher-background="#151126"
- @refresherrefresh="scrollRefresh"
- @refresherpulling="scrollPulling"
- @refresherrestore="scrollRestore"
- @refresherabort="scrollAbort"
- @scrolltolower="scrollToBottom"
- >
- <!-- <view :id="startItem"></view>
- <view class="msg-line" v-for="(item,index) in messageList" :key="index" v-if="item.hide!==true">
-
- <view class="line" v-if="item.flow==='in'">
- <view class="time font20 fw400" v-if="item.showTime">
- {{item.timeStr}}
- </view>
- <view class="msg-item flex-start" >
- <view class="msg-head">
- <image :src="item.avatar" mode="aspectFill" class="head-img"></image>
- </view>
- <view class="msg-text font28 fw400">
- <rich-text :nodes="item.payload.text"></rich-text>
- </view>
-
- <view class="msg-tag font22 fw400">
-
- </view>
- </view>
- </view>
- <view class="line" v-if="(item.flow==='out'||item.payload.data.systemMsgType===10)&&item.payload.data.systemMsgType!==4">
- <view class="time font20 fw400" v-if="item.showTime">
- {{item.timeStr}}
- </view>
- <view class="msg-item flex-end" >
- <view class="msg-tag font22 fw400" v-if="!item.payload.data">
- {{item.isRead?'已读':'未读'}}
- </view>
- <image :src="`${assetsUrl}talk-payatention.png`" mode="aspectFill" class="err-icon" v-else></image>
- <view class="msg-text font28 fw400" style="background-color: #6C52F4;border-radius: 16rpx 4rpx 16rpx 16rpx;" v-if="item.payload.text!==undefined">
- <rich-text :nodes="item.payload.text"></rich-text>
- </view>
- <view class="msg-head">
- <image :src="item.avatar" mode="aspectFill" class="head-img"></image>
- </view>
- </view>
-
- </view>
- <view class="err-line flex-center" v-if="item.payload.data">
- <text class="err-text font20 fw400">{{item.payload.data.context}}</text><text class="err-text font20 fw400" @click="toPath(item.payload.data.highlightLink)" :style="{'color':`${item.payload.data.highlightColor}`}">{{item.payload.data.highlightContext}}</text>
- </view>
- </view>
-
- <view :id="endItem"></view> -->
-
- <view id="message-scroll" style="width:100%">
- <view class="no-message" v-if="isCompleted">没有更多啦</view>
- <view v-for="item in messageList" :key="item.ID" class="t-message">
- <view v-if="conversation.type !== '@TIM#SYSTEM'" :id="item.ID">
- <view class="t-message-item">
- <TUI-TipMessage v-if="item.type === 'TIMGroupTipElem'" :message="item"></TUI-TipMessage>
- <view v-if="item.type !== 'TIMGroupTipElem'" :class="item.flow === 'out' ? 't-self-message' : 't-recieve-message'">
- <image
- class="t-message-avatar"
- v-if="item.flow === 'in'"
- :src="item.avatar || 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/avatar_21.png'"
- ></image>
- <view class="read-receipts" v-if="conversation.type === 'C2C' && item.flow === 'out'">
- <view v-if="item.isPeerRead">已读</view>
- <view v-else>未读</view>
- </view>
- <view>
- <TUI-TextMessage v-if="item.type === 'TIMTextElem'" :message="item" :isMine="item.flow === 'out'"></TUI-TextMessage>
- <TUI-ImageMessage v-if="item.type === 'TIMImageElem'" :message="item" :isMine="item.flow === 'out'"></TUI-ImageMessage>
- <TUI-VideoMessage v-if="item.type === 'TIMVideoFileElem'" :message="item" :isMine="item.flow === 'out'"></TUI-VideoMessage>
- <TUI-AudioMessage v-if="item.type === 'TIMSoundElem'" :message="item" :isMine="item.flow === 'out'"></TUI-AudioMessage>
- <TUI-CustomMessage v-if="item.type === 'TIMCustomElem'" :message="item" :isMine="item.flow === 'out'"></TUI-CustomMessage>
- <TUI-FaceMessage v-if="item.type === 'TIMFaceElem'" :message="item" :isMine="item.flow === 'out'"></TUI-FaceMessage>
- <TUI-FileMessage v-if="item.type === 'TIMFileElem'" :message="item" :isMine="item.flow === 'out'"></TUI-FileMessage>
- </view>
- <image
- class="t-message-avatar"
- v-if="item.flow === 'out'"
- :src="item.avatar || 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/avatar_21.png'"
- ></image>
- </view>
- </view>
- </view>
- <view v-else :id="item.ID" :data-value="item.ID"><TUI-SystemMessage :message="item"></TUI-SystemMessage></view>
- </view>
- </view>
- </scroll-view>
- <view class="message-input">
- <TUI-message-input id="message-input" ref="messageInput" :conversation="conversation" @sendMessage="sendMessage" />
- </view>
- </view>
- </template>
- <script>
- import TIM from 'tim-wx-sdk';
- import COS from 'cos-wx-sdk-v5';
- import {emojiUrl,emojiMap,emojiName} from '@/util/emojiMap.js';
- import TUITextMessage from '../message-elements/text-message/index';
- import TUIImageMessage from '../message-elements/image-message/index';
- import TUIVideoMessage from '../message-elements/video-message/index';
- import TUIAudioMessage from '../message-elements/audio-message/index';
- import TUICustomMessage from '../message-elements/custom-message/index';
- import TUITipMessage from '../message-elements/tip-message/index';
- import TUISystemMessage from '../message-elements/system-message/index';
- import TUIFaceMessage from '../message-elements/face-message/index';
- import TUIFileMessage from '../message-elements/file-message/index';
- import TUIMessageInput from '../message-elements/message-input/index';
- export default {
- components: {
- TUITextMessage,
- TUIImageMessage,
- TUIVideoMessage,
- TUIAudioMessage,
- TUICustomMessage,
- TUITipMessage,
- TUISystemMessage,
- TUIFaceMessage,
- TUIFileMessage,
- TUIMessageInput
- },
- data() {
- return {
- assetsUrl:this.$util.assetsUrl,
- scrollHeight:0,
- topNavHeight:0,
- inputText:'',
- userInfo:null,
- messageList:[],
- message:null,//消息实例
- onlineState:'',
- scrollRefreshing:false,
- scrollTriggered:true,
- scrollTo:'',
- startItem:'',
- endItem:'',
- nextReqMessageID:'',
- isLoadPreData:false,//是否加载上一页历史记录
- isCompleted:false,//历史记录是否已全部加载完成,
- emojiUrl,
- emojiMap,
- emojiName,
- showEmojis:false
- };
- },
- computed: {
- statusBarHeight() {
- return this.$store.state.statusBarHeight;
- },
- topbarOffsetHeight() {
- return this.$store.state.topbarOffsetHeight;
- }
- },
- created() {
- let pages=getCurrentPages();
- let prePage=pages[pages.length-2];
- this.userInfo=prePage.$vm.userInfo;
- this.IMinit();
- },
- destroyed() {
- console.log('destory')
- uni.$TUIKit.logout();
- uni.$TUIKit.destroy();
- },
- mounted() {
-
- if(this.userInfo.lastActiveTime===0||this.userInfo.online){
- this.onlineState='在线';
- }
- else if(this.userInfo.lastActiveTime<30&&!this.userInfo.online){
- this.onlineState='刚刚';
- }
- else{
- this.onlineState='离线';
- }
- this.computedScollviewHeight();
-
-
-
- },
- methods:{
- back(){
- uni.navigateBack({
- delta:1
- })
- },
- /**
- * 计算scroll高度
- */
- computedScollviewHeight() {
- let query = uni.createSelectorQuery().in(this);
- let heightLeaf =0;
- query.selectAll('#topnav,#talk').boundingClientRect(data => {
- data.forEach(item=>{
- heightLeaf+=item.height;
- })
- }).exec(() => {
- let sysInfo = uni.getSystemInfoSync();
- this.scrollHeight = sysInfo.windowHeight - heightLeaf;
- setTimeout(()=>{
- this.endItem='view_id_' + parseInt(Math.random() * 1000000)
- this.scrollTo=this.endItem;
- console.log('滑动到底部了')
- },1000)
-
- });
-
- },
- /**
- * 推荐下拉刷新、加载更多
- */
- scrollRefresh(){
- if (this.scrollRefreshing)
- {
- return;
- }
- this.scrollRefreshing = true;
- setTimeout(() => {
- this.scrollTriggered = false;
- this.scrollRefreshing = false;
- }, 1000);
- this.isLoadPreData=true;
- this.loadHistoryMessage();
- },
- scrollPulling(e) {},
- scrollRestore() {this.scrollTriggered = true;},
- scrollAbort() {},
- scrollToBottom(){
- },
- toPath(path){
- uni.navigateTo({
- url:path
- })
- },
- action(str){
- switch(str){
- case 'emo':
- this.showEmojis=!this.showEmojis;
- setTimeout(()=>{
- this.computedScollviewHeight();
-
- },300)
- break;
- }
-
- },
- emojiInput(index){
- console.log(this.emojiName[index]);
- this.inputText+=this.emojiName[index];
- },
- IMinit(){
- /**
- * IM初始化
- */
- const SDKAppID = 1400456480,that=this;
- uni.$TUIKit = TIM.create({
- SDKAppID: SDKAppID
- });
- uni.$TUIKitTIM = TIM;
- uni.$TUIKitEvent = TIM.EVENT;
- uni.$TUIKitVersion = TIM.VERSION;
- uni.$TUIKitTypes = TIM.TYPES; // 监听系统级事件
- uni.$resetLoginData = this.resetLoginData();
- uni.$TUIKit.on(uni.$TUIKitEvent.SDK_READY, this.onSDKReady);
- uni.$TUIKit.on(uni.$TUIKitEvent.SDK_NOT_READY, this.onSdkNotReady);
- uni.$TUIKit.on(uni.$TUIKitEvent.KICKED_OUT, this.onKickedOut);
- uni.$TUIKit.on(uni.$TUIKitEvent.ERROR, this.onTIMError);
- uni.$TUIKit.on(uni.$TUIKitEvent.NET_STATE_CHANGE, this.onNetStateChange);
- uni.$TUIKit.on(uni.$TUIKitEvent.SDK_RELOAD, this.onSDKReload);
-
- },
- createMessageConversation(){
- /**
- * 创建消息会话
- */
- this.message=uni.$TUIKit.createTextMessage({
- //to: that.userInfo.id,
- to:'7421',
- conversationType: 'C2C',
- needReadReceipt: true,
- payload:{
- text:'tim'
- }
- })
- this.loadHistoryMessage();
- },
- sendMessage(){
- /**
- * 发送消息
- */
- const that=this;
- if(this.inputText===''){return;}
- this.message.payload.text=this.inputText;
- uni.$TUIKit.sendMessage(this.message).then(res=>{
- console.log(res);
- res.data.message.timeStr=this.$moment(res.data.message.time*1000).calendar(null,{
- sameDay: '[今天] hh:mm',
- lastDay: '[昨天] hh:mm',
- sameElse: 'YYYY-MM-DD hh:mm:ss'
- });
- if(res.code===0){
- // let allStr=res.data.message.payload.text;
- // let allObj={
- // name:'div',
- // attrs:{
- // class:'input',
- // style:''
- // },
- // children:[]
- // }
- // let j=0;
- // for(j=0;j<this.emojiName.length;j++){
- // if(allStr.indexOf(this.emojiName[j])>-1){
- // let imgurl=this.emojiUrl+this.emojiMap[this.emojiName[j]];
- // let obj={
- // name:'img',
- // attrs:{
- // src:imgurl,
- // class:'',
- // style:'width:20px;height:20px;display:inline;'
- // },
- // children:[]
- // }
- // allObj.children.push(obj);
- // }
-
- // }
- // if(j>=this.emojiName.length){//不包含表情
- // let obj={
- // name:'div',
- // attrs:{
- // class:'input',
- // style:''
- // },
- // children:[
- // {
- // type:'text',
- // text:allStr
- // }
- // ]
- // }
- // allObj.children.push(obj);
- // }
- // res.data.message.payload.text=[allObj];
- that.messageList.push(res.data.message);
- that.inputText='';
- }
- that.endItem='view_id_' + parseInt(Math.random() * 1000000)
- that.scrollTo=that.endItem;
- }).catch(err=>{
- uni.showToast({
- title:'发送失败',
- icon:"none"
- });
- let user=JSON.parse(uni.getStorageSync('userInfo'))
- let obj={
- avatar:user.icon,
- flow:'out',
- payload:{
- data:{
- context:'聊天信息涉嫌违规内容,多次违规可能会被封号,请遵守',
- highlightColor: "#44CBFB",
- highlightContext: "《平台行为规范》",
- highlightLink: "/pages/webview/webview?url=https://h5.sugarpark.cn/agreement/behavior-standard.html",
- systemMsgType: 10,
- type: 99,
- },
- text:'****'
-
-
- }
- }
-
- })
- },
- loadHistoryMessage(){
- /**
- * 获取历史消息
- */
- uni.$TUIKit.getMessageList({
- conversationID:this.message.conversationID,
- nextReqMessageID:this.nextReqMessageID,
- count:15
- }).then(res=>{
-
- let result=JSON.parse(JSON.stringify(res));
- console.log(result,result.data.nextReqMessageID,this.nextReqMessageID)
-
- if(this.isCompleted){
- return;
- }
- this.nextReqMessageID=result.data.nextReqMessageID;
-
- if(result.code===0&&result.data.messageList.length>0){
- for(let i=0;i<result.data.messageList.length;i++){
- /**
- * 处理时间
- */
- result.data.messageList[i].timeStr=this.$moment(result.data.messageList[i].time*1000).calendar(null,{
- sameDay: '[今天] hh:mm',
- lastDay: '[昨天] hh:mm',
- sameElse: 'YYYY-MM-DD hh:mm:ss'
- });
- if(i>=1){
- result.data.messageList[i].showTime=(result.data.messageList[i].time-result.data.messageList[i-1].time<300?false:true);
- }
- /**
- * 处理表情
- */
- // if(result.data.messageList[i].payload.text){
- // let allStr=result.data.messageList[i].payload.text;
- // let arr=[];
- // let allObj={
- // name:'div',
- // attrs:{
- // class:'input',
- // style:''
- // },
- // children:[]
- // }
- // for(let j=0;j<this.emojiName.length;j++){
- // if(allStr.indexOf(this.emojiName[j])>-1){
- // arr.push(this.emojiName[j]);
- // let imgurl=this.emojiUrl+this.emojiMap[this.emojiName[j]];
- // let obj={
- // name:'img',
- // attrs:{
- // src:imgurl,
- // class:'',
- // style:'width:20px;height:20px;display:inline;'
- // },
- // children:[]
- // }
- // allObj.children.push(obj);
- // }
- // }
- // result.data.messageList[i].payload.text=[allObj];
- // }
-
- /**
- * 处理非常规消息
- */
- // if(result.data.messageList[i].payload.data){
- // let data=JSON.parse(result.data.messageList[i].payload.data);
- // result.data.messageList[i].flow='out';
- // result.data.messageList[i].avatar=JSON.parse(uni.getStorageSync('userInfo')).icon;
- // if(data.systemMsgType===10){
- // result.data.messageList[i].payload.text='****';
- // data.highlightLink=`/pages/webview/webview?url=${this.$util.protocal.behaviorStandar}`;
- // if(data.context&&data.context.indexOf(data.highlightContext)!==-1){
- // data.context=data.context.substring(0,data.context.indexOf(data.highlightContext));
- // data.highlightColor=`#${data.highlightColor.substring(2)}`
- // }
- // }
- // if(data.systemMsgType===4){
- // data.context='上传真人认证照片,会有更多人喜欢哦~';
- // data.highlightLink='/pages/mine/album';
- // if(data.context&&data.context.indexOf(data.highlightContext)!==-1){
- // data.context=data.context.substring(data.context.indexOf(data.highlightContext)+data.highlightContext.length,data.context.length);
- // data.highlightColor=`#${data.highlightColor.substring(2)}`
- // }
- // }
- // result.data.messageList[i].payload.data=data;
- // }
-
- }
- this.messageList=[...result.data.messageList,...this.messageList];
- console.log(this.messageList);
- this.isCompleted=result.data.isCompleted;
- if(this.isLoadPreData){
- this.startItem='view_id_' + parseInt(Math.random() * 1000000)
- this.scrollTo=this.startItem;
- console.log('滑动到顶部了')
- this.isLoadPreData=false;
- }
- else{
- this.endItem='view_id_' + parseInt(Math.random() * 1000000)
- this.scrollTo=this.endItem;
- console.log('滑动到底部了')
- }
-
-
- }
- })
- },
-
- resetLoginData() {
- let user=JSON.parse(uni.getStorageSync('userInfo'));
- this.$api.IM.loadSig({}).then(res=>{
- this.$store.commit('setImLoadSig',res.data.sig);
- uni.$TUIKit.login({
- userID:String(user.id),
- userSig:res.data.sig
- })
- })
-
- },
- onTIMError() {},
- onSDKReady({name}) {
- const isSDKReady = name === uni.$TUIKitEvent.SDK_READY ? true : false
- if(isSDKReady){
- this.createMessageConversation();
- }
-
- },
- onNetStateChange() {},
- onSDKReload() {},
- onSdkNotReady() {},
- onKickedOut() {
- uni.showToast({
- title: '您被踢下线',
- icon: 'error'
- });
- uni.reLaunch({
- url: '/pages/login/login'
- })
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .container{
- width: 100vw;
- height: 100vh;
- background-color: $bgcolor1;
- position: relative;
- overflow: hidden;
- .topnav {
- padding: 0 10rpx;
- position: fixed;
- top: 0;
- left: 0;
- width: 100vw;
- z-index: 100;
- background-color: $bgcolor1;
- .nav-item{
- width: 40rpx;
- height: 40rpx;
- margin-left: 16rpx;
-
- .nav-img{
- width: 40rpx;
- height: 40rpx;
- }
- }
- .nav-center{
- flex: 1;
- flex-direction: column;
- .nav-text{
-
- color: $fontcolor5;
- height: 40rpx;
- text-align: center;
- }
- .nav-tip{
- color:$fontcolor2;
- }
- }
-
- }
- .scroll-view{
- transition: height .3s;
- }
-
- .t-message-item {
- /*max-width: 60vw;*/
- padding: 16rpx 0;
- }
- .t-recieve-message {
- display: flex;
- flex-direction: row;
- justify-items: flex-start;
- align-items: center;
- width: 100vw;
- }
- .t-message-avatar {
- margin-left: 20rpx;
- margin-right: 12rpx;
- border-radius: 10rpx;
- width: 80rpx;
- height: 80rpx;
- }
- .t-self-message {
- display: flex;
- flex-direction: row;
- justify-content: flex-end;
- /*align-items: center;*/
- width: 100vw;
- }
- .t-self-message-body {
- display: flex;
- justify-content: flex-start;
- flex-wrap: wrap;
- outline: none;
- }
- .t-recieve-message-body {
- display: flex;
- justify-content: flex-start;
- flex-wrap: wrap;
- outline: none;
- /*background: #F8F8F8;*/
- border-radius: 2px 10px 10px 10px;
- margin-left: 8rpx;
- }
- .read-receipts {
- line-height: 42px;
- height: 42px;
- font-size: 12px;
- color: #6e7981;
- margin-right: 10px
- }
- .no-message {
- text-align: center;
- position: fixed;
- width: 100%;
- font-size: 12px;
- color: #a5b5c1;
- height: 40px;
- top: -40px;
- right: 0;
- }
- // .msg-line{
- // margin:16rpx 32rpx;
- // .time{
- // color: #ffffff;
- // text-align: center;
- // margin: 40rpx 0rpx;
- // }
- // .line{
- // .msg-item{
- // .msg-head{
- // width:80rpx;
- // height:80rpx;
- // border-radius:34rpx;
- // .head-img{
- // width:80rpx;
- // height:80rpx;
- // border-radius:34rpx;
- // }
-
- // }
- // .msg-text{
- // padding: 20rpx 24rpx;
- // border-radius: 4rpx 16rpx 16rpx 16rpx;
- // background: #1F1A30;
- // color:#ffffff;
- // margin-left:24rpx;
- // margin-right:16rpx;
- // }
- // .err-icon{
- // width: 40rpx;
- // height: 40rpx;
- // }
- // .msg-tag{
- // width:44rpx;
- // height: 80rpx;
- // color:#6C52F4;
- // line-height:80rpx;
- // text-align:center;
- // }
- // }
- // }
- // .err-line{
- // flex-wrap: wrap;
- // width: 73%;
- // padding: 20rpx 24rpx;
- // margin: 0 auto;
- // .err-text{
- // color:#ffffff ;
- // text-align: center;
- // }
- // }
-
- // }
- .talk-box{
- position: fixed;
- bottom: 0;
- left: 0;
- width: 100vw;
- padding-top: 16rpx;
- background-color: $bgcolor1;
- .input-box{
- margin: 0rpx 32rpx;
- height: 80rpx;
- border-radius: 80rpx;
- background-color: $bgcolor4;
- padding: 0 24rpx;
- .input{
- width: 100%;
- height: 100%;
- color: #ffffff;
- font-size: 22rpx;
- }
- }
- .action-box{
- margin-top: 36rpx;
- padding-bottom: 16rpx;
- .act-img{
- width: 56rpx;
- height: 56rpx;
- }
- }
- .emoji-box{
- padding: 0 11rpx;
- box-sizing: border-box;
- height: 400rpx;
- flex-wrap: wrap;
- transition: height .3s;
- .emoji-item{
- width: 64rpx;
- height: 64rpx;
- padding: 20rpx;
- .emoji-img{
- width: 64rpx;
- height: 64rpx;
- }
- }
- }
- }
- }
- </style>
|