index.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <template>
  2. <mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ use: false }" :up="upOption"
  3. @up="upCallback">
  4. <!-- tab栏 -->
  5. <u-tabs :list="tabs" :is-scroll="false" :current="curTab" active-color="#FA2209" :duration="0.2" @change="onChangeTab" />
  6. <!-- 商品评价列表 -->
  7. <view class="comment-list">
  8. <view class="comment-item" v-for="(item, index) in list.data" :key="index">
  9. <view class="item-head">
  10. <!-- 用户信息 -->
  11. <view class="user-info">
  12. <image class="user-avatar" mode="aspectFill" :src="item.user.avatar_url"></image>
  13. <text class="user-name f-26">{{ item.user.nick_name }}</text>
  14. </view>
  15. <!-- 评星 -->
  16. <u-rate active-color="#f4a213" :current="rates[item.score]" :disabled="true" />
  17. <!-- 评价日期-->
  18. <view class="flex-box f-22 col-9 t-r">{{ item.create_time }}</view>
  19. </view>
  20. <!-- 评价内容 -->
  21. <view class="item-content m-top20">
  22. <text class="f-26">{{ item.content }}</text>
  23. </view>
  24. <!-- 评价图片 -->
  25. <view class="images-list clearfix" v-if="item.images.length">
  26. <view class="image-preview" v-for="(image, imgIdx) in item.images" :key="imgIdx">
  27. <image class="image" mode="aspectFill" :src="image.image_url" @click="onPreviewImages(index, imgIdx)"></image>
  28. </view>
  29. </view>
  30. <!-- 商品规格 -->
  31. <view class="goods-props clearfix">
  32. <view class="goods-props-item" v-for="(props, idx) in item.orderGoods.goods_props" :key="idx">
  33. <text class="group-name">{{ props.group.name }}: </text>
  34. <text>{{ props.value.name }};</text>
  35. </view>
  36. </view>
  37. </view>
  38. </view>
  39. </mescroll-body>
  40. </template>
  41. <script>
  42. import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue'
  43. import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins'
  44. import { getEmptyPaginateObj, getMoreListData } from '@/utils/app'
  45. import * as CommentApi from '@/api/comment'
  46. const pageSize = 15
  47. const tabs = [{
  48. name: `全部`,
  49. scoreType: -1
  50. }, {
  51. name: `好评`,
  52. scoreType: 10
  53. }, {
  54. name: `中评`,
  55. scoreType: 20
  56. }, {
  57. name: `差评`,
  58. scoreType: 30
  59. }]
  60. export default {
  61. components: {
  62. MescrollBody
  63. },
  64. mixins: [MescrollMixin],
  65. data() {
  66. return {
  67. // 当前商品ID
  68. goodsId: null,
  69. // 当前标签索引
  70. curTab: 0,
  71. // 评价列表数据
  72. list: getEmptyPaginateObj(),
  73. // 评价总数量
  74. total: { all: 0, negative: 0, praise: 0, review: 0 },
  75. // 评星数据转换
  76. rates: { 10: 5, 20: 3, 30: 1 },
  77. // 标签栏数据
  78. tabs,
  79. // 上拉加载配置
  80. upOption: {
  81. // 首次自动执行
  82. auto: true,
  83. // 每页数据的数量; 默认10
  84. page: { size: pageSize },
  85. // 数量要大于4条才显示无更多数据
  86. noMoreSize: 4,
  87. // 空布局
  88. empty: {
  89. tip: '亲,暂无相关商品评价'
  90. }
  91. },
  92. }
  93. },
  94. /**
  95. * 生命周期函数--监听页面加载
  96. */
  97. onLoad(options) {
  98. // 记录属性值
  99. this.goodsId = options.goodsId
  100. // 获取指定评分总数
  101. this.getTotal()
  102. },
  103. methods: {
  104. /**
  105. * 上拉加载的回调 (页面初始化时也会执行一次)
  106. * 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10
  107. * @param {Object} page
  108. */
  109. upCallback(page) {
  110. const app = this
  111. // 设置列表数据
  112. app.getCommentList(page.num)
  113. .then(list => {
  114. const curPageLen = list.data.length
  115. const totalSize = list.data.total
  116. app.mescroll.endBySize(curPageLen, totalSize)
  117. })
  118. .catch(() => app.mescroll.endErr())
  119. },
  120. // 加载评价列表数据
  121. getCommentList(pageNo = 1) {
  122. const app = this
  123. return new Promise((resolve, reject) => {
  124. CommentApi.list(app.goodsId, { scoreType: app.getScoreType(), page: pageNo }, { load: false })
  125. .then(result => {
  126. // 合并新数据
  127. const newList = result.data.list
  128. app.list.data = getMoreListData(newList, app.list, pageNo)
  129. resolve(newList)
  130. })
  131. })
  132. },
  133. // 评分类型
  134. getScoreType() {
  135. return this.tabs[this.curTab].scoreType
  136. },
  137. // 获取指定评分总数
  138. getTotal() {
  139. const app = this
  140. CommentApi.total(app.goodsId)
  141. .then(result => {
  142. // tab标签内容
  143. const total = result.data.total
  144. app.getTabs(total)
  145. })
  146. },
  147. // 获取tab标签内容
  148. getTabs(total) {
  149. const tabs = this.tabs
  150. tabs[0].name = `全部(${total.all})`
  151. tabs[1].name = `好评(${total.praise})`
  152. tabs[2].name = `中评(${total.review})`
  153. tabs[3].name = `差评(${total.negative})`
  154. },
  155. // 切换标签项
  156. onChangeTab(index) {
  157. const app = this
  158. // 设置当前选中的标签
  159. app.curTab = index
  160. // 刷新评价列表
  161. app.onRefreshList()
  162. },
  163. // 刷新评价列表
  164. onRefreshList() {
  165. this.list = getEmptyPaginateObj()
  166. setTimeout(() => {
  167. this.mescroll.resetUpScroll()
  168. }, 120)
  169. },
  170. // 预览评价图片
  171. onPreviewImages(dataIdx, imgIndex) {
  172. const app = this
  173. const images = app.list.data[dataIdx].images
  174. const imageUrls = images.map(item => item.image_url)
  175. uni.previewImage({
  176. current: imageUrls[imgIndex],
  177. urls: imageUrls
  178. })
  179. }
  180. }
  181. }
  182. </script>
  183. <style lang="scss" scoped>
  184. .comment-item {
  185. padding: 30rpx;
  186. box-sizing: border-box;
  187. border-bottom: 1rpx solid #f7f7f7;
  188. background: #fff;
  189. }
  190. .item-head {
  191. display: flex;
  192. align-items: center;
  193. // 用户信息
  194. .user-info {
  195. margin-right: 15rpx;
  196. display: flex;
  197. align-items: center;
  198. .user-avatar {
  199. width: 50rpx;
  200. height: 50rpx;
  201. border-radius: 50%;
  202. margin-right: 15rpx;
  203. }
  204. .user-name {
  205. color: #999;
  206. }
  207. }
  208. }
  209. // 评价内容
  210. .item-content {
  211. font-size: 30rpx;
  212. color: #333;
  213. margin: 16rpx 0;
  214. }
  215. // 评价图片
  216. .images-list {
  217. &::after {
  218. clear: both;
  219. content: " ";
  220. display: table;
  221. }
  222. .image-preview {
  223. float: left;
  224. margin-bottom: 15rpx;
  225. margin-right: 15rpx;
  226. &:nth-child(3n+0) {
  227. margin-right: 0;
  228. }
  229. .image {
  230. display: block;
  231. width: 220rpx;
  232. height: 220rpx;
  233. }
  234. }
  235. }
  236. // 商品规格
  237. .goods-props {
  238. font-size: 24rpx;
  239. color: #999;
  240. .goods-props-item {
  241. float: left;
  242. .group-name {
  243. margin-right: 6rpx;
  244. }
  245. }
  246. }
  247. </style>