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

296 lines
6.4 KiB

2 weeks ago
  1. <template>
  2. <view class="waterfall-item" @click="handleClick">
  3. <!-- 主图片 -->
  4. <view class="main-image" v-if="mainImage">
  5. <image :src="mainImage" mode="aspectFill" @click.stop="previewImage([mainImage])"></image>
  6. <!-- 分类标签 -->
  7. <view class="category-tag" v-if="item.classId_dictText">
  8. #{{ item.classId_dictText }}
  9. </view>
  10. </view>
  11. <!-- 内容区域 -->
  12. <view class="content">
  13. <!-- 标题/内容 -->
  14. <view class="title" v-if="item.title" v-html="formatContent(item.title)"></view>
  15. <!-- 地址信息 -->
  16. <view class="address" v-if="item.address">
  17. <uv-icon name="map-pin" size="24rpx" color="#999"></uv-icon>
  18. <text>{{ item.address }}</text>
  19. </view>
  20. <!-- 用户信息 -->
  21. <view class="user-info">
  22. <view class="user-avatar">
  23. <image :src="item.userImage" mode="aspectFill" @click.stop="previewImage([item.userImage])"></image>
  24. </view>
  25. <view class="user-details">
  26. <view class="username">{{ item.userName }}</view>
  27. <view class="user-tags">
  28. <text class="tag" v-if="item.sex" :style="{'background-color': sexColors[item.sex] || '#999'}">{{ item.sex }}</text>
  29. <text class="tag" v-if="item.yearDate">{{ item.yearDate }}</text>
  30. <text class="auth-tag" v-if="item.isContent">{{ item.isContent }}</text>
  31. </view>
  32. </view>
  33. </view>
  34. <!-- 互动数据 -->
  35. <view class="interaction">
  36. <view class="interaction-item">
  37. <uv-icon name="eye" size="24rpx" color="#999"></uv-icon>
  38. <text>{{ item.isBrowse || 0 }}</text>
  39. </view>
  40. <view class="interaction-item">
  41. <uv-icon name="chat" size="24rpx" color="#999"></uv-icon>
  42. <text>{{ item.isComment || 0 }}</text>
  43. </view>
  44. <view class="interaction-item" @click.stop="handleLike">
  45. <uv-icon name="thumb-up" size="24rpx" :color="isLiked ? '#ff4757' : '#999'"></uv-icon>
  46. <text :style="{color: isLiked ? '#ff4757' : '#999'}">{{ item.isUp || 0 }}</text>
  47. </view>
  48. <!-- 发布时间 -->
  49. <view class="publish-time">
  50. {{ formatTime(item.createTime) }}
  51. </view>
  52. </view>
  53. </view>
  54. </view>
  55. </template>
  56. <script>
  57. export default {
  58. props: {
  59. item: {
  60. type: Object,
  61. default: () => ({})
  62. }
  63. },
  64. data() {
  65. return {
  66. isLiked: false,
  67. sexColors: {
  68. '男': '#4A90E2',
  69. '女': '#FF69B4',
  70. '其他': '#999'
  71. }
  72. }
  73. },
  74. computed: {
  75. // 主图片 - 优先显示微信图片,然后是第一张图片
  76. mainImage() {
  77. if (this.item.wxImage) {
  78. return this.item.wxImage
  79. }
  80. if (this.item.image) {
  81. const images = this.item.image.split(',').filter(img => img.trim())
  82. return images.length > 0 ? images[0] : null
  83. }
  84. return null
  85. }
  86. },
  87. methods: {
  88. // 处理点击事件
  89. handleClick() {
  90. this.$emit('click', this.item)
  91. },
  92. // 处理点赞事件
  93. handleLike() {
  94. this.isLiked = !this.isLiked
  95. this.$emit('like', this.item)
  96. },
  97. // 预览图片
  98. previewImage(urls, current = 0) {
  99. if (!urls || urls.length === 0) return
  100. uni.previewImage({
  101. urls: urls,
  102. current: current
  103. })
  104. },
  105. // 格式化内容
  106. formatContent(content) {
  107. if (!content) return ''
  108. // 尝试使用全局utils,如果不存在则返回原内容
  109. if (this.$utils && this.$utils.stringFormatHtml) {
  110. return this.$utils.stringFormatHtml(content)
  111. }
  112. // 简单的HTML处理
  113. return content.replace(/\n/g, '<br/>')
  114. },
  115. // 格式化时间
  116. formatTime(timeStr) {
  117. if (!timeStr) return ''
  118. // 如果已经包含"发布",直接返回
  119. if (timeStr.includes('发布')) {
  120. return timeStr
  121. }
  122. // 简单的时间格式处理
  123. const now = new Date()
  124. const time = new Date(timeStr)
  125. const diff = now - time
  126. const days = Math.floor(diff / (1000 * 60 * 60 * 24))
  127. if (days === 0) {
  128. return '今天'
  129. } else if (days === 1) {
  130. return '昨天'
  131. } else if (days < 7) {
  132. return `${days}天前`
  133. } else {
  134. // 返回月-日格式
  135. const month = time.getMonth() + 1
  136. const day = time.getDate()
  137. return `${month}-${day}`
  138. }
  139. }
  140. }
  141. }
  142. </script>
  143. <style scoped lang="scss">
  144. .waterfall-item {
  145. background-color: #fff;
  146. border-radius: 16rpx;
  147. overflow: hidden;
  148. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
  149. margin-bottom: 20rpx;
  150. .main-image {
  151. position: relative;
  152. width: 100%;
  153. image {
  154. width: 100%;
  155. height: 400rpx;
  156. object-fit: cover;
  157. }
  158. .category-tag {
  159. position: absolute;
  160. top: 16rpx;
  161. right: 16rpx;
  162. background: rgba(255, 215, 0, 0.9);
  163. color: #333;
  164. padding: 8rpx 16rpx;
  165. border-radius: 20rpx;
  166. font-size: 22rpx;
  167. font-weight: 500;
  168. }
  169. }
  170. .content {
  171. padding: 24rpx;
  172. .title {
  173. font-size: 28rpx;
  174. line-height: 1.4;
  175. color: #333;
  176. margin-bottom: 16rpx;
  177. display: -webkit-box;
  178. -webkit-box-orient: vertical;
  179. -webkit-line-clamp: 3;
  180. overflow: hidden;
  181. }
  182. .address {
  183. display: flex;
  184. align-items: center;
  185. margin-bottom: 20rpx;
  186. text {
  187. font-size: 24rpx;
  188. color: #666;
  189. margin-left: 8rpx;
  190. }
  191. }
  192. .user-info {
  193. display: flex;
  194. align-items: center;
  195. margin-bottom: 20rpx;
  196. .user-avatar {
  197. width: 60rpx;
  198. height: 60rpx;
  199. border-radius: 30rpx;
  200. overflow: hidden;
  201. margin-right: 16rpx;
  202. image {
  203. width: 100%;
  204. height: 100%;
  205. }
  206. }
  207. .user-details {
  208. flex: 1;
  209. .username {
  210. font-size: 26rpx;
  211. color: #333;
  212. font-weight: 500;
  213. margin-bottom: 6rpx;
  214. }
  215. .user-tags {
  216. display: flex;
  217. align-items: center;
  218. flex-wrap: wrap;
  219. .tag {
  220. font-size: 20rpx;
  221. color: white;
  222. background-color: #999;
  223. padding: 4rpx 12rpx;
  224. border-radius: 12rpx;
  225. margin-right: 8rpx;
  226. margin-bottom: 4rpx;
  227. }
  228. .auth-tag {
  229. font-size: 20rpx;
  230. color: white;
  231. background-color: #ffd036;
  232. padding: 4rpx 12rpx;
  233. border-radius: 12rpx;
  234. margin-right: 8rpx;
  235. margin-bottom: 4rpx;
  236. }
  237. }
  238. }
  239. }
  240. .interaction {
  241. display: flex;
  242. align-items: center;
  243. justify-content: space-between;
  244. .interaction-item {
  245. display: flex;
  246. align-items: center;
  247. text {
  248. font-size: 24rpx;
  249. color: #999;
  250. margin-left: 6rpx;
  251. }
  252. }
  253. .publish-time {
  254. font-size: 24rpx;
  255. color: #999;
  256. margin-left: auto;
  257. }
  258. }
  259. }
  260. }
  261. </style>