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

    pinglun组件:

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

  • 相关阅读:
    Tapdata 与 Apache Doris 完成兼容性互认证,共建新一代数据架构
    ping回显间隔长或第一个包很久才显示是怎么回事?
    Vue组件化开发-插槽的使用详解
    15:00面试,15:08就出来了,问的问题有点变态。。。
    学习二十大奋进新征程线上知识答题小程序登录技术点分析与实现
    初高(重要的是高中)中数学知识点综合(持续更新)
    JAVA:实现SquareRootBinarySearch平方根二分搜索算法(附完整源码)
    mysql8-基于docker搭建主从同步
    Java最强大的技术之一:反射
    django-haystack使用小结
  • 原文地址:https://blog.csdn.net/m0_57033755/article/details/132603278