当前位置:   article > 正文

uniapp 微信小程序仿抖音评论区功能,支持展开收起_类似于抖音的评论区功能

类似于抖音的评论区功能

最近需要写一个评论区功能,所以打算仿照抖音做一个评论功能,支持展开和收起,

首先我们需要对功能做一个拆解,评论区功能,两个模块,一个是发表评论模块,一个是评论展示区。接下来对这两个模块进行详细描述。

使用到的技术 uniapp  uview2.0   文章最后我会贴上全部源码

一、发表评论模块

这个模块使用uview的两个组件来完成分别是u-popup弹出层和u-input输入框

下面是代码和展示图:

  1. <u-popup :show="talkShow" mode="bottom" :customStyle="{'width':'100%','border-radius':'8rpx'}" @close="popclosed" @open="keyboard=true" :safeAreaInsetBottom="true">
  2. <view class="flex justify-between align-center" style="padding: 32rpx;">
  3. <div class="cirbOX padding-left padding-right-sm">
  4. <u--form labelPosition="left" :model="talkData" :rules="Rules" ref="Form" :borderBottom="false">
  5. <u-form-item label=" " prop="txt" :borderBottom="false" ref="item1" labelWidth='0'>
  6. <u--input :focus="keyboard" v-model="talkData.txt" cursorSpacing="30" maxlength="100" :placeholder="pinglunHolder" border="none" clearable></u--input>
  7. </u-form-item>
  8. </u--form>
  9. </div>
  10. <div class="submitpinglun" @click="submit">发布</div>
  11. </view>
  12. </u-popup>

这部分需要注意两点

1.input组件的focus属性的设置:

在弹出层弹出的时候 在open事件中对input的focus属性布尔值设置为true,close时候设置focus为false。这样做的目的是在弹出输入评论的弹窗时会拉起小键盘,这个交互方式是模仿的微信朋友圈发布评论的形式。

2.input的cursorSpacing属性(输入框聚焦时底部与键盘的距离)设置:

当键盘拉起时候整个输入框因为设置了cursorSpacing="30",故整体页面会被小键盘托起。 当收起小键盘时候,输入框有回归到手机底部,因为我们popup设置的是底部的弹出层。这样是和微信朋友圈发布评论是对标的。

二、展示评论区的功能

这一部分我封装成了组件,因为需求的要求需要下拉加载评论故在组件外部循环一级评论,组件内部展示一级评论和二级评论,其中二级评论是在组件内部去循环,

循环一级评论的时候需要注意,因为后续要获取pinglun组件的实例,所以在ref的设置上面起初我按照for循环提供的index来拼的字符串,这也导致后续bug的出现埋下伏笔,所以我后续调整了,选择了id这个唯一值作为组件实例的ref名字,这个很关键!

  1. <div v-for="(item,index) in onePagePinglunList" :key="item.id" class="margin-bottom">
  2. <pinglun :ref="`pinglun-${item.levelOneCommentVo.id}`" :caseIdData="caseId" :data="item" :indexxx="index" @comment="goComment" @noLogin="sonNoLogin"></pinglun>
  3. </div>

组件代码:

  1. <template>
  2. <div>
  3. <!-- 一级评论 -->
  4. <div class="flex justify-start align-start margin-bottom-sm">
  5. <div class="margin-right-xs">
  6. <d-image :dSrc="onePageList.levelOneCommentVo.userAvatar" dMode="aspectFit" dWidth="72rpx" dHeight="72rpx"></d-image>
  7. </div>
  8. <div class="flex-sub">
  9. <div class="flex justify-start align-center">
  10. <div class="name margin-right-sm">{{onePageList.levelOneCommentVo.userName}}</div>
  11. <div class="zuozhe flex justify-center align-center" v-if="onePageList.levelOneCommentVo.belongAuthor===1">作者</div>
  12. </div>
  13. <div class="flex justify-between align-center" @click="goPinglun(1,onePageList.levelOneCommentVo.id,onePageList.levelOneCommentVo.userName,onePageList.levelOneCommentVo.id)">
  14. <div class="content flex-sub">{{onePageList.levelOneCommentVo.content}}</div>
  15. <div class="flex flex-direction align-center" style="width: 68rpx;" @click.stop="likepinglun(1,'',onePageList.levelOneCommentVo.id)">
  16. <div class="margin-bottom-xs">
  17. <div v-show="onePageList.levelOneCommentVo.isCurrentUserLike===0">
  18. <u-icon name="heart" color="#667286" size="34rpx"></u-icon>
  19. </div>
  20. <div v-show="onePageList.levelOneCommentVo.isCurrentUserLike===1">
  21. <u-icon name="heart-fill" color="red" size="34rpx"></u-icon>
  22. </div>
  23. </div>
  24. <div class="likeNum">{{onePageList.levelOneCommentVo.likeCount}}</div>
  25. </div>
  26. </div>
  27. <div class="time">{{ $u.timeFrom(new Date(onePageList.levelOneCommentVo.createTime).getTime())}}</div>
  28. </div>
  29. </div>
  30. <!-- 二级评论 -->
  31. <div class="erpinglunBox" :style="{'height':`${pingjiaBoxMaxHeight}px`,'opacity':pinglunOpcity,}">
  32. <div class="pinglunDom">
  33. <div v-for="(item,index) in onePageList.twoLevelpinglun" :key="item.id" class="margin-bottom-sm">
  34. <div class="flex justify-start align-start">
  35. <div class="margin-right-xs">
  36. <d-image :dSrc="item.userAvatar" dMode="aspectFit" dWidth="72rpx" dHeight="72rpx"></d-image>
  37. </div>
  38. <div class="flex-sub">
  39. <div class="flex justify-start align-center">
  40. <div class="name margin-right-sm">{{item.userName}}</div>
  41. <div class="zuozhe flex justify-center align-center margin-right-sm" v-if="item.belongAuthor===1">作者</div>
  42. <div class="name" v-if="item.isReplayTwoComment===1">回复 {{item.replayLevelTwoCommentUser.userName}}</div>
  43. </div>
  44. <div class="flex justify-between align-center" @click="goPinglun(2,item.id,item.userName,onePageList.levelOneCommentVo.id)">
  45. <div class="content flex-sub">{{item.content}}</div>
  46. <div class="flex flex-direction align-center" style="width: 68rpx;" @click.stop="likepinglun(2,index,item.id)">
  47. <div class="margin-bottom-xs">
  48. <div v-show="item.isCurrentUserLike===0">
  49. <u-icon name="heart" color="#667286" size="34rpx"></u-icon>
  50. </div>
  51. <div v-show="item.isCurrentUserLike===1">
  52. <u-icon name="heart-fill" color="red" size="34rpx"></u-icon>
  53. </div>
  54. </div>
  55. <div class="likeNum">{{item.likeCount}}</div>
  56. </div>
  57. </div>
  58. <div class="time">{{ $u.timeFrom(new Date(item.createTime).getTime())}}</div>
  59. </div>
  60. </div>
  61. </div>
  62. </div>
  63. </div>
  64. <!-- 展开和收起按钮 -->
  65. <div class="flex justify-start align-center" style="padding-left: 84rpx;">
  66. <div class="seeMore padding-top-sm padding-bottom flex align-center" v-if="onePageList.levelTwoCommentCount > 0&&params.current <= totalPage" @click="$u.throttle(getTwoLevelPinglun, 1000,true)">
  67. <div class="margin-right-xs">查看更多回复</div>
  68. <u-icon name="arrow-down" color="#00875A" size="28rpx" :bold="true"></u-icon>
  69. </div>
  70. <div class="seeMore retract padding-top-sm padding-bottom margin-left flex justify-center align-center" v-if="params.current > 1" @click="$u.throttle(retract, 1000,true)">
  71. <div class="margin-right-xs">收起</div>
  72. <u-icon name="arrow-up" color="#00875A" size="28rpx" :bold="true"></u-icon>
  73. </div>
  74. </div>
  75. </div>
  76. </template>

