推拿小程序前端代码仓库
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.

266 lines
5.0 KiB

2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
  1. <template>
  2. <view class="card flex product product-card__view" :class="[direction, size]" @click="$emit('click')">
  3. <view class="img" :class="[ isRecommend ? 'is-recommend' : '']">
  4. <image :src="data.image" mode="aspectFill"></image>
  5. <image v-if="isRecommend" class="mark" src="@/static/image/home/mark-recommend.png"></image>
  6. </view>
  7. <view class="flex right">
  8. <view class="flex flex-column info">
  9. <view class="title">{{ data.title }}</view>
  10. <!-- todo: check -->
  11. <view class="text-ellipsis">{{ getDesc(data.details) }}</view>
  12. <view class="flex price" :class="[role]">
  13. <view>
  14. <text class="price-unit">¥</text>
  15. <text>{{ data.price }}</text>
  16. </view>
  17. <view class="flex tag" v-if="role">
  18. <image class="icon" :src="vipInfo.massageVipCombo.imagePrice"></image>
  19. <text>{{ vipInfo.massageVipCombo.title }}</text>
  20. </view>
  21. </view>
  22. <view class="flex sales">
  23. <image class="icon" src="@/static/image/home/icon-sales.png"></image>
  24. <text>{{ `已售出 ${data.sales}` }}</text>
  25. </view>
  26. </view>
  27. <template v-if="!readonly">
  28. <button plain class="btn" @click="goToPlaceOrder(data.id)">立即下单</button>
  29. </template>
  30. </view>
  31. </view>
  32. </template>
  33. <script>
  34. import { mapGetters, mapState } from 'vuex'
  35. export default {
  36. props: {
  37. data: {
  38. type: Object,
  39. default() {
  40. return {}
  41. }
  42. },
  43. direction: {
  44. type: String,
  45. default: 'horizontal' // horizontal | vertical
  46. },
  47. size: {
  48. type: String,
  49. default: 'small' // small | medium
  50. },
  51. readonly: {
  52. type: Boolean,
  53. default: false,
  54. },
  55. },
  56. data() {
  57. return {
  58. }
  59. },
  60. computed: {
  61. ...mapGetters(['role']),
  62. ...mapState(['vipInfo']),
  63. isRecommend() {
  64. return this.data.isHot === '1'
  65. }
  66. },
  67. methods: {
  68. goToPlaceOrder(id) {
  69. this.$utils.navigateTo(`/pages_order/product/productDetail?id=${id}`)
  70. },
  71. getDesc(str) {
  72. if (!str) {
  73. return ''
  74. }
  75. return str.replace(/<.*?>/g, '')
  76. },
  77. },
  78. }
  79. </script>
  80. <style scoped lang="scss">
  81. .product {
  82. margin-top: 20rpx;
  83. background-color: $uni-fg-color;
  84. color: #999999;
  85. font-size: 22rpx;
  86. box-sizing: border-box;
  87. .img {
  88. width: 164rpx;
  89. height: 164rpx;
  90. box-sizing: border-box;
  91. position: relative;
  92. image {
  93. width: 100%;
  94. height: 100%;
  95. }
  96. &.is-recommend {
  97. border: 3rpx solid $uni-color-light;
  98. .mark {
  99. position: absolute;
  100. top: 0;
  101. left: 0;
  102. width: 68rpx;
  103. height: 68rpx;
  104. }
  105. }
  106. }
  107. .info {
  108. flex: 1;
  109. display: inline-flex;
  110. align-items: flex-start;
  111. box-sizing: border-box;
  112. }
  113. .title {
  114. color: #000000;
  115. font-size: 28rpx;
  116. font-weight: 700;
  117. margin-bottom: 7rpx;
  118. }
  119. .price {
  120. color: #FF2A2A;
  121. font-size: 30rpx;
  122. margin-top: 7rpx;
  123. align-items: flex-start;
  124. &-unit {
  125. font-size: 18rpx;
  126. margin-right: 3rpx;
  127. }
  128. .tag {
  129. font-size: 18rpx;
  130. font-weight: 700;
  131. padding: 9rpx 12rpx 9rpx 19rpx;
  132. margin-left: 4rpx;
  133. .icon {
  134. width: 27rpx;
  135. height: 19rpx;
  136. margin-right: 3rpx;
  137. }
  138. }
  139. &.member-personal {
  140. color: $uni-color-light;
  141. .tag {
  142. background-color: rgba($color: #D8FF8F, $alpha: 0.72);
  143. }
  144. }
  145. &.member-business {
  146. color: #FFB465;
  147. .tag {
  148. background-color: rgba($color: #FFFBC4, $alpha: 0.72);
  149. }
  150. }
  151. }
  152. .sales {
  153. justify-content: flex-start;
  154. margin-top: 8rpx;
  155. .icon {
  156. width: 19rpx;
  157. height: 23rpx;
  158. margin-right: 4rpx;
  159. }
  160. }
  161. .btn {
  162. white-space: nowrap;
  163. display: inline-block;
  164. margin: 0 0 0 10rpx;
  165. border: none !important;
  166. background-color: $uni-color-light;
  167. color: $uni-text-color-inverse;
  168. font-size: 22rpx;
  169. line-height: 1;
  170. padding: 14rpx 28rpx;
  171. box-sizing: border-box;
  172. width: auto;
  173. height: auto;
  174. border-radius: 29rpx;
  175. }
  176. .right {
  177. flex: 1;
  178. padding-left: 14rpx;
  179. }
  180. &.vertical {
  181. padding: 23rpx 22rpx;
  182. .right {
  183. width: calc(100% - 212rpx);
  184. flex-direction: column;
  185. align-items: flex-start;
  186. padding-left: 23rpx;
  187. .text-ellipsis {
  188. width: 100%;
  189. }
  190. }
  191. .info {
  192. width: 100%;
  193. }
  194. .img {
  195. width: 212rpx;
  196. height: 212rpx;
  197. border-radius: 15rpx;
  198. overflow: hidden;
  199. }
  200. .price {
  201. .tag {
  202. margin-left: 15rpx;
  203. }
  204. }
  205. .btn {
  206. margin-top: 4rpx;
  207. background-image: linear-gradient(#84A73F, #D8FF8F);
  208. padding: 12rpx 28rpx;
  209. border-radius: 10rpx;
  210. }
  211. }
  212. &.medium {
  213. padding: 27rpx 25rpx;
  214. width: 100%;
  215. box-sizing: border-box;
  216. .img {
  217. width: 184rpx;
  218. height: 184rpx;
  219. }
  220. .title {
  221. margin-bottom: 14rpx;
  222. }
  223. .price {
  224. margin-top: 15rpx;
  225. }
  226. .sales {
  227. margin-top: 15rpx;
  228. }
  229. }
  230. }
  231. </style>