瑶都万能墙
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.

268 lines
5.5 KiB

  1. <template>
  2. <view class="comment-list" v-if="comments && comments.length > 0">
  3. <view class="comment-header">
  4. <view class="comment-icon">💬</view>
  5. <text class="comment-count">评论</text>
  6. </view>
  7. <view class="comment-container">
  8. <view
  9. class="comment-item"
  10. v-for="(comment, index) in comments"
  11. :key="index"
  12. >
  13. <view class="comment-user">
  14. <image
  15. class="user-avatar"
  16. :src="comment.userHead || '/static/image/center/default-avatar.png'"
  17. @click.stop="previewImage([comment.userHead])"
  18. mode="aspectFill"
  19. ></image>
  20. <view class="comment-content">
  21. <view class="user-info">
  22. <text class="username">{{ comment.userName }}</text>
  23. <text class="comment-time">{{ formatTime(comment.createTime) }}</text>
  24. </view>
  25. <view class="comment-text" v-html="$utils.stringFormatHtml(comment.userValue)">
  26. </view>
  27. <!-- 评论图片 -->
  28. <view class="comment-images" v-if="getCommentImages(comment).length > 0">
  29. <view
  30. class="comment-image"
  31. v-for="(img, imgIndex) in getCommentImages(comment)"
  32. :key="imgIndex"
  33. @click.stop="previewImage(getCommentImages(comment), imgIndex)"
  34. >
  35. <image :src="img" mode="aspectFill"></image>
  36. </view>
  37. </view>
  38. </view>
  39. </view>
  40. </view>
  41. <!-- 查看更多评论按钮 -->
  42. <view
  43. class="more-btn"
  44. v-if="hasMoreComments"
  45. @click="goToDetail"
  46. >
  47. <text>查看更多评论</text>
  48. <text class="more-icon"></text>
  49. </view>
  50. </view>
  51. </view>
  52. </template>
  53. <script>
  54. export default {
  55. name: 'CommentList',
  56. props: {
  57. comments: {
  58. type: Array,
  59. default: () => []
  60. },
  61. hasMoreComments: {
  62. type: Boolean,
  63. default: false
  64. }
  65. },
  66. data() {
  67. return {
  68. }
  69. },
  70. computed: {
  71. },
  72. methods: {
  73. goToDetail() {
  74. this.$emit('goToDetail')
  75. },
  76. getCommentImages(comment) {
  77. if (!comment.userImage) {
  78. return []
  79. }
  80. return comment.userImage.split(',').filter(img => img.trim())
  81. },
  82. formatTime(time) {
  83. if (!time) return ''
  84. // 如果时间已经包含"发布",直接返回
  85. if (time.includes && time.includes('发布')) {
  86. return time
  87. }
  88. // 使用dayjs格式化时间戳
  89. if (typeof time === 'number' || (typeof time === 'string' && /^\d+$/.test(time))) {
  90. const timestamp = Number(time)
  91. const now = this.$dayjs()
  92. const commentTime = this.$dayjs(timestamp)
  93. // 计算时间差
  94. const diffMinutes = now.diff(commentTime, 'minute')
  95. const diffHours = now.diff(commentTime, 'hour')
  96. const diffDays = now.diff(commentTime, 'day')
  97. if (diffMinutes < 1) {
  98. return '刚刚'
  99. } else if (diffMinutes < 60) {
  100. return `${diffMinutes}分钟前`
  101. } else if (diffHours < 24) {
  102. return `${diffHours}小时前`
  103. } else if (diffDays < 7) {
  104. return `${diffDays}天前`
  105. } else {
  106. return commentTime.format('MM-DD HH:mm')
  107. }
  108. }
  109. // 否则添加"发布"后缀
  110. return time + '发布'
  111. },
  112. previewImage(images, current = 0) {
  113. if (!images || images.length === 0) return
  114. uni.previewImage({
  115. urls: images,
  116. current: current
  117. })
  118. }
  119. }
  120. }
  121. </script>
  122. <style scoped lang="scss">
  123. .comment-list {
  124. margin-top: 20rpx;
  125. background-color: #f8f8f8;
  126. border-radius: 12rpx;
  127. overflow: hidden;
  128. .comment-header {
  129. display: flex;
  130. align-items: center;
  131. padding: 20rpx 30rpx 15rpx;
  132. background-color: #f0f0f0;
  133. border-bottom: 1rpx solid #e5e5e5;
  134. .comment-icon {
  135. font-size: 28rpx;
  136. margin-right: 10rpx;
  137. }
  138. .comment-count {
  139. font-size: 26rpx;
  140. color: #666;
  141. font-weight: 500;
  142. }
  143. }
  144. .comment-container {
  145. padding: 0 30rpx 20rpx;
  146. .comment-item {
  147. padding: 20rpx 0;
  148. border-bottom: 1rpx solid #f0f0f0;
  149. &:last-child {
  150. border-bottom: none;
  151. }
  152. .comment-user {
  153. display: flex;
  154. align-items: flex-start;
  155. .user-avatar {
  156. width: 60rpx;
  157. height: 60rpx;
  158. border-radius: 50%;
  159. margin-right: 20rpx;
  160. flex-shrink: 0;
  161. }
  162. .comment-content {
  163. flex: 1;
  164. .user-info {
  165. display: flex;
  166. align-items: center;
  167. margin-bottom: 8rpx;
  168. .username {
  169. font-size: 26rpx;
  170. color: #576b95;
  171. font-weight: 500;
  172. margin-right: 20rpx;
  173. }
  174. .comment-time {
  175. font-size: 22rpx;
  176. color: #999;
  177. }
  178. }
  179. .comment-text {
  180. font-size: 28rpx;
  181. color: #333;
  182. line-height: 1.5;
  183. word-break: break-all;
  184. margin-bottom: 10rpx;
  185. }
  186. .comment-images {
  187. display: flex;
  188. flex-wrap: wrap;
  189. margin-top: 15rpx;
  190. .comment-image {
  191. margin-right: 10rpx;
  192. margin-bottom: 10rpx;
  193. image {
  194. width: 100rpx;
  195. height: 100rpx;
  196. border-radius: 8rpx;
  197. }
  198. }
  199. }
  200. }
  201. }
  202. }
  203. .expand-btn {
  204. display: flex;
  205. align-items: center;
  206. justify-content: center;
  207. padding: 15rpx 0;
  208. margin-top: 10rpx;
  209. color: #576b95;
  210. font-size: 26rpx;
  211. .expand-icon {
  212. margin-left: 10rpx;
  213. font-size: 20rpx;
  214. }
  215. }
  216. .more-btn {
  217. display: flex;
  218. align-items: center;
  219. justify-content: center;
  220. padding: 15rpx 0;
  221. margin-top: 10rpx;
  222. color: #576b95;
  223. font-size: 26rpx;
  224. background-color: #f5f5f5;
  225. border-radius: 8rpx;
  226. .more-icon {
  227. margin-left: 10rpx;
  228. font-size: 24rpx;
  229. }
  230. }
  231. }
  232. }
  233. </style>