感觉唯一的难点在于因为展开收缩使用的过渡动画,大家应该都知道,想使用这个过渡必须设置有效值,也就是说比如我给高度写过渡动画,从一个高度到一个高度,都需要是具体的值,atuo这种被内容撑开的高度是不作数的。

这里拿高度,需要注意的是需要等待渲染完毕再去获取高度,不然拿到的值就是不准确的。

下面是我写的获取高度的函数。如果一个nexttick也获取不到准确高度,那么就再加个延时器,就差不多可以获取到准确高度了。

  1. updatHeight() {
  2. let that = this
  3. this.$nextTick(() => {
  4. // this.timer = setTimeout(() => {
  5. this.createSelectorQuery().select(".pinglunDom").boundingClientRect(function(rect) {
  6. // console.log(rect);
  7. that.pingjiaBoxMaxHeight = rect.height
  8. that.pinglunOpcity = 1
  9. }).exec();
  10. // }, 0)
  11. })
  12. },

还有一个需要注意的点,就是在一级评论发布之后,需要拿到所有pinglu组件的实例去调用这个方法,重置所有二级评论的高度。调用这个方法的前提也必须是一级评论的渲染完毕,不然还是不起作用

以下是代码:

  1. this.$forceUpdate();
  2. this.$nextTick(() => {
  3. for (let i = 0; i < this.onePagePinglunList.length; i++) {
  4. this.$refs[`pinglun-${this.onePagePinglunList[i].levelOneCommentVo.id}`][0].updatHeight()
  5. if (this.onePagePinglunList[i].twoLevelpinglun.length === 0) {
  6. this.$refs[`pinglun-${this.onePagePinglunList[i].levelOneCommentVo.id}`][0].params.current = 1
  7. }
  8. }
  9. })

至此应该就没什么需要注意的地方了

可能也是第一次写这个功能,还有很多可以优化的地方。希望对各位有所帮助,接下来我把评论功能所有源码贴在下面。

因为我的评论功能是在案例详情里面的,所以有两个文件,一个是案例详情,一个就是封装的评论组件 

