ProductTabs.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <template>
  2. <section class="mb-product-section">
  3. <!-- tabs 盖在视频下半部分 -->
  4. <section class="mb-tabs-wrapper">
  5. <section class="mb-tabs">
  6. <div v-for="(tab, index) in productTabs" :key="index" class="mb-tab-item" :class="{ 'mb-active': activeTab === index }"
  7. @click="activeTab = index">
  8. {{ tab.name }}
  9. </div>
  10. </section>
  11. </section>
  12. <!-- cards 正常向下排列 -->
  13. <section class="mb-cards" :class="{ 'mb-is-multi': isMultiLayout }">
  14. <div v-for="(card, index) in displayCards" :key="index" class="mb-card">
  15. <h3 class="mb-card-title">{{ card.title }}</h3>
  16. <p class="mb-card-description">{{ card.description }}</p>
  17. <div v-if="card.features?.length" class="mb-card-features">
  18. <span v-for="(feature, idx) in card.features" :key="idx" class="mb-feature-tag">{{ feature }}</span>
  19. </div>
  20. <div class="mb-card-actions">
  21. <button class="mb-btn-primary" type="button">更多详情</button>
  22. <button class="mb-btn-secondary" type="button">0 元体验</button>
  23. </div>
  24. </div>
  25. </section>
  26. </section>
  27. </template>
  28. <script setup>
  29. import { ref, computed } from 'vue'
  30. import { productTabs } from '~/utils/product'
  31. const activeTab = ref(0)
  32. const currentTabData = computed(() => productTabs[activeTab.value])
  33. const displayCards = computed(() => {
  34. const cards = currentTabData.value?.cards ?? []
  35. return cards
  36. })
  37. const isMultiLayout = computed(() => currentTabData.value?.layout === 'multi')
  38. </script>
  39. <style lang="scss" scoped>
  40. .mb-product-section {
  41. width: 100%;
  42. }
  43. .mb-tabs-wrapper {
  44. position: relative;
  45. width: 100%;
  46. z-index: 3;
  47. padding: 0 6px;
  48. box-sizing: border-box;
  49. }
  50. .mb-tabs {
  51. width: 100%;
  52. box-sizing: border-box;
  53. height: 42px;
  54. margin: 0 auto;
  55. border-radius: 150px;
  56. background: linear-gradient(177deg, rgba(165, 101, 255, 0.30) -20.47%, rgba(3, 0, 20, 0.30) 134.25%);
  57. backdrop-filter: blur(20px);
  58. display: flex;
  59. align-items: center;
  60. padding: 0 12px;
  61. overflow-x: auto;
  62. scroll-behavior: smooth;
  63. -webkit-overflow-scrolling: touch;
  64. scrollbar-width: none;
  65. -ms-overflow-style: none;
  66. &::-webkit-scrollbar {
  67. display: none;
  68. }
  69. .mb-tab-item {
  70. flex-shrink: 0;
  71. font-weight: 400;
  72. color: #ffffff;
  73. font-size: 12px;
  74. line-height: 16px;
  75. cursor: pointer;
  76. white-space: nowrap;
  77. transition: color 0.3s ease, background 0.3s ease, transform 0.3s ease;
  78. display: flex;
  79. align-items: center;
  80. justify-content: center;
  81. min-width: 88px;
  82. height: 32px;
  83. padding: 0 16px;
  84. border-radius: 16px;
  85. background: transparent;
  86. &.mb-active {
  87. background: linear-gradient(62.84deg, rgba(130, 77, 255, 1) 0%, rgba(164, 125, 255, 1) 100%);
  88. color: #ffffff;
  89. font-weight: 500;
  90. }
  91. &:hover:not(.mb-active) {
  92. color: #bdbdbd;
  93. transform: translateY(-1px);
  94. }
  95. }
  96. }
  97. .mb-cards {
  98. width: 100%;
  99. box-sizing: border-box;
  100. margin-top: 20px;
  101. padding: 0 10px;
  102. display: flex;
  103. flex-direction: column;
  104. gap: 8px;
  105. }
  106. .mb-cards.mb-is-multi {
  107. flex-direction: row;
  108. overflow-x: auto;
  109. scroll-snap-type: x mandatory;
  110. scroll-padding: 10px;
  111. scroll-behavior: smooth;
  112. -webkit-overflow-scrolling: touch;
  113. scrollbar-width: none;
  114. -ms-overflow-style: none;
  115. &::-webkit-scrollbar {
  116. display: none;
  117. }
  118. }
  119. .mb-card {
  120. width: 100%;
  121. border-radius: 20px;
  122. border: 1px solid rgba(198, 186, 255, 0.30);
  123. background: linear-gradient(177deg, rgba(165, 101, 255, 0.25) -20.47%, rgba(3, 0, 20, 0.25) 134.25%);
  124. backdrop-filter: blur(20px);
  125. padding: 18px 16px 16px;
  126. box-sizing: border-box;
  127. min-height: 290px;
  128. display: flex;
  129. flex-direction: column;
  130. }
  131. .mb-cards.mb-is-multi .mb-card {
  132. flex: 0 0 96%;
  133. scroll-snap-align: center;
  134. }
  135. .mb-card-title {
  136. margin: 0;
  137. text-align: center;
  138. color: #ffffff;
  139. font-size: 16px;
  140. font-weight: 500;
  141. line-height: 18px;
  142. }
  143. .mb-card-description {
  144. margin: 12px 0 0;
  145. color: rgba(255, 255, 255, 0.65);
  146. font-size: 12px;
  147. font-weight: 400;
  148. line-height: 18px;
  149. display: -webkit-box;
  150. -webkit-box-orient: vertical;
  151. -webkit-line-clamp: 6;
  152. overflow: hidden;
  153. }
  154. .mb-card-features {
  155. margin-top: 12px;
  156. display: flex;
  157. flex-direction: column;
  158. gap: 10px;
  159. }
  160. .mb-feature-tag {
  161. font-size: 12px;
  162. font-weight: 400;
  163. line-height: 12px;
  164. color: #9b71ff;
  165. }
  166. .mb-card-actions {
  167. margin-top: auto;
  168. padding-top: 14px;
  169. display: flex;
  170. justify-content: flex-end;
  171. gap: 12px;
  172. }
  173. .mb-btn-primary {
  174. display: flex;
  175. width: 72px;
  176. height: 20px;
  177. justify-content: center;
  178. align-items: center;
  179. flex-shrink: 0;
  180. border-radius: 4px;
  181. background: linear-gradient(117deg, #A39DFF -41.28%, #7D46FF 60.31%);
  182. color: #FFF;
  183. font-size: 12px;
  184. font-weight: 400;
  185. padding: 2px 6px;
  186. }
  187. .mb-btn-secondary {
  188. display: flex;
  189. width: 72px;
  190. height: 20px;
  191. justify-content: center;
  192. align-items: center;
  193. flex-shrink: 0;
  194. border-radius: 4px;
  195. background: rgba(255, 255, 255, 0.20);
  196. backdrop-filter: blur(2px);
  197. color: #FFF;
  198. font-size: 12px;
  199. font-weight: 400;
  200. padding: 2px 6px;
  201. }
  202. </style>