index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  1. <!-- 商品的详情页 -->
  2. <template>
  3. <view class="">
  4. <u-navbar leftIconColor="#888888" autoBack :bgColor="bgColor" :title="navTitle"
  5. titleStyle="color: #000000"></u-navbar>
  6. <!-- 添加动画小球 -->
  7. <view class="cart-ball" :class="{ active: ballShow }" :style="ballStyle" v-show="ballShow">
  8. <view class="inner"></view>
  9. </view>
  10. <!-- 产品主图轮播 -->
  11. <swiper class="swiper" :style="{height: '750rpx'}" :indicator-dots="true" :autoplay="true" :interval="3500"
  12. @change="e => (currentNum = e.detail.current)">
  13. <swiper-item v-for="(item, index) in imageList" :key="index">
  14. <image :src="item" mode="aspectFill" style="width: 100%; height: 100%;"></image>
  15. </swiper-item>
  16. </swiper>
  17. <!-- 商品信息 -->
  18. <view class="product-info">
  19. <view class="product-main">
  20. <!-- 价格区域 -->
  21. <view class="price-section">
  22. <text class="current-price">¥{{detail.price}}</text>
  23. <text class="price-suffix" v-if="skuNum != 0">起</text>
  24. <text class="original-price">¥{{detail.originalPrice}}</text>
  25. </view>
  26. <!-- 商品名称 -->
  27. <text class="product-name">{{detail.name}}</text>
  28. <!-- 销量库存信息 -->
  29. <view class="product-stats">
  30. <text class="stat-item">销量 {{detail.salesTotal}}件</text>
  31. <view class="divider"></view>
  32. <text class="stat-item">剩余 {{detail.stock}}件</text>
  33. </view>
  34. </view>
  35. <!-- 分享按钮 -->
  36. <view class="share-section">
  37. <button open-type="share" class="share-btn">
  38. <u-icon name="share" size="22" label="分享" labelPos="bottom" labelSize="12"></u-icon>
  39. </button>
  40. </view>
  41. </view>
  42. <!-- 商品属性 -->
  43. <view class="productStats">
  44. <view class="mar-b-30">
  45. <text class="font28">服务</text>
  46. <text class="font28 font-666 mar-lr-32 flex-1">快递:免运费</text>
  47. </view>
  48. <view @click="skuPopUp">
  49. <view class="mar-b-20 flex-items flex-sp-between">
  50. <view>
  51. <text class="font28">选择</text>
  52. <text class="font28 font-666 mar-lr-32 flex-1">规格</text>
  53. </view>
  54. <view class="mar-r-8">
  55. <view class="flex-items">
  56. <view class="guige">
  57. 共{{skuNum}}种规格可选
  58. </view>
  59. <uni-icons color="#d0d7df" type="right" size="20"></uni-icons>
  60. </view>
  61. </view>
  62. </view>
  63. <view class="mar-b-30 mar-lr-64 flex-items">
  64. <view v-for="(item,index) in detail.sku">
  65. <image class="skuImg" :src="item.skuImage" mode="aspectFit"></image>
  66. </view>
  67. </view>
  68. </view>
  69. <view>
  70. <text class="font28">参数</text>
  71. <text class="font28 font-666 mar-lr-32 flex-1">{{detail.parameter}}</text>
  72. </view>
  73. </view>
  74. <!-- 评价 -->
  75. <view class="productStats" @click="goScore">
  76. <view class="flex-items flex-sp-between">
  77. <view class="font30 font-bold">
  78. 评价 ({{scoreList.length}})
  79. </view>
  80. <view class="mar-r-16">
  81. <uni-icons color="#d0d7df" type="right" size="20"></uni-icons>
  82. </view>
  83. </view>
  84. <view class="mar-b-30 mar-t-40" v-for="(item,index) in scoreList" :key="index">
  85. <view class="flex-items flex-sp-between">
  86. <view class="flex-items">
  87. <view class="mar-r-14">
  88. <image class="avatar" :src="item.avatar||'../../../static/images/avatar.png'"
  89. mode="aspectFill">
  90. </image>
  91. </view>
  92. <view class="font28">
  93. {{item.account}}
  94. <uni-rate activeColor="#E2A28A" size="16" :value="item.score" allow-half />
  95. </view>
  96. </view>
  97. <view class="font-gray mar-r-14">
  98. {{item.scoreTime}}
  99. </view>
  100. </view>
  101. <view class="mar-t-30 font28 mar-l-80">
  102. {{item.content}}
  103. </view>
  104. <view class="flex-items mar-l-80">
  105. <view class="mar-t-30 font28 mar-r-14" v-for="(item,index) in item.imgList">
  106. <image v-if="item&&index<3" class="scoreImg" :src="item" mode="aspectFit"></image>
  107. </view>
  108. </view>
  109. </view>
  110. </view>
  111. <!-- 详情和规格 -->
  112. <view class="bg-white font32 pad-32 text-align font-gray">
  113. —— 商品详情 ——
  114. </view>
  115. <view class="bg-white">
  116. <u-parse :content="detail.context" :tagStyle="style"></u-parse>
  117. </view>
  118. <view class="height104"></view>
  119. <!-- 底部操作栏 -->
  120. <view class="navigation">
  121. <view class="flex">
  122. <view class="left">
  123. <view class="item" @tap="goOrder">
  124. <u-icon name="order" size="22"></u-icon>
  125. <view class="text u-line-1">订单</view>
  126. </view>
  127. <view class="item" @tap="goCart">
  128. <view class="cart-icon-wrapper">
  129. <u-icon name="shopping-cart" size="24"></u-icon>
  130. <view class="cart-badge" v-if="cartCount > 0">{{cartCount}}</view>
  131. </view>
  132. <view class="text u-line-1">购物车</view>
  133. </view>
  134. <view class="item" @click="handlerCollect">
  135. <u-icon :name="isCollect? 'star-fill' :'star'" :color="isCollect? '#F95B5B' : ''"
  136. size="22"></u-icon>
  137. <view class="text u-line-1">收藏</view>
  138. </view>
  139. </view>
  140. <view class="right">
  141. <view class="cart cartBtn u-line-1" :class="{ 'disabled': !detail.stock || detail.stock <= 0 }"
  142. @click="addCart">加入购物车</view>
  143. <view class="buy buyBtn u-line-1" :class="{ 'disabled': !detail.stock || detail.stock <= 0 }"
  144. @click="goPay">立即购买</view>
  145. </view>
  146. </view>
  147. <!-- 规格选择弹窗 -->
  148. <uni-popup borderRadius="20rpx 20rpx 0 0" ref="popup" background-color="#fff">
  149. <view class="popup">
  150. <view class="flex-items">
  151. <view>
  152. <image class="prpupImg" :src="skuSelect.skuImage" mode="aspectFit"
  153. @click="previewImage(skuSelect.skuImage)"></image>
  154. </view>
  155. <view class="mar-l-20">
  156. <view class="font32 pad-b-24">
  157. {{detail.name}}
  158. </view>
  159. <view class="pad-t-10">
  160. <text class="font40 font-red font-bold">¥{{skuSelect.price}}</text>
  161. </view>
  162. <view class="pad-t-15">
  163. <text class="font28 font-gray">剩余{{skuSelect.skuStock}}件</text>
  164. </view>
  165. </view>
  166. </view>
  167. <!-- 线条 -->
  168. <view class="gray-line mar-tb-8"></view>
  169. <view class="font38 font-bold mar-tb-20">
  170. 请选择规格
  171. </view>
  172. <view class="flex-container">
  173. <view class="hotBg"
  174. :style="selectId==item.id ? {backgroundColor: '#F2D0A2' } : {backgroundColor: '#ebebeb' }"
  175. v-for="(item, index) in detail.sku" :key="index" @click="selectRadio(item,index)">
  176. <view class="font28 ">
  177. {{item.skuName}}
  178. </view>
  179. </view>
  180. </view>
  181. <view class="flex-items flex-sp-between mar-b-60">
  182. <view class="mar-l-16 font32">
  183. 购买数量
  184. </view>
  185. <view class="mar-r-16">
  186. <u-number-box v-model="count"></u-number-box>
  187. </view>
  188. <button class="fixed-button" @click="goSettle">{{popupText}}</button>
  189. </view>
  190. </view>
  191. </uni-popup>
  192. <u-safe-bottom></u-safe-bottom>
  193. </view>
  194. </view>
  195. </template>
  196. <script>
  197. import {
  198. mapMutations,
  199. mapActions,
  200. mapGetters
  201. } from 'vuex';
  202. import {
  203. productCartCount,
  204. productDetail,
  205. productAddCollect,
  206. productClearCollect,
  207. scoreList,
  208. productCartSave
  209. } from '../../../config/api.js';
  210. import {
  211. MAIN_COLOR
  212. } from '../../../common/config.js'
  213. export default {
  214. computed: {
  215. ...mapGetters(['isLogin']),
  216. navTitle() {
  217. return this.bgColor !== 'transparent' ? '商品详情' : ''
  218. },
  219. navIconColor() {
  220. return this.bgColor !== 'transparent' ? '#FFFFFF' : '#cecece'
  221. }
  222. },
  223. data() {
  224. return {
  225. count: 1,
  226. skuNum: 0,
  227. popupText: "立即购买",
  228. selectId: "",
  229. skuSelect: {},
  230. bgColor: 'transparent',
  231. currentSkuText: '',
  232. currentNum: 0,
  233. buyType: 'sku',
  234. params: {
  235. current: 1,
  236. size: 2,
  237. productId: "",
  238. images: 1
  239. },
  240. imgList: [],
  241. isCollect: false,
  242. list: ['商品详情'],
  243. curNow: 0,
  244. radios: [],
  245. detail: {},
  246. imageList: [],
  247. scoreList: [],
  248. user: {},
  249. cartCount: 0,
  250. style: {
  251. img: 'width: 100%; vertical-align: top;',
  252. },
  253. showShare: false,
  254. ballShow: false,
  255. ballStyle: {
  256. left: '0px',
  257. top: '0px'
  258. }
  259. };
  260. },
  261. onPageScroll(e) {
  262. if (e.scrollTop >= 100) {
  263. this.bgColor = "#FFF"
  264. } else {
  265. this.bgColor = 'transparent'
  266. }
  267. },
  268. onLoad(opt) {
  269. this.params.productId = opt.id
  270. this.getDetail(this.params.productId)
  271. this.getScoreList()
  272. if (this.isLogin) {
  273. this.getCartCount()
  274. }
  275. setTimeout(() => {
  276. if (opt.skuId) {
  277. this.onceOrder(opt.skuId)
  278. }
  279. }, 300)
  280. },
  281. // 分享功能
  282. onShareAppMessage() {
  283. return {
  284. title: this.detail.name || '商品详情',
  285. path: `/packageShop/pages/detail/index?id=${this.params.productId}`,
  286. imageUrl: this.imageList && this.imageList.length > 0 ? this.imageList[0] : ''
  287. }
  288. },
  289. methods: {
  290. goCart() {
  291. if (!this.isLogin) {
  292. uni.navigateTo({
  293. url: '/packageUser/pages/login/index'
  294. });
  295. return;
  296. }
  297. this.$route('/packageShop/pages/cart/index')
  298. },
  299. goOrder() {
  300. if (!this.isLogin) {
  301. uni.navigateTo({
  302. url: '/packageUser/pages/login/index'
  303. });
  304. return;
  305. }
  306. this.$route('/packageOrder/pages/list/index?status=0')
  307. },
  308. getCartCount() {
  309. if (!this.isLogin) return;
  310. productCartCount().then((res) => {
  311. this.cartCount = res.data
  312. })
  313. },
  314. goSettle() {
  315. if (this.buyType === 'buy') {
  316. if (!this.skuSelect || !this.skuSelect.id) {
  317. return uni.$u.toast('请选择商品规格');
  318. }
  319. // 检查选中规格的库存
  320. if (!this.skuSelect.skuStock || this.skuSelect.skuStock <= 0) {
  321. return uni.$u.toast('该规格库存不足,无法购买');
  322. }
  323. // 检查购买数量是否超过库存
  324. if (this.count > this.skuSelect.skuStock) {
  325. return uni.$u.toast(`该规格仅剩${this.skuSelect.skuStock}件,请调整购买数量`);
  326. }
  327. if (!this.isLogin) {
  328. uni.navigateTo({
  329. url: '/packageUser/pages/login/index'
  330. });
  331. return;
  332. }
  333. this.skuSelect.count = this.count;
  334. this.skuSelect.productName = this.detail.name;
  335. const sku = JSON.stringify(this.skuSelect);
  336. uni.navigateTo({
  337. url: `/packageShop/pages/settle/index?sku=${encodeURIComponent(sku)}`,
  338. });
  339. } else {
  340. if (!this.skuSelect || !this.skuSelect.id) {
  341. return uni.$u.toast('请选择商品规格');
  342. }
  343. // 检查选中规格的库存
  344. if (!this.skuSelect.skuStock || this.skuSelect.skuStock <= 0) {
  345. return uni.$u.toast('该规格库存不足,无法加入购物车');
  346. }
  347. // 检查购买数量是否超过库存
  348. if (this.count > this.skuSelect.skuStock) {
  349. return uni.$u.toast(`该规格仅剩${this.skuSelect.skuStock}件,请调整数量`);
  350. }
  351. if (!this.isLogin) {
  352. uni.navigateTo({
  353. url: '/packageUser/pages/login/index'
  354. });
  355. return;
  356. }
  357. productCartSave({
  358. skuId: this.skuSelect.id,
  359. count: this.count
  360. }).then((res) => {
  361. if (res.code == 200) {
  362. this.startAddCartAnim();
  363. this.$refs.popup.close();
  364. this.getCartCount();
  365. uni.$u.toast("加入购物车成功");
  366. }
  367. })
  368. }
  369. },
  370. goScore() {
  371. this.$route('/packageOrder/pages/score/product-score?productId=' + this.params.productId)
  372. },
  373. skuPopUp(buyType) {
  374. this.$refs.popup.open("bottom")
  375. this.buyType = buyType;
  376. this.skuSelect = this.detail.sku[0]
  377. this.selectId = this.skuSelect.id
  378. },
  379. onceOrder(skuId) {
  380. console.log(skuId, "skuid")
  381. this.$refs.popup.open("bottom");
  382. this.buyType = "buy";
  383. const matchedSku = this.detail.sku.find(item => item.id === skuId);
  384. if (matchedSku) {
  385. this.skuSelect = matchedSku;
  386. this.selectId = this.skuSelect.id;
  387. } else {
  388. uni.$u.toast("该规格已下架")
  389. }
  390. },
  391. getScoreList() {
  392. scoreList(this.params).then((res) => {
  393. this.scoreList = res.data.records
  394. this.scoreList.forEach(item => {
  395. item.imgList = item.images.split(",")
  396. })
  397. })
  398. },
  399. async getDetail(id) {
  400. uni.showLoading({
  401. title: '加载中...',
  402. mask: true
  403. });
  404. try {
  405. const res = await productDetail({
  406. id
  407. })
  408. if (res.code === 200) {
  409. this.detail = res.data
  410. this.skuNum = this.detail.sku.length
  411. this.imageList = res.data.carouselImg.split(",");
  412. this.isCollect = res.data.isCollect
  413. } else if (res.code === 401) {
  414. uni.navigateTo({
  415. url: '/packageUser/pages/login/index'
  416. });
  417. }
  418. } catch (e) {
  419. console.error('获取商品详情失败:', e);
  420. if (e.code === 401) {
  421. uni.navigateTo({
  422. url: '/packageUser/pages/login/index'
  423. });
  424. } else {
  425. uni.$u.toast('获取商品详情失败');
  426. }
  427. }
  428. uni.hideLoading()
  429. },
  430. navigationTo(routerName) {
  431. if (routerName) {
  432. this.$route(routerName);
  433. }
  434. },
  435. async handlerCollect() {
  436. if (this.isCollect) {
  437. try {
  438. await productClearCollect({
  439. productId: this.params.productId
  440. })
  441. this.$u.toast('取消收藏成功!')
  442. this.isCollect = !this.isCollect
  443. } catch (e) {
  444. this.$u.toast('取消收藏失败!')
  445. }
  446. } else {
  447. try {
  448. await productAddCollect({
  449. productId: this.params.productId
  450. })
  451. this.$u.toast('收藏成功!')
  452. this.isCollect = !this.isCollect
  453. } catch (e) {
  454. this.$u.toast('收藏失败!')
  455. }
  456. }
  457. },
  458. addCart() {
  459. // 检查商品总库存
  460. if (!this.detail.stock || this.detail.stock <= 0) {
  461. return uni.$u.toast('商品库存不足,暂不能加入购物车');
  462. }
  463. this.skuPopUp('cart')
  464. this.popupText = "加入购物车"
  465. },
  466. goPay() {
  467. // 检查商品总库存
  468. if (!this.detail.stock || this.detail.stock <= 0) {
  469. return uni.$u.toast('商品库存不足,暂不能购买');
  470. }
  471. this.skuPopUp('buy')
  472. this.popupText = "立即购买"
  473. },
  474. sectionChange(index) {
  475. this.curNow = index;
  476. },
  477. selectRadio(item, index) {
  478. this.selectId = item.id;
  479. this.skuSelect = this.detail.sku[index]
  480. },
  481. // 预览图片
  482. previewImage(imageSrc) {
  483. uni.previewImage({
  484. urls: [imageSrc],
  485. current: imageSrc
  486. });
  487. },
  488. startAddCartAnim() {
  489. const query = uni.createSelectorQuery();
  490. query.select('.prpupImg').boundingClientRect();
  491. query.select('.cart-icon-wrapper').boundingClientRect();
  492. query.exec(([productRect, cartRect]) => {
  493. if (productRect && cartRect) {
  494. const startX = productRect.left + productRect.width / 2;
  495. const startY = productRect.top + productRect.height / 2;
  496. this.ballStyle = {
  497. left: startX + 'px',
  498. top: startY + 'px'
  499. }
  500. this.ballShow = true;
  501. setTimeout(() => {
  502. this.ballStyle = {
  503. left: cartRect.left + cartRect.width / 2 + 'px',
  504. top: cartRect.top + cartRect.height / 2 + 'px'
  505. }
  506. setTimeout(() => {
  507. this.ballShow = false;
  508. }, 450);
  509. }, 50);
  510. }
  511. });
  512. },
  513. }
  514. };
  515. </script>
  516. <style lang="scss">
  517. .popup {
  518. position: relative;
  519. padding: 30rpx;
  520. padding-bottom: 120rpx;
  521. /* 给底部按钮留出空间 */
  522. background-color: #fff;
  523. }
  524. .prpupImg {
  525. border-radius: 20rpx;
  526. width: 220rpx;
  527. height: 220rpx;
  528. cursor: pointer;
  529. transition: transform 0.2s ease;
  530. }
  531. .prpupImg:active {
  532. transform: scale(0.95);
  533. }
  534. .guige {
  535. background-color: #F5F5F5;
  536. padding: 10rpx;
  537. border-radius: 15rpx;
  538. }
  539. .skuImg {
  540. width: 60rpx;
  541. height: 60rpx;
  542. margin-right: 30rpx;
  543. }
  544. .productStats {
  545. margin: 25rpx 15rpx 25rpx 15rpx;
  546. border-radius: 20rpx;
  547. padding: 32rpx;
  548. background-color: #FFFFFF;
  549. }
  550. .vertical-line {
  551. margin-left: 20rpx;
  552. margin-right: 20rpx;
  553. width: 1px;
  554. height: 20rpx;
  555. background-color: #a8a8a8;
  556. }
  557. .productInfo {
  558. background-color: white;
  559. padding: 20rpx;
  560. margin: 25rpx 15rpx 25rpx 15rpx;
  561. border-radius: 20rpx;
  562. }
  563. /* 新的商品信息样式 */
  564. .product-info {
  565. background-color: #ffffff;
  566. padding: 32rpx 24rpx;
  567. margin: 24rpx 16rpx;
  568. border-radius: 24rpx;
  569. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
  570. display: flex;
  571. align-items: flex-start;
  572. justify-content: space-between;
  573. }
  574. .product-main {
  575. flex: 1;
  576. margin-right: 24rpx;
  577. }
  578. .price-section {
  579. display: flex;
  580. align-items: baseline;
  581. margin-bottom: 16rpx;
  582. }
  583. .current-price {
  584. font-size: 48rpx;
  585. font-weight: bold;
  586. color: #ff4757;
  587. margin-right: 8rpx;
  588. }
  589. .price-suffix {
  590. font-size: 28rpx;
  591. font-weight: bold;
  592. color: #ff4757;
  593. margin-right: 16rpx;
  594. }
  595. .original-price {
  596. font-size: 28rpx;
  597. color: #999999;
  598. text-decoration: line-through;
  599. }
  600. .product-name {
  601. font-size: 34rpx;
  602. font-weight: bold;
  603. color: #333333;
  604. line-height: 1.4;
  605. margin-bottom: 16rpx;
  606. display: -webkit-box;
  607. -webkit-box-orient: vertical;
  608. -webkit-line-clamp: 2;
  609. overflow: hidden;
  610. }
  611. .product-stats {
  612. display: flex;
  613. align-items: center;
  614. }
  615. .stat-item {
  616. font-size: 25rpx;
  617. color: #666666;
  618. }
  619. .divider {
  620. width: 2rpx;
  621. height: 24rpx;
  622. background-color: #e0e0e0;
  623. margin: 0 16rpx;
  624. }
  625. .share-section {
  626. flex-shrink: 0;
  627. }
  628. .share-btn {
  629. background: #ffffff;
  630. border: 2rpx solid #f0f0f0;
  631. border-radius: 20rpx;
  632. padding: 0;
  633. transition: all 0.25s ease;
  634. display: flex;
  635. align-items: center;
  636. justify-content: center;
  637. width: 80rpx;
  638. height: 80rpx;
  639. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
  640. position: relative;
  641. }
  642. .share-btn::after {
  643. content: '';
  644. position: absolute;
  645. top: -2rpx;
  646. left: -2rpx;
  647. right: -2rpx;
  648. bottom: -2rpx;
  649. background: linear-gradient(45deg, #667eea, #764ba2, #f093fb, #f5576c);
  650. border-radius: 20rpx;
  651. z-index: -1;
  652. opacity: 0;
  653. transition: opacity 0.25s ease;
  654. }
  655. .share-btn:active::after {
  656. opacity: 1;
  657. }
  658. .share-btn:active {
  659. transform: scale(0.92);
  660. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.15);
  661. border-color: transparent;
  662. }
  663. .share-btn .u-icon {
  664. color: #666666;
  665. transition: all 0.25s ease;
  666. font-size: 24rpx;
  667. }
  668. .share-btn:active .u-icon {
  669. color: #ffffff;
  670. transform: rotate(15deg) scale(1.1);
  671. }
  672. .swiper {
  673. width: 100%;
  674. position: relative;
  675. }
  676. .navigation {
  677. position: fixed;
  678. bottom: 0;
  679. width: 100%;
  680. border: solid 2rpx #f2f2f2;
  681. background-color: #ffffff;
  682. padding: 16rpx 0;
  683. .flex {
  684. display: flex;
  685. flex-direction: row;
  686. .left {
  687. width: 40%;
  688. display: flex;
  689. font-size: 20rpx;
  690. justify-content: space-around;
  691. .item {
  692. display: flex;
  693. flex-direction: column;
  694. justify-content: center;
  695. align-items: center;
  696. flex: 1;
  697. .tabbar-slot-icon {
  698. width: 44rpx;
  699. height: 44rpx;
  700. margin: 0 auto;
  701. }
  702. }
  703. }
  704. .right {
  705. width: 60%;
  706. display: flex;
  707. font-size: 28rpx;
  708. align-items: center;
  709. .cartBtn {
  710. width: 210rpx;
  711. height: 72rpx;
  712. font-size: 28rpx;
  713. text-align: center;
  714. line-height: 72rpx;
  715. border-radius: 36rpx 0rpx 0rpx 36rpx;
  716. color: #ffffff;
  717. }
  718. .buyBtn {
  719. font-size: 28rpx;
  720. width: 210rpx;
  721. height: 72rpx;
  722. text-align: center;
  723. line-height: 72rpx;
  724. border-radius: 0rpx 36rpx 36rpx 0rpx;
  725. color: #ffffff;
  726. }
  727. .buy {
  728. background: #F95B5B
  729. }
  730. .cart {
  731. background: #F9AE5B
  732. }
  733. .disabled {
  734. background: #cccccc !important;
  735. color: #999999 !important;
  736. cursor: not-allowed;
  737. }
  738. }
  739. }
  740. }
  741. .gray-line {
  742. height: 1px;
  743. background-color: #f9f9f9;
  744. width: 100%;
  745. }
  746. .flex-container {
  747. display: flex;
  748. flex-wrap: wrap;
  749. margin-bottom: 30rpx;
  750. }
  751. .hotBg {
  752. margin-bottom: 10rpx;
  753. margin-right: 30rpx;
  754. padding: 10px;
  755. font-size: 28rpx;
  756. border-radius: 5px;
  757. }
  758. .selected {
  759. background-color: orange;
  760. }
  761. .fixed-button {
  762. position: fixed;
  763. bottom: 0;
  764. left: 0;
  765. width: 100%;
  766. padding: 15rpx;
  767. background-color: #F95B5B;
  768. color: white;
  769. border: none;
  770. }
  771. .avatar {
  772. width: 70rpx;
  773. height: 70rpx;
  774. border-radius: 50%;
  775. overflow: hidden;
  776. }
  777. .scoreImg {
  778. width: 150rpx;
  779. height: 150rpx;
  780. }
  781. .cart-icon-wrapper {
  782. position: relative;
  783. display: inline-block;
  784. }
  785. .cart-badge {
  786. position: absolute;
  787. top: -10rpx;
  788. right: -10rpx;
  789. background-color: #FF4B4B;
  790. color: #fff;
  791. font-size: 20rpx;
  792. padding: 2rpx 8rpx;
  793. border-radius: 20rpx;
  794. min-width: 28rpx;
  795. height: 28rpx;
  796. text-align: center;
  797. line-height: 28rpx;
  798. }
  799. .cart-ball {
  800. position: fixed;
  801. z-index: 999;
  802. pointer-events: none;
  803. transition: all 0.45s cubic-bezier(0.49, -0.29, 0.75, 0.41);
  804. .inner {
  805. width: 16px;
  806. height: 16px;
  807. border-radius: 50%;
  808. background: #ff6b81;
  809. transition: all 0.45s linear;
  810. }
  811. }
  812. .cart-ball.active .inner {
  813. animation: ball-circular 0.45s linear;
  814. }
  815. @keyframes ball-circular {
  816. 0% {
  817. transform: scale(1);
  818. }
  819. 50% {
  820. transform: scale(0.8);
  821. }
  822. 100% {
  823. transform: scale(0.5);
  824. }
  825. }
  826. .custom-share-btn {
  827. background: #ffffff;
  828. border: 2rpx solid #e3e3e3;
  829. border-radius: 20rpx;
  830. padding: 0;
  831. transition: all 0.25s ease;
  832. display: flex;
  833. align-items: center;
  834. justify-content: center;
  835. width: 80rpx;
  836. height: 80rpx;
  837. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
  838. position: relative;
  839. }
  840. .custom-share-btn::after {
  841. content: '';
  842. position: absolute;
  843. top: -2rpx;
  844. left: -2rpx;
  845. right: -2rpx;
  846. bottom: -2rpx;
  847. background: linear-gradient(45deg, #667eea, #764ba2, #f093fb, #f5576c);
  848. border-radius: 20rpx;
  849. z-index: -1;
  850. opacity: 0;
  851. transition: opacity 0.25s ease;
  852. }
  853. .custom-share-btn:active::after {
  854. opacity: 1;
  855. }
  856. .custom-share-btn:active {
  857. transform: scale(0.92);
  858. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.15);
  859. border-color: transparent;
  860. }
  861. .custom-share-btn .u-icon {
  862. color: #666666;
  863. transition: all 0.25s ease;
  864. font-size: 24rpx;
  865. }
  866. .custom-share-btn:active .u-icon {
  867. color: #ffffff;
  868. transform: rotate(15deg) scale(1.1);
  869. }
  870. </style>