案例详情:

  1. <template>
  2. <div :style="{'padding-bottom':`${(safeAreaBottom*2)+144}`+'rpx'}">
  3. <div style="padding: 32rpx 32rpx 50rpx;">
  4. <div class="margin-bottom-sm txt-1">成功蜕变历程</div>
  5. <div class="toplicheng flex justify-center align-center margin-bottom-sm">
  6. <div class="flex flex-direction align-center">
  7. <div class="flex align-center">
  8. <d-image dSrc="https://tj-data.oss-cn-hangzhou.aliyuncs.com/uploadFiles/wx/mzkHomeland/caseDetailIcON2.png" dMode="aspectFit" dWidth="32rpx" dHeight="32rpx"></d-image>
  9. <div class="toptxt1 margin-left-xs">体重</div>
  10. </div>
  11. <div class="toptxt2 margin-top-xs">{{topweightcha||0}}kg</div>
  12. </div>
  13. <div class="midBox flex flex-direction align-center">
  14. <div class="xmonth flex justify-center align-center margin-bottom-xs">逆糖3个月</div>
  15. <div class="topshuxian"></div>
  16. </div>
  17. <div class="flex flex-direction align-center">
  18. <div class="flex align-center">
  19. <d-image dSrc="https://tj-data.oss-cn-hangzhou.aliyuncs.com/uploadFiles/wx/mzkHomeland/caseDetailIcON1.png" dMode="aspectFit" dWidth="32rpx" dHeight="32rpx"></d-image>
  20. <div class="toptxt1 margin-left-xs">空腹血糖</div>
  21. </div>
  22. <div class="toptxt2 margin-top-xs">{{topxuetangcha||0}}mmol/L</div>
  23. </div>
  24. </div>
  25. <!-- 案例信息 -->
  26. <div class="caseBox">
  27. <div class="case-head-box flex justify-between align-center">
  28. <div class="head-left-box flex">
  29. <div class="avatarBox">
  30. <u-avatar :src="detailData.userInfoVo.userAvatar || 'https://tj-data.oss-cn-hangzhou.aliyuncs.com/uploadFiles/wx/mzkHomeland/healthy.png'" size="72rpx" mode="aspectFill"></u-avatar>
  31. </div>
  32. <div>
  33. <div class="txt-1 margin-bottom-xs">{{detailData.userInfoVo.userName||'暂无昵称'}}</div>
  34. <div class="txt-2">{{detailData.isExistServicePack?detailData.servicePackVo.servicePackName:'暂无服务包'}}</div>
  35. </div>
  36. </div>
  37. <div class=" flex justify-center align-center" style="width: 80rpx;height: 80rpx;">
  38. <u-icon name="share-square" color="" size="34rpx"></u-icon>
  39. </div>
  40. </div>
  41. <div class="caseBoxContentBox">
  42. <u-row justify="space-start">
  43. <u-col span="4">
  44. <view class="txt-4 margin-bottom">项目</view>
  45. </u-col>
  46. <u-col span="4">
  47. <view class="txt-4 margin-bottom">管理前</view>
  48. </u-col>
  49. <u-col span="4">
  50. <view class="txt-4 margin-bottom">管理后</view>
  51. </u-col>
  52. </u-row>
  53. <u-row justify="space-start">
  54. <u-col span="4">
  55. <view>
  56. <div class="txt-3">服务时间</div>
  57. </view>
  58. </u-col>
  59. <u-col span="4">
  60. <view>
  61. <div class="startTime">
  62. {{detailData.managementInfoVo.managementStartTime||'--'}}
  63. </div>
  64. </view>
  65. </u-col>
  66. <u-col span="4">
  67. <view>
  68. <div class="endTime">
  69. {{detailData.managementInfoVo.managementEndTime||'--'}}
  70. </div>
  71. </view>
  72. </u-col>
  73. </u-row>
  74. <div class="line"></div>
  75. <u-row justify="space-start">
  76. <u-col span="4">
  77. <view>
  78. <div class="txt-3">体重</div>
  79. <div class="txt-7">kg</div>
  80. </view>
  81. </u-col>
  82. <u-col span="4">
  83. <view>
  84. <div class="yellow-box flex justify-center align-center" style="position: relative;">
  85. {{detailData.managementInfoVo.beforeManagementWeight||'--'}}
  86. <div class="jiantou" v-if="detailData.managementInfoVo.beforeManagementFastingSugarBloodTrend===3">
  87. <d-image dSrc="https://tj-data.oss-cn-hangzhou.aliyuncs.com/uploadFiles/wx/mzkHomeland/redUp.png" dMode="aspectFit" dWidth="24rpx" dHeight="24rpx"></d-image>
  88. </div>
  89. <div class="jiantou" v-else-if="detailData.managementInfoVo.beforeManagementFastingSugarBloodTrend===1">
  90. <d-image dSrc="https://tj-data.oss-cn-hangzhou.aliyuncs.com/uploadFiles/wx/mzkHomeland/greenDown.png" dMode="aspectFit" dWidth="24rpx" dHeight="24rpx"></d-image>
  91. </div>
  92. </div>
  93. </view>
  94. </u-col>
  95. <u-col span="4">
  96. <view>
  97. <div class="green-box flex justify-center align-center">{{detailData.managementInfoVo.afterManagementWeight||'--'}}</div>
  98. </view>
  99. </u-col>
  100. </u-row>
  101. <div class="line"></div>
  102. <u-row justify="space-start">
  103. <u-col span="4">
  104. <view>
  105. <div class="txt-3">空腹血糖</div>
  106. <div class="txt-7">mmol/L</div>
  107. </view>
  108. </u-col>
  109. <u-col span="4">
  110. <view>
  111. <div class="yellow-box flex justify-center align-center" style="position: relative;">
  112. {{detailData.managementInfoVo.beforeManagementFastingSugarBlood||'--'}}
  113. <div class="jiantou"
  114. v-if="detailData.managementInfoVo.beforeManagementWeightTrend===3||detailData.managementInfoVo.beforeManagementWeightTrend===4||detailData.managementInfoVo.beforeManagementWeightTrend===5">
  115. <d-image dSrc="https://tj-data.oss-cn-hangzhou.aliyuncs.com/uploadFiles/wx/mzkHomeland/redUp.png" dMode="aspectFit" dWidth="24rpx" dHeight="24rpx"></d-image>
  116. </div>
  117. <div class="jiantou" v-else-if="detailData.managementInfoVo.beforeManagementWeightTrend===1">
  118. <d-image dSrc="https://tj-data.oss-cn-hangzhou.aliyuncs.com/uploadFiles/wx/mzkHomeland/greenDown.png" dMode="aspectFit" dWidth="24rpx" dHeight="24rpx"></d-image>
  119. </div>
  120. </div>
  121. </view>
  122. </u-col>
  123. <u-col span="4">
  124. <view>
  125. <div class="green-box flex justify-center align-center">
  126. {{detailData.managementInfoVo.afterManagementFastingSugarBlood||'--'}}
  127. </div>
  128. </view>
  129. </u-col>
  130. </u-row>
  131. <div class="line"></div>
  132. <u-row justify="space-start">
  133. <u-col span="4">
  134. <view>
  135. <div class="txt-3">用药数量</div>
  136. </view>
  137. </u-col>
  138. <u-col span="4">
  139. <view>
  140. <div class="yellow-box flex justify-center align-center">
  141. {{detailData.managementInfoVo.beforeManagementMedicationCount||'0'}}
  142. </div>
  143. </view>
  144. </u-col>
  145. <u-col span="4">
  146. <view>
  147. <div class="green-box flex justify-center align-center">
  148. {{detailData.managementInfoVo.afterManagementMedicationCount||'0'}}
  149. </div>
  150. </view>
  151. </u-col>
  152. </u-row>
  153. <div class="line"></div>
  154. <u-row justify="space-start">
  155. <u-col span="4">
  156. <view>
  157. <div class="txt-3">对比照片</div>
  158. </view>
  159. </u-col>
  160. <u-col span="4">
  161. <view>
  162. <div class="margin-bottom-sm">
  163. <div>
  164. <div v-if="detailData.managementInfoVo.beforeManagementImagePhoto===''" class="noPicBox flex justify-center align-center">暂无</div>
  165. <div v-else>
  166. <d-image :dSrc="detailData.managementInfoVo.beforeManagementImagePhoto" dMode="aspectFit" dWidth="140rpx" dHeight="140rpx">
  167. </d-image>
  168. </div>
  169. </div>
  170. </div>
  171. </view>
  172. </u-col>
  173. <u-col span="4">
  174. <view>
  175. <div class="margin-bottom-sm">
  176. <div>
  177. <div v-if="detailData.managementInfoVo.afterManagementImagePhoto===''" class="noPicBox flex justify-center align-center">暂无</div>
  178. <div v-else>
  179. <d-image :dSrc="detailData.managementInfoVo.afterManagementImagePhoto" dMode="aspectFit" dWidth="140rpx" dHeight="140rpx">
  180. </d-image>
  181. </div>
  182. </div>
  183. </div>
  184. </view>
  185. </u-col>
  186. </u-row>
  187. </div>
  188. </div>
  189. <!-- 评价 -->
  190. <div class="evaluateBox margin-top-sm margin-bottom-sm">
  191. <div class="margin-bottom-sm txt-1">健康评价</div>
  192. <div class="margin-top-sm flex flex-wrap pingjiaBox">
  193. <view class="pingjiaDom">
  194. <div v-for="(item,index) in defaultPingjia" :key="item.id" class="flex ">
  195. <div class="tag margin-right-sm flex align-center margin-bottom-sm" :style="{'background':item.styleBg}">
  196. <div style="height: 100%; " class="flex align-start margin-right-sm">
  197. <d-image :dSrc="item.styleIcon" dMode="aspectFit" dWidth="26rpx" dHeight="26rpx">
  198. </d-image>
  199. </div>
  200. <text :style="{'max-width': '544rpx','word-break': 'break-all','color':item.styleColor}">{{item.content}}</text>
  201. </div>
  202. </div>
  203. </view>
  204. </div>
  205. </div>
  206. <!-- echart -->
  207. <!-- <div class="margin-bottom-sm" style="position: relative;overflow: hidden;" v-for="(item,index) in echartList" :key="index">
  208. <detailChart :echarType="item"></detailChart>
  209. </div> -->
  210. </div>
  211. <!-- 评论 -->
  212. <div style="padding: 0 32rpx 56rpx;background: #FFFFFF;">
  213. <div class="flex justify-between align-center">
  214. <div class="pingluntitle">{{detailData.interActionVo.commentCount||'0'}} 评论</div>
  215. <div></div>
  216. </div>
  217. <div v-for="(item,index) in onePagePinglunList" :key="item.id" class="margin-bottom">
  218. <pinglun :ref="`pinglun-${item.levelOneCommentVo.id}`" :caseIdData="caseId" :data="item" :indexxx="index" @comment="goComment" @noLogin="sonNoLogin" @shouqi="shouqiTwoPinglun"></pinglun>
  219. </div>
  220. </div>
  221. <div class="contentB">- 让每个人都能从知识中获得健康 -</div>
  222. <!-- 底部评价评论点赞收藏 -->
  223. <div class="pingjialikeBox flex justify-between align-center" :style="{'bottom':`${(safeAreaBottom*2)}`+'rpx'}">
  224. <div class="talksomething flex justify-center align-center" @click="openPinglun">说点什么吧</div>
  225. <div class="flex justify-around" style="width: 428rpx;">
  226. <div class="flex align-center btn" @click="$u.throttle(clickLike, 500,true)">
  227. <div v-show="detailData.interActionVo.isCurrentUserLike===0">
  228. <u-icon name="heart" color="" size="34rpx"></u-icon>
  229. </div>
  230. <div v-show="detailData.interActionVo.isCurrentUserLike===1">
  231. <u-icon name="heart-fill" color="red" size="34rpx"></u-icon>
  232. </div>
  233. <text class="margin-left-xs">{{detailData.interActionVo.likeCount||'0'}}</text>
  234. </div>
  235. <div class="flex align-center btn" @click="$u.throttle(clickCollect, 500,true)">
  236. <div v-show="detailData.interActionVo.isCurrentUserCollection===0">
  237. <u-icon name="star" color="" size="34rpx"></u-icon>
  238. </div>
  239. <div v-show="detailData.interActionVo.isCurrentUserCollection===1">
  240. <u-icon name="star-fill" color="#ff991f" size="34rpx"></u-icon>
  241. </div>
  242. <text class="margin-left-xs">{{detailData.interActionVo.collectionCount||'0'}}</text>
  243. </div>
  244. <div class=" flex align-center btn">
  245. <u-icon name="chat" color="" size="34rpx"></u-icon>
  246. <text class="margin-left-xs">{{detailData.interActionVo.commentCount||'0'}}</text>
  247. </div>
  248. </div>
  249. </div>
  250. <u-popup :show="talkShow" mode="bottom" :customStyle="{'width':'100%','border-radius':'8rpx'}" @close="popclosed" @open="keyboard=true" :safeAreaInsetBottom="true">
  251. <view class="flex justify-between align-center" style="padding: 32rpx;">
  252. <div class="cirbOX padding-left padding-right-sm">
  253. <u--form labelPosition="left" :model="talkData" :rules="Rules" ref="Form" :borderBottom="false">
  254. <u-form-item label=" " prop="txt" :borderBottom="false" ref="item1" labelWidth='0'>
  255. <u--input :focus="keyboard" v-model="talkData.txt" cursorSpacing="30" maxlength="100" :placeholder="pinglunHolder" border="none" clearable></u--input>
  256. </u-form-item>
  257. </u--form>
  258. </div>
  259. <div class="submitpinglun" @click="submit">发布</div>
  260. </view>
  261. </u-popup>
  262. <u-modal title="确认登录" :show="show1" width="608rpx" content="为了您的良好体验,建议您先确认登录 ~" :closeOnClickOverlay="true" @close="show1=false">
  263. <u-button slot="confirmButton" text="确定" shape="circle" color="#00875A" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber" :customStyle="{'width':'264rpx','height':'68rpx'}"></u-button>
  264. </u-modal>
  265. <u-toast ref="uToast"></u-toast>
  266. </div>
  267. </template>
  268. <script>
  269. import { mapState } from 'vuex';
  270. import detailChart from "./detailEchart.vue"
  271. import pinglun from "./pinglun.vue"
  272. import { sub } from '@/utils/tool.js'
  273. import { getDetail, getCurveModule, collection, like, savecomment, getLevelOnePage } from '@/api/case/case.js'
  274. export default {
  275. data() {
  276. return {
  277. show1: false,
  278. keyboard: false,
  279. pinglunHolder: '说点什么吧',
  280. Rules: {
  281. 'txt': [{
  282. required: true,
  283. type: 'any',
  284. message: '评论不能为空',
  285. trigger: ['blur', 'change']
  286. },
  287. {
  288. validator: (rule, value, callback) => {
  289. return value.length < 100;
  290. },
  291. message: '您评论的字数超过100,请调整您的字数~',
  292. trigger: ['blur', 'change']
  293. }
  294. ],
  295. },
  296. talkShow: false,
  297. talkData: { //弹框form值 评论
  298. txt: ""
  299. },
  300. caseId: null,
  301. echartList: [],
  302. detailData: {},
  303. defaultPingjia: [],
  304. topweightcha: null,
  305. topxuetangcha: null,
  306. pinglunForm: { //接口参数
  307. caseId: null,
  308. caseLevelOneCommentId: '', //对一级评论进行回复时不可为空
  309. caseLevelTwoCommentId: '', //对二级评论进行回复时不可为空
  310. content: null,
  311. userId: null,
  312. },
  313. params: {
  314. current: 1,
  315. limit: 5,
  316. likeSort: 2, //点赞数排序 1:升序 2:降序
  317. timeSort: 2, //创建时间排序 1:升序 2:降序
  318. },
  319. totalPage: 1,
  320. onePagePinglunList: [],
  321. pinglunType: null, //判断用户评论的类型是案例评论(3)还是一级评论(1)还是二级评论(2)
  322. erpinglunIndex: 0, //暂存二级评论发送给父级组件给的一级评论的index
  323. }
  324. },
  325. components: { detailChart, pinglun },
  326. computed: {
  327. ...mapState(["hasLogin", "safeAreaBottom", "userInfo", ])
  328. },
  329. // 发送给朋友
  330. onShareAppMessage(res) {
  331. return {
  332. title: '妙智健康案例',
  333. path: `/pages-caseStory/caseDetail/index?caseId=${this.caseId}&title=${this.detailData.userInfoVo.userName}`
  334. }
  335. },
  336. //分享到朋友圈
  337. onShareTimeline(res) {
  338. return {
  339. title: '妙智健康案例',
  340. query: `caseId=${this.caseId}&title=${this.detailData.userInfoVo.userName}`,
  341. path: `/pages-caseStory/caseDetail/index` //自定义路径拼参数会导致接收参数会失败
  342. }
  343. },
  344. onReady() {},
  345. onLoad(option) {
  346. this.$refs.Form.setRules(this.Rules)
  347. this.caseId = option?.caseId
  348. uni.setNavigationBarTitle({
  349. title: `${option.title||''}案例`
  350. });
  351. this.getdetailData()
  352. this.getLevelOnePageData()
  353. },
  354. onUnload() {
  355. // this.$store.commit('set_caseShareEchartPicList', [])
  356. },
  357. onShow() {
  358. },
  359. methods: {
  360. sub,
  361. async getPhoneNumber(e) {
  362. // console.log("获取手机号code", e) //获取手机号已经不需要先进行wx.login(最新文档)
  363. if (!e.detail.code) {
  364. uni.showToast({
  365. title: '登录需要获取您的手机号',
  366. icon: 'none',
  367. duration: 2500
  368. })
  369. return
  370. }
  371. let resss = await this.$store.dispatch("loginFn", e) //能同步拿到vux中mutaion的resolve,然后给fourDataNum赋值(登录后数据更新)
  372. console.log(resss);
  373. if (resss.state === 1) { //登录成功
  374. this.show1 = false
  375. }
  376. },
  377. async getdetailData() {
  378. uni.showLoading({
  379. title: '加载中...'
  380. })
  381. try {
  382. let res = await getDetail({
  383. caseId: this.caseId,
  384. userId: this.hasLogin ? this.userInfo?.userId : ''
  385. })
  386. let echarRes = await getCurveModule({
  387. caseId: this.caseId,
  388. })
  389. if (res.state === 1) {
  390. this.detailData = res.content
  391. this.defaultPingjia = res.content.personnelEvaluationVoList
  392. this.topweightcha = this.sub(this.detailData.managementInfoVo.afterManagementWeight, this.detailData.managementInfoVo.beforeManagementWeight)
  393. this.topxuetangcha = this.sub(this.detailData.managementInfoVo.afterManagementFastingSugarBlood, this.detailData.managementInfoVo.beforeManagementFastingSugarBlood)
  394. }
  395. if (echarRes.state === 1) {
  396. this.echartList = echarRes.content.map(item => {
  397. let obj = {
  398. title: item.caseCurveType === 1 ? '硅基' : (item.caseCurveType === 2 ? "微策" : "体重"),
  399. defaultTime: item.caseCurveType === 1 ? item.curveStartDate : [item.curveStartDate, item.curveEndDate],
  400. userId: res.content.userInfoVo.userId
  401. }
  402. return obj
  403. })
  404. }
  405. uni.hideLoading();
  406. } catch (e) {
  407. uni.hideLoading();
  408. uni.$u.toast(e)
  409. }
  410. },
  411. async clickLike(item, index) {
  412. if (!this.hasLogin) {
  413. this.show1 = true
  414. return
  415. }
  416. try {
  417. let res = await like({
  418. userId: this.userInfo?.userId,
  419. caseId: this.caseId,
  420. })
  421. if (res.state === 1) {
  422. if (this.detailData.interActionVo.isCurrentUserLike === 1) {
  423. this.detailData.interActionVo.isCurrentUserLike = 0
  424. this.detailData.interActionVo.likeCount--
  425. } else if (this.detailData.interActionVo.isCurrentUserLike === 0) {
  426. this.detailData.interActionVo.isCurrentUserLike = 1
  427. this.detailData.interActionVo.likeCount++
  428. }
  429. }
  430. } catch (e) {
  431. uni.$u.toast(e)
  432. }
  433. },
  434. async clickCollect(item) {
  435. if (!this.hasLogin) {
  436. this.show1 = true
  437. return
  438. }
  439. try {
  440. let res = await collection({
  441. userId: this.userInfo?.userId,
  442. caseId: this.caseId,
  443. })
  444. if (res.state === 1) {
  445. if (this.detailData.interActionVo.isCurrentUserCollection === 1) {
  446. this.detailData.interActionVo.isCurrentUserCollection = 0
  447. this.detailData.interActionVo.collectionCount--
  448. } else if (this.detailData.interActionVo.isCurrentUserCollection === 0) {
  449. this.detailData.interActionVo.isCurrentUserCollection = 1
  450. this.detailData.interActionVo.collectionCount++
  451. }
  452. }
  453. } catch (e) {
  454. uni.$u.toast(e)
  455. }
  456. },
  457. popclosed() {
  458. this.talkData.txt = ''
  459. this.keyboard = false
  460. this.talkShow = false
  461. console.log(this.keyboard);
  462. },
  463. async getLevelOnePageData() {
  464. uni.showLoading({
  465. title: '加载中...'
  466. })
  467. try {
  468. let res = await getLevelOnePage({ userId: this.hasLogin ? this.userInfo?.userId : '', caseId: Number(this.caseId), ...this.params })
  469. if (res.state === 1) {
  470. for (let i = 0; i < res.content.records.length; i++) {
  471. res.content.records[i].twoLevelpinglun = []
  472. if (this.onePagePinglunList.some(item => item.levelOneCommentVo.id === res.content.records[i].levelOneCommentVo.id)) { //删除重复项
  473. res.content.records.splice(i, 1)
  474. }
  475. }
  476. this.onePagePinglunList = [...this.onePagePinglunList, ...res.content.records]
  477. this.totalPage = Math.ceil(res.content.total / this.params.limit) //总页数=总数量/每页数量
  478. }
  479. uni.hideLoading();
  480. } catch (e) {
  481. uni.hideLoading();
  482. uni.$u.toast(e)
  483. }
  484. },
  485. openPinglun() {
  486. if (!this.hasLogin) {
  487. this.show1 = true
  488. return
  489. }
  490. this.pinglunType = 3 //案例评论
  491. this.pinglunHolder = '说点什么吧'
  492. this.pinglunForm.caseLevelOneCommentId = '' //不回复一二级评论时候置空该字段
  493. this.pinglunForm.caseLevelTwoCommentId = '' //不回复一二级评论时候置空该字段
  494. this.talkShow = true
  495. // this.keyboard = true
  496. },
  497. goComment(e) { //处理回复一级二级评论 案例的顶级评论在openPinglun()函数中
  498. console.log(e);
  499. this.pinglunType = e.type //评论类型
  500. console.log('this.pinglunType', this.pinglunType);
  501. if (e.type === 1) { //一级评论
  502. this.pinglunForm.caseLevelOneCommentId = e.id
  503. this.erpinglunIndex = e.index
  504. this.pinglunHolder = `回复 @${e.replyName}`
  505. } else if (e.type === 2) { //二级评论
  506. this.pinglunForm.caseLevelTwoCommentId = e.id
  507. this.erpinglunIndex = e.index
  508. this.pinglunHolder = `回复 @${e.replyName}`
  509. }
  510. console.log("点击的item", this.$refs[`pinglun-${this.erpinglunIndex}`][0].onePageList);
  511. this.talkShow = true
  512. // this.keyboard = true
  513. console.log(this.keyboard);
  514. },
  515. async submit() {
  516. this.pinglunForm.userId = this.userInfo.userId
  517. this.pinglunForm.content = this.talkData.txt
  518. this.pinglunForm.caseId = this.caseId
  519. // let form = {
  520. // caseId: this.caseId,
  521. // caseLevelOneCommentId: '', //对一级评论进行回复时不可为空
  522. // caseLevelTwoCommentId: '', //对二级评论进行回复时不可为空
  523. // content: this.talkData.txt,
  524. // userId: this.userInfo.userId,
  525. // }
  526. try {
  527. let res = await savecomment(this.pinglunForm)
  528. if (res.state === 1) {
  529. if (this.pinglunType === 3) { //案例评论
  530. this.onePagePinglunList.unshift({
  531. twoLevelpinglun: [],
  532. ...res.content.caseCommentHomeVo
  533. })
  534. this.$forceUpdate();
  535. this.$nextTick(() => {
  536. for (let i = 0; i < this.onePagePinglunList.length; i++) {
  537. this.$refs[`pinglun-${this.onePagePinglunList[i].levelOneCommentVo.id}`][0].updatHeight() //重置子组件内部height 不管新增一级还是二级都需要全部重置高度不然会出现bug
  538. if (this.onePagePinglunList[i].twoLevelpinglun.length === 0) {
  539. this.$refs[`pinglun-${this.onePagePinglunList[i].levelOneCommentVo.id}`][0].params.current = 1
  540. }
  541. }
  542. console.log(this.$refs[`pinglun-${127}`][0].onePageList);
  543. })
  544. this.$forceUpdate();
  545. } else if (this.pinglunType === 1 || this.pinglunType === 2) { //回复一级评论或二级评论 push完需要注意的是在获取分页数据时候去重,因为这个push操作是模拟更新数据,后端并不知晓所以后端未做去重
  546. console.log(this.$refs[`pinglun-${this.erpinglunIndex}`][0].onePageList.twoLevelpinglun);
  547. this.$refs[`pinglun-${this.erpinglunIndex}`][0].onePageList.twoLevelpinglun.push({
  548. ...res.content.caseLevelTwoCommentVo
  549. })
  550. console.log(this.$refs[`pinglun-${this.erpinglunIndex}`][0].onePageList.twoLevelpinglun);
  551. let indxx;
  552. for (let i = 0; i < this.onePagePinglunList.length; i++) {
  553. if (this.onePagePinglunList[i].levelOneCommentVo.id === this.erpinglunIndex) {
  554. indxx = i
  555. break
  556. }
  557. }
  558. // 目的是防止发表一级评论之后父级向下重新注入数据,会触发pinglun组件内部的watch,导致会重置组件内部的twoLevelpinglun为[],
  559. this.onePagePinglunList[indxx].twoLevelpinglun = this.$refs[`pinglun-${this.erpinglunIndex}`][0].onePageList.twoLevelpinglun
  560. this.onePagePinglunList[indxx].levelTwoCommentCount++
  561. this.$refs[`pinglun-${this.erpinglunIndex}`][0].updatHeight() //重置子组件内部height
  562. }
  563. this.talkData.txt = '' //重置评论
  564. this.keyboard = false //自动聚焦设为false
  565. this.talkShow = false //关闭弹窗
  566. this.updatePinglunNum() //更新评论数量
  567. console.log(this.keyboard);
  568. this.$refs.uToast.show({
  569. type: 'success',
  570. message: "已发送评论~",
  571. duration: 1200,
  572. })
  573. }
  574. } catch (e) {
  575. uni.$u.toast(e)
  576. }
  577. },
  578. sonNoLogin(e) {
  579. console.log(e);
  580. if (!this.hasLogin) {
  581. this.show1 = true
  582. return
  583. }
  584. },
  585. async updatePinglunNum() {
  586. try {
  587. let res = await getDetail({
  588. caseId: this.caseId,
  589. userId: this.hasLogin ? this.userInfo?.userId : ''
  590. })
  591. if (res.state === 1) {
  592. this.detailData = res.content
  593. }
  594. } catch (e) {
  595. uni.$u.toast(e)
  596. }
  597. },
  598. //因为每次发表二级评论都会往父级的twoLevelpinglun添加属性,也就是submit函数里面的565行代码,会导致一个bug 就是发布二级评论后,
  599. // 因为同时给父级也赋值了,故收起二级评论后,再发表一级评论,重置了了渲染,会将父级被赋值的twoLevelpinglun同步到二级评论的twoLevelpinglun,相当于之前收起操作白重置了twoLevelpinglun
  600. shouqiTwoPinglun(index) {
  601. let indxx;
  602. for (let i = 0; i < this.onePagePinglunList.length; i++) {
  603. if (this.onePagePinglunList[i].levelOneCommentVo.id === index) {
  604. indxx = i
  605. break
  606. }
  607. }
  608. this.onePagePinglunList[indxx].twoLevelpinglun = []
  609. },
  610. },
  611. // 上拉加载
  612. async onReachBottom() {
  613. if (this.params.current > this.totalPage) {
  614. this.$refs.uToast.show({
  615. type: 'warning',
  616. message: "已经到底啦~",
  617. duration: 1200,
  618. })
  619. return
  620. }
  621. this.params.current += 1
  622. await this.getLevelOnePageData()
  623. uni.stopPullDownRefresh() //停止上拉加载
  624. },
  625. // 下拉刷新触发
  626. async onPullDownRefresh() {
  627. this.params.current = 1 //重置页码
  628. this.onePagePinglunList = []
  629. await this.getLevelOnePageData()
  630. this.$refs.uToast.show({
  631. type: 'success',
  632. message: "刷新成功",
  633. duration: 1200,
  634. })
  635. uni.stopPullDownRefresh() //停止下拉刷新
  636. },
  637. }
  638. </script>
  639. <style lang="scss" scoped>
  640. @import '@/pages-caseStory/style/caseCommon.scss';
  641. .pingluntitle {
  642. font-size: 28rpx;
  643. font-family: PingFangSC;
  644. color: #1F3253;
  645. height: 90rpx;
  646. line-height: 90rpx;
  647. }
  648. .contentB {
  649. margin: 42rpx 0;
  650. font-size: 24rpx;
  651. font-weight: 400;
  652. color: #667286;
  653. text-align: center;
  654. }
  655. .pingjialikeBox {
  656. padding: 32rpx;
  657. width: 100%;
  658. height: 144rpx;
  659. background: #FFFFFF;
  660. position: fixed;
  661. left: 0;
  662. .btn {
  663. height: 70rpx;
  664. width: 78rpx;
  665. }
  666. }
  667. .toplicheng {
  668. height: 160rpx;
  669. background: linear-gradient(47deg, rgba(23, 144, 109, 0.84) 0%, #5DC063 100%);
  670. border-radius: 12rpx;
  671. }
  672. .topshuxian {
  673. width: 1rpx;
  674. height: 80rpx;
  675. opacity: 0.5;
  676. border: 2rpx solid #FFFFFF;
  677. }
  678. .xmonth {
  679. width: 156rpx;
  680. height: 47rpx;
  681. background: #FFFFFF;
  682. border-radius: 0rpx 0rpx 14rpx 14rpx;
  683. opacity: 0.8;
  684. font-size: 24rpx;
  685. font-weight: 400;
  686. color: #00875A;
  687. }
  688. .toptxt1 {
  689. font-size: 28rpx;
  690. font-weight: 400;
  691. color: #FFFFFF;
  692. }
  693. .toptxt2 {
  694. font-size: 36rpx;
  695. font-weight: bold;
  696. color: #E2FFF5;
  697. }
  698. .midBox {
  699. width: 156rpx;
  700. height: 160rpx;
  701. margin-left: 70rpx;
  702. margin-right: 23rpx;
  703. }
  704. .noPicBox {
  705. width: 140rpx;
  706. height: 140rpx;
  707. background: #E7EFF6;
  708. }
  709. .jiantou {
  710. position: absolute;
  711. top: 0;
  712. right: 0;
  713. }
  714. .evaluateBox {
  715. background: #FFFFFF;
  716. border-radius: 12rpx;
  717. padding: 40rpx 32rpx 78rpx;
  718. .tag {
  719. background: #FFF6E9;
  720. border-radius: 30rpx;
  721. padding: 20rpx 30rpx 20rpx 20rpx;
  722. vertical-align: center;
  723. }
  724. }
  725. .talksomething {
  726. width: 248rpx;
  727. height: 80rpx;
  728. background: #F4F5F7;
  729. border-radius: 40rpx;
  730. font-size: 28rpx;
  731. font-weight: 400;
  732. color: #697588;
  733. }
  734. .cirbOX {
  735. width: 600rpx;
  736. height: 80rpx;
  737. background: #F4F5F7;
  738. border-radius: 40rpx;
  739. }
  740. .submitpinglun {
  741. height: 80rpx;
  742. width: 64rpx;
  743. font-size: 32rpx;
  744. font-weight: 500;
  745. color: #00875A;
  746. line-height: 80rpx;
  747. }
  748. </style>

pinglun组件:

  1. <template>
  2. <div>
  3. <!-- 一级评论 -->
  4. <div class="flex justify-start align-start margin-bottom-sm">
  5. <div class="margin-right-xs">
  6. <d-image :dSrc="onePageList.levelOneCommentVo.userAvatar" dMode="aspectFit" dWidth="72rpx" dHeight="72rpx"></d-image>
  7. </div>
  8. <div class="flex-sub">
  9. <div class="flex justify-start align-center">
  10. <div class="name margin-right-sm">{{onePageList.levelOneCommentVo.userName}}</div>
  11. <div class="zuozhe flex justify-center align-center" v-if="onePageList.levelOneCommentVo.belongAuthor===1">作者</div>
  12. </div>
  13. <div class="flex justify-between align-center" @click="goPinglun(1,onePageList.levelOneCommentVo.id,onePageList.levelOneCommentVo.userName,onePageList.levelOneCommentVo.id)">
  14. <div class="content flex-sub">{{onePageList.levelOneCommentVo.content}}</div>
  15. <div class="flex flex-direction align-center" style="width: 68rpx;" @click.stop="likepinglun(1,'',onePageList.levelOneCommentVo.id)">
  16. <div class="margin-bottom-xs">
  17. <div v-show="onePageList.levelOneCommentVo.isCurrentUserLike===0">
  18. <u-icon name="heart" color="#667286" size="34rpx"></u-icon>
  19. </div>
  20. <div v-show="onePageList.levelOneCommentVo.isCurrentUserLike===1">
  21. <u-icon name="heart-fill" color="red" size="34rpx"></u-icon>
  22. </div>
  23. </div>
  24. <div class="likeNum">{{onePageList.levelOneCommentVo.likeCount}}</div>
  25. </div>
  26. </div>
  27. <div class="time">{{ $u.timeFrom(new Date(onePageList.levelOneCommentVo.createTime).getTime())}}</div>
  28. </div>
  29. </div>
  30. <!-- 二级评论 -->
  31. <div class="erpinglunBox" :style="{'height':`${pingjiaBoxMaxHeight}px`,'opacity':pinglunOpcity,}">
  32. <div class="pinglunDom">
  33. <div v-for="(item,index) in onePageList.twoLevelpinglun" :key="item.id" class="margin-bottom-sm">
  34. <div class="flex justify-start align-start">
  35. <div class="margin-right-xs">
  36. <d-image :dSrc="item.userAvatar" dMode="aspectFit" dWidth="72rpx" dHeight="72rpx"></d-image>
  37. </div>
  38. <div class="flex-sub">
  39. <div class="flex justify-start align-center">
  40. <div class="name margin-right-sm">{{item.userName}}</div>
  41. <div class="zuozhe flex justify-center align-center margin-right-sm" v-if="item.belongAuthor===1">作者</div>
  42. <div class="name" v-if="item.isReplayTwoComment===1">回复 {{item.replayLevelTwoCommentUser.userName}}</div>
  43. </div>
  44. <div class="flex justify-between align-center" @click="goPinglun(2,item.id,item.userName,onePageList.levelOneCommentVo.id)">
  45. <div class="content flex-sub">{{item.content}}</div>
  46. <div class="flex flex-direction align-center" style="width: 68rpx;" @click.stop="likepinglun(2,index,item.id)">
  47. <div class="margin-bottom-xs">
  48. <div v-show="item.isCurrentUserLike===0">
  49. <u-icon name="heart" color="#667286" size="34rpx"></u-icon>
  50. </div>
  51. <div v-show="item.isCurrentUserLike===1">
  52. <u-icon name="heart-fill" color="red" size="34rpx"></u-icon>
  53. </div>
  54. </div>
  55. <div class="likeNum">{{item.likeCount}}</div>
  56. </div>
  57. </div>
  58. <div class="time">{{ $u.timeFrom(new Date(item.createTime).getTime())}}</div>
  59. </div>
  60. </div>
  61. </div>
  62. </div>
  63. </div>
  64. <!-- 展开和收起按钮 -->
  65. <div class="flex justify-start align-center" style="padding-left: 84rpx;">
  66. <div class="seeMore padding-top-sm padding-bottom flex align-center" v-if="onePageList.levelTwoCommentCount > 0&&params.current <= totalPage" @click="$u.throttle(getTwoLevelPinglun, 1000,true)">
  67. <div class="margin-right-xs">查看更多回复</div>
  68. <u-icon name="arrow-down" color="#00875A" size="28rpx" :bold="true"></u-icon>
  69. </div>
  70. <div class="seeMore retract padding-top-sm padding-bottom margin-left flex justify-center align-center" v-if="params.current > 1" @click="$u.throttle(retract, 1000,true)">
  71. <div class="margin-right-xs">收起</div>
  72. <u-icon name="arrow-up" color="#00875A" size="28rpx" :bold="true"></u-icon>
  73. </div>
  74. </div>
  75. </div>
  76. </template>
  77. <script>
  78. import { mapState } from 'vuex';
  79. import { commentlike, getLevelOnePage, getLevelTwoPage } from '@/api/case/case.js'
  80. export default {
  81. data() {
  82. return {
  83. caseId: null,
  84. indexxxx: null, //一级评论的index
  85. params: {
  86. current: 1,
  87. limit: 5,
  88. timeSort: 1, //创建时间排序 1:升序 2:降序
  89. },
  90. totalPage: 1,
  91. onePageList: {},
  92. pingjiaBoxMaxHeight: 0,
  93. pinglunOpcity: 0,
  94. timer: null,
  95. timer1: null,
  96. }
  97. },
  98. props: {
  99. caseIdData: {
  100. type: Number,
  101. // 定义是否必须传
  102. required: true,
  103. // 定义默认值
  104. default: 0
  105. },
  106. data: {
  107. type: Object,
  108. // 定义是否必须传
  109. required: true,
  110. // 定义默认值
  111. default: {}
  112. },
  113. indexxx: {
  114. type: Number,
  115. // 定义是否必须传
  116. required: true,
  117. // 定义默认值
  118. default: 0
  119. }
  120. },
  121. watch: {
  122. caseIdData: {
  123. immediate: true,
  124. handler(val) {
  125. this.caseId = val;
  126. }
  127. },
  128. data: {
  129. immediate: true,
  130. handler(val) {
  131. this.onePageList = val;
  132. }
  133. },
  134. indexxx: {
  135. immediate: true,
  136. handler(val) {
  137. this.indexxxx = val;
  138. }
  139. }
  140. },
  141. components: {},
  142. computed: {
  143. ...mapState(["hasLogin", "userInfo"])
  144. },
  145. mounted() {},
  146. beforeDestroy() {
  147. clearTimeout(this.timer)
  148. clearTimeout(this.timer1)
  149. },
  150. methods: {
  151. async likepinglun(type, index, id) {
  152. if (!this.hasLogin) {
  153. this.$emit('noLogin', '一二级评论点赞未登录')
  154. return
  155. }
  156. let form = {};
  157. if (type === 1) {
  158. form.caseLevelOneCommentId = id
  159. } else if (type === 2) {
  160. form.caseLevelTwoCommentId = id
  161. }
  162. try {
  163. let res = await commentlike({ ...form, userId: this.userInfo?.userId })
  164. if (res.state === 1) { //如果接口回调成功
  165. if (type === 1) { //如果点击的是一级评论的点赞
  166. if (this.onePageList.levelOneCommentVo.isCurrentUserLike === 0) { //判断点赞之前是0还是1 然后取反 并且对应点赞数量同步加减
  167. this.onePageList.levelOneCommentVo.isCurrentUserLike = 1
  168. this.onePageList.levelOneCommentVo.likeCount++
  169. } else if (this.onePageList.levelOneCommentVo.isCurrentUserLike === 1) {
  170. this.onePageList.levelOneCommentVo.isCurrentUserLike = 0
  171. this.onePageList.levelOneCommentVo.likeCount--
  172. }
  173. } else if (type === 2) { //如果点击的是二级评论的点赞
  174. if (this.onePageList.twoLevelpinglun[index].isCurrentUserLike === 0) {
  175. this.onePageList.twoLevelpinglun[index].isCurrentUserLike = 1
  176. this.onePageList.twoLevelpinglun[index].likeCount++
  177. } else if (this.onePageList.twoLevelpinglun[index].isCurrentUserLike === 1) {
  178. this.onePageList.twoLevelpinglun[index].isCurrentUserLike = 0
  179. this.onePageList.twoLevelpinglun[index].likeCount--
  180. }
  181. }
  182. }
  183. } catch (e) {
  184. uni.$u.toast(e)
  185. }
  186. },
  187. goPinglun(e, id, name, indexx) {
  188. if (e === 1) { //一级评论
  189. this.$emit('comment', {
  190. type: e,
  191. id: id,
  192. // index: this.indexxxx,
  193. index: indexx,
  194. replyName: name, //点击的谁的评论进行回复,用于在输入框的placeholder回显
  195. })
  196. } else if (e === 2) { //二级评论
  197. this.$emit('comment', {
  198. type: e,
  199. id: id,
  200. // index: this.indexxxx,
  201. index: indexx,
  202. replyName: name, //点击的谁的评论进行回复,用于在输入框的placeholder回显
  203. })
  204. }
  205. },
  206. async getTwoLevelPinglun() {
  207. try {
  208. let res = await getLevelTwoPage({ userId: this.hasLogin ? this.userInfo?.userId : '', caseLevelOneCommentId: this.onePageList.levelOneCommentVo.id, ...this.params })
  209. if (res.state === 1) {
  210. for (let i = 0; i < res.content.records.length; i++) {
  211. res.content.records[i].twoLevelpinglun = []
  212. if (this.onePageList.twoLevelpinglun.some(item => item.id === res.content.records[i].id)) { //删除重复项
  213. res.content.records.splice(i, 1)
  214. console.log("发现重复项,删除他!!!");
  215. }
  216. }
  217. this.onePageList.twoLevelpinglun = [...this.onePageList.twoLevelpinglun, ...res.content.records]
  218. this.totalPage = Math.ceil(res.content.total / this.params.limit) //总页数=总数量/每页数量
  219. this.params.current += 1
  220. this.updatHeight()
  221. }
  222. } catch (e) {
  223. uni.$u.toast(e)
  224. }
  225. },
  226. retract() {
  227. this.pingjiaBoxMaxHeight = 0
  228. this.pinglunOpcity = 0
  229. this.params.current = 1
  230. this.onePageList.twoLevelpinglun = []
  231. this.timer1 = setTimeout(() => { //因为展开动画需要1s 故 在收起的时候延迟置空数组,
  232. console.log(this.onePageList);
  233. this.$emit('shouqi', this.onePageList.levelOneCommentVo.id)
  234. }, 800)
  235. },
  236. updatHeight() {
  237. let that = this
  238. this.$nextTick(() => {
  239. // this.timer = setTimeout(() => {
  240. this.createSelectorQuery().select(".pinglunDom").boundingClientRect(function(rect) {
  241. // console.log(rect);
  242. that.pingjiaBoxMaxHeight = rect.height
  243. that.pinglunOpcity = 1
  244. }).exec();
  245. // }, 0)
  246. })
  247. },
  248. }
  249. }
  250. </script>
  251. <style lang="scss" scoped>
  252. .name {
  253. font-size: 24rpx;
  254. font-weight: 400;
  255. color: #667286;
  256. }
  257. .content {
  258. font-size: 28rpx;
  259. font-weight: 400;
  260. color: #1F3253;
  261. }
  262. .time {
  263. font-size: 20rpx;
  264. font-weight: 400;
  265. color: #AFAFAF;
  266. }
  267. .likeNum {
  268. font-size: 20rpx;
  269. font-weight: 400;
  270. color: #667286;
  271. }
  272. .zuozhe {
  273. width: 60rpx;
  274. height: 28rpx;
  275. background: #FFFFFF;
  276. border-radius: 18rpx;
  277. border: 1rpx solid #00875A;
  278. font-size: 20rpx;
  279. font-weight: 400;
  280. color: #00875A;
  281. }
  282. .seeMore {
  283. font-size: 24rpx;
  284. font-weight: 400;
  285. color: #00875A;
  286. }
  287. .retract {
  288. width: 150rpx;
  289. text-align: center;
  290. }
  291. .erpinglunBox {
  292. padding-left: 84rpx;
  293. transition: height 1s, opacity 2s;
  294. overflow: hidden;
  295. }
  296. </style>

案例详情引入的scss文件:

  1. .font-20 {
  2. font-size: 20rpx;
  3. font-weight: 400;
  4. }
  5. .font-24 {
  6. font-size: 24rpx;
  7. font-weight: 400;
  8. }
  9. .txt-1 {
  10. font-size: 28rpx;
  11. font-weight: 500;
  12. color: #0F2C50;
  13. }
  14. .txt-2 {
  15. @extend .font-20;
  16. color: #667286;
  17. }
  18. .txt-3 {
  19. @extend .font-24;
  20. color: #667286;
  21. }
  22. .txt-4 {
  23. font-size: 24rpx;
  24. font-weight: 500;
  25. color: #667286;
  26. }
  27. .txt-5 {
  28. font-size: 36rpx;
  29. font-weight: bold;
  30. }
  31. .txt-6 {
  32. @extend .font-24;
  33. color: #9CADC6;
  34. }
  35. .txt-7 {
  36. @extend .font-20;
  37. color: #B7BCC3;
  38. }
  39. .txt-8 {
  40. @extend .font-24;
  41. color: #fff;
  42. }
  43. .txt-9 {
  44. @extend .font-24;
  45. color: #0F2C50;
  46. }
  47. .txt-10 {
  48. font-size: 28rpx;
  49. font-weight: 400;
  50. color: #667286;
  51. }
  52. .yell-green-base {
  53. width: 140rpx;
  54. height: 52rpx;
  55. border-radius: 2rpx;
  56. font-size: 36rpx;
  57. font-weight: bold;
  58. }
  59. .yellow-box {
  60. @extend .yell-green-base;
  61. background-color: #FFF4CD;
  62. color: #FF991F;
  63. }
  64. .green-box {
  65. @extend .yell-green-base;
  66. background: #E2FFEE;
  67. color: #00875A;
  68. }
  69. .timeFont{
  70. font-size: 32rpx;
  71. font-family: DINAlternate-Bold, DINAlternate;
  72. font-weight: bold;
  73. }
  74. .startTime{
  75. @extend .timeFont;
  76. color: #FF991F;
  77. }
  78. .endTime{
  79. @extend .timeFont;
  80. color: #00875A;
  81. }
  82. .line {
  83. height: 1rpx;
  84. border: 1rpx solid #E6E6E6;
  85. margin: 16rpx 0;
  86. }
  87. .caseBox {
  88. background: #FFFFFF;
  89. border-radius: 12rpx;
  90. margin-top: 20rpx;
  91. padding: 0 32rpx;
  92. .case-head-box {
  93. height: 140rpx;
  94. }
  95. .avatarBox {
  96. width: 72rpx;
  97. height: 72rpx;
  98. margin-right: 16rpx;
  99. }
  100. .caseDetailBtn {
  101. width: 100rpx;
  102. height: 44rpx;
  103. background: #00875A;
  104. border-radius: 22rpx;
  105. }
  106. .rateBox {
  107. height: 80rpx;
  108. }
  109. .mar-80 {
  110. margin-right: 80rpx;
  111. }
  112. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/683526
推荐阅读
相关标签
  

闽ICP备14008679号