当前位置:   article > 正文

uniapp 仿微信聊天页面和消息列表

uniapp 仿微信聊天页面和消息列表

1 消息列表

  1. <!-- 底部消息列表 -->
  2. <template>
  3. <view class="chatList">
  4. <view v-if="chatList.length>0">
  5. <u-swipe-action :show="item.show" :index="index" v-for="(item, index) in chatList" :key="item.ChatId"
  6. @click="click(index)" :options="options" @content-click="toChat(item.ChatId)">
  7. <view class="item u-border-bottom">
  8. <view class="left">
  9. <view class="photo">
  10. <image :src="item.HeadIcon?$t.img(item.HeadIcon):image"></u-image>
  11. <u-badge type="error" :offset="[0,0]" :count="item.UnRead"></u-badge>
  12. </view>
  13. <!-- 此层wrap在此为必写的,否则可能会出现标题定位错误 -->
  14. <view class="center">
  15. <!-- <view class="title-wrap">
  16. <text class="title u-line-2">{{ item.userName }}</text>
  17. </view> -->
  18. <view class="title">
  19. {{ item.UserName }}
  20. </view>
  21. <view class="note u-line-1">
  22. {{ item.note||'' }}
  23. </view>
  24. </view>
  25. </view>
  26. <view class="right">
  27. {{changeTime(item.LastChatDate)}}
  28. </view>
  29. </view>
  30. </u-swipe-action>
  31. </view>
  32. <view v-else class="nomore">
  33. <u-image width="620" height="400" mode="scaleToFill" :src="noData" />
  34. <u-loadmore status="nomore" />
  35. </view>
  36. </view>
  37. </template>
  38. <script>
  39. import dateTime from '@/commons/dateTime.js';
  40. export default {
  41. data() {
  42. return {
  43. chatList: [],
  44. options: [{
  45. text: '删除',
  46. style: {
  47. backgroundColor: '#dd524d'
  48. }
  49. }],
  50. disabled: false,
  51. btnWidth: 180,
  52. show: false,
  53. noData: this.$t.imgPath('noData.png'),
  54. image: this.$t.imgPath('man.png'),
  55. }
  56. },
  57. methods: {
  58. getList() {
  59. this.$api.chat.GetChatList({
  60. ChatType: 1
  61. }).then(res => {
  62. this.chatList = res.response
  63. this.chatList.forEach(item => {
  64. item.show = false
  65. })
  66. })
  67. },
  68. changeTime(date) {
  69. return dateTime.dateTime(date);
  70. },
  71. toChat(chatId) {
  72. this.$u.route({
  73. url: '/chatPage/chat',
  74. params: {
  75. chatId
  76. }
  77. })
  78. },
  79. click(index) {
  80. this.$api.chat.DeleteChat({
  81. chatId: this.chatList[index].ChatId
  82. }).then(res => {
  83. const {
  84. success,
  85. response
  86. } = res
  87. if (success) {
  88. this.$u.toast(`已结束对话`);
  89. this.getList()
  90. }
  91. })
  92. },
  93. },
  94. onShow() {
  95. this.getList()
  96. }
  97. }
  98. </script>
  99. <style lang="scss" scoped>
  100. .chatList {
  101. .item {
  102. display: flex;
  103. padding: 20rpx;
  104. justify-content: space-between;
  105. .left {
  106. display: flex;
  107. justify-content: start;
  108. .photo {
  109. margin-right: 10rpx;
  110. position: relative;
  111. image {
  112. width: 100rpx;
  113. flex: 0 0 10rpx;
  114. height: 100rpx;
  115. margin-right: 20rpx;
  116. border-radius: 50rpx;
  117. }
  118. }
  119. .center {
  120. width: 400rpx;
  121. overflow: hidden;
  122. .title {
  123. font-size: 30rpx;
  124. font-weight: 500;
  125. color: #333333;
  126. margin-top: 0;
  127. margin-bottom: 20rpx;
  128. }
  129. .note {
  130. font-size: 24rpx;
  131. color: darkgrey;
  132. }
  133. }
  134. }
  135. .right {
  136. font-size: 24rpx;
  137. color: darkgrey;
  138. }
  139. }
  140. .nomore {
  141. padding-top: 300rpx;
  142. ::v-deep .u-image {
  143. margin: 0 auto 30rpx;
  144. }
  145. }
  146. }
  147. </style>

