comment.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. <template>
  2. <view class="video-comment-wrap">
  3. <view class="flex action-wrap">
  4. <view class="item" @click="handleSetLike(1)">
  5. <image :src="info.op_type===1?like_act_img:like_img" mode="aspectFill"/>
  6. <text>{{info.like_total>0?info.like_total:''}}</text>
  7. </view>
  8. <view class="item" @click="handleSetLike(2)" style="text-align:center">
  9. <image :src="info.op_type===2?tease_act_img:tease_img" mode="aspectFill"/>
  10. <text>{{info.tease_total>0?info.tease_total:''}}</text>
  11. </view>
  12. <view class="item" @click="showComment" style="text-align:right">
  13. <image :src="comment_img" mode="aspectFill"/>
  14. <text>{{info.comment_total>0?info.comment_total:''}}</text>
  15. </view>
  16. </view>
  17. <view class="list-commnet-box" v-if="info.comment_list.length>0">
  18. <template class="item" v-for="(item,index) in info.comment_list" >
  19. <image class="avatar" :src="item.qa_avatar_url" mode="aspectFill" lazy-load="false" :key="index"/>
  20. <text :key="index">{{item.comment}}</text>
  21. </template>
  22. </view>
  23. <!-- 评论弹窗 -->
  24. <van-action-sheet
  25. :show="isShowComment"
  26. title="视频评论"
  27. @close="closeCommentHandle"
  28. @clickOverlay="isShowComment=false"
  29. >
  30. <view class="comment-cont" @touchmove.stop>
  31. <view class="commment-top">
  32. <text class="title">{{comment_obj.title}} {{comment_obj.total}}</text>
  33. <view class="comment-top-right">
  34. <text :class="select_comment_type === 1 && 'act'" @click="changeCommentTypeHandle(1)">全部</text>
  35. <text :class="select_comment_type === 2 && 'act'" @click="changeCommentTypeHandle(2)">我的</text>
  36. </view>
  37. </view>
  38. <scroll-view class="comment-list-cont" v-if="comment_obj.total" scroll-y>
  39. <view class="comment-list-item" v-for="(item,index) in commentList" :key="item.community_question_comment_id">
  40. <view class="flex comment">
  41. <image class="avatar" :src="item.qa_avatar_url" mode="aspectFill" lazy-load="true"/>
  42. <view style="display:flex;align-items:center">{{item.content}}</view>
  43. </view>
  44. <view class="del" v-if="select_comment_type === 2" @click="delCommentHandle(item,index)">删除该评论</view>
  45. </view>
  46. </scroll-view>
  47. <view class="nodata" v-else>
  48. <image src="@/static/nodata.png"></image>
  49. <view>暂无评论</view>
  50. </view>
  51. <view class="write-wrap" :style="{bottom: writeBottom+'px'}">
  52. <textarea
  53. v-model="comment_cont"
  54. placeholder="发布一条友善的评论"
  55. auto-height
  56. :adjust-position="false"
  57. :show-confirm-bar="false"
  58. :cursor-spacing="20"
  59. class="write-ipt"
  60. @blur="setWritePosition(50)"
  61. @focus="checkNickHandle"
  62. />
  63. <view class="confirm-btn" @click="publishMessageHandle">发布</view>
  64. </view>
  65. </view>
  66. </van-action-sheet>
  67. </view>
  68. </template>
  69. <script>
  70. import {apiSetLike,apiHotComment,apiMyComment,apiPublishComment,apiDelComment} from '@/api/question'
  71. export default {
  72. props:{
  73. videoInfo:null
  74. },
  75. data() {
  76. return {
  77. info:this.videoInfo,
  78. tease_img: require('@/static/question/tease.png'),
  79. tease_act_img: require('@/static/question/tease_act.png'),
  80. like_img: require('@/static/question/like.png'),
  81. like_act_img: require('@/static/question/like_act.png'),
  82. comment_img: require('@/static/question/comment.png'),
  83. isShowComment: false,
  84. comment_cont: '',
  85. writeBottom: 50,
  86. select_comment_type:1,//默认全部
  87. comment_obj: {
  88. title: '全部评论',
  89. total: 0
  90. },
  91. comment_total: 0,
  92. commentList: []
  93. }
  94. },
  95. methods: {
  96. /* 关闭评论弹窗 */
  97. closeCommentHandle() {
  98. this.isShowComment = false;
  99. this.comment_cont = '';
  100. this.select_comment_type = 1;//默认全部
  101. },
  102. /* 切换评论类型*/
  103. changeCommentTypeHandle(type) {
  104. if(type === this.select_comment_type) return
  105. this.commentList = [];
  106. this.select_comment_type = type;
  107. this.getComment();
  108. },
  109. showComment(){
  110. this.getComment()
  111. this.isShowComment=true
  112. },
  113. // 获取评论
  114. async getComment(flag){
  115. const params={
  116. community_question_id:this.info.community_video_id,
  117. curr_page: 1,
  118. page_size: 10000,
  119. source:2
  120. }
  121. const { code,data } = this.select_comment_type===1 ? await apiHotComment(params) : await apiMyComment(params);
  122. if(code !== 200) return
  123. this.commentList = data.list || [];
  124. this.comment_obj = {
  125. title: this.select_comment_type === 1 ? '全部评论' : '我的评论',
  126. total: data.paging.totals
  127. }
  128. // 如果flag='refresh' 则获取一次全部留言 更新到列表上面去
  129. if(flag==='refresh'){
  130. const res=await apiHotComment(params)
  131. const arr=res.data.list||[]
  132. this.info.comment_list=arr.map(item=>{
  133. return {
  134. comment:item.content,
  135. qa_avatar_url:item.qa_avatar_url
  136. }
  137. })
  138. this.info.comment_total=arr.length
  139. }
  140. },
  141. //删除我的评论
  142. delCommentHandle({community_question_comment_id},index){
  143. wx.showModal({
  144. title: "",
  145. content: "评论删除后不可恢复,确认删除吗?",
  146. confirmColor: "#EE3636",
  147. cancelColor: '#333',
  148. success: async(res) => {
  149. if( res.cancel) return
  150. const { code } = await apiDelComment({ community_question_comment_id });
  151. if( code !== 200 ) return
  152. this.commentList.splice(index,1)
  153. this.comment_obj.total--
  154. wx.showToast({title: '删除成功'});
  155. this.getComment('refresh')
  156. }
  157. })
  158. },
  159. setWritePosition(val=50) {
  160. console.log(val)
  161. this.writeBottom = val < 50 ? 50 : val-8;
  162. },
  163. checkNickHandle(e){
  164. this.setWritePosition(e.detail.height);
  165. },
  166. //发布留言
  167. async publishMessageHandle(){
  168. if(!this.comment_cont) return wx.showToast({title: '请输入留言内容',icon: 'none'})
  169. const { code } = await apiPublishComment({
  170. content: this.comment_cont,
  171. community_question_id: this.info.community_video_id,
  172. source:2,
  173. })
  174. if(code===200){
  175. wx.showToast({title: '发布成功'});
  176. this.comment_cont = '';
  177. this.getComment('refresh')
  178. }
  179. },
  180. //吐槽/点赞
  181. async handleSetLike(type){
  182. const res=await apiSetLike({
  183. community_question_id:this.info.community_video_id,
  184. op_type: type,
  185. enable: type === 1 ? Number(this.info.op_type!==1) : Number(this.info.op_type!==2),
  186. source:2
  187. })
  188. if(res.code===200){
  189. const { enabled,op_type,like_total,tease_total } = res.data;
  190. this.info.tease_total = tease_total;
  191. this.info.like_total = like_total;
  192. this.info.op_type = enabled === 0 ? 0 : op_type ;
  193. uni.showToast({
  194. title: enabled === 0 ? '取消成功' : op_type=== 1 ? '点赞成功' : '吐槽成功'
  195. })
  196. }
  197. },
  198. },
  199. }
  200. </script>
  201. <style lang="scss" scoped>
  202. .video-comment-wrap{
  203. .action-wrap{
  204. justify-content: space-between;
  205. padding: 0 56rpx;
  206. .item{
  207. min-width: 80rpx;
  208. image{
  209. width: 48rpx;
  210. height: 48rpx;
  211. vertical-align: middle;
  212. }
  213. text{
  214. font-size: 28rpx;
  215. color: #999;
  216. vertical-align: middle;
  217. }
  218. }
  219. }
  220. }
  221. .list-commnet-box{
  222. margin-top: 34rpx;
  223. background-color: #F9F9F9;
  224. padding: 20rpx;
  225. // .item{
  226. color: #666;
  227. font-size: 28rpx;
  228. .avatar{
  229. width: 56rpx;
  230. height: 56rpx;
  231. border-radius: 50%;
  232. margin-right: 14rpx;
  233. vertical-align: middle;
  234. }
  235. text{
  236. vertical-align: middle;
  237. line-height: 56rpx;
  238. margin-right: 20rpx;
  239. }
  240. // }
  241. }
  242. .comment-cont {
  243. height: calc(100vh - 250rpx);
  244. border-top: 4rpx solid #F4F4F4;
  245. position: relative;
  246. padding: 24rpx 0;
  247. overflow: hidden;
  248. .commment-top {
  249. display: flex;
  250. justify-content: space-between;
  251. align-items: center;
  252. padding: 0 24rpx;
  253. .title {
  254. font-weight: bold;
  255. font-size: 30rpx;
  256. color: #000;
  257. }
  258. .comment-top-right {
  259. display: flex;
  260. align-items: center;
  261. background-color: #F6F6F6;
  262. border: 1px solid #F6F6F6;
  263. color: #666;
  264. border-radius: 48rpx;
  265. text {
  266. padding: 0 12rpx;
  267. height: 48rpx;
  268. line-height: 48rpx;
  269. &.act {
  270. background-color: #FFFFFF;
  271. color: #000;
  272. border-radius: 48rpx;
  273. }
  274. }
  275. }
  276. }
  277. .comment-list-cont {
  278. height: calc(100vh - 550rpx);
  279. overflow-y: auto;
  280. position: relative;
  281. padding: 30rpx 0;
  282. .comment-list-item {
  283. margin-bottom: 30rpx;
  284. padding: 0 24rpx;
  285. .comment {
  286. color: #666;
  287. .avatar{
  288. width: 56rpx;
  289. height: 56rpx;
  290. border-radius: 50%;
  291. flex-shrink: 0;
  292. margin-right: 20rpx;
  293. }
  294. view{
  295. flex: 1;
  296. }
  297. }
  298. .del {
  299. color: #D80000;
  300. margin-top: 10rpx;
  301. margin-left: 76rpx;
  302. width: 200rpx;
  303. }
  304. }
  305. }
  306. .write-wrap {
  307. padding: 0 24rpx;
  308. border-top: 4rpx solid #F4F4F4;
  309. position: absolute;
  310. // bottom: 50px;
  311. left: 0;
  312. right: 0;
  313. display: flex;
  314. align-items: center;
  315. z-index: 99;
  316. background-color: #fff;
  317. padding-bottom: calc(5px + constant(safe-area-inset-bottom));
  318. padding-bottom: calc(5px + env(safe-area-inset-bottom));
  319. ::-webkit-scrollbar {
  320. display: none;
  321. }
  322. .write-ipt {
  323. padding: 30rpx 0;
  324. flex: 1;
  325. }
  326. .confirm-btn {
  327. width: 100rpx;
  328. margin-left: 20rpx;
  329. text-align: center;
  330. padding: 20rpx 0;
  331. color: #E3B377;
  332. }
  333. }
  334. }
  335. .nodata {
  336. text-align: center;
  337. color: #999;
  338. }
  339. </style>