木邻有你前端代码仓库
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.

310 lines
7.0 KiB

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
  1. <template>
  2. <view class="goods-detail">
  3. <!-- 轮播图 -->
  4. <view class="banner-container">
  5. <uv-swiper
  6. indicator
  7. indicatorMode="dot"
  8. indicatorActiveColor="blue"
  9. height="700rpx"
  10. :list="goodsData.image.split(',')"></uv-swiper>
  11. </view>
  12. <!-- 商品信息 -->
  13. <view class="goods-info">
  14. <!-- 积分信息 -->
  15. <view class="points-section">
  16. <image src="/static/积分图标.png" class="points-icon" mode="aspectFit"></image>
  17. <text class="points-text">{{ goodsData.price }}积分</text>
  18. </view>
  19. <!-- 商品标题 -->
  20. <view class="title-section">
  21. <text class="goods-title">{{ goodsData.title }}</text>
  22. </view>
  23. </view>
  24. <!-- 商品详情独立容器 -->
  25. <view class="detail-container">
  26. <!-- 商品详情标题 -->
  27. <view class="detail-title-section">
  28. <rich-text :nodes="goodsData.details"></rich-text>
  29. </view>
  30. <!-- 商品图集 -->
  31. <!-- <view class="gallery-section">
  32. <view class="gallery-grid">
  33. <image
  34. v-for="(img, index) in goodsData.image.split(',')"
  35. :key="index"
  36. :src="img"
  37. class="gallery-image"
  38. mode="aspectFill"
  39. @click="previewImage(img, goodsData.image.split(','))"
  40. ></image>
  41. </view>
  42. </view> -->
  43. </view>
  44. <!-- 底部操作栏 -->
  45. <view class="bottom-bar">
  46. <view class="stock-info">
  47. <text class="stock-text">{{ goodsData.sales }}/{{ goodsData.inventory }}</text>
  48. <text class="stock-label">库存</text>
  49. </view>
  50. <view class="favorite-section" @click="toggleFavorite">
  51. <uv-icon name="heart" size="24" :color="goodsData.isCollection === 1 ? 'red' : '#cccccc'"></uv-icon>
  52. <text class="favorite-text">收藏</text>
  53. </view>
  54. <view class="exchange-btn" @click="onExchange">
  55. <text class="exchange-text">申请兑换</text>
  56. </view>
  57. </view>
  58. <GlobalPopup ref="globalPopupRef" />
  59. </view>
  60. </template>
  61. <script>
  62. export default {
  63. name: 'GoodsDetail',
  64. data() {
  65. return {
  66. goodsId: '',
  67. goodsData: {
  68. id: 1,
  69. name: '哪吒之魔童闹海新款首套装哪吒校内艺术手办树脂摆件学生小礼品',
  70. points: 100,
  71. category: '积分兑换',
  72. exchangeCount: 120,
  73. stock: 50,
  74. description: '这是一款美味的薄脆小饼干,口感酥脆,营养丰富。采用优质原料制作,无添加剂,适合全家人享用。每一口都能感受到浓郁的香味和酥脆的口感,是您休闲时光的最佳选择。',
  75. gallery: [
  76. '/static/商城_商品1.png',
  77. '/static/商城_商品2.png',
  78. '/static/bannerImage.png',
  79. '/static/商城_商品1.png',
  80. '/static/商城_商品2.png',
  81. '/static/bannerImage.png'
  82. ]
  83. }
  84. }
  85. },
  86. onLoad(options) {
  87. if (options.id) {
  88. this.goodsId = options.id;
  89. this.getGoodsDetail(options.id);
  90. }
  91. },
  92. methods: {
  93. async getGoodsDetail(id) {
  94. let params = {}
  95. if (uni.getStorageSync('token')) {
  96. params.token = uni.getStorageSync('token')
  97. }
  98. const res = await this.$api.shop.queryGoodsById({ goodsId: id, ...params })
  99. this.goodsData = res.result
  100. },
  101. async toggleFavorite() {
  102. const res = await this.$api.shop.collectionGoods({ goodsId: this.goodsId })
  103. uni.showToast({
  104. title: res.message,
  105. icon: res.code === 200 ? 'success' : 'none'
  106. });
  107. this.getGoodsDetail(this.goodsId)
  108. },
  109. previewImage(current, urls) {
  110. uni.previewImage({
  111. current: current,
  112. urls: urls
  113. });
  114. },
  115. onExchange() {
  116. uni.showModal({
  117. title: '确认兑换',
  118. content: `确定要用${this.goodsData.price}积分兑换${this.goodsData.title}吗?`,
  119. success: async (res) => {
  120. if (res.confirm) {
  121. const res2 = await this.$api.shop.buyGoods({
  122. goodsId: this.goodsId
  123. })
  124. if (res2.code === 200){
  125. this.$refs.globalPopupRef.open({
  126. content: '恭喜您兑换成功!',
  127. subContent: '请及时到社区领取商品!',
  128. titleType: 'exchange',
  129. popupType: 'success'
  130. })
  131. // 延迟返回上一页
  132. // setTimeout(() => {
  133. // uni.navigateBack();
  134. // }, 1500);
  135. }
  136. }
  137. }
  138. });
  139. }
  140. }
  141. }
  142. </script>
  143. <style lang="scss" scoped>
  144. .goods-detail {
  145. background: #f8f8f8;
  146. min-height: 100vh;
  147. padding-bottom: 120rpx; // 为底部固定栏留出空间
  148. }
  149. .banner-container {
  150. height: 700rpx;
  151. .banner-swiper {
  152. width: 100%;
  153. .banner-image {
  154. width: 100%;
  155. height: 100%;
  156. }
  157. }
  158. }
  159. .goods-info {
  160. background: #ffffff;
  161. margin-top: 20rpx;
  162. padding: 30rpx;
  163. }
  164. .points-section {
  165. display: flex;
  166. align-items: center;
  167. margin-bottom: 20rpx;
  168. .points-icon {
  169. width: 32rpx;
  170. height: 32rpx;
  171. margin-right: 8rpx;
  172. }
  173. .points-text {
  174. font-size: 32rpx;
  175. font-weight: bold;
  176. color: #1488DB;
  177. }
  178. }
  179. .title-section {
  180. margin-bottom: 40rpx;
  181. .goods-title {
  182. font-size: 28rpx;
  183. color: #333333;
  184. line-height: 1.5;
  185. display: block;
  186. }
  187. }
  188. .detail-container {
  189. background: #ffffff;
  190. margin-top: 20rpx;
  191. padding: 30rpx;
  192. margin-bottom: 120rpx;
  193. }
  194. .detail-title-section {
  195. display: flex;
  196. align-items: center;
  197. justify-content: center;
  198. margin-bottom: 30rpx;
  199. .detail-title {
  200. font-size: 28rpx;
  201. font-weight: bold;
  202. color: #333333;
  203. }
  204. }
  205. .gallery-section {
  206. margin-bottom: 40rpx;
  207. .gallery-grid {
  208. display: grid;
  209. grid-template-columns: repeat(3, 1fr);
  210. gap: 16rpx;
  211. .gallery-image {
  212. width: 100%;
  213. height: 200rpx;
  214. border-radius: 12rpx;
  215. border: 1rpx solid #f0f0f0;
  216. }
  217. }
  218. }
  219. .bottom-bar {
  220. position: fixed;
  221. bottom: 0;
  222. left: 0;
  223. right: 0;
  224. background: #ffffff;
  225. padding: 20rpx 30rpx;
  226. border-top: 1rpx solid #f0f0f0;
  227. z-index: 999;
  228. box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1);
  229. display: flex;
  230. align-items: center;
  231. justify-content: space-between;
  232. .stock-info {
  233. display: flex;
  234. flex-direction: column;
  235. align-items: center;
  236. .stock-text {
  237. font-size: 24rpx;
  238. color: #1488DB;
  239. margin-bottom: 4rpx;
  240. font-weight: bold;
  241. }
  242. .stock-label {
  243. font-size: 22rpx;
  244. color: #999999;
  245. }
  246. }
  247. .favorite-section {
  248. flex: 1;
  249. display: flex;
  250. flex-direction: column;
  251. align-items: center;
  252. .favorite-text {
  253. font-size: 22rpx;
  254. color: #999999;
  255. margin-top: 4rpx;
  256. }
  257. }
  258. .exchange-btn {
  259. flex: 2;
  260. margin-left: 50rpx;
  261. height: 80rpx;
  262. border-radius: 40rpx;
  263. background-color: #1488DB;
  264. display: flex;
  265. align-items: center;
  266. justify-content: center;
  267. .exchange-text {
  268. color: #ffffff;
  269. font-size: 28rpx;
  270. // font-weight: bold;
  271. }
  272. }
  273. }
  274. </style>