SectionCTA.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. <template>
  2. <section class="section-cta relative py-32 overflow-hidden" ref="ctaRef">
  3. <!-- 深色背景 -->
  4. <div class="absolute inset-0" style="background: linear-gradient(135deg, #0f0c29 0%, #1e0a3c 35%, #0d1b3e 65%, #0a0a1a 100%);"></div>
  5. <!-- 背景图 -->
  6. <div class="absolute inset-0">
  7. <img src="https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1600&h=700&fit=crop&q=80"
  8. alt="背景" class="w-full h-full object-cover opacity-10" />
  9. </div>
  10. <!-- 网格纹理 -->
  11. <div class="absolute inset-0 pointer-events-none" style="background-image: linear-gradient(rgba(139,92,246,0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(139,92,246,0.05) 1px, transparent 1px); background-size: 60px 60px;"></div>
  12. <!-- 动态光晕 -->
  13. <div class="absolute inset-0 pointer-events-none overflow-hidden">
  14. <div class="cta-orb cta-orb-1"></div>
  15. <div class="cta-orb cta-orb-2"></div>
  16. <div class="cta-orb cta-orb-3"></div>
  17. </div>
  18. <!-- 浮动节点装饰 -->
  19. <div class="absolute inset-0 overflow-hidden pointer-events-none">
  20. <div v-for="(node, idx) in floatingNodes" :key="idx"
  21. class="absolute rounded-2xl overflow-hidden shadow-2xl border border-white/10 cta-float-node"
  22. :style="{ left: node.x, top: node.y, width: node.size, height: node.size, animationDelay: node.delay, animationDuration: node.duration }">
  23. <img :src="node.img" :alt="'node'" class="w-full h-full object-cover opacity-40" />
  24. <div class="absolute inset-0 flex items-center justify-center text-2xl">{{ node.icon }}</div>
  25. <div class="absolute inset-0" :style="{ background: node.glow }"></div>
  26. </div>
  27. </div>
  28. <!-- 主内容 -->
  29. <div class="relative z-10 max-w-4xl mx-auto px-6 text-center text-white">
  30. <!-- 用户头像群 -->
  31. <div class="flex items-center justify-center gap-1 mb-10 reveal-up" :class="{ 'is-visible': isVisible }">
  32. <div class="flex -space-x-2.5">
  33. <img v-for="(av, i) in avatars" :key="i" :src="av" :alt="t('cta.user')"
  34. class="w-10 h-10 rounded-full object-cover ring-2 ring-white/20 shadow-lg hover:scale-110 hover:z-10 transition-transform duration-200 cursor-pointer"
  35. :style="{ zIndex: avatars.length - i }" />
  36. </div>
  37. <div class="ml-4 text-left">
  38. <div class="text-sm font-bold text-white">{{ t('cta.usersUsing') }}</div>
  39. <div class="flex items-center gap-1 text-xs text-yellow-300 mt-0.5">
  40. <span>★★★★★</span>
  41. <span class="text-white/50 ml-1">{{ t('cta.rating') }}</span>
  42. </div>
  43. </div>
  44. </div>
  45. <!-- 主标题 -->
  46. <div class="reveal-up" :class="{ 'is-visible': isVisible }" style="transition-delay: 0.15s;">
  47. <h2 class="text-5xl lg:text-7xl font-black mb-6 leading-tight tracking-tight">
  48. {{ t('cta.titlePrefix') }}<br />
  49. <span class="cta-gradient-text">{{ t('cta.title') }}</span>
  50. </h2>
  51. <p class="text-white/60 text-xl mb-12 max-w-3xl mx-auto text-center leading-relaxed" v-html="t('cta.description')">
  52. </p>
  53. </div>
  54. <!-- 按钮组 -->
  55. <div class="flex flex-col sm:flex-row items-center justify-center gap-4 mb-12 reveal-up" :class="{ 'is-visible': isVisible }" style="transition-delay: 0.3s;">
  56. <!-- 主按钮 -->
  57. <button class="cta-btn-primary group" @mouseenter="primaryHover = true" @mouseleave="primaryHover = false">
  58. <div class="cta-btn-shine" :class="{ 'cta-btn-shine-active': primaryHover }"></div>
  59. <span class="relative z-10 flex items-center gap-2">
  60. <span>🚀</span>
  61. <span>{{ t('cta.cta.startFree') }}</span>
  62. </span>
  63. </button>
  64. <!-- 次按钮 -->
  65. <button class="cta-btn-secondary group">
  66. <div class="cta-btn-play">
  67. <svg class="w-4 h-4 ml-0.5" fill="currentColor" viewBox="0 0 20 20">
  68. <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"/>
  69. </svg>
  70. </div>
  71. {{ t('cta.cta.watchDemo') }}
  72. </button>
  73. </div>
  74. <!-- 信任标签 -->
  75. <div class="flex flex-wrap items-center justify-center gap-x-6 gap-y-3 text-sm text-white/40 reveal-up" :class="{ 'is-visible': isVisible }" style="transition-delay: 0.45s;">
  76. <span v-for="trust in trustItems" :key="trust.key" class="flex items-center gap-2 hover:text-white/70 transition-colors duration-200 cursor-default">
  77. <span class="text-emerald-400 font-bold">✓</span>
  78. {{ t(`cta.trust.${trust.key}`) }}
  79. </span>
  80. </div>
  81. <!-- 底部数据展示 -->
  82. <div class="mt-16 grid grid-cols-3 gap-6 max-w-lg mx-auto reveal-up" :class="{ 'is-visible': isVisible }" style="transition-delay: 0.6s;">
  83. <div v-for="stat in bottomStats" :key="stat.key" class="cta-bottom-stat">
  84. <div class="text-2xl font-black mb-1" :style="{ color: stat.color }">{{ stat.value }}</div>
  85. <div class="text-white/40 text-xs">{{ t(`cta.stats.${stat.key}`) }}</div>
  86. </div>
  87. </div>
  88. </div>
  89. </section>
  90. </template>
  91. <script setup>
  92. import { ref, onMounted } from 'vue'
  93. import { useI18n } from 'vue-i18n'
  94. const { t } = useI18n()
  95. const isVisible = ref(false)
  96. const ctaRef = ref(null)
  97. const primaryHover = ref(false)
  98. onMounted(() => {
  99. const observer = new IntersectionObserver(
  100. (entries) => { entries.forEach(e => { if (e.isIntersecting) { isVisible.value = true; observer.unobserve(e.target) } }) },
  101. { threshold: 0.1 }
  102. )
  103. if (ctaRef.value) observer.observe(ctaRef.value)
  104. })
  105. const floatingNodes = [
  106. { x: '4%', y: '12%', size: '72px', icon: '⚡', delay: '0s', duration: '6s', img: 'https://images.unsplash.com/photo-1518770660439-4636190af475?w=100&h=100&fit=crop', glow: 'linear-gradient(135deg, rgba(245,158,11,0.3), transparent)' },
  107. { x: '88%', y: '8%', size: '64px', icon: '🤖', delay: '1s', duration: '7s', img: 'https://images.unsplash.com/photo-1677442135703-1787eea5ce01?w=100&h=100&fit=crop', glow: 'linear-gradient(135deg, rgba(139,92,246,0.3), transparent)' },
  108. { x: '2%', y: '62%', size: '58px', icon: '📊', delay: '2s', duration: '8s', img: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=100&h=100&fit=crop', glow: 'linear-gradient(135deg, rgba(59,130,246,0.3), transparent)' },
  109. { x: '91%', y: '58%', size: '68px', icon: '🔗', delay: '0.5s', duration: '9s', img: 'https://images.unsplash.com/photo-1555949963-ff9fe0c870eb?w=100&h=100&fit=crop', glow: 'linear-gradient(135deg, rgba(16,185,129,0.3), transparent)' },
  110. { x: '46%', y: '4%', size: '52px', icon: '✨', delay: '1.5s', duration: '7.5s', img: 'https://images.unsplash.com/photo-1558494949-ef010cbdcc31?w=100&h=100&fit=crop', glow: 'linear-gradient(135deg, rgba(236,72,153,0.3), transparent)' }
  111. ]
  112. const avatars = [
  113. 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=60&h=60&fit=crop',
  114. 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=60&h=60&fit=crop',
  115. 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=60&h=60&fit=crop',
  116. 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=60&h=60&fit=crop',
  117. 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=60&h=60&fit=crop'
  118. ]
  119. const trustItems = [
  120. { key: 'noCreditCard' },
  121. { key: 'quickStart' },
  122. { key: 'freeForever' },
  123. { key: 'cancelAnytime' }
  124. ]
  125. // 底部数据
  126. const bottomStats = [
  127. { value: '50K+', key: 'activeUsers', color: '#a78bfa' },
  128. { value: '99.9%', key: 'uptime', color: '#34d399' },
  129. { value: '4.9★', key: 'userRating', color: '#fbbf24' }
  130. ]
  131. </script>
  132. <style scoped>
  133. /* 光晕 */
  134. .cta-orb {
  135. position: absolute;
  136. border-radius: 50%;
  137. filter: blur(100px);
  138. pointer-events: none;
  139. }
  140. .cta-orb-1 {
  141. width: 600px; height: 600px;
  142. top: -150px; left: -100px;
  143. background: radial-gradient(circle, rgba(124,58,237,0.25) 0%, transparent 70%);
  144. animation: ctaOrbFloat 12s ease-in-out infinite;
  145. }
  146. .cta-orb-2 {
  147. width: 500px; height: 500px;
  148. top: 50%; right: -100px;
  149. background: radial-gradient(circle, rgba(236,72,153,0.2) 0%, transparent 70%);
  150. animation: ctaOrbFloat 16s ease-in-out infinite reverse;
  151. }
  152. .cta-orb-3 {
  153. width: 400px; height: 400px;
  154. bottom: -100px; left: 40%;
  155. background: radial-gradient(circle, rgba(59,130,246,0.15) 0%, transparent 70%);
  156. animation: ctaOrbFloat 10s ease-in-out infinite;
  157. }
  158. @keyframes ctaOrbFloat {
  159. 0%, 100% { transform: translate(0, 0); }
  160. 50% { transform: translate(30px, -40px); }
  161. }
  162. /* 浮动节点 */
  163. .cta-float-node {
  164. animation: ctaNodeFloat linear infinite;
  165. }
  166. @keyframes ctaNodeFloat {
  167. 0%, 100% { transform: translateY(0px) rotate(0deg); }
  168. 33% { transform: translateY(-14px) rotate(4deg); }
  169. 66% { transform: translateY(-7px) rotate(-3deg); }
  170. }
  171. /* 渐变文字 */
  172. .cta-gradient-text {
  173. background: linear-gradient(135deg, #fbbf24 0%, #f472b6 40%, #a78bfa 80%);
  174. -webkit-background-clip: text;
  175. background-clip: text;
  176. -webkit-text-fill-color: transparent;
  177. animation: gradientShift 4s ease-in-out infinite;
  178. background-size: 200% 200%;
  179. }
  180. @keyframes gradientShift {
  181. 0%, 100% { background-position: 0% 50%; }
  182. 50% { background-position: 100% 50%; }
  183. }
  184. /* 主按钮 */
  185. .cta-btn-primary {
  186. position: relative;
  187. overflow: hidden;
  188. background: white;
  189. color: #7c3aed;
  190. font-weight: 900;
  191. font-size: 16px;
  192. padding: 16px 40px;
  193. border-radius: 20px;
  194. transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
  195. box-shadow: 0 8px 32px rgba(255,255,255,0.15);
  196. }
  197. .cta-btn-primary:hover {
  198. transform: translateY(-3px) scale(1.03);
  199. box-shadow: 0 20px 50px rgba(255,255,255,0.25);
  200. }
  201. .cta-btn-primary:active {
  202. transform: translateY(-1px) scale(1.01);
  203. }
  204. .cta-btn-shine {
  205. position: absolute;
  206. inset: 0;
  207. background: linear-gradient(90deg, transparent 0%, rgba(124,58,237,0.08) 50%, transparent 100%);
  208. transform: translateX(-100%);
  209. transition: transform 0.6s ease;
  210. }
  211. .cta-btn-shine-active {
  212. transform: translateX(100%);
  213. }
  214. /* 次按钮 */
  215. .cta-btn-secondary {
  216. display: flex;
  217. align-items: center;
  218. gap: 12px;
  219. background: rgba(255,255,255,0.08);
  220. border: 1px solid rgba(255,255,255,0.15);
  221. color: white;
  222. font-weight: 700;
  223. font-size: 15px;
  224. padding: 16px 28px;
  225. border-radius: 20px;
  226. transition: all 0.3s ease;
  227. backdrop-filter: blur(8px);
  228. }
  229. .cta-btn-secondary:hover {
  230. background: rgba(255,255,255,0.15);
  231. border-color: rgba(255,255,255,0.3);
  232. transform: translateY(-2px);
  233. }
  234. .cta-btn-play {
  235. width: 36px; height: 36px;
  236. background: rgba(255,255,255,0.15);
  237. border-radius: 50%;
  238. display: flex;
  239. align-items: center;
  240. justify-content: center;
  241. transition: all 0.3s ease;
  242. }
  243. .cta-btn-secondary:hover .cta-btn-play {
  244. background: rgba(255,255,255,0.25);
  245. transform: scale(1.1);
  246. }
  247. /* 底部数据 */
  248. .cta-bottom-stat {
  249. text-align: center;
  250. padding: 16px;
  251. border-radius: 16px;
  252. background: rgba(255,255,255,0.04);
  253. border: 1px solid rgba(255,255,255,0.06);
  254. transition: all 0.3s ease;
  255. }
  256. .cta-bottom-stat:hover {
  257. background: rgba(255,255,255,0.08);
  258. border-color: rgba(255,255,255,0.12);
  259. transform: translateY(-3px);
  260. }
  261. /* 滚动动画 */
  262. .reveal-up {
  263. opacity: 0;
  264. transform: translateY(40px);
  265. transition: opacity 0.8s ease, transform 0.8s ease;
  266. }
  267. .reveal-up.is-visible {
  268. opacity: 1;
  269. transform: translateY(0);
  270. }
  271. /* ===== 响应式 ===== */
  272. /* 标题自适应 */
  273. .section-cta h2 {
  274. font-size: clamp(2.25rem, 6vw, 4.5rem);
  275. }
  276. .section-cta p {
  277. font-size: clamp(1rem, 2.5vw, 1.25rem);
  278. }
  279. /* 平板(≤1024px)*/
  280. @media (max-width: 1024px) {
  281. .section-cta { padding-top: 5rem; padding-bottom: 5rem; }
  282. /* 浮动节点在平板上隐藏以防溢出 */
  283. .cta-float-node { display: none; }
  284. }
  285. /* 手机横屏 / 小平板(≤768px)*/
  286. @media (max-width: 768px) {
  287. .section-cta { padding-top: 4rem; padding-bottom: 4rem; }
  288. .section-cta .max-w-4xl { padding-left: 1.25rem; padding-right: 1.25rem; }
  289. .cta-btn-primary { padding: 14px 32px; font-size: 15px; }
  290. .cta-btn-secondary { padding: 14px 22px; font-size: 14px; }
  291. .section-cta .mt-16 { margin-top: 2.5rem; }
  292. .section-cta .mb-12 { margin-bottom: 2rem; }
  293. .section-cta .mb-10 { margin-bottom: 1.5rem; }
  294. /* 底部数据卡片 */
  295. .cta-bottom-stat { padding: 12px 8px; }
  296. .cta-bottom-stat .text-2xl { font-size: 1.25rem; }
  297. }
  298. /* 手机竖屏(≤480px)*/
  299. @media (max-width: 480px) {
  300. .section-cta { padding-top: 3rem; padding-bottom: 3rem; }
  301. .section-cta .max-w-4xl { padding-left: 1rem; padding-right: 1rem; }
  302. .cta-btn-primary { padding: 12px 24px; font-size: 14px; border-radius: 16px; }
  303. .cta-btn-secondary { padding: 12px 18px; font-size: 13px; border-radius: 16px; gap: 8px; }
  304. .cta-btn-play { width: 30px; height: 30px; }
  305. .section-cta .w-10 { width: 2rem; height: 2rem; }
  306. .section-cta .mt-16 { margin-top: 2rem; }
  307. /* 底部数据卡片 */
  308. .cta-bottom-stat { padding: 10px 6px; }
  309. .cta-bottom-stat .text-2xl { font-size: 1.1rem; }
  310. .cta-bottom-stat .text-xs { font-size: 0.65rem; }
  311. /* 信任标签 */
  312. .section-cta .text-sm { font-size: 0.75rem; }
  313. }
  314. /* 极小屏(≤360px)*/
  315. @media (max-width: 360px) {
  316. .cta-btn-primary { padding: 11px 20px; font-size: 13px; }
  317. .cta-btn-secondary { padding: 11px 14px; font-size: 12px; }
  318. .cta-bottom-stat .text-2xl { font-size: 1rem; }
  319. }
  320. </style>