2.聊天页面

  1. <template>
  2. <view class="chat">
  3. <scroll-view :style="{height: `${windowHeight-inputHeight}rpx`}" id="scrollview" scroll-y="true"
  4. :scroll-top="scrollTop" class="scroll-view">
  5. <!-- 聊天主体 -->
  6. <view id="msglistview" class="chat-body">
  7. <!-- 聊天记录 -->
  8. <view v-for="(item,index) in msgList" :key="index">
  9. <!-- 自己发的消息 -->
  10. <view class="chat-time" v-if="item.CreateDate != ''">{{changeTime(item.CreateDate)}}</view>
  11. <view class="item self" v-if="item.MessageType == 2">
  12. <!-- 文字内容 -->
  13. <view class="content right">
  14. {{item.Message}}
  15. </view>
  16. </view>
  17. <!-- 机器人发的消息 -->
  18. <view class="item Ai" v-if="item.MessageType == 1">
  19. <!-- 文字内容 -->
  20. <view class="content left">
  21. {{item.Message}}
  22. </view>
  23. </view>
  24. </view>
  25. </view>
  26. </scroll-view>
  27. <!-- 底部消息发送栏 -->
  28. <!-- 用来占位,防止聊天消息被发送框遮挡 -->
  29. <view class="chat-bottom" :style="{height: `${inputHeight}rpx`}">
  30. <view class="send-msg" :style="{bottom:`${keyboardHeight}rpx`}">
  31. <view class="uni-textarea">
  32. <textarea v-model="chatMsg" maxlength="300" confirm-type="send" @confirm="handleSend"
  33. :show-confirm-bar="false" :adjust-position="false" @linechange="sendHeight" @focus="focus"
  34. @blur="blur" auto-height :hold-keyboard="true"></textarea>
  35. </view>
  36. <button @click="handleSend" class="send-btn">发送</button>
  37. </view>
  38. </view>
  39. </view>
  40. </template>
  41. <script>
  42. import dateTime from '@/commons/dateTime.js';
  43. export default {
  44. data() {
  45. return {
  46. //键盘高度
  47. keyboardHeight: 0,
  48. //底部消息发送高度
  49. bottomHeight: 0,
  50. //滚动距离
  51. scrollTop: 0,
  52. userId: '',
  53. //发送的消息
  54. chatMsg: "",
  55. msgList: [],
  56. autoRefreshId: 1, // 判断自动刷新 1 刷新,0 停止
  57. theTime: '',
  58. unshiftmsg: [],
  59. oldTime: new Date(),
  60. }
  61. },
  62. updated() {
  63. //页面更新时调用聊天消息定位到最底部
  64. this.scrollToBottom();
  65. },
  66. computed: {
  67. windowHeight() {
  68. return this.rpxTopx(uni.getSystemInfoSync().windowHeight)
  69. },
  70. // 键盘弹起来的高度+发送框高度
  71. inputHeight() {
  72. return this.bottomHeight + this.keyboardHeight
  73. }
  74. },
  75. onLoad(data) {
  76. console.log(data);
  77. this.chatId = data.chatId
  78. this.getChatInfo()
  79. uni.onKeyboardHeightChange(res => {
  80. //这里正常来讲代码直接写
  81. //this.keyboardHeight=this.rpxTopx(res.height)就行了
  82. //但是之前界面ui设计聊天框的高度有点高,为了不让键盘和聊天输入框之间距离差太大所以我改动了一下。
  83. this.keyboardHeight = this.rpxTopx(res.height - 30)
  84. if (this.keyboardHeight < 0) this.keyboardHeight = 0;
  85. })
  86. },
  87. onUnload() {
  88. uni.offKeyboardHeightChange()
  89. this.autoRefreshId = 0; // 同时改变autoRefreshId 数值
  90. clearInterval(this.theTime) // 清除指定的定时
  91. clearInterval() // 清除所有
  92. },
  93. onHide() {
  94. this.autoRefreshId = 0; // 同时改变autoRefreshId 数值
  95. clearInterval(this.theTime) // 清除指定的定时
  96. clearInterval() // 清除所有
  97. },
  98. onShow() {
  99. let that = this
  100. if (that.autoRefreshId == 1) {
  101. that.theTime = setInterval(() => {
  102. this.getChatInfo()
  103. }, 5000);
  104. } else {
  105. clearInterval(that.theTime)
  106. }
  107. },
  108. methods: {
  109. getChatInfo() {
  110. this.$api.chat.ChatInfo({
  111. ChatId: this.chatId
  112. }).then(res => {
  113. const {
  114. success,
  115. response
  116. } = res
  117. if (success) {
  118. this.msgList = response.reverse()
  119. // // 数组倒叙 主要是应对后端传过来的数据
  120. // for (var i = 0; i < this.msgList.length; i++) {
  121. // //时间间隔处理
  122. // if (i < this.msgList.length - 1) { //这里表示头部时间还是显示一下
  123. // let t = dateTime.spaceTime(this.oldTime, this.msgList[i].createDate);
  124. // if (t) {
  125. // this.oldTime = t;
  126. // }
  127. // this.msgList[i].createDate = t;
  128. // }
  129. // this.unshiftmsg.unshift(this.msgList[i]);
  130. // }
  131. }
  132. })
  133. },
  134. focus() {
  135. this.scrollToBottom()
  136. },
  137. blur() {
  138. this.scrollToBottom()
  139. },
  140. // px转换成rpx
  141. rpxTopx(px) {
  142. let deviceWidth = wx.getSystemInfoSync().windowWidth
  143. let rpx = (750 / deviceWidth) * Number(px)
  144. return Math.floor(rpx)
  145. },
  146. // 监视聊天发送栏高度
  147. sendHeight() {
  148. setTimeout(() => {
  149. let query = uni.createSelectorQuery();
  150. query.select('.send-msg').boundingClientRect()
  151. query.exec(res => {
  152. this.bottomHeight = this.rpxTopx(res[0].height)
  153. })
  154. }, 10)
  155. },
  156. // 滚动至聊天底部
  157. scrollToBottom(e) {
  158. setTimeout(() => {
  159. let query = uni.createSelectorQuery().in(this);
  160. query.select('#scrollview').boundingClientRect();
  161. query.select('#msglistview').boundingClientRect();
  162. query.exec((res) => {
  163. if (res[1].height > res[0].height) {
  164. this.scrollTop = this.rpxTopx(res[1].height - res[0].height)
  165. }
  166. })
  167. }, 15)
  168. },
  169. // 发送消息
  170. handleSend() {
  171. //如果消息不为空
  172. if (!this.$u.test.isEmpty(this.chatMsg)) {
  173. this.$api.chat.AnswerChat({
  174. chatId: this.chatId,
  175. message: this.chatMsg,
  176. }).then(res => {
  177. if (res.success) {
  178. this.getChatInfo()
  179. this.chatMsg = '';
  180. this.scrollToBottom()
  181. } else {
  182. this.$u.toast('发送失败')
  183. }
  184. })
  185. } else {
  186. this.$u.toast('不能发送空白消息')
  187. }
  188. },
  189. changeTime(date) {
  190. return dateTime.dateTime1(date);
  191. },
  192. }
  193. }
  194. </script>
  195. <style lang="scss" scoped>
  196. view,
  197. button,
  198. text,
  199. input,
  200. textarea {
  201. margin: 0;
  202. padding: 0;
  203. box-sizing: border-box;
  204. }
  205. /* 聊天消息 */
  206. .chat {
  207. .scroll-view {
  208. ::-webkit-scrollbar {
  209. display: none;
  210. width: 0 !important;
  211. height: 0 !important;
  212. -webkit-appearance: none;
  213. background: transparent;
  214. color: transparent;
  215. }
  216. // background-color: orange;
  217. background-color: #F6F6F6;
  218. .chat-body {
  219. display: flex;
  220. flex-direction: column;
  221. padding-top: 23rpx;
  222. // background-color:skyblue;
  223. .chat-time {
  224. font-size: 24rpx;
  225. color: rgba(39, 40, 50, 0.3);
  226. line-height: 34rpx;
  227. padding: 10rpx 0rpx;
  228. text-align: center;
  229. }
  230. .self {
  231. justify-content: flex-end;
  232. }
  233. .item {
  234. display: flex;
  235. padding: 23rpx 30rpx;
  236. // background-color: greenyellow;
  237. .right {
  238. background-color: #EF7F25;
  239. color: #FFFFFF;
  240. border-radius: 30rpx 30rpx 5rpx 30rpx;
  241. }
  242. .left {
  243. background-color: rgba(239, 127, 37, 0.1);
  244. border: 3rpx solid #EF7F25;
  245. color: #9e9e9e;
  246. border-radius: 30rpx 30rpx 30rpx 5rpx;
  247. }
  248. // // 聊天消息的三角形
  249. // .right::after {
  250. // position: absolute;
  251. // display: inline-block;
  252. // content: '';
  253. // width: 0;
  254. // height: 0;
  255. // left: 100%;
  256. // top: 10px;
  257. // border: 12rpx solid transparent;
  258. // border-left: 12rpx solid #EF7F25;
  259. // }
  260. // .left::after {
  261. // position: absolute;
  262. // display: inline-block;
  263. // content: '';
  264. // width: 0;
  265. // height: 0;
  266. // top: 10px;
  267. // right: 100%;
  268. // border: 12rpx solid transparent;
  269. // border-right: 12rpx solid #FFFFFF;
  270. // }
  271. .content {
  272. position: relative;
  273. max-width: 486rpx;
  274. word-wrap: break-word;
  275. padding: 24rpx 24rpx;
  276. margin: 0 24rpx;
  277. font-size: 32rpx;
  278. font-family: PingFang SC;
  279. font-weight: 500;
  280. line-height: 42rpx;
  281. }
  282. }
  283. }
  284. }
  285. /* 底部聊天发送栏 */
  286. .chat-bottom {
  287. width: 100%;
  288. height: 177rpx;
  289. background: #F4F5F7;
  290. transition: all 0.1s ease;
  291. .send-msg {
  292. display: flex;
  293. align-items: flex-end;
  294. padding: 16rpx 30rpx;
  295. width: 100%;
  296. min-height: 177rpx;
  297. position: fixed;
  298. bottom: 0;
  299. background: #EDEDED;
  300. transition: all 0.1s ease;
  301. }
  302. .uni-textarea {
  303. padding-bottom: 70rpx;
  304. textarea {
  305. width: 537rpx;
  306. min-height: 75rpx;
  307. max-height: 500rpx;
  308. background: #FFFFFF;
  309. border-radius: 8rpx;
  310. font-size: 32rpx;
  311. font-family: PingFang SC;
  312. color: #333333;
  313. line-height: 43rpx;
  314. padding: 5rpx 8rpx;
  315. }
  316. }
  317. .send-btn {
  318. display: flex;
  319. align-items: center;
  320. justify-content: center;
  321. margin-bottom: 70rpx;
  322. margin-left: 25rpx;
  323. width: 128rpx;
  324. height: 75rpx;
  325. background: #EF7F25;
  326. border-radius: 30rpx;
  327. font-size: 28rpx;
  328. font-family: PingFang SC;
  329. font-weight: 500;
  330. color: #FFFFFF;
  331. line-height: 28rpx;
  332. }
  333. }
  334. }
  335. </style>

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