国外MOSE官网
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.

307 lines
6.8 KiB

4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days ago
18 hours ago
4 days 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.isCollected ? '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. </view>
  59. </template>
  60. <script>
  61. export default {
  62. name: 'GoodsDetail',
  63. data() {
  64. return {
  65. goodsId: '',
  66. goodsData: {
  67. id: 1,
  68. name: '哪吒之魔童闹海新款首套装哪吒校内艺术手办树脂摆件学生小礼品',
  69. points: 100,
  70. category: '积分兑换',
  71. exchangeCount: 120,
  72. stock: 50,
  73. description: '这是一款美味的薄脆小饼干,口感酥脆,营养丰富。采用优质原料制作,无添加剂,适合全家人享用。每一口都能感受到浓郁的香味和酥脆的口感,是您休闲时光的最佳选择。',
  74. gallery: [
  75. '/static/商城_商品1.png',
  76. '/static/商城_商品2.png',
  77. '/static/bannerImage.png',
  78. '/static/商城_商品1.png',
  79. '/static/商城_商品2.png',
  80. '/static/bannerImage.png'
  81. ]
  82. }
  83. }
  84. },
  85. onLoad(options) {
  86. if (options.id) {
  87. this.goodsId = options.id;
  88. this.getGoodsDetail(options.id);
  89. }
  90. },
  91. methods: {
  92. async getGoodsDetail(id) {
  93. const res = await this.$api.shop.queryGoodsById({ goodsId: id })
  94. this.goodsData = res.result
  95. },
  96. async toggleFavorite() {
  97. const res = await this.$api.shop.collectionGoods({ goodsId: this.goodsId })
  98. uni.showToast({
  99. title: res.message,
  100. icon: res.code === 200 ? 'success' : 'none'
  101. });
  102. this.getGoodsDetail(this.goodsId)
  103. },
  104. previewImage(current, urls) {
  105. uni.previewImage({
  106. current: current,
  107. urls: urls
  108. });
  109. },
  110. onExchange() {
  111. uni.showModal({
  112. title: '确认兑换',
  113. content: `确定要用${this.goodsData.price}积分兑换${this.goodsData.title}吗?`,
  114. success: async (res) => {
  115. if (res.confirm) {
  116. const res = await this.$api.shop.buyGoods({
  117. goodsId: this.goodsId
  118. })
  119. if (res.code === 200){
  120. uni.showToast({
  121. title: res.message,
  122. icon: 'success'
  123. });
  124. // 延迟返回上一页
  125. setTimeout(() => {
  126. uni.navigateBack();
  127. }, 1000);
  128. }else {
  129. uni.showToast({
  130. title: res.message,
  131. icon: 'none'
  132. });
  133. }
  134. }
  135. }
  136. });
  137. }
  138. }
  139. }
  140. </script>
  141. <style lang="scss" scoped>
  142. .goods-detail {
  143. background: #f8f8f8;
  144. min-height: 100vh;
  145. padding-bottom: 120rpx; // 为底部固定栏留出空间
  146. }
  147. .banner-container {
  148. height: 700rpx;
  149. .banner-swiper {
  150. width: 100%;
  151. .banner-image {
  152. width: 100%;
  153. height: 100%;
  154. }
  155. }
  156. }
  157. .goods-info {
  158. background: #ffffff;
  159. margin-top: 20rpx;
  160. padding: 30rpx;
  161. }
  162. .points-section {
  163. display: flex;
  164. align-items: center;
  165. margin-bottom: 20rpx;
  166. .points-icon {
  167. width: 32rpx;
  168. height: 32rpx;
  169. margin-right: 8rpx;
  170. }
  171. .points-text {
  172. font-size: 32rpx;
  173. font-weight: bold;
  174. color: #1488DB;
  175. }
  176. }
  177. .title-section {
  178. margin-bottom: 40rpx;
  179. .goods-title {
  180. font-size: 28rpx;
  181. color: #333333;
  182. line-height: 1.5;
  183. display: block;
  184. }
  185. }
  186. .detail-container {
  187. background: #ffffff;
  188. margin-top: 20rpx;
  189. padding: 30rpx;
  190. margin-bottom: 120rpx;
  191. }
  192. .detail-title-section {
  193. display: flex;
  194. align-items: center;
  195. justify-content: center;
  196. margin-bottom: 30rpx;
  197. .detail-title {
  198. font-size: 28rpx;
  199. font-weight: bold;
  200. color: #333333;
  201. }
  202. }
  203. .gallery-section {
  204. margin-bottom: 40rpx;
  205. .gallery-grid {
  206. display: grid;
  207. grid-template-columns: repeat(3, 1fr);
  208. gap: 16rpx;
  209. .gallery-image {
  210. width: 100%;
  211. height: 200rpx;
  212. border-radius: 12rpx;
  213. border: 1rpx solid #f0f0f0;
  214. }
  215. }
  216. }
  217. .bottom-bar {
  218. position: fixed;
  219. bottom: 0;
  220. left: 0;
  221. right: 0;
  222. background: #ffffff;
  223. padding: 20rpx 30rpx;
  224. border-top: 1rpx solid #f0f0f0;
  225. z-index: 999;
  226. box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1);
  227. display: flex;
  228. align-items: center;
  229. justify-content: space-between;
  230. .stock-info {
  231. display: flex;
  232. flex-direction: column;
  233. align-items: center;
  234. .stock-text {
  235. font-size: 24rpx;
  236. color: #1488DB;
  237. margin-bottom: 4rpx;
  238. font-weight: bold;
  239. }
  240. .stock-label {
  241. font-size: 22rpx;
  242. color: #999999;
  243. }
  244. }
  245. .favorite-section {
  246. flex: 1;
  247. display: flex;
  248. flex-direction: column;
  249. align-items: center;
  250. .favorite-text {
  251. font-size: 22rpx;
  252. color: #999999;
  253. margin-top: 4rpx;
  254. }
  255. }
  256. .exchange-btn {
  257. flex: 2;
  258. margin-left: 50rpx;
  259. height: 80rpx;
  260. border-radius: 40rpx;
  261. background-color: #1488DB;
  262. display: flex;
  263. align-items: center;
  264. justify-content: center;
  265. .exchange-text {
  266. color: #ffffff;
  267. font-size: 28rpx;
  268. // font-weight: bold;
  269. }
  270. }
  271. }
  272. </style>