与牧同行-小程序用户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

336 lines
12 KiB

  1. <view class="consult-page">
  2. <!-- 头部专家信息 -->
  3. <view class="consult-header">
  4. <view class="header-content">
  5. <view class="header-center">
  6. <view class="expert-info">
  7. <text class="expert-name">{{expertInfo.name}}</text>
  8. <view class="expert-status">
  9. <view class="status-dot {{expertInfo.online ? 'online' : 'offline'}}"></view>
  10. <text class="status-text">{{expertInfo.online ? '在线' : '离线'}}</text>
  11. </view>
  12. </view>
  13. </view>
  14. </view>
  15. </view>
  16. <!-- 聊天内容区域 -->
  17. <scroll-view
  18. id="chatScroll"
  19. class="chat-container"
  20. scroll-y
  21. scroll-top="{{scrollTop}}"
  22. scroll-with-animation="{{scrollAnimate}}"
  23. enable-back-to-top="true"
  24. show-scrollbar="{{false}}"
  25. bindscroll="onScroll"
  26. >
  27. <!-- 日期分隔线 -->
  28. <view class="date-divider" wx:if="{{showDateDivider}}">
  29. <text class="date-text">{{todayDate}}</text>
  30. </view>
  31. <!-- 消息列表 -->
  32. <block wx:for="{{messageList}}" wx:key="id">
  33. <!-- 对方消息 -->
  34. <view class="message-item message-left" wx:if="{{item.sender === 'expert'}}">
  35. <view class="message-avatar">
  36. <image src="/pagesA/images/1.png" class="avatar-img"></image>
  37. </view>
  38. <view class="message-content-wrapper">
  39. <!-- 气泡箭头 -->
  40. <view class="message-arrow arrow-left"></view>
  41. <!-- 文本消息 -->
  42. <view class="message-bubble bubble-left" wx:if="{{item.type === 'text'}}">
  43. <text class="message-text">{{item.content}}</text>
  44. </view>
  45. <!-- 图片消息 -->
  46. <view class="media-bubble" wx:elif="{{item.type === 'image'}}">
  47. <image
  48. src="{{item.content}}"
  49. class="message-image"
  50. mode="aspectFill"
  51. bindtap="previewImage"
  52. data-url="{{item.content}}"
  53. ></image>
  54. </view>
  55. <!-- 视频消息 -->
  56. <view class="media-bubble" wx:elif="{{item.type === 'video'}}">
  57. <video
  58. src="{{item.content}}"
  59. class="message-video"
  60. controls
  61. show-center-play-btn
  62. poster="{{item.thumb}}"
  63. ></video>
  64. <view class="video-play-overlay">
  65. <image src="/images/icons/play.png" class="play-icon"></image>
  66. </view>
  67. </view>
  68. <!-- 语音消息 -->
  69. <view class="message-bubble bubble-left message-audio" wx:elif="{{item.type === 'audio'}}">
  70. <image src="/images/icons/voice_left.png" class="audio-icon-left"></image>
  71. <view class="audio-content">
  72. <view class="audio-wave">
  73. <view class="wave-bar" style="animation-delay: 0s;"></view>
  74. <view class="wave-bar" style="animation-delay: 0.2s;"></view>
  75. <view class="wave-bar" style="animation-delay: 0.4s;"></view>
  76. </view>
  77. <text class="audio-duration">{{item.duration || 0}}''</text>
  78. </view>
  79. </view>
  80. <!-- 文件消息 -->
  81. <view class="message-bubble bubble-left message-file" wx:elif="{{item.type === 'file'}}">
  82. <view class="file-icon-box">
  83. <image src="/images/icons/file_icon.png" class="file-icon"></image>
  84. </view>
  85. <view class="file-info">
  86. <text class="file-name">{{item.fileName}}</text>
  87. <text class="file-size">{{formatFileSize(item.fileSize)}}</text>
  88. </view>
  89. </view>
  90. </view>
  91. </view>
  92. <!-- 我的消息 -->
  93. <view class="message-item message-right" wx:else>
  94. <view class="message-content-wrapper">
  95. <!-- 气泡箭头 -->
  96. <view class="message-arrow arrow-right"></view>
  97. <!-- 文本消息 -->
  98. <view class="message-bubble bubble-right" wx:if="{{item.type === 'text'}}">
  99. <text class="message-text">{{item.content}}</text>
  100. </view>
  101. <!-- 图片消息 -->
  102. <view class="media-bubble" wx:elif="{{item.type === 'image'}}">
  103. <image
  104. src="{{item.content}}"
  105. class="message-image"
  106. mode="aspectFill"
  107. bindtap="previewImage"
  108. data-url="{{item.content}}"
  109. ></image>
  110. <view class="upload-progress" wx:if="{{item.status === 'uploading'}}">
  111. <view class="progress-circle">
  112. <text class="progress-text">{{item.progress}}%</text>
  113. </view>
  114. </view>
  115. </view>
  116. <!-- 视频消息 -->
  117. <view class="media-bubble" wx:elif="{{item.type === 'video'}}">
  118. <video
  119. src="{{item.content}}"
  120. class="message-video"
  121. controls
  122. show-center-play-btn
  123. poster="{{item.thumb}}"
  124. ></video>
  125. <view class="video-play-overlay">
  126. <image src="/images/icons/play.png" class="play-icon"></image>
  127. </view>
  128. <view class="upload-progress" wx:if="{{item.status === 'uploading'}}">
  129. <view class="progress-circle">
  130. <text class="progress-text">{{item.progress}}%</text>
  131. </view>
  132. </view>
  133. </view>
  134. <!-- 语音消息 -->
  135. <view class="message-bubble bubble-right message-audio" wx:elif="{{item.type === 'audio'}}">
  136. <view class="audio-content">
  137. <view class="audio-wave">
  138. <view class="wave-bar" style="animation-delay: 0s;"></view>
  139. <view class="wave-bar" style="animation-delay: 0.2s;"></view>
  140. <view class="wave-bar" style="animation-delay: 0.4s;"></view>
  141. </view>
  142. <text class="audio-duration">{{item.duration || 0}}''</text>
  143. </view>
  144. <image src="/images/icons/voice_right.png" class="audio-icon-right"></image>
  145. </view>
  146. <!-- 文件消息 -->
  147. <view class="message-bubble bubble-right message-file" wx:elif="{{item.type === 'file'}}">
  148. <view class="file-icon-box">
  149. <image src="/images/icons/file_icon.png" class="file-icon"></image>
  150. </view>
  151. <view class="file-info">
  152. <text class="file-name">{{item.fileName}}</text>
  153. <text class="file-size">{{formatFileSize(item.fileSize)}}</text>
  154. </view>
  155. <view class="upload-progress" wx:if="{{item.status === 'uploading'}}">
  156. <view class="progress-circle">
  157. <text class="progress-text">{{item.progress}}%</text>
  158. </view>
  159. </view>
  160. </view>
  161. </view>
  162. <view class="message-avatar">
  163. <image src="/pagesA/images/2.png" class="avatar-img"></image>
  164. </view>
  165. </view>
  166. </block>
  167. <!-- 底部留白区域 -->
  168. <view class="chat-bottom-space"></view>
  169. <!-- 加载更多提示 -->
  170. <view class="load-more-tip" wx:if="{{loadingMore}}">
  171. <text>加载中...</text>
  172. </view>
  173. <!-- 没有消息提示 -->
  174. <view class="empty-tip" wx:if="{{messageList.length === 0 && !loading}}">
  175. <image src="/images/icons/empty_chat.png" class="empty-icon"></image>
  176. <text class="empty-text">暂无聊天记录,开始咨询吧</text>
  177. </view>
  178. </scroll-view>
  179. <!-- 输入区域 -->
  180. <view class="input-section">
  181. <!-- 语音输入模式 -->
  182. <view class="voice-input-panel" wx:if="{{inputMode === 'voice'}}">
  183. <!-- 切换到文字输入按钮 -->
  184. <view class="voice-input-btn" bindtap="switchInputMode">
  185. <image src="/pagesA/images/xjp.png" class="voice-btn-icon"></image>
  186. </view>
  187. <!-- 语音输入按钮 -->
  188. <view class="input-wrapper">
  189. <view
  190. class="voice-record-btn"
  191. bindtouchstart="startVoiceRecord"
  192. bindtouchmove="onVoiceTouchMove"
  193. bindtouchend="endVoiceRecord"
  194. bindtouchcancel="cancelVoiceRecord"
  195. >
  196. <text class="voice-tip">{{voiceTip}}</text>
  197. </view>
  198. </view>
  199. <view class="more-btn" bindtap="showMediaActionSheet" >
  200. <image src="/pagesA/images/add.png" class="more-icon"></image>
  201. </view>
  202. </view>
  203. <!-- 文字输入模式 -->
  204. <view class="text-input-panel" wx:else>
  205. <!-- 切换到语音输入按钮 -->
  206. <view class="voice-input-btn" bindtap="switchInputMode">
  207. <image src="/pagesA/images/yy.png" class="voice-btn-icon"></image>
  208. </view>
  209. <!-- 文字输入框 -->
  210. <view class="input-wrapper">
  211. <input
  212. type="text"
  213. class="chat-input"
  214. placeholder="{{inputPlaceholder}}"
  215. placeholder-class="input-placeholder"
  216. value="{{inputValue}}"
  217. bindinput="onInput"
  218. bindconfirm="sendTextMessage"
  219. confirm-type="send"
  220. focus="{{inputFocus}}"
  221. adjust-position="{{false}}"
  222. cursor-spacing="20"
  223. bindfocus="onInputFocus"
  224. bindblur="onInputBlur"
  225. />
  226. <!-- 输入框操作按钮 -->
  227. <view class="input-actions" wx:if="{{inputValue.trim()}}">
  228. <button class="clear-btn" bindtap="clearInput">
  229. <image src="/images/icons/clear.png" class="clear-icon"></image>
  230. </button>
  231. </view>
  232. </view>
  233. <!-- 发送/更多按钮 -->
  234. <!-- <button
  235. class="send-btn"
  236. bindtap="sendTextMessage"
  237. wx:if="{{inputValue.trim()}}"
  238. >
  239. <text class="send-text">发送</text>
  240. </button> -->
  241. <view class="more-btn" bindtap="showMediaActionSheet" >
  242. <image src="/pagesA/images/add.png" class="more-icon"></image>
  243. </view>
  244. </view>
  245. </view>
  246. <!-- 多媒体选择面板 -->
  247. <view class="media-action-sheet" wx:if="{{showMediaSheet}}" catchtap="hideMediaActionSheet">
  248. <view class="media-sheet-content" catchtap="stopPropagation">
  249. <view class="media-sheet-header">
  250. <text class="sheet-title">发送内容</text>
  251. <view class="close-sheet-btn" bindtap="hideMediaActionSheet">
  252. <image src="/pagesA/images/cuo.png"></image>
  253. </view>
  254. </view>
  255. <view class="media-options-grid">
  256. <view class="media-option" bindtap="chooseImage">
  257. <view class="option-icon-box">
  258. <image src="/pagesA/images/zp.png"></image>
  259. </view>
  260. <text class="option-text">照片</text>
  261. </view>
  262. <view class="media-option" bindtap="chooseVideo">
  263. <view class="option-icon-box">
  264. <image src="/pagesA/images/ps.png"></image>
  265. </view>
  266. <text class="option-text">视频</text>
  267. </view>
  268. <view class="media-option" bindtap="chooseFile">
  269. <view class="option-icon-box">
  270. <image src="/pagesA/images/wj.png"></image>
  271. </view>
  272. <text class="option-text">文件</text>
  273. </view>
  274. </view>
  275. <view class="sheet-bottom">
  276. <text class="bottom-tip">最多可选择9张照片</text>
  277. </view>
  278. </view>
  279. </view>
  280. <!-- 录音提示 -->
  281. <view class="recording-modal" wx:if="{{isRecording}}">
  282. <view class="recording-box {{isCanceling ? 'is-canceling' : ''}}">
  283. <view class="recording-icon">
  284. <image
  285. src="{{isCanceling ? '/images/icons/cancel_recording.png' : '/images/icons/recording.png'}}"
  286. class="recording-mic-icon"
  287. ></image>
  288. </view>
  289. <text class="recording-tip">{{recordingTip}}</text>
  290. <view class="recording-meter">
  291. <view class="recording-waves">
  292. <view
  293. class="recording-wave"
  294. wx:for="{{[1,2,3,4,5]}}"
  295. wx:key="index"
  296. style="animation-delay: {{index * 0.1}}s;"
  297. ></view>
  298. </view>
  299. <text class="recording-time">{{recordingTime}}s</text>
  300. </view>
  301. </view>
  302. </view>
  303. </view>