当前位置:   article > 正文

uni-app实现聊天页面功能_uniapp聊天框

uniapp聊天框

聊天页面

  1. <template>
  2. <view class="contents">
  3. <view class="shang" style="position: fixed;top:0;width: 100vw;">
  4. <view class="dingbu" :style="{paddingTop:`${statusBar}px`}">
  5. <view @click="toBack" class="zhuce">
  6. <u-icon name="arrow-left" color="#fff" size="22"></u-icon>
  7. </view>
  8. <text>{{user.userBei.username}}</text>
  9. <view style="width: 22px;"></view>
  10. </view>
  11. </view>
  12. <view class="chat" :style="{paddingTop:`${42+statusBar}px`}">
  13. <scroll-view :style="{height: `${windowHeight-inputHeight- (statusBar*2)-84}rpx`}" id="scrollview"
  14. scroll-y="true" :scroll-top="scrollTop" class="scroll-view">
  15. <!-- 聊天主体 -->
  16. <view id="msglistview" class="chat-body">
  17. <view v-if="msgList.length">
  18. <!-- 聊天记录 -->
  19. <view class="liaotian-item" :class="item.type==2?'liaotian-item-right':''"
  20. v-for="(item,index) in msgList" :key="index">
  21. <!-- 别人发的消息 -->
  22. <view class="item-left" v-if="item.type==1">
  23. <image :src="user.userBei.image" mode=""></image>
  24. <view>
  25. <text class="content">{{item.text}}</text>
  26. <text class="time">{{item.time}}</text>
  27. </view>
  28. </view>
  29. <!-- 自己发的消息 -->
  30. <view class="item-right" v-if="item.type==2">
  31. <view>
  32. <text class="content">{{item.text}}</text>
  33. <text class="time">{{item.time}}</text>
  34. </view>
  35. <image :src="user.user.image" mode=""></image>
  36. </view>
  37. </view>
  38. </view>
  39. <view v-else class="no-chat">
  40. <text class="xian"></text>
  41. <text
  42. class="wenzi">{{yuyan=='en'?'There are currently no chat records available':'暂无聊天记录'}}</text>
  43. <text class="xian"></text>
  44. </view>
  45. </view>
  46. </scroll-view>
  47. <!-- 底部消息发送栏 -->
  48. <!-- 用来占位,防止聊天消息被发送框遮挡 -->
  49. <view class="chat-bottom">
  50. <view class="send-msg" :style="{bottom:`${keyboardHeight}rpx`}">
  51. <view class="uni-textarea">
  52. <textarea v-model="chatMsg" maxlength="255" confirm-type="send" @confirm="handleSend"
  53. :show-confirm-bar="false" :adjust-position="false" @linechange="sendHeight" @focus="focus"
  54. @blur="blur"></textarea>
  55. </view>
  56. <button @click="handleSend" class="send-btn">{{yuyan=='en'?'Send':'发送'}}</button>
  57. </view>
  58. </view>
  59. </view>
  60. </view>
  61. </template>
  62. <script>
  63. import app from '../../App.vue';
  64. export default {
  65. data() {
  66. return {
  67. yuyan: "",
  68. statusBar: app.globalData.statusBar,
  69. imgUrl: app.globalData.imgUrl,
  70. //键盘高度
  71. keyboardHeight: 0,
  72. //底部消息发送高度
  73. bottomHeight: 0,
  74. //滚动距离
  75. scrollTop: 0,
  76. userId: '',
  77. //发送的消息
  78. chatMsg: "",
  79. msgList: [{
  80. text: '嘿!你在做什么?今天有空吗?跟我一起去兜风?',
  81. type: 1,
  82. time: "10:15"
  83. },
  84. {
  85. text: '听起来不错!你现在在哪里?',
  86. type: 2,
  87. time: "10:15"
  88. },
  89. {
  90. text: '听起来不错!',
  91. type: 2,
  92. time: "10:15"
  93. }
  94. ],
  95. user: {},
  96. }
  97. },
  98. updated() {
  99. //页面更新时调用聊天消息定位到最底部
  100. this.scrollToBottom();
  101. },
  102. computed: {
  103. windowHeight() {
  104. return this.rpxTopx(uni.getSystemInfoSync().windowHeight)
  105. },
  106. // 键盘弹起来的高度+发送框高度
  107. inputHeight() {
  108. return this.bottomHeight + this.keyboardHeight
  109. }
  110. },
  111. filters: {
  112. time(time) {
  113. // 时间戳
  114. let timeNow = new Date();
  115. // 获取当前时间的时间日期
  116. let day1 = (timeNow.getDate() < 10 ? '0' + timeNow.getDate() : timeNow.getDate());
  117. let timestamp = time;
  118. // 此处时间戳以毫秒为单位
  119. let date = new Date(parseInt(timestamp) * 1000);
  120. let Year = date.getFullYear();
  121. let Moth = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
  122. let Day = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate());
  123. let Hour = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours());
  124. let Minute = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
  125. let Sechond = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
  126. // let GMT =Year+'/' + Moth + '/' + Day+' '+ Hour + ':' + Minute + ':' + Sechond;
  127. if (day1 == Day) {
  128. return Hour + ':' + Minute
  129. } else {
  130. return Year + '/' + Moth + '/' + Day + Hour + ':' + Minute
  131. }
  132. },
  133. },
  134. onLoad(options) {
  135. uni.onKeyboardHeightChange(res => {
  136. //这里正常来讲代码直接写
  137. //this.keyboardHeight=this.rpxTopx(res.height)就行了
  138. //但是之前界面ui设计聊天框的高度有点高,为了不让键盘和聊天输入框之间距离差太大所以我改动了一下。
  139. this.keyboardHeight = this.rpxTopx(res.height - 30)
  140. if (this.keyboardHeight < 0) this.keyboardHeight = 0;
  141. })
  142. // this.scrollToBottom()
  143. this.yuyan = uni.getLocale()
  144. this.userId = options.id
  145. this.getUserInfor()
  146. },
  147. onShow() {
  148. this.yuyan = uni.getLocale()
  149. },
  150. onUnload() {
  151. uni.offKeyboardHeightChange()
  152. },
  153. methods: {
  154. // 退回
  155. toBack() {
  156. uni.navigateBack()
  157. },
  158. focus() {
  159. this.scrollToBottom()
  160. },
  161. blur() {
  162. this.scrollToBottom()
  163. },
  164. // px转换成rpx
  165. rpxTopx(px) {
  166. let deviceWidth = uni.getSystemInfoSync().windowWidth
  167. let rpx = (750 / deviceWidth) * Number(px)
  168. return Math.floor(rpx)
  169. },
  170. // 监视聊天发送栏高度
  171. sendHeight() {
  172. setTimeout(() => {
  173. let query = uni.createSelectorQuery();
  174. query.select('.send-msg').boundingClientRect()
  175. query.exec(res => {
  176. this.bottomHeight = this.rpxTopx(res[0].height)
  177. })
  178. }, 10)
  179. },
  180. // 滚动至聊天底部
  181. scrollToBottom(e) {
  182. setTimeout(() => {
  183. let query = uni.createSelectorQuery().in(this);
  184. query.select('#scrollview').boundingClientRect();
  185. query.select('#msglistview').boundingClientRect();
  186. query.exec((res) => {
  187. if (res[1].height > res[0].height) {
  188. this.scrollTop = this.rpxTopx(res[1].height - res[0].height)
  189. }
  190. })
  191. }, 15)
  192. },
  193. // 发送消息
  194. handleSend() {
  195. //如果消息不为空
  196. if (this.chatMsg) {
  197. let obj = {
  198. text: this.chatMsg,
  199. type: 2,
  200. time: "10:15",
  201. }
  202. this.msgList.push(obj);
  203. this.chatMsg = '';
  204. this.scrollToBottom()
  205. } else {
  206. uni.showToast({
  207. title: this.yuyan == 'en' ? 'Cannot send a blank message' : '不能发送空白消息',
  208. icon: "none"
  209. })
  210. }
  211. },
  212. // 查询两个用户信息
  213. getUserInfor() {
  214. let data = {
  215. uid: app.globalData.uid,
  216. userId: this.userId,
  217. }
  218. this.yrApi.request('User/getUserXiaoxiInfor', 'POST', data).then(res => {
  219. if (res.data.code == 0) {
  220. this.user = res.data.data
  221. }
  222. })
  223. },
  224. }
  225. }
  226. </script>
  227. <style lang="scss" scoped>
  228. view,
  229. button,
  230. text,
  231. input,
  232. textarea {
  233. margin: 0;
  234. padding: 0;
  235. box-sizing: border-box;
  236. }
  237. .contents {
  238. min-height: 100vh;
  239. box-sizing: border-box;
  240. background-color: rgba(255, 255, 255, 1);
  241. .shang {
  242. z-index: 1;
  243. background: rgba(86, 125, 244, 1);
  244. padding: 20rpx;
  245. display: flex;
  246. justify-content: left;
  247. .dingbu {
  248. width: 100%;
  249. box-sizing: border-box;
  250. display: flex;
  251. justify-content: space-between;
  252. align-items: center;
  253. text {
  254. font-size: 36rpx;
  255. font-weight: 500;
  256. line-height: 42.18rpx;
  257. color: rgba(255, 255, 255, 1);
  258. display: block;
  259. }
  260. .zhuce {
  261. display: flex;
  262. align-items: center;
  263. text {
  264. font-size: 36rpx;
  265. font-weight: 500;
  266. line-height: 42.18rpx;
  267. color: rgba(255, 255, 255, 1);
  268. display: block;
  269. }
  270. }
  271. .zhuc {
  272. width: 160rpx;
  273. height: 80rpx;
  274. border-radius: 20rpx;
  275. border: 2rpx solid rgba(255, 255, 255, 1);
  276. font-size: 32rpx;
  277. font-weight: 700;
  278. line-height: 75rpx;
  279. text-align: center;
  280. color: rgba(255, 255, 255, 1);
  281. }
  282. .yuyan {
  283. width: 80rpx;
  284. height: 80rpx;
  285. border-radius: 20rpx;
  286. background: rgba(255, 255, 255, 0.2);
  287. display: flex;
  288. align-items: center;
  289. justify-content: center;
  290. box-sizing: border-box;
  291. text {
  292. color: #fff;
  293. }
  294. .qiu {
  295. width: 40rpx;
  296. height: 40rpx;
  297. }
  298. text {
  299. font-size: 32rpx;
  300. font-weight: 700;
  301. line-height: 75rpx;
  302. text-align: center;
  303. color: rgba(255, 255, 255, 1);
  304. }
  305. }
  306. }
  307. }
  308. /* 聊天消息 */
  309. .chat {
  310. .scroll-view {
  311. ::-webkit-scrollbar {
  312. display: none;
  313. width: 0 !important;
  314. height: 0 !important;
  315. -webkit-appearance: none;
  316. background: transparent;
  317. color: transparent;
  318. }
  319. .chat-body {
  320. padding: 24rpx;
  321. box-sizing: border-box;
  322. .liaotian-item {
  323. margin-top: 16px;
  324. display: flex;
  325. align-items: flex-start;
  326. .item-left {
  327. display: flex;
  328. align-items: flex-start;
  329. width: 80%;
  330. image {
  331. width: 34px;
  332. height: 34px;
  333. border-radius: 50%;
  334. flex-shrink: 0;
  335. margin-right: 10px;
  336. }
  337. .content {
  338. display: block;
  339. padding: 12px 14px;
  340. border-radius: 0px 15px 15px 15px;
  341. background: rgba(255, 255, 255, 1);
  342. box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.05);
  343. font-size: 14px;
  344. font-weight: 500;
  345. line-height: 20px;
  346. color: rgba(51, 51, 51, 1);
  347. }
  348. .time {
  349. display: block;
  350. font-size: 12px;
  351. font-weight: 400;
  352. line-height: 16px;
  353. color: rgba(117, 129, 143, 1);
  354. margin-top: 10rpx;
  355. }
  356. }
  357. .item-right {
  358. display: flex;
  359. align-items: flex-start;
  360. justify-content: flex-end;
  361. width: 80%;
  362. image {
  363. width: 34px;
  364. height: 34px;
  365. border-radius: 50%;
  366. flex-shrink: 0;
  367. margin-left: 10px;
  368. }
  369. .content {
  370. display: block;
  371. padding: 12px 14px;
  372. border-radius: 15px 0px 15px 15px;
  373. background: rgba(86, 125, 244, 1);
  374. box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.05);
  375. font-size: 14px;
  376. font-weight: 500;
  377. line-height: 20px;
  378. color: rgba(255, 255, 255, 1);
  379. }
  380. .time {
  381. display: block;
  382. font-size: 12px;
  383. font-weight: 400;
  384. line-height: 16px;
  385. color: rgba(117, 129, 143, 1);
  386. margin-top: 10rpx;
  387. text-align: right;
  388. }
  389. }
  390. }
  391. .liaotian-item-right {
  392. justify-content: flex-end;
  393. }
  394. }
  395. .no-chat {
  396. display: flex;
  397. align-items: center;
  398. margin-top: 20rpx;
  399. .wenzi {
  400. display: block;
  401. flex-shrink: 0;
  402. font-size: 14px;
  403. font-weight: 500;
  404. line-height: 22px;
  405. color: rgba(153, 153, 153, 1);
  406. margin: 0 20rpx;
  407. }
  408. .xian {
  409. display: block;
  410. width: 100%;
  411. border-bottom: 1rpx solid rgba(153, 153, 153, 1);
  412. }
  413. }
  414. }
  415. /* 底部聊天发送栏 */
  416. .chat-bottom {
  417. width: 100%;
  418. background: rgba(245, 245, 245, 1);
  419. transition: all 0.1s ease;
  420. // padding-bottom:calc(env(safe-area-inset-bottom));
  421. .send-msg {
  422. display: flex;
  423. align-items: center;
  424. padding: 16rpx 30rpx;
  425. padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
  426. position: fixed;
  427. bottom: 0;
  428. width: 100vw;
  429. transition: all 0.1s ease;
  430. box-sizing: border-box;
  431. background-color: rgba(245, 245, 245, 1);
  432. }
  433. .uni-textarea {
  434. textarea {
  435. width: calc(100vw - 208rpx);
  436. background: #FFFFFF;
  437. border-radius: 10rpx;
  438. font-size: 32rpx;
  439. color: #333333;
  440. line-height: 55rpx;
  441. padding: 10rpx;
  442. height: 75rpx;
  443. box-sizing: border-box;
  444. }
  445. }
  446. .send-btn {
  447. display: flex;
  448. align-items: center;
  449. justify-content: center;
  450. margin-left: 20rpx;
  451. width: 128rpx;
  452. height: 75rpx;
  453. background: #4F7DF5;
  454. border-radius: 8rpx;
  455. font-size: 28rpx;
  456. font-family: PingFang SC;
  457. font-weight: 500;
  458. color: #FFFFFF;
  459. line-height: 28rpx;
  460. flex-shrink: 0;
  461. }
  462. }
  463. }
  464. }
  465. </style>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/698561
推荐阅读
相关标签
  

闽ICP备14008679号