推拿小程序前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
5.7 KiB

3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <template>
  2. <view class="page">
  3. <!-- 导航栏 -->
  4. <navbar title="商品详情" leftClick @leftClick="$utils.navigateBack" color="#fff" />
  5. <uv-swiper :list="bannerList" indicator indicatorMode="dot" height="475rpx"></uv-swiper>
  6. <view class="overview">
  7. <view class="flex sale">
  8. <view class="flex price" :class="[role]">
  9. <view>
  10. <text class="price-unit"></text>
  11. <text>{{ productDetail.price }}</text>
  12. </view>
  13. <view class="flex tag" v-if="role">
  14. <image class="icon" :src="vipInfo.massageVipCombo.imagePrice"></image>
  15. <text>{{ vipInfo.massageVipCombo.title }}</text>
  16. </view>
  17. </view>
  18. <view>
  19. <text>{{ `已售出:${productDetail.sales}` }}</text>
  20. </view>
  21. </view>
  22. <view class="title">
  23. <text>{{ productDetail.title }}</text>
  24. </view>
  25. <view class="flex desc">
  26. <view v-for="tag in tags" :key="tag" class="flex tag">
  27. <view class="dot"></view>
  28. <text>{{ tag }}</text>
  29. </view>
  30. </view>
  31. </view>
  32. <!-- 商品详情 -->
  33. <view class="detail">
  34. <view class="header">
  35. <cardTitle>商品详情</cardTitle>
  36. </view>
  37. <uv-parse :content="productDetail.details"></uv-parse>
  38. </view>
  39. <!-- 分享和购买按钮 -->
  40. <view class="flex bar">
  41. <button plain class="flex flex-column btn btn-share" open-type="share">
  42. <image class="btn-share-icon" src="../static/productDetail/icon-share.png"></image>
  43. <text>分享</text>
  44. </button>
  45. <view class="flex count">
  46. <text>合计</text>
  47. <view class="price">
  48. <text class="price-unit">¥</text>
  49. <!-- todo: check -->
  50. <text>{{ productDetail.price }}</text>
  51. </view>
  52. </view>
  53. <button plain class="btn btn-pay" @click="submit">立即支付</button>
  54. </view>
  55. </view>
  56. </template>
  57. <script>
  58. import { mapGetters, mapState } from 'vuex'
  59. import cardTitle from '@/components/base/cardTitle.vue'
  60. export default {
  61. components: {
  62. cardTitle,
  63. },
  64. data() {
  65. return {
  66. productDetail: {
  67. image: '',
  68. details: '',
  69. },
  70. id: 0,
  71. }
  72. },
  73. computed: {
  74. ...mapGetters(['role']),
  75. ...mapState(['vipInfo']),
  76. // todo: check
  77. bannerList() {
  78. const { image } = this.productDetail
  79. if (!image) {
  80. return []
  81. }
  82. return Array.isArray(image) ? image : image.split(',')
  83. },
  84. tags() {
  85. const { tag } = this.productDetail
  86. return tag?.split('、') || []
  87. }
  88. },
  89. onLoad(args) {
  90. this.id = args.id
  91. this.fetchProductDetail(this.id)
  92. },
  93. onShow() {
  94. },
  95. onShareAppMessage(res) {
  96. const {
  97. title,
  98. } = this.productDetail
  99. let o = {
  100. title: title,
  101. // todo: check
  102. imageUrl: bannerList[0],
  103. query: `id=${this.productDetail.id}`,
  104. }
  105. return o
  106. },
  107. methods: {
  108. // 获取商品
  109. async fetchProductDetail(id) {
  110. try {
  111. this.productDetail = await this.$fetch('queryProductDetail', { id })
  112. } catch (err) {
  113. }
  114. },
  115. // 立即下单
  116. submit() {
  117. this.$store.commit('setPayOrderProduct', [
  118. this.productDetail
  119. ])
  120. this.$utils.navigateTo('/pages_order/order/createOrder')
  121. },
  122. }
  123. }
  124. </script>
  125. <style scoped lang="scss">
  126. $bar-height: 132rpx;
  127. .page {
  128. padding-bottom: calc(#{$bar-height} + env(safe-area-inset-bottom));
  129. background-color: #F3F3F3;
  130. /deep/ .nav-bar__view {
  131. background-image: linear-gradient(#84A73F, #D8FF8F);
  132. }
  133. .overview {
  134. padding: 16rpx 31rpx 18rpx 24rpx;
  135. background-color: $uni-fg-color;
  136. .sale {
  137. justify-content: space-between;
  138. color: #949494;
  139. font-size: 20rpx;
  140. .price {
  141. color: #FF2A2A;
  142. font-size: 45rpx;
  143. &-unit {
  144. font-size: 30rpx;
  145. margin-right: 3rpx;
  146. }
  147. .tag {
  148. font-size: 18rpx;
  149. font-weight: 700;
  150. padding: 9rpx 12rpx 9rpx 19rpx;
  151. margin-left: 15rpx;
  152. .icon {
  153. width: 27rpx;
  154. height: 19rpx;
  155. margin-right: 3rpx;
  156. }
  157. }
  158. &.member-personal {
  159. color: $uni-color-light;
  160. .tag {
  161. background-color: rgba($color: #D8FF8F, $alpha: 0.72);
  162. }
  163. }
  164. &.member-business {
  165. color: #FFB465;
  166. .tag {
  167. background-color: rgba($color: #FFFBC4, $alpha: 0.72);
  168. }
  169. }
  170. }
  171. }
  172. .title {
  173. color: #3A3A3A;
  174. font-size: 28rpx;
  175. font-weight: 700;
  176. margin-top: 15rpx;
  177. }
  178. .desc {
  179. justify-content: space-between;
  180. margin-top: 20rpx;
  181. .tag {
  182. color: #949494;
  183. font-size: 22rpx;
  184. .dot {
  185. width: 8rpx;
  186. height: 8rpx;
  187. border-radius: 50%;
  188. background-color: #949494;
  189. margin-right: 16rpx;
  190. }
  191. }
  192. }
  193. }
  194. .detail {
  195. margin-top: 12rpx;
  196. padding: 18rpx 28rpx;
  197. background-color: $uni-fg-color;
  198. .header {
  199. margin-bottom: 30rpx;
  200. }
  201. }
  202. .bar {
  203. position: fixed;
  204. bottom: 0;
  205. left: 0;
  206. width: 100vw;
  207. height: $bar-height;
  208. padding-bottom: env(safe-area-inset-bottom);
  209. background-color: $uni-fg-color;
  210. .count {
  211. flex: 1;
  212. color: #000000;
  213. font-size: 28rpx;
  214. margin-left: 29rpx;
  215. padding-left: 40rpx;
  216. border-left: 1rpx solid #B3997E;
  217. justify-content: flex-start;
  218. .price {
  219. color: #FF2A2A;
  220. font-size: 30rpx;
  221. &-unit {
  222. font-size: 18rpx;
  223. }
  224. }
  225. }
  226. .btn {
  227. border: none;
  228. line-height: 1;
  229. background-color: transparent;
  230. padding: 0;
  231. width: auto;
  232. height: auto;
  233. margin: 0;
  234. &-share {
  235. margin-left: 58rpx;
  236. color: #000000;
  237. font-size: 22rpx;
  238. &-icon {
  239. width: 48rpx;
  240. height: 50rpx;
  241. margin-bottom: 11rpx;
  242. }
  243. }
  244. &-pay {
  245. margin-right: 27rpx;
  246. padding: 24rpx 137rpx;
  247. color: $uni-text-color-inverse;
  248. font-size: 28rpx;
  249. border-radius: 44rpx;
  250. background-image: linear-gradient(to right, #84A73F, #D8FF8F);
  251. }
  252. }
  253. }
  254. }
  255. </style>