community-comment-list.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. <template>
  2. <view class="comment">
  3. <!-- 评论一级 -->
  4. <view class="comment--item">
  5. <view class="flex col-top row-between">
  6. <!-- 用户头像 -->
  7. <navigator hover-class="none" open-type="navigate"
  8. :url="'/bundle_b/pages/community_user/community_user?id=' + commentInfo.user_id">
  9. <u-image :src="commentInfo.avatar" width="88" height="88" borderRadius="50%"></u-image>
  10. </navigator>
  11. <view class="m-l-16 flex-1" @click="onComment(commentInfo.id, commentInfo.nickname)">
  12. <!-- 用户名称 -->
  13. <view class="lighter sm flex">
  14. {{ commentInfo.nickname }}
  15. <text v-if="commentInfo.is_author" class="lighter xxs author">作者</text>
  16. </view>
  17. <!-- 评论内容 -->
  18. <view class="m-t-10 nr normal content">{{ commentInfo.comment }}</view>
  19. <!-- 评论时间 -->
  20. <view class="muted xs m-t-10">{{ commentInfo.create_time }}</view>
  21. </view>
  22. <!-- 点赞 -->
  23. <view class="good text-center m-l-30"
  24. @click="handleCommentLike(commentInfo.id, commentInfo.is_like, commentInfo)">
  25. <image
  26. :src="commentInfo.is_like ? '/static/images/icon_good_s.png' : '/static/images/icon_good.png'">
  27. </image>
  28. <view class="xxs muted">{{ commentInfo.like }}</view>
  29. </view>
  30. </view>
  31. </view>
  32. <!-- 评论二级 -->
  33. <view v-if="commentInfo.child.length">
  34. <block v-for="(commentItem2, commentIndex2) in commentInfo.child" :key="commentItem2.id">
  35. <view class="comment--item sons m-t-20">
  36. <view class="flex col-top row-between">
  37. <navigator hover-class="none" open-type="navigate"
  38. :url="'/bundle_b/pages/community_user/community_user?id=' + commentItem2.user_id">
  39. <u-image :src="commentItem2.avatar" width="88" height="88" borderRadius="50%"></u-image>
  40. </navigator>
  41. <view class="m-l-16 flex-1" @click="onComment(commentItem2.id, commentItem2.nickname)">
  42. <!-- 用户名称 -->
  43. <view class="lighter sm flex">
  44. {{ commentItem2.nickname }}
  45. <text v-if="commentItem2.is_author" class="lighter xxs author">作者</text>
  46. </view>
  47. <!-- 评论内容 -->
  48. <view class="m-t-10 nr normal content">
  49. <text v-if="commentItem2.is_second == 0">
  50. 回复<text class="primary m-l-6 m-r-6">@{{commentItem2.reply_nickname}}</text>
  51. </text>
  52. {{ commentItem2.comment }}
  53. </view>
  54. <!-- 评论时间 -->
  55. <view class="muted xs m-t-10">{{ commentItem2.create_time }}</view>
  56. <!-- 展开更多 -->
  57. </view>
  58. <!-- 点赞 -->
  59. <view class="good text-center m-l-30"
  60. @click="handleCommentLike(commentItem2.id, commentItem2.is_like, commentItem2)">
  61. <image
  62. :src="commentItem2.is_like ? '/static/images/icon_good_s.png' : '/static/images/icon_good.png'">
  63. </image>
  64. <view class="xxs muted">{{ commentItem2.like }}</view>
  65. </view>
  66. </view>
  67. </view>
  68. </block>
  69. <!-- 是否有更多评论 -->
  70. <view class="sons primary xs m-t-10 flex" @click="handleLoadingMore"
  71. v-if="commentInfo.more != 0 && (commentInfo.more+2) > commentInfo.child.length && more && !commentInfo.loading">
  72. 展开更多回复
  73. <u-icon name="arrow-down" size="22" :color="colorConfig.primary"></u-icon>
  74. </view>
  75. <!-- 加载中 -->
  76. <view class="sons primary xs" v-if="commentInfo.loading">
  77. <u-loading :color="colorConfig.primary" :size="30" mode="circle"></u-loading>
  78. <text class="m-l-20">加载中</text>
  79. </view>
  80. </view>
  81. <view class="border-b"></view>
  82. </view>
  83. </template>
  84. <script>
  85. import {
  86. apiCommunityCommentLike,
  87. getCommunityCommentChildLists
  88. } from '@/api/community.js';
  89. import { debounce } from "@/utils/tools.js"
  90. export default {
  91. name: "community-comment-list",
  92. props: {
  93. comment: {
  94. type: Object
  95. }
  96. },
  97. data() {
  98. return {
  99. more: 1,
  100. page: 1,
  101. pageSize: 5,
  102. commentInfo: {}
  103. }
  104. },
  105. watch: {
  106. comment: {
  107. handler: function(val) {
  108. if ( this.commentInfo.hasOwnProperty('child') ) {
  109. this.commentInfo.child.push(...JSON.parse(JSON.stringify(val.child)))
  110. this.commentInfo.child = this.removeDiffrent(this.commentInfo.child, 'id')
  111. } else {
  112. this.commentInfo = val;
  113. }
  114. },
  115. deep: true,
  116. immediate: true
  117. },
  118. },
  119. mounted() {
  120. this.handleCommentLike = debounce(this.handleCommentLike, 100)
  121. },
  122. methods: {
  123. // 点击评论-commentId是评论的id,index是这个组件在父组件中的第几个
  124. onComment(commentId, commentUserName) {
  125. if(!this.isLogin) return this.$Router.push('/pages/login/login')
  126. this.$emit('reply', {
  127. commentId: commentId,
  128. parentId: this.commentInfo.id,
  129. commentUserName: commentUserName
  130. })
  131. },
  132. /**
  133. * 点赞评论
  134. * @constructor
  135. * @param {number} commentId - 评论的ID
  136. * @param {boolean} status - 点赞评论状态
  137. * @param {object} isParent - 是否是一级评论
  138. */
  139. handleCommentLike(commentId, status, item) {
  140. if(!this.isLogin) return this.$Router.push('/pages/login/login')
  141. // 点赞因为请求的话后端会重新排序导致混乱,所以目前点赞成功后会在本地更改状态不会重新请求
  142. switch (status) {
  143. case 0:
  144. this.$set(item, 'like', item.like += 1)
  145. this.$set(item, 'is_like', 1)
  146. break;
  147. case 1:
  148. this.$set(item, 'like', item.like -= 1)
  149. this.$set(item, 'is_like', 0)
  150. break;
  151. }
  152. apiCommunityCommentLike({
  153. id: commentId,
  154. status: status ? 0 : 1,
  155. type: 2
  156. }).then(res => {
  157. if (res.code !== 1) {
  158. // 不成功把它们改回去
  159. switch (status) {
  160. case 0:
  161. this.$set(item, 'like', item.like -= 1)
  162. this.$set(item, 'is_like', 1)
  163. break;
  164. case 1:
  165. this.$set(item, 'like', item.like += 1)
  166. this.$set(item, 'is_like', 0)
  167. break;
  168. }
  169. this.$toast({
  170. title: res.msg
  171. })
  172. }
  173. })
  174. },
  175. // 加载更多
  176. handleLoadingMore() {
  177. if(!this.isLogin) return this.$Router.push('/pages/login/login')
  178. this.commentInfo.loading = true;
  179. getCommunityCommentChildLists({
  180. comment_id: this.commentInfo.id,
  181. page_no: this.page,
  182. page_size: this.pageSize
  183. }).then(res => {
  184. if (res.code === 1) {
  185. this.more = res.data.more;
  186. this.commentInfo.child.push(...res.data.list)
  187. // 去除重复评论
  188. this.commentInfo.child = this.removeDiffrent(this.commentInfo.child, 'id')
  189. if (res.data.more === 1) this.page += 1
  190. } else {
  191. this.$toast({
  192. title: res.msg
  193. })
  194. }
  195. this.commentInfo.loading = false;
  196. })
  197. },
  198. /**
  199. * 去重
  200. * @constructor
  201. * @param {Array} arr - 需要去重的数组对象
  202. * @param {string} key - 需要去重的对象key值
  203. * @returns {Array} Array
  204. */
  205. removeDiffrent(arr, key = 'id') {
  206. let obj = {};
  207. return arr.reduce((setArr, item) => {
  208. obj[item[key]] ? '' : obj[item[key]] = true && setArr.push(item);
  209. return setArr;
  210. }, []);
  211. }
  212. }
  213. }
  214. </script>
  215. <style lang="scss" scoped>
  216. .comment {
  217. transition: all .5s;
  218. padding: 24rpx 24rpx 0 24rpx;
  219. .border-b {
  220. margin-left: 104rpx;
  221. padding-bottom: 18rpx;
  222. border-bottom: 1px solid $-color-border;
  223. }
  224. .sons {
  225. margin-left: 104rpx;
  226. }
  227. &--item {
  228. transition: all .5s;
  229. .author {
  230. padding: 0 16rpx;
  231. margin-left: 10rpx;
  232. background-color: #eee;
  233. border-radius: 18rpx;
  234. }
  235. .content {
  236. white-space: pre-line;
  237. }
  238. .good {
  239. image {
  240. width: 26rpx;
  241. height: 26rpx;
  242. }
  243. }
  244. }
  245. }
  246. </style>