SectionHowItWorks.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <section class="section-how relative overflow-hidden bg-violet-50 py-24">
  3. <!-- 背景装饰 -->
  4. <div class="absolute inset-0 pointer-events-none" style="background-image: radial-gradient(circle at 1px 1px, rgba(139,92,246,0.06) 1px, transparent 0); background-size: 32px 32px;"></div>
  5. <div class="relative z-10 max-w-7xl mx-auto px-6">
  6. <!-- 标题 -->
  7. <div class="text-center mb-20">
  8. <span class="inline-flex items-center gap-2 bg-green-50 border border-green-200 text-green-600 text-xs font-bold px-4 py-1.5 rounded-full mb-5 uppercase tracking-wide">
  9. <span class="w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse"></span>
  10. {{ $t('howItWorks.badge') }}
  11. </span>
  12. <h2 class="text-4xl lg:text-5xl font-black text-gray-900 mb-4">
  13. {{ $t('howItWorks.title') }}<span class="bg-gradient-to-r from-green-600 to-teal-500 bg-clip-text text-transparent">{{ $t('howItWorks.subtitle') }}</span>
  14. </h2>
  15. <p class="text-gray-500 text-lg max-w-xl mx-auto">{{ $t('howItWorks.description') }}</p>
  16. </div>
  17. <!-- 时间轴主体 -->
  18. <div class="relative">
  19. <!-- 中央连接线 -->
  20. <div class="hidden lg:block absolute left-1/2 top-0 bottom-0 w-px -translate-x-1/2" style="background: linear-gradient(180deg, transparent 0%, #d1fae5 10%, #6ee7b7 30%, #34d399 50%, #6ee7b7 70%, #d1fae5 90%, transparent 100%);"></div>
  21. <!-- 流动粒子 -->
  22. <div class="hidden lg:block absolute left-1/2 -translate-x-1/2 top-0 bottom-0 overflow-hidden w-px pointer-events-none">
  23. <div class="timeline-particle"></div>
  24. <div class="timeline-particle" style="animation-delay: 1.5s;"></div>
  25. <div class="timeline-particle" style="animation-delay: 3s;"></div>
  26. </div>
  27. <!-- 步骤列表 -->
  28. <div class="space-y-16 lg:space-y-24">
  29. <div v-for="(step, idx) in steps" :key="step.title"
  30. class="relative flex flex-col lg:flex-row items-center gap-8 lg:gap-0"
  31. :class="idx % 2 === 1 ? 'lg:flex-row-reverse' : ''">
  32. <!-- 内容侧 -->
  33. <div class="w-full lg:w-5/12 group"
  34. :class="idx % 2 === 0 ? 'lg:pr-16 lg:text-right' : 'lg:pl-16'">
  35. <div class="inline-flex items-center gap-2 mb-4"
  36. :class="idx % 2 === 0 ? 'lg:flex-row-reverse' : ''">
  37. <span class="text-xs font-bold px-3 py-1 rounded-full" :class="step.badgeClass">{{ step.badge }}</span>
  38. <span class="text-gray-400 text-xs">Step {{ idx + 1 }}</span>
  39. </div>
  40. <h3 class="text-2xl lg:text-3xl font-black text-gray-900 mb-3">{{ step.title }}</h3>
  41. <p class="text-gray-500 text-base leading-relaxed mb-5">{{ step.desc }}</p>
  42. <!-- 特性标签 -->
  43. <div class="flex flex-wrap gap-2"
  44. :class="idx % 2 === 0 ? 'lg:justify-end' : ''">
  45. <span v-for="tag in step.tags" :key="tag"
  46. class="flex items-center gap-1.5 text-xs font-medium px-3 py-1.5 rounded-xl border"
  47. :class="step.tagClass">
  48. <span class="w-1.5 h-1.5 rounded-full" :class="step.dotClass"></span>
  49. {{ tag }}
  50. </span>
  51. </div>
  52. <!-- 时间指标 -->
  53. <div class="mt-5 inline-flex items-center gap-2 px-4 py-2 rounded-2xl"
  54. :class="step.timeClass">
  55. <span class="text-lg font-black" :class="step.timeNumClass">{{ step.time }}</span>
  56. <span class="text-xs font-medium opacity-70">{{ step.timeLabel }}</span>
  57. </div>
  58. </div>
  59. <!-- 中央节点 -->
  60. <div class="relative z-10 flex-shrink-0 lg:absolute lg:left-1/2 lg:-translate-x-1/2">
  61. <div class="w-16 h-16 rounded-2xl flex items-center justify-center text-2xl shadow-xl border-4 border-white transition-transform duration-300 hover:scale-110"
  62. :class="step.nodeBg">
  63. {{ step.icon }}
  64. </div>
  65. <!-- 步骤序号 -->
  66. <div class="absolute -top-2 -right-2 w-6 h-6 rounded-full flex items-center justify-center text-xs font-black text-white shadow-md"
  67. :class="step.numBg">
  68. {{ idx + 1 }}
  69. </div>
  70. </div>
  71. <!-- 预览侧 -->
  72. <div class="w-full lg:w-5/12"
  73. :class="idx % 2 === 0 ? 'lg:pl-16' : 'lg:pr-16'">
  74. <div class="relative rounded-2xl overflow-hidden shadow-xl border border-gray-100 group cursor-pointer hover:shadow-2xl transition-all duration-500 hover:-translate-y-1">
  75. <!-- 图片 -->
  76. <div class="relative h-52 overflow-hidden">
  77. <img :src="step.img" :alt="step.title"
  78. class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-700" />
  79. <div class="absolute inset-0" :class="step.imgOverlay"></div>
  80. </div>
  81. <!-- 底部信息条 -->
  82. <div class="bg-white px-5 py-3 flex items-center justify-between border-t border-gray-50">
  83. <div class="flex items-center gap-2">
  84. <span class="w-2 h-2 rounded-full" :class="step.dotClass"></span>
  85. <span class="text-sm font-semibold text-gray-700">{{ step.previewLabel }}</span>
  86. </div>
  87. <span class="text-xs text-gray-400">{{ step.previewSub }}</span>
  88. </div>
  89. <!-- 悬停播放按钮 -->
  90. <div class="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
  91. <div class="w-14 h-14 bg-white/90 rounded-full flex items-center justify-center shadow-xl">
  92. <svg class="w-6 h-6 text-gray-700 ml-1" fill="currentColor" viewBox="0 0 20 20">
  93. <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd"/>
  94. </svg>
  95. </div>
  96. </div>
  97. </div>
  98. </div>
  99. </div>
  100. </div>
  101. </div>
  102. <!-- 底部 CTA -->
  103. <div class="text-center mt-20">
  104. <div class="inline-flex flex-col items-center gap-4">
  105. <div class="flex items-center gap-3 text-sm text-gray-500">
  106. <span class="flex items-center gap-1.5"><span class="w-2 h-2 bg-green-400 rounded-full"></span>{{ $t('howItWorks.benefits.noCreditCard') }}</span>
  107. <span class="w-px h-4 bg-gray-200"></span>
  108. <span class="flex items-center gap-1.5"><span class="w-2 h-2 bg-blue-400 rounded-full"></span>{{ $t('howItWorks.benefits.quickStart') }}</span>
  109. <span class="w-px h-4 bg-gray-200"></span>
  110. <span class="flex items-center gap-1.5"><span class="w-2 h-2 bg-violet-400 rounded-full"></span>{{ $t('howItWorks.benefits.freeBasic') }}</span>
  111. </div>
  112. <button class="bg-gradient-to-r from-green-500 to-teal-500 text-white font-bold text-base px-8 py-4 rounded-2xl shadow-xl shadow-green-200/60 hover:shadow-green-300/60 hover:-translate-y-0.5 transition-all duration-300">
  113. {{ $t('howItWorks.cta.startFree') }} →
  114. </button>
  115. </div>
  116. </div>
  117. </div>
  118. </section>
  119. </template>
  120. <script setup>
  121. import { useI18n } from 'vue-i18n'
  122. const { t } = useI18n()
  123. const steps = [
  124. {
  125. icon: '🎯',
  126. title: t('howItWorks.steps.0.title'),
  127. desc: t('howItWorks.steps.0.desc'),
  128. badge: t('howItWorks.steps.0.badge'),
  129. badgeClass: 'bg-green-100 text-green-700',
  130. tags: [t('howItWorks.steps.0.tags.0'), t('howItWorks.steps.0.tags.1'), t('howItWorks.steps.0.tags.2')],
  131. tagClass: 'bg-green-50 text-green-600 border-green-100',
  132. dotClass: 'bg-green-400',
  133. time: '< 5 min',
  134. timeLabel: t('howItWorks.steps.0.timeLabel'),
  135. timeClass: 'bg-green-50',
  136. timeNumClass: 'text-green-600',
  137. nodeBg: 'bg-gradient-to-br from-green-400 to-teal-500',
  138. numBg: 'bg-green-500',
  139. img: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=600&h=350&fit=crop&q=80',
  140. imgOverlay: 'bg-gradient-to-t from-green-900/40 to-transparent',
  141. previewLabel: t('howItWorks.steps.0.previewLabel'),
  142. previewSub: t('howItWorks.steps.0.previewSub')
  143. },
  144. {
  145. icon: '⚙️',
  146. title: t('howItWorks.steps.1.title'),
  147. desc: t('howItWorks.steps.1.desc'),
  148. badge: t('howItWorks.steps.1.badge'),
  149. badgeClass: 'bg-violet-100 text-violet-700',
  150. tags: [ t('howItWorks.steps.1.tags.0'),
  151. t('howItWorks.steps.1.tags.1'),
  152. t('howItWorks.steps.1.tags.2')],
  153. tagClass: 'bg-violet-50 text-violet-600 border-violet-100',
  154. dotClass: 'bg-violet-400',
  155. time: t('howItWorks.steps.1.time'),
  156. timeLabel: t('howItWorks.steps.1.timeLabel'),
  157. timeClass: 'bg-violet-50',
  158. timeNumClass: 'text-violet-600',
  159. nodeBg: 'bg-gradient-to-br from-violet-500 to-blue-500',
  160. numBg: 'bg-violet-500',
  161. img: 'https://images.unsplash.com/photo-1518770660439-4636190af475?w=600&h=350&fit=crop&q=80',
  162. imgOverlay: 'bg-gradient-to-t from-violet-900/40 to-transparent',
  163. previewLabel: t('howItWorks.steps.1.previewLabel'),
  164. previewSub: t('howItWorks.steps.1.previewSub')
  165. },
  166. {
  167. icon: '🚀',
  168. title: t('howItWorks.steps.2.title'),
  169. desc: t('howItWorks.steps.2.desc'),
  170. badge:t('howItWorks.steps.2.badge'),
  171. badgeClass: 'bg-blue-100 text-blue-700',
  172. tags: [t('howItWorks.steps.2.tags.0'),
  173. t('howItWorks.steps.2.tags.1'),
  174. t('howItWorks.steps.2.tags.2')],
  175. tagClass: 'bg-blue-50 text-blue-600 border-blue-100',
  176. dotClass: 'bg-blue-400',
  177. time: '99.9%',
  178. timeLabel: t('howItWorks.steps.2.timeLabel'),
  179. timeClass: 'bg-blue-50',
  180. timeNumClass: 'text-blue-600',
  181. nodeBg: 'bg-gradient-to-br from-blue-500 to-cyan-500',
  182. numBg: 'bg-blue-500',
  183. img: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=600&h=350&fit=crop&q=80',
  184. imgOverlay: 'bg-gradient-to-t from-blue-900/40 to-transparent',
  185. previewLabel: t('howItWorks.steps.2.previewLabel'),
  186. previewSub: t('howItWorks.steps.2.previewSub')
  187. }
  188. ]
  189. </script>
  190. <style scoped>
  191. .timeline-particle {
  192. position: absolute;
  193. top: -8px;
  194. left: 50%;
  195. transform: translateX(-50%);
  196. width: 6px;
  197. height: 6px;
  198. border-radius: 50%;
  199. background: #34d399;
  200. box-shadow: 0 0 8px #34d399;
  201. animation: particleFall 4.5s linear infinite;
  202. }
  203. @keyframes particleFall {
  204. 0% { top: -8px; opacity: 0; }
  205. 10% { opacity: 1; }
  206. 90% { opacity: 1; }
  207. 100% { top: 100%; opacity: 0; }
  208. }
  209. </style>