post-card.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <template>
  2. <view class="pcard" @tap="$emit('open', post)">
  3. <view class="pcard-hd">
  4. <image class="pcard-avatar" :src="avatarUrl" mode="aspectFill" />
  5. <view class="pcard-meta">
  6. <text class="pcard-nick">{{ nickname }}</text>
  7. <text class="pcard-time">{{ timeText }}</text>
  8. </view>
  9. <view
  10. class="pcard-follow"
  11. :class="{ 'pcard-follow--on': isFollowed }"
  12. @tap.stop="$emit('follow', post)"
  13. >
  14. <text class="pcard-follow-text">{{ isFollowed ? copy.followed : copy.followPlus }}</text>
  15. </view>
  16. </view>
  17. <post-content-block
  18. :post="post"
  19. @open-video="$emit('open-video', $event)"
  20. @open-detail="$emit('open-detail', $event)"
  21. />
  22. <view class="pcard-ft">
  23. <view class="pcard-action" @tap.stop="$emit('like', post)">
  24. <text class="pcard-like" :class="{ 'pcard-like--on': post.isLike === 1 }">♥</text>
  25. <text class="pcard-num">{{ post.likes || 0 }}</text>
  26. </view>
  27. <view class="pcard-action" @tap.stop="$emit('comment', post)">
  28. <text class="pcard-comment">💬</text>
  29. <text class="pcard-num">{{ post.comments || 0 }}</text>
  30. </view>
  31. <view class="pcard-action">
  32. <text class="pcard-view">👁</text>
  33. <text class="pcard-num">{{ post.views || 0 }}</text>
  34. </view>
  35. </view>
  36. </view>
  37. </template>
  38. <script>
  39. import PostContentBlock from '@/components/dynamics/post-content-block.vue'
  40. export default {
  41. name: 'PostCard',
  42. components: { PostContentBlock },
  43. props: {
  44. post: { type: Object, default: () => ({}) }
  45. },
  46. computed: {
  47. copy() {
  48. const t = this.$t.bind(this)
  49. return {
  50. followPlus: t('dynamics.followPlus'),
  51. followed: t('dynamics.followed'),
  52. guest: t('dynamics.guest')
  53. }
  54. },
  55. nickname() {
  56. if (this.post.shop && this.post.shop.shopname) return this.post.shop.shopname
  57. if (this.post.user && this.post.user.nickname) return this.post.user.nickname
  58. return this.copy.guest
  59. },
  60. avatarUrl() {
  61. const path = (this.post.shop && this.post.shop.avatar)
  62. || (this.post.user && this.post.user.avatar)
  63. || ''
  64. if (this.$appKit && typeof this.$appKit.oss === 'function') {
  65. return this.$appKit.oss(path, 72, 72)
  66. }
  67. return path
  68. },
  69. timeText() {
  70. if (this.$appKit && typeof this.$appKit.timeFormat === 'function') {
  71. return this.$appKit.timeFormat(this.post.createtime, 'yyyy-mm-dd') || ''
  72. }
  73. return ''
  74. },
  75. isFollowed() {
  76. const flag = this.post && this.post.isFollow
  77. return flag === 1 || flag === '1' || flag === true
  78. }
  79. }
  80. }
  81. </script>
  82. <style scoped>
  83. .pcard {
  84. margin: 0 32rpx 28rpx;
  85. padding: 28rpx;
  86. background-color: #ffffff;
  87. border-radius: 28rpx;
  88. box-shadow: 0 8rpx 32rpx rgba(74, 140, 255, 0.08);
  89. }
  90. .pcard-hd {
  91. display: flex;
  92. flex-direction: row;
  93. align-items: center;
  94. margin-bottom: 24rpx;
  95. }
  96. .pcard-avatar {
  97. width: 72rpx;
  98. height: 72rpx;
  99. border-radius: 36rpx;
  100. background-color: #eef2f8;
  101. flex-shrink: 0;
  102. }
  103. .pcard-meta {
  104. flex: 1;
  105. min-width: 0;
  106. margin-left: 20rpx;
  107. }
  108. .pcard-nick {
  109. font-size: 30rpx;
  110. font-weight: 700;
  111. color: #1a1d26;
  112. display: block;
  113. overflow: hidden;
  114. text-overflow: ellipsis;
  115. white-space: nowrap;
  116. }
  117. .pcard-time {
  118. font-size: 24rpx;
  119. color: #8a8d9e;
  120. margin-top: 4rpx;
  121. }
  122. .pcard-follow {
  123. padding: 8rpx 20rpx;
  124. border-radius: 999rpx;
  125. background-color: #4a8cff;
  126. flex-shrink: 0;
  127. }
  128. .pcard-follow--on {
  129. background-color: #eef2f8;
  130. }
  131. .pcard-follow-text {
  132. font-size: 22rpx;
  133. color: #ffffff;
  134. }
  135. .pcard-follow--on .pcard-follow-text {
  136. color: #8a8d9e;
  137. }
  138. .pcard-ft {
  139. display: flex;
  140. flex-direction: row;
  141. align-items: center;
  142. margin-top: 24rpx;
  143. padding-top: 20rpx;
  144. border-top: 1rpx solid rgba(0, 0, 0, 0.05);
  145. }
  146. .pcard-action {
  147. display: flex;
  148. flex-direction: row;
  149. align-items: center;
  150. margin-right: 36rpx;
  151. }
  152. .pcard-like,
  153. .pcard-comment,
  154. .pcard-view {
  155. font-size: 30rpx;
  156. margin-right: 8rpx;
  157. color: #b0b4c0;
  158. }
  159. .pcard-like--on {
  160. color: #ff4d4f;
  161. }
  162. .pcard-num {
  163. font-size: 26rpx;
  164. color: #5c6070;
  165. }
  166. </style>