chat.vue 4.2 KB

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