chat.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <template>
  2. <view class="chat-container">
  3. <view class="chat-header">
  4. <text class="chat-title">{{ chatName }}</text>
  5. </view>
  6. <scroll-view class="chat-messages" scroll-y :scroll-into-view="scrollInto">
  7. <view
  8. class="message-item"
  9. :class="{ mine: msg.isMine }"
  10. v-for="(msg, index) in messages"
  11. :key="index"
  12. :id="'msg-' + index"
  13. >
  14. <view class="message-time">{{ msg.time }}</view>
  15. <view class="message-bubble">
  16. {{ msg.content }}
  17. </view>
  18. </view>
  19. </scroll-view>
  20. <view class="chat-input">
  21. <input
  22. class="input-field"
  23. v-model="inputText"
  24. placeholder="输入消息..."
  25. @confirm="sendMessage"
  26. />
  27. <button class="send-btn" @click="sendMessage">发送</button>
  28. </view>
  29. </view>
  30. </template>
  31. <script>
  32. import { getGuideMessages } from '../../utils/api.js'
  33. export default {
  34. data() {
  35. return {
  36. conversationId: '',
  37. chatName: '',
  38. messages: [],
  39. inputText: '',
  40. scrollInto: ''
  41. }
  42. },
  43. onLoad(options) {
  44. this.conversationId = options.conversationId || ''
  45. this.chatName = options.name || '聊天'
  46. this.loadMessages()
  47. },
  48. methods: {
  49. async loadMessages() {
  50. try {
  51. const res = await uni.request({
  52. url: `${getApp().globalData.baseUrl}/api/guide/messages/${this.conversationId}`,
  53. method: 'GET',
  54. header: { Authorization: `Bearer ${uni.getStorageSync('token')}` }
  55. })
  56. if (res.data && res.data.data) {
  57. this.messages = res.data.data
  58. }
  59. } catch (e) {
  60. console.error(e)
  61. this.messages = [
  62. { content: '老师,孩子今天的任务完成了', time: '2024-01-15 10:20', isMine: false },
  63. { content: '好的,我看一下', time: '2024-01-15 10:25', isMine: true },
  64. { content: '谢谢老师', time: '2024-01-15 10:30', isMine: false }
  65. ]
  66. }
  67. this.$nextTick(() => {
  68. this.scrollToBottom()
  69. })
  70. },
  71. async sendMessage() {
  72. if (!this.inputText.trim()) return
  73. const newMessage = {
  74. content: this.inputText,
  75. time: new Date().toLocaleString(),
  76. isMine: true
  77. }
  78. this.messages.push(newMessage)
  79. this.inputText = ''
  80. this.$nextTick(() => {
  81. this.scrollToBottom()
  82. })
  83. try {
  84. await uni.request({
  85. url: `${getApp().globalData.baseUrl}/api/guide/messages`,
  86. method: 'POST',
  87. header: { Authorization: `Bearer ${uni.getStorageSync('token')}` },
  88. data: {
  89. conversationId: this.conversationId,
  90. content: newMessage.content
  91. }
  92. })
  93. } catch (e) {
  94. console.error(e)
  95. }
  96. },
  97. scrollToBottom() {
  98. const len = this.messages.length
  99. if (len > 0) {
  100. this.scrollInto = 'msg-' + (len - 1)
  101. }
  102. }
  103. }
  104. }
  105. </script>
  106. <style scoped>
  107. .chat-container {
  108. display: flex;
  109. flex-direction: column;
  110. height: 100vh;
  111. background: #f5f5f5;
  112. }
  113. .chat-header {
  114. background: #fff;
  115. padding: 30rpx;
  116. text-align: center;
  117. border-bottom: 1rpx solid #eee;
  118. }
  119. .chat-title {
  120. font-size: 32rpx;
  121. font-weight: bold;
  122. color: #333;
  123. }
  124. .chat-messages {
  125. flex: 1;
  126. padding: 30rpx;
  127. overflow-y: auto;
  128. }
  129. .message-item {
  130. display: flex;
  131. flex-direction: column;
  132. margin-bottom: 30rpx;
  133. }
  134. .message-item.mine {
  135. align-items: flex-end;
  136. }
  137. .message-time {
  138. font-size: 22rpx;
  139. color: #999;
  140. margin-bottom: 10rpx;
  141. }
  142. .message-bubble {
  143. max-width: 70%;
  144. padding: 20rpx 30rpx;
  145. background: #fff;
  146. border-radius: 16rpx;
  147. font-size: 28rpx;
  148. color: #333;
  149. word-wrap: break-word;
  150. }
  151. .message-item.mine .message-bubble {
  152. background: #667eea;
  153. color: #fff;
  154. }
  155. .chat-input {
  156. display: flex;
  157. align-items: center;
  158. padding: 20rpx 30rpx;
  159. background: #fff;
  160. border-top: 1rpx solid #eee;
  161. }
  162. .input-field {
  163. flex: 1;
  164. padding: 20rpx 30rpx;
  165. background: #f5f5f5;
  166. border-radius: 40rpx;
  167. font-size: 28rpx;
  168. }
  169. .send-btn {
  170. margin-left: 20rpx;
  171. padding: 20rpx 40rpx;
  172. background: #667eea;
  173. color: #fff;
  174. border-radius: 40rpx;
  175. font-size: 28rpx;
  176. }
  177. </style>