index.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. <template>
  2. <u-popup v-model="visible" mode="bottom" border-radius="24" :safe-area-inset-bottom="true" :mask-close-able="true"
  3. @close="close">
  4. <view class="popup-content">
  5. <!-- Header -->
  6. <view class="header">
  7. <text class="title">选择商品品相</text>
  8. <image src="/pages-sell/static/select-good/icon-close.png" class="close-icon" @click="close"></image>
  9. </view>
  10. <!-- Product Info -->
  11. <view class="product-info">
  12. <image :src="currentProduct.cover" class="book-cover" mode="aspectFill"></image>
  13. <view class="info-right">
  14. <view class="price-row">
  15. <text class="currency">¥</text>
  16. <text class="price">{{ currentProduct.price }}</text>
  17. <view class="drop-tag">
  18. <text>↓可降至 ¥{{ currentProduct.minPrice || '8.67' }}</text>
  19. </view>
  20. </view>
  21. <view class="tag-row">
  22. <view class="quality-tag">
  23. <text>品相{{ currentQualityName }}</text>
  24. </view>
  25. </view>
  26. </view>
  27. </view>
  28. <!-- Tips -->
  29. <view class="tips-row">
  30. <text>不同品相有什么区别</text>
  31. <image src="/pages-sell/static/select-good/icon-tips.png" class="tips-icon"></image>
  32. </view>
  33. <!-- Promo Note -->
  34. <view class="promo-note">
  35. <text>下单时用书购余额支付可享余额价 ( 售价 8 折优惠 )</text>
  36. </view>
  37. <!-- Options -->
  38. <view class="options-list">
  39. <view class="option-item" v-for="(opt, index) in qualityOptions" :key="index"
  40. :class="{ active: currentQuality === opt.value }" @click="selectQuality(opt.value)">
  41. <image v-if="currentQuality === opt.value" src="/pages-sell/static/select-good/selected.png"
  42. class="bg-image"></image>
  43. <view class="left">
  44. <text class="opt-name">{{ opt.name }}</text>
  45. <view class="opt-discount" :class="{ active: currentQuality === opt.value }">
  46. <text>{{ opt.discount }}折</text>
  47. </view>
  48. </view>
  49. <view class="right">
  50. <text>¥{{ opt.price }} ( 余额价 ¥{{ opt.balancePrice }} )</text>
  51. </view>
  52. </view>
  53. </view>
  54. <!-- Quantity -->
  55. <view class="quantity-row">
  56. <text class="label">数量</text>
  57. <u-number-box v-model="quantity" :min="1" :max="99"></u-number-box>
  58. </view>
  59. <!-- Footer Buttons -->
  60. <view class="footer-btns">
  61. <view class="btn btn-orange">
  62. <text class="price">¥0.3</text>
  63. <text class="desc">分享一人可降 0.5 元</text>
  64. </view>
  65. <view class="btn btn-green" @click="handleConfirm">
  66. <text class="price">¥0.5</text>
  67. <text class="desc">加入购物车</text>
  68. </view>
  69. </view>
  70. </view>
  71. </u-popup>
  72. </template>
  73. <script>
  74. export default {
  75. name: 'SelectGoodPopup',
  76. data() {
  77. return {
  78. visible: false,
  79. quantity: 1,
  80. currentQuality: 'medium',
  81. currentProduct: {},
  82. qualityOptions: [
  83. { name: '中等', value: 'medium', discount: '5.3', price: '33.3', balancePrice: '8.6' },
  84. { name: '良品', value: 'good', discount: '5.3', price: '33.3', balancePrice: '8.6' },
  85. { name: '良品', value: 'good2', discount: '5.3', price: '33.3', balancePrice: '8.6' }
  86. ]
  87. };
  88. },
  89. computed: {
  90. currentQualityName() {
  91. const opt = this.qualityOptions.find(o => o.value === this.currentQuality);
  92. return opt ? opt.name : '';
  93. }
  94. },
  95. methods: {
  96. open(product) {
  97. this.currentProduct = product || {};
  98. this.visible = true;
  99. this.quantity = 1;
  100. this.currentQuality = 'medium';
  101. },
  102. close() {
  103. this.visible = false;
  104. },
  105. selectQuality(val) {
  106. this.currentQuality = val;
  107. },
  108. handleConfirm() {
  109. this.$emit('confirm', {
  110. product: this.currentProduct,
  111. quality: this.currentQuality,
  112. quantity: this.quantity
  113. });
  114. this.close();
  115. }
  116. }
  117. };
  118. </script>
  119. <style lang="scss" scoped>
  120. .popup-content {
  121. padding: 30rpx 30rpx 20rpx;
  122. background-color: #fff;
  123. position: relative;
  124. }
  125. .header {
  126. display: flex;
  127. justify-content: center;
  128. align-items: center;
  129. position: relative;
  130. margin-bottom: 30rpx;
  131. padding-bottom: 30rpx;
  132. border-bottom: 2rpx dashed #eee;
  133. .title {
  134. font-size: 34rpx;
  135. font-weight: bold;
  136. color: #333;
  137. }
  138. .close-icon {
  139. position: absolute;
  140. right: 0;
  141. top: 0;
  142. width: 24rpx;
  143. height: 24rpx;
  144. padding: 10rpx;
  145. box-sizing: content-box;
  146. }
  147. }
  148. .product-info {
  149. display: flex;
  150. margin-bottom: 30rpx;
  151. .book-cover {
  152. width: 140rpx;
  153. height: 180rpx;
  154. border-radius: 8rpx;
  155. margin-right: 24rpx;
  156. background-color: #f5f5f5;
  157. }
  158. .info-right {
  159. flex: 1;
  160. display: flex;
  161. flex-direction: column;
  162. justify-content: space-between;
  163. padding: 10rpx 0;
  164. .price-row {
  165. display: flex;
  166. align-items: center;
  167. .currency {
  168. font-size: 36rpx;
  169. color: #D81A00;
  170. font-weight: bold;
  171. }
  172. .price {
  173. font-size: 40rpx;
  174. color: #D81A00;
  175. font-weight: bold;
  176. margin-right: 20rpx;
  177. line-height: 1;
  178. }
  179. .drop-tag {
  180. background: #E8F9EA;
  181. padding: 4rpx 12rpx;
  182. border-radius: 4rpx;
  183. text {
  184. color: #38C248;
  185. font-size: 24rpx;
  186. font-weight: 500;
  187. }
  188. }
  189. }
  190. .tag-row {
  191. .quality-tag {
  192. display: inline-block;
  193. background: linear-gradient(0deg, #FFAB26 0%, #FFD426 100%);
  194. border-radius: 21rpx 0px 21rpx 0px;
  195. padding: 2rpx 24rpx;
  196. margin-bottom: 24rpx;
  197. text {
  198. color: #fff;
  199. font-size: 24rpx;
  200. font-weight: 500;
  201. }
  202. }
  203. }
  204. }
  205. }
  206. .tips-row {
  207. display: flex;
  208. align-items: center;
  209. margin-bottom: 16rpx;
  210. text {
  211. font-size: 26rpx;
  212. color: #8D8D8D;
  213. margin-right: 10rpx;
  214. }
  215. .tips-icon {
  216. width: 36rpx;
  217. height: 36rpx;
  218. }
  219. }
  220. .promo-note {
  221. margin-bottom: 40rpx;
  222. text {
  223. font-size: 26rpx;
  224. color: #8D8D8D;
  225. }
  226. }
  227. .options-list {
  228. margin-bottom: 40rpx;
  229. .option-item {
  230. position: relative;
  231. display: flex;
  232. justify-content: space-between;
  233. align-items: center;
  234. background: #F8F8F8;
  235. border-radius: 12rpx;
  236. padding: 24rpx 30rpx;
  237. margin-bottom: 24rpx;
  238. border: 2rpx solid #dfdfdf;
  239. transition: all 0.2s;
  240. &.active {
  241. border-color: transparent;
  242. }
  243. .bg-image {
  244. position: absolute;
  245. top: -6rpx;
  246. left: -1%;
  247. width: 102%;
  248. height: 110rpx;
  249. z-index: 0;
  250. }
  251. .left,
  252. .right {
  253. position: relative;
  254. z-index: 1;
  255. }
  256. .left {
  257. display: flex;
  258. align-items: center;
  259. .opt-name {
  260. font-size: 30rpx;
  261. font-weight: bold;
  262. color: #333;
  263. margin-right: 16rpx;
  264. }
  265. .opt-discount {
  266. background: #D8D8D8;
  267. border-radius: 8rpx 0 8rpx 0;
  268. padding: 2rpx 10rpx;
  269. text {
  270. color: #fff;
  271. font-size: 22rpx;
  272. }
  273. &.active {
  274. background: #38C248;
  275. }
  276. }
  277. }
  278. .right {
  279. text {
  280. font-size: 28rpx;
  281. color: #333;
  282. }
  283. }
  284. }
  285. }
  286. .quantity-row {
  287. display: flex;
  288. justify-content: space-between;
  289. align-items: center;
  290. margin-bottom: 50rpx;
  291. .label {
  292. font-size: 30rpx;
  293. font-weight: bold;
  294. color: #333;
  295. }
  296. }
  297. .footer-btns {
  298. display: flex;
  299. justify-content: space-between;
  300. padding-bottom: 10rpx;
  301. .btn {
  302. flex: 1;
  303. height: 100rpx;
  304. display: flex;
  305. flex-direction: column;
  306. align-items: center;
  307. justify-content: center;
  308. font-family: Source Han Sans SC;
  309. font-weight: 500;
  310. .price {
  311. font-size: 38rpx;
  312. color: #fff;
  313. line-height: 1.2;
  314. }
  315. .desc {
  316. font-size: 24rpx;
  317. color: #fff;
  318. }
  319. &.btn-orange {
  320. background: linear-gradient(0deg, #EFA941 0%, #FFB84F 100%);
  321. width: 340rpx;
  322. border-radius: 50rpx 0 0 50rpx;
  323. }
  324. &.btn-green {
  325. width: 340rpx;
  326. background: linear-gradient(0deg, #38C248 0%, #5FEA6F 100%);
  327. border-radius: 0 50rpx 50rpx 0;
  328. }
  329. }
  330. }
  331. </style>