talk.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. <template>
  2. <view class="container">
  3. <view id="topnav" class="topnav flex-start" :style="{'height':`${topbarOffsetHeight-statusBarHeight}px`,'padding-top':`${statusBarHeight}px`}">
  4. <view class="nav-item flex-center" @click="back">
  5. <image :src="`${assetsUrl}back.png`" mode="widthFix" class="nav-img"></image>
  6. </view>
  7. <view class="nav-center flex-center">
  8. <view class="nav-text font32 fw600">
  9. {{userInfo.nick}}
  10. </view>
  11. <view class="nav-tip font20 fw400" >
  12. {{onlineState}} · {{userInfo.distance}}
  13. </view>
  14. </view>
  15. <view class="nav-item"></view>
  16. </view>
  17. <scroll-view
  18. class="scroll-view"
  19. scroll-y="true"
  20. :style="{'height': `${scrollHeight}px`,'margin-top':`${topbarOffsetHeight}px`}"
  21. v-if="scrollHeight>0"
  22. lower-threshold="200"
  23. :scroll-into-view="scrollTo"
  24. refresher-enabled="true"
  25. :refresher-triggered="scrollTriggered"
  26. :refresher-threshold="45"
  27. refresher-default-style="white"
  28. refresher-background="#151126"
  29. @refresherrefresh="scrollRefresh"
  30. @refresherpulling="scrollPulling"
  31. @refresherrestore="scrollRestore"
  32. @refresherabort="scrollAbort"
  33. @scrolltolower="scrollToBottom"
  34. >
  35. <!-- <view :id="startItem"></view>
  36. <view class="msg-line" v-for="(item,index) in messageList" :key="index" v-if="item.hide!==true">
  37. <view class="line" v-if="item.flow==='in'">
  38. <view class="time font20 fw400" v-if="item.showTime">
  39. {{item.timeStr}}
  40. </view>
  41. <view class="msg-item flex-start" >
  42. <view class="msg-head">
  43. <image :src="item.avatar" mode="aspectFill" class="head-img"></image>
  44. </view>
  45. <view class="msg-text font28 fw400">
  46. <rich-text :nodes="item.payload.text"></rich-text>
  47. </view>
  48. <view class="msg-tag font22 fw400">
  49. </view>
  50. </view>
  51. </view>
  52. <view class="line" v-if="(item.flow==='out'||item.payload.data.systemMsgType===10)&&item.payload.data.systemMsgType!==4">
  53. <view class="time font20 fw400" v-if="item.showTime">
  54. {{item.timeStr}}
  55. </view>
  56. <view class="msg-item flex-end" >
  57. <view class="msg-tag font22 fw400" v-if="!item.payload.data">
  58. {{item.isRead?'已读':'未读'}}
  59. </view>
  60. <image :src="`${assetsUrl}talk-payatention.png`" mode="aspectFill" class="err-icon" v-else></image>
  61. <view class="msg-text font28 fw400" style="background-color: #6C52F4;border-radius: 16rpx 4rpx 16rpx 16rpx;" v-if="item.payload.text!==undefined">
  62. <rich-text :nodes="item.payload.text"></rich-text>
  63. </view>
  64. <view class="msg-head">
  65. <image :src="item.avatar" mode="aspectFill" class="head-img"></image>
  66. </view>
  67. </view>
  68. </view>
  69. <view class="err-line flex-center" v-if="item.payload.data">
  70. <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>
  71. </view>
  72. </view>
  73. <view :id="endItem"></view> -->
  74. <view id="message-scroll" style="width:100%">
  75. <view class="no-message" v-if="isCompleted">没有更多啦</view>
  76. <view v-for="item in messageList" :key="item.ID" class="t-message">
  77. <view v-if="conversation.type !== '@TIM#SYSTEM'" :id="item.ID">
  78. <view class="t-message-item">
  79. <TUI-TipMessage v-if="item.type === 'TIMGroupTipElem'" :message="item"></TUI-TipMessage>
  80. <view v-if="item.type !== 'TIMGroupTipElem'" :class="item.flow === 'out' ? 't-self-message' : 't-recieve-message'">
  81. <image
  82. class="t-message-avatar"
  83. v-if="item.flow === 'in'"
  84. :src="item.avatar || 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/avatar_21.png'"
  85. ></image>
  86. <view class="read-receipts" v-if="conversation.type === 'C2C' && item.flow === 'out'">
  87. <view v-if="item.isPeerRead">已读</view>
  88. <view v-else>未读</view>
  89. </view>
  90. <view>
  91. <TUI-TextMessage v-if="item.type === 'TIMTextElem'" :message="item" :isMine="item.flow === 'out'"></TUI-TextMessage>
  92. <TUI-ImageMessage v-if="item.type === 'TIMImageElem'" :message="item" :isMine="item.flow === 'out'"></TUI-ImageMessage>
  93. <TUI-VideoMessage v-if="item.type === 'TIMVideoFileElem'" :message="item" :isMine="item.flow === 'out'"></TUI-VideoMessage>
  94. <TUI-AudioMessage v-if="item.type === 'TIMSoundElem'" :message="item" :isMine="item.flow === 'out'"></TUI-AudioMessage>
  95. <TUI-CustomMessage v-if="item.type === 'TIMCustomElem'" :message="item" :isMine="item.flow === 'out'"></TUI-CustomMessage>
  96. <TUI-FaceMessage v-if="item.type === 'TIMFaceElem'" :message="item" :isMine="item.flow === 'out'"></TUI-FaceMessage>
  97. <TUI-FileMessage v-if="item.type === 'TIMFileElem'" :message="item" :isMine="item.flow === 'out'"></TUI-FileMessage>
  98. </view>
  99. <image
  100. class="t-message-avatar"
  101. v-if="item.flow === 'out'"
  102. :src="item.avatar || 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/avatar_21.png'"
  103. ></image>
  104. </view>
  105. </view>
  106. </view>
  107. <view v-else :id="item.ID" :data-value="item.ID"><TUI-SystemMessage :message="item"></TUI-SystemMessage></view>
  108. </view>
  109. </view>
  110. </scroll-view>
  111. <view class="message-input">
  112. <TUI-message-input id="message-input" ref="messageInput" :conversation="conversation" @sendMessage="sendMessage" />
  113. </view>
  114. </view>
  115. </template>
  116. <script>
  117. import TIM from 'tim-wx-sdk';
  118. import COS from 'cos-wx-sdk-v5';
  119. import {emojiUrl,emojiMap,emojiName} from '@/util/emojiMap.js';
  120. import TUITextMessage from '../message-elements/text-message/index';
  121. import TUIImageMessage from '../message-elements/image-message/index';
  122. import TUIVideoMessage from '../message-elements/video-message/index';
  123. import TUIAudioMessage from '../message-elements/audio-message/index';
  124. import TUICustomMessage from '../message-elements/custom-message/index';
  125. import TUITipMessage from '../message-elements/tip-message/index';
  126. import TUISystemMessage from '../message-elements/system-message/index';
  127. import TUIFaceMessage from '../message-elements/face-message/index';
  128. import TUIFileMessage from '../message-elements/file-message/index';
  129. import TUIMessageInput from '../message-elements/message-input/index';
  130. export default {
  131. components: {
  132. TUITextMessage,
  133. TUIImageMessage,
  134. TUIVideoMessage,
  135. TUIAudioMessage,
  136. TUICustomMessage,
  137. TUITipMessage,
  138. TUISystemMessage,
  139. TUIFaceMessage,
  140. TUIFileMessage,
  141. TUIMessageInput
  142. },
  143. data() {
  144. return {
  145. assetsUrl:this.$util.assetsUrl,
  146. scrollHeight:0,
  147. topNavHeight:0,
  148. inputText:'',
  149. userInfo:null,
  150. messageList:[],
  151. message:null,//消息实例
  152. onlineState:'',
  153. scrollRefreshing:false,
  154. scrollTriggered:true,
  155. scrollTo:'',
  156. startItem:'',
  157. endItem:'',
  158. nextReqMessageID:'',
  159. isLoadPreData:false,//是否加载上一页历史记录
  160. isCompleted:false,//历史记录是否已全部加载完成,
  161. emojiUrl,
  162. emojiMap,
  163. emojiName,
  164. showEmojis:false
  165. };
  166. },
  167. computed: {
  168. statusBarHeight() {
  169. return this.$store.state.statusBarHeight;
  170. },
  171. topbarOffsetHeight() {
  172. return this.$store.state.topbarOffsetHeight;
  173. }
  174. },
  175. created() {
  176. let pages=getCurrentPages();
  177. let prePage=pages[pages.length-2];
  178. this.userInfo=prePage.$vm.userInfo;
  179. this.IMinit();
  180. },
  181. destroyed() {
  182. console.log('destory')
  183. uni.$TUIKit.logout();
  184. uni.$TUIKit.destroy();
  185. },
  186. mounted() {
  187. if(this.userInfo.lastActiveTime===0||this.userInfo.online){
  188. this.onlineState='在线';
  189. }
  190. else if(this.userInfo.lastActiveTime<30&&!this.userInfo.online){
  191. this.onlineState='刚刚';
  192. }
  193. else{
  194. this.onlineState='离线';
  195. }
  196. this.computedScollviewHeight();
  197. },
  198. methods:{
  199. back(){
  200. uni.navigateBack({
  201. delta:1
  202. })
  203. },
  204. /**
  205. * 计算scroll高度
  206. */
  207. computedScollviewHeight() {
  208. let query = uni.createSelectorQuery().in(this);
  209. let heightLeaf =0;
  210. query.selectAll('#topnav,#talk').boundingClientRect(data => {
  211. data.forEach(item=>{
  212. heightLeaf+=item.height;
  213. })
  214. }).exec(() => {
  215. let sysInfo = uni.getSystemInfoSync();
  216. this.scrollHeight = sysInfo.windowHeight - heightLeaf;
  217. setTimeout(()=>{
  218. this.endItem='view_id_' + parseInt(Math.random() * 1000000)
  219. this.scrollTo=this.endItem;
  220. console.log('滑动到底部了')
  221. },1000)
  222. });
  223. },
  224. /**
  225. * 推荐下拉刷新、加载更多
  226. */
  227. scrollRefresh(){
  228. if (this.scrollRefreshing)
  229. {
  230. return;
  231. }
  232. this.scrollRefreshing = true;
  233. setTimeout(() => {
  234. this.scrollTriggered = false;
  235. this.scrollRefreshing = false;
  236. }, 1000);
  237. this.isLoadPreData=true;
  238. this.loadHistoryMessage();
  239. },
  240. scrollPulling(e) {},
  241. scrollRestore() {this.scrollTriggered = true;},
  242. scrollAbort() {},
  243. scrollToBottom(){
  244. },
  245. toPath(path){
  246. uni.navigateTo({
  247. url:path
  248. })
  249. },
  250. action(str){
  251. switch(str){
  252. case 'emo':
  253. this.showEmojis=!this.showEmojis;
  254. setTimeout(()=>{
  255. this.computedScollviewHeight();
  256. },300)
  257. break;
  258. }
  259. },
  260. emojiInput(index){
  261. console.log(this.emojiName[index]);
  262. this.inputText+=this.emojiName[index];
  263. },
  264. IMinit(){
  265. /**
  266. * IM初始化
  267. */
  268. const SDKAppID = 1400456480,that=this;
  269. uni.$TUIKit = TIM.create({
  270. SDKAppID: SDKAppID
  271. });
  272. uni.$TUIKitTIM = TIM;
  273. uni.$TUIKitEvent = TIM.EVENT;
  274. uni.$TUIKitVersion = TIM.VERSION;
  275. uni.$TUIKitTypes = TIM.TYPES; // 监听系统级事件
  276. uni.$resetLoginData = this.resetLoginData();
  277. uni.$TUIKit.on(uni.$TUIKitEvent.SDK_READY, this.onSDKReady);
  278. uni.$TUIKit.on(uni.$TUIKitEvent.SDK_NOT_READY, this.onSdkNotReady);
  279. uni.$TUIKit.on(uni.$TUIKitEvent.KICKED_OUT, this.onKickedOut);
  280. uni.$TUIKit.on(uni.$TUIKitEvent.ERROR, this.onTIMError);
  281. uni.$TUIKit.on(uni.$TUIKitEvent.NET_STATE_CHANGE, this.onNetStateChange);
  282. uni.$TUIKit.on(uni.$TUIKitEvent.SDK_RELOAD, this.onSDKReload);
  283. },
  284. createMessageConversation(){
  285. /**
  286. * 创建消息会话
  287. */
  288. this.message=uni.$TUIKit.createTextMessage({
  289. //to: that.userInfo.id,
  290. to:'7421',
  291. conversationType: 'C2C',
  292. needReadReceipt: true,
  293. payload:{
  294. text:'tim'
  295. }
  296. })
  297. this.loadHistoryMessage();
  298. },
  299. sendMessage(){
  300. /**
  301. * 发送消息
  302. */
  303. const that=this;
  304. if(this.inputText===''){return;}
  305. this.message.payload.text=this.inputText;
  306. uni.$TUIKit.sendMessage(this.message).then(res=>{
  307. console.log(res);
  308. res.data.message.timeStr=this.$moment(res.data.message.time*1000).calendar(null,{
  309. sameDay: '[今天] hh:mm',
  310. lastDay: '[昨天] hh:mm',
  311. sameElse: 'YYYY-MM-DD hh:mm:ss'
  312. });
  313. if(res.code===0){
  314. // let allStr=res.data.message.payload.text;
  315. // let allObj={
  316. // name:'div',
  317. // attrs:{
  318. // class:'input',
  319. // style:''
  320. // },
  321. // children:[]
  322. // }
  323. // let j=0;
  324. // for(j=0;j<this.emojiName.length;j++){
  325. // if(allStr.indexOf(this.emojiName[j])>-1){
  326. // let imgurl=this.emojiUrl+this.emojiMap[this.emojiName[j]];
  327. // let obj={
  328. // name:'img',
  329. // attrs:{
  330. // src:imgurl,
  331. // class:'',
  332. // style:'width:20px;height:20px;display:inline;'
  333. // },
  334. // children:[]
  335. // }
  336. // allObj.children.push(obj);
  337. // }
  338. // }
  339. // if(j>=this.emojiName.length){//不包含表情
  340. // let obj={
  341. // name:'div',
  342. // attrs:{
  343. // class:'input',
  344. // style:''
  345. // },
  346. // children:[
  347. // {
  348. // type:'text',
  349. // text:allStr
  350. // }
  351. // ]
  352. // }
  353. // allObj.children.push(obj);
  354. // }
  355. // res.data.message.payload.text=[allObj];
  356. that.messageList.push(res.data.message);
  357. that.inputText='';
  358. }
  359. that.endItem='view_id_' + parseInt(Math.random() * 1000000)
  360. that.scrollTo=that.endItem;
  361. }).catch(err=>{
  362. uni.showToast({
  363. title:'发送失败',
  364. icon:"none"
  365. });
  366. let user=JSON.parse(uni.getStorageSync('userInfo'))
  367. let obj={
  368. avatar:user.icon,
  369. flow:'out',
  370. payload:{
  371. data:{
  372. context:'聊天信息涉嫌违规内容,多次违规可能会被封号,请遵守',
  373. highlightColor: "#44CBFB",
  374. highlightContext: "《平台行为规范》",
  375. highlightLink: "/pages/webview/webview?url=https://h5.sugarpark.cn/agreement/behavior-standard.html",
  376. systemMsgType: 10,
  377. type: 99,
  378. },
  379. text:'****'
  380. }
  381. }
  382. })
  383. },
  384. loadHistoryMessage(){
  385. /**
  386. * 获取历史消息
  387. */
  388. uni.$TUIKit.getMessageList({
  389. conversationID:this.message.conversationID,
  390. nextReqMessageID:this.nextReqMessageID,
  391. count:15
  392. }).then(res=>{
  393. let result=JSON.parse(JSON.stringify(res));
  394. console.log(result,result.data.nextReqMessageID,this.nextReqMessageID)
  395. if(this.isCompleted){
  396. return;
  397. }
  398. this.nextReqMessageID=result.data.nextReqMessageID;
  399. if(result.code===0&&result.data.messageList.length>0){
  400. for(let i=0;i<result.data.messageList.length;i++){
  401. /**
  402. * 处理时间
  403. */
  404. result.data.messageList[i].timeStr=this.$moment(result.data.messageList[i].time*1000).calendar(null,{
  405. sameDay: '[今天] hh:mm',
  406. lastDay: '[昨天] hh:mm',
  407. sameElse: 'YYYY-MM-DD hh:mm:ss'
  408. });
  409. if(i>=1){
  410. result.data.messageList[i].showTime=(result.data.messageList[i].time-result.data.messageList[i-1].time<300?false:true);
  411. }
  412. /**
  413. * 处理表情
  414. */
  415. // if(result.data.messageList[i].payload.text){
  416. // let allStr=result.data.messageList[i].payload.text;
  417. // let arr=[];
  418. // let allObj={
  419. // name:'div',
  420. // attrs:{
  421. // class:'input',
  422. // style:''
  423. // },
  424. // children:[]
  425. // }
  426. // for(let j=0;j<this.emojiName.length;j++){
  427. // if(allStr.indexOf(this.emojiName[j])>-1){
  428. // arr.push(this.emojiName[j]);
  429. // let imgurl=this.emojiUrl+this.emojiMap[this.emojiName[j]];
  430. // let obj={
  431. // name:'img',
  432. // attrs:{
  433. // src:imgurl,
  434. // class:'',
  435. // style:'width:20px;height:20px;display:inline;'
  436. // },
  437. // children:[]
  438. // }
  439. // allObj.children.push(obj);
  440. // }
  441. // }
  442. // result.data.messageList[i].payload.text=[allObj];
  443. // }
  444. /**
  445. * 处理非常规消息
  446. */
  447. // if(result.data.messageList[i].payload.data){
  448. // let data=JSON.parse(result.data.messageList[i].payload.data);
  449. // result.data.messageList[i].flow='out';
  450. // result.data.messageList[i].avatar=JSON.parse(uni.getStorageSync('userInfo')).icon;
  451. // if(data.systemMsgType===10){
  452. // result.data.messageList[i].payload.text='****';
  453. // data.highlightLink=`/pages/webview/webview?url=${this.$util.protocal.behaviorStandar}`;
  454. // if(data.context&&data.context.indexOf(data.highlightContext)!==-1){
  455. // data.context=data.context.substring(0,data.context.indexOf(data.highlightContext));
  456. // data.highlightColor=`#${data.highlightColor.substring(2)}`
  457. // }
  458. // }
  459. // if(data.systemMsgType===4){
  460. // data.context='上传真人认证照片,会有更多人喜欢哦~';
  461. // data.highlightLink='/pages/mine/album';
  462. // if(data.context&&data.context.indexOf(data.highlightContext)!==-1){
  463. // data.context=data.context.substring(data.context.indexOf(data.highlightContext)+data.highlightContext.length,data.context.length);
  464. // data.highlightColor=`#${data.highlightColor.substring(2)}`
  465. // }
  466. // }
  467. // result.data.messageList[i].payload.data=data;
  468. // }
  469. }
  470. this.messageList=[...result.data.messageList,...this.messageList];
  471. console.log(this.messageList);
  472. this.isCompleted=result.data.isCompleted;
  473. if(this.isLoadPreData){
  474. this.startItem='view_id_' + parseInt(Math.random() * 1000000)
  475. this.scrollTo=this.startItem;
  476. console.log('滑动到顶部了')
  477. this.isLoadPreData=false;
  478. }
  479. else{
  480. this.endItem='view_id_' + parseInt(Math.random() * 1000000)
  481. this.scrollTo=this.endItem;
  482. console.log('滑动到底部了')
  483. }
  484. }
  485. })
  486. },
  487. resetLoginData() {
  488. let user=JSON.parse(uni.getStorageSync('userInfo'));
  489. this.$api.IM.loadSig({}).then(res=>{
  490. this.$store.commit('setImLoadSig',res.data.sig);
  491. uni.$TUIKit.login({
  492. userID:String(user.id),
  493. userSig:res.data.sig
  494. })
  495. })
  496. },
  497. onTIMError() {},
  498. onSDKReady({name}) {
  499. const isSDKReady = name === uni.$TUIKitEvent.SDK_READY ? true : false
  500. if(isSDKReady){
  501. this.createMessageConversation();
  502. }
  503. },
  504. onNetStateChange() {},
  505. onSDKReload() {},
  506. onSdkNotReady() {},
  507. onKickedOut() {
  508. uni.showToast({
  509. title: '您被踢下线',
  510. icon: 'error'
  511. });
  512. uni.reLaunch({
  513. url: '/pages/login/login'
  514. })
  515. }
  516. }
  517. }
  518. </script>
  519. <style lang="scss" scoped>
  520. .container{
  521. width: 100vw;
  522. height: 100vh;
  523. background-color: $bgcolor1;
  524. position: relative;
  525. overflow: hidden;
  526. .topnav {
  527. padding: 0 10rpx;
  528. position: fixed;
  529. top: 0;
  530. left: 0;
  531. width: 100vw;
  532. z-index: 100;
  533. background-color: $bgcolor1;
  534. .nav-item{
  535. width: 40rpx;
  536. height: 40rpx;
  537. margin-left: 16rpx;
  538. .nav-img{
  539. width: 40rpx;
  540. height: 40rpx;
  541. }
  542. }
  543. .nav-center{
  544. flex: 1;
  545. flex-direction: column;
  546. .nav-text{
  547. color: $fontcolor5;
  548. height: 40rpx;
  549. text-align: center;
  550. }
  551. .nav-tip{
  552. color:$fontcolor2;
  553. }
  554. }
  555. }
  556. .scroll-view{
  557. transition: height .3s;
  558. }
  559. .t-message-item {
  560. /*max-width: 60vw;*/
  561. padding: 16rpx 0;
  562. }
  563. .t-recieve-message {
  564. display: flex;
  565. flex-direction: row;
  566. justify-items: flex-start;
  567. align-items: center;
  568. width: 100vw;
  569. }
  570. .t-message-avatar {
  571. margin-left: 20rpx;
  572. margin-right: 12rpx;
  573. border-radius: 10rpx;
  574. width: 80rpx;
  575. height: 80rpx;
  576. }
  577. .t-self-message {
  578. display: flex;
  579. flex-direction: row;
  580. justify-content: flex-end;
  581. /*align-items: center;*/
  582. width: 100vw;
  583. }
  584. .t-self-message-body {
  585. display: flex;
  586. justify-content: flex-start;
  587. flex-wrap: wrap;
  588. outline: none;
  589. }
  590. .t-recieve-message-body {
  591. display: flex;
  592. justify-content: flex-start;
  593. flex-wrap: wrap;
  594. outline: none;
  595. /*background: #F8F8F8;*/
  596. border-radius: 2px 10px 10px 10px;
  597. margin-left: 8rpx;
  598. }
  599. .read-receipts {
  600. line-height: 42px;
  601. height: 42px;
  602. font-size: 12px;
  603. color: #6e7981;
  604. margin-right: 10px
  605. }
  606. .no-message {
  607. text-align: center;
  608. position: fixed;
  609. width: 100%;
  610. font-size: 12px;
  611. color: #a5b5c1;
  612. height: 40px;
  613. top: -40px;
  614. right: 0;
  615. }
  616. // .msg-line{
  617. // margin:16rpx 32rpx;
  618. // .time{
  619. // color: #ffffff;
  620. // text-align: center;
  621. // margin: 40rpx 0rpx;
  622. // }
  623. // .line{
  624. // .msg-item{
  625. // .msg-head{
  626. // width:80rpx;
  627. // height:80rpx;
  628. // border-radius:34rpx;
  629. // .head-img{
  630. // width:80rpx;
  631. // height:80rpx;
  632. // border-radius:34rpx;
  633. // }
  634. // }
  635. // .msg-text{
  636. // padding: 20rpx 24rpx;
  637. // border-radius: 4rpx 16rpx 16rpx 16rpx;
  638. // background: #1F1A30;
  639. // color:#ffffff;
  640. // margin-left:24rpx;
  641. // margin-right:16rpx;
  642. // }
  643. // .err-icon{
  644. // width: 40rpx;
  645. // height: 40rpx;
  646. // }
  647. // .msg-tag{
  648. // width:44rpx;
  649. // height: 80rpx;
  650. // color:#6C52F4;
  651. // line-height:80rpx;
  652. // text-align:center;
  653. // }
  654. // }
  655. // }
  656. // .err-line{
  657. // flex-wrap: wrap;
  658. // width: 73%;
  659. // padding: 20rpx 24rpx;
  660. // margin: 0 auto;
  661. // .err-text{
  662. // color:#ffffff ;
  663. // text-align: center;
  664. // }
  665. // }
  666. // }
  667. .talk-box{
  668. position: fixed;
  669. bottom: 0;
  670. left: 0;
  671. width: 100vw;
  672. padding-top: 16rpx;
  673. background-color: $bgcolor1;
  674. .input-box{
  675. margin: 0rpx 32rpx;
  676. height: 80rpx;
  677. border-radius: 80rpx;
  678. background-color: $bgcolor4;
  679. padding: 0 24rpx;
  680. .input{
  681. width: 100%;
  682. height: 100%;
  683. color: #ffffff;
  684. font-size: 22rpx;
  685. }
  686. }
  687. .action-box{
  688. margin-top: 36rpx;
  689. padding-bottom: 16rpx;
  690. .act-img{
  691. width: 56rpx;
  692. height: 56rpx;
  693. }
  694. }
  695. .emoji-box{
  696. padding: 0 11rpx;
  697. box-sizing: border-box;
  698. height: 400rpx;
  699. flex-wrap: wrap;
  700. transition: height .3s;
  701. .emoji-item{
  702. width: 64rpx;
  703. height: 64rpx;
  704. padding: 20rpx;
  705. .emoji-img{
  706. width: 64rpx;
  707. height: 64rpx;
  708. }
  709. }
  710. }
  711. }
  712. }
  713. </style>