SectionPlatforms.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. <template>
  2. <section class="section-platforms relative overflow-hidden bg-white py-24">
  3. <!-- 背景 -->
  4. <div class="absolute inset-0 pointer-events-none" style="background: linear-gradient(180deg, #f8faff 0%, #ffffff 50%, #f0fdf4 100%);"></div>
  5. <div class="relative z-10 max-w-7xl mx-auto px-6">
  6. <!-- 标题 -->
  7. <div class="text-center mb-14">
  8. <span class="inline-flex items-center gap-2 bg-indigo-50 border border-indigo-200 text-indigo-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-indigo-500 rounded-full animate-pulse"></span>
  10. {{ $t('platforms.badge') }}
  11. </span>
  12. <h2 class="text-4xl lg:text-5xl font-black text-gray-900 mb-4">
  13. {{ $t('platforms.title') }}<span class="bg-gradient-to-r from-indigo-600 to-violet-600 bg-clip-text text-transparent">{{ $t('platforms.subtitle') }}</span>
  14. </h2>
  15. <p class="text-gray-500 text-lg max-w-2xl mx-auto">{{ $t('platforms.description') }}</p>
  16. </div>
  17. <!-- 引擎选择器 -->
  18. <div class="flex justify-center gap-3 mb-10 flex-wrap">
  19. <button
  20. v-for="(engine, idx) in engines"
  21. :key="engine.id"
  22. @click="activeEngine = idx"
  23. class="group flex items-center gap-3 px-5 py-3 rounded-2xl border-2 transition-all duration-300 font-semibold text-sm"
  24. :class="activeEngine === idx
  25. ? `border-${engine.color}-400 bg-${engine.color}-50 text-${engine.color}-700 shadow-lg`
  26. : 'border-gray-200 bg-white text-gray-500 hover:border-gray-300 hover:bg-gray-50'"
  27. >
  28. <span class="text-xl">{{ engine.logo }}</span>
  29. <span>{{ engine.name }}</span>
  30. <span class="text-xs px-2 py-0.5 rounded-full font-bold"
  31. :class="activeEngine === idx ? `bg-${engine.color}-100 text-${engine.color}-600` : 'bg-gray-100 text-gray-400'">
  32. {{ engine.tag }}
  33. </span>
  34. </button>
  35. </div>
  36. <!-- 主展示区:左侧详情 + 右侧对比矩阵 -->
  37. <div class="grid grid-cols-1 lg:grid-cols-5 gap-8 items-start">
  38. <!-- 左侧:引擎详情卡片 -->
  39. <div class="lg:col-span-2">
  40. <Transition name="engine-slide" mode="out-in">
  41. <div :key="activeEngine" class="relative rounded-3xl overflow-hidden bg-gray-900 shadow-2xl">
  42. <!-- 封面图 -->
  43. <div class="relative h-52 overflow-hidden">
  44. <img :src="currentEngine.img" :alt="currentEngine.name"
  45. class="w-full h-full object-cover opacity-60"/>
  46. <div class="absolute inset-0" :style="`background: linear-gradient(to bottom, ${currentEngine.gradientFrom}, ${currentEngine.gradientTo});`"></div>
  47. <!-- Logo -->
  48. <div class="absolute top-5 left-5 flex items-center gap-3">
  49. <div class="w-12 h-12 rounded-2xl flex items-center justify-center text-2xl bg-white/10 backdrop-blur-sm border border-white/20">
  50. {{ currentEngine.logo }}
  51. </div>
  52. <div>
  53. <div class="text-white font-black text-xl">{{ currentEngine.name }}</div>
  54. <div class="text-white/60 text-xs">{{ currentEngine.subtitle }}</div>
  55. </div>
  56. </div>
  57. <!-- 适用标签 -->
  58. <div class="absolute bottom-4 left-5 right-5 flex flex-wrap gap-1.5">
  59. <span v-for="use in currentEngine.useCases" :key="use"
  60. class="text-xs bg-white/15 backdrop-blur-sm text-white border border-white/20 px-2.5 py-1 rounded-full">
  61. {{ use }}
  62. </span>
  63. </div>
  64. </div>
  65. <!-- 详情内容 -->
  66. <div class="p-6">
  67. <p class="text-gray-300 text-sm leading-relaxed mb-5">{{ currentEngine.desc }}</p>
  68. <!-- 核心指标 -->
  69. <div class="grid grid-cols-3 gap-3 mb-5">
  70. <div v-for="metric in currentEngine.metrics" :key="metric.label"
  71. class="text-center p-3 rounded-2xl bg-white/10 border border-white/20">
  72. <div class="font-black text-base mb-0.5" :class="metric.color">{{ metric.value }}</div>
  73. <div class="text-gray-500 text-xs">{{ metric.label }}</div>
  74. </div>
  75. </div>
  76. <!-- 优势列表 -->
  77. <div class="space-y-2 mb-5">
  78. <div v-for="pro in currentEngine.pros" :key="pro"
  79. class="flex items-center gap-2 text-sm text-gray-300">
  80. <span class="w-4 h-4 rounded-full flex items-center justify-center text-xs flex-shrink-0" :class="currentEngine.checkBg">✓</span>
  81. {{ pro }}
  82. </div>
  83. </div>
  84. <!-- CTA -->
  85. <button class="w-full py-3 rounded-2xl font-bold text-sm transition-all duration-300 hover:-translate-y-0.5 hover:shadow-lg"
  86. :class="currentEngine.btnClass">
  87. {{ $t('platforms.cta.learn') }} {{ currentEngine.name }} →
  88. </button>
  89. </div>
  90. </div>
  91. </Transition>
  92. </div>
  93. <!-- 右侧:功能对比矩阵 -->
  94. <div class="lg:col-span-3">
  95. <div class="bg-white border border-gray-100 rounded-3xl overflow-hidden shadow-lg">
  96. <!-- 矩阵标题行 -->
  97. <div class="grid grid-cols-5 bg-gray-50 border-b border-gray-100">
  98. <div class="col-span-1 p-4 text-xs font-bold text-gray-400 uppercase">{{ $t('platforms.comparison.featureTitle') }}</div>
  99. <div v-for="engine in engines" :key="engine.id"
  100. class="p-4 text-center transition-all duration-300"
  101. :class="activeEngine === engines.indexOf(engine) ? `bg-${engine.color}-50` : ''">
  102. <div class="text-lg mb-1">{{ engine.logo }}</div>
  103. <div class="text-xs font-bold text-gray-700">{{ engine.name }}</div>
  104. </div>
  105. </div>
  106. <!-- 矩阵内容行 -->
  107. <div v-for="(feature, fIdx) in comparisonFeatures" :key="feature.name"
  108. class="grid grid-cols-5 border-b border-gray-50 transition-all duration-200 cursor-default"
  109. :class="[
  110. fIdx % 2 === 0 ? '' : 'bg-gray-50/30',
  111. hoveredRow === fIdx ? 'bg-indigo-50/60 shadow-sm' : 'hover:bg-gray-50/50'
  112. ]"
  113. @mouseenter="hoveredRow = fIdx"
  114. @mouseleave="hoveredRow = null">
  115. <!-- 功能名 -->
  116. <div class="col-span-1 p-4 flex items-center gap-2 relative group">
  117. <span class="text-base">{{ feature.icon }}</span>
  118. <div>
  119. <div class="text-sm font-semibold text-gray-700 flex items-center gap-1">
  120. {{ feature.name }}
  121. <span v-if="feature.tip" class="w-3.5 h-3.5 bg-gray-200 text-gray-500 rounded-full text-xs flex items-center justify-center cursor-help flex-shrink-0">?</span>
  122. </div>
  123. <div class="text-xs text-gray-400">{{ feature.desc }}</div>
  124. </div>
  125. <!-- Tooltip -->
  126. <div v-if="feature.tip" class="compare-tooltip">
  127. {{ feature.tip }}
  128. </div>
  129. </div>
  130. <!-- 各引擎支持情况 -->
  131. <div v-for="(engine, eIdx) in engines" :key="engine.id"
  132. class="p-4 flex items-center justify-center transition-all duration-300"
  133. :class="activeEngine === eIdx ? `bg-${engine.color}-50/50` : ''">
  134. <div class="flex flex-col items-center gap-1">
  135. <span v-if="feature.support[eIdx] === 'full'" class="w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center text-xs font-bold">✓</span>
  136. <span v-else-if="feature.support[eIdx] === 'partial'" class="w-6 h-6 bg-amber-100 text-amber-600 rounded-full flex items-center justify-center text-xs font-bold">~</span>
  137. <span v-else class="w-6 h-6 bg-gray-100 text-gray-400 rounded-full flex items-center justify-center text-xs">—</span>
  138. <span v-if="feature.notes && feature.notes[eIdx]" class="text-xs text-gray-400 text-center leading-tight max-w-[70px]">{{ feature.notes[eIdx] }}</span>
  139. </div>
  140. </div>
  141. </div>
  142. </div>
  143. <!-- 底部推荐 -->
  144. <div class="mt-6 p-5 bg-gradient-to-r from-indigo-50 to-violet-50 rounded-2xl border border-indigo-100">
  145. <div class="flex items-start gap-3">
  146. <span class="text-2xl flex-shrink-0">💡</span>
  147. <div>
  148. <div class="font-bold text-gray-800 mb-1 text-sm">{{ $t('platforms.engineSelection.title') }}</div>
  149. <div class="text-gray-500 text-xs leading-relaxed">
  150. <span class="font-semibold text-gray-700">n8n</span> {{ $t('platforms.engineSelection.n8n') }}
  151. <span class="font-semibold text-gray-700">Coze</span> {{ $t('platforms.engineSelection.coze') }};
  152. <span class="font-semibold text-gray-700">Dify</span> {{ $t('platforms.engineSelection.dify') }};
  153. <span class="font-semibold text-gray-700">FastGPT</span> {{ $t('platforms.engineSelection.fastgpt') }}。
  154. <a href="#" class="text-indigo-600 font-semibold ml-1 hover:underline">{{ $t('platforms.engineSelection.guide') }} →</a>
  155. </div>
  156. </div>
  157. </div>
  158. </div>
  159. </div>
  160. </div>
  161. </div>
  162. </section>
  163. </template>
  164. <script setup>
  165. import { ref, computed } from 'vue'
  166. import { useI18n } from 'vue-i18n'
  167. const { t } = useI18n()
  168. const activeEngine = ref(0)
  169. const hoveredRow = ref(null)
  170. const engines = [
  171. {
  172. id: 'n8n', name: 'n8n', logo: '🔧', tag: t('platforms.engines.n8n.tag'), subtitle: t('platforms.engines.n8n.subtitle'),
  173. color: 'red',
  174. img: 'https://images.unsplash.com/photo-1518770660439-4636190af475?w=600&h=350&fit=crop&q=80',
  175. gradientFrom: 'rgba(239,68,68,0.4)', gradientTo: 'rgba(17,24,39,0.95)',
  176. desc: t('platforms.engines.n8n.desc'),
  177. useCases: [t('platforms.engines.n8n.useCases.0'), t('platforms.engines.n8n.useCases.1'), t('platforms.engines.n8n.useCases.2')],
  178. metrics: [
  179. { value: '400+', label: t('platforms.engines.n8n.metrics.0.label'), color: 'text-red-400' },
  180. { value: t('platforms.engines.n8n.metrics.1.value'), label: t('platforms.engines.n8n.metrics.1.label'), color: 'text-green-400' },
  181. { value: '99.9%', label: t('platforms.engines.n8n.metrics.2.label'), color: 'text-blue-400' }
  182. ],
  183. pros: [t('platforms.engines.n8n.pros.0'), t('platforms.engines.n8n.pros.1'), t('platforms.engines.n8n.pros.2'), t('platforms.engines.n8n.pros.3')],
  184. checkBg: 'bg-red-100 text-red-600',
  185. btnClass: 'bg-gradient-to-r from-red-500 to-orange-500 text-white shadow-lg shadow-red-200/50'
  186. },
  187. {
  188. id: 'coze', name: 'Coze', logo: '🤖', tag: t('platforms.engines.coze.tag'), subtitle: t('platforms.engines.coze.subtitle'),
  189. color: 'blue',
  190. img: 'https://images.unsplash.com/photo-1677442135703-1787eea5ce01?w=600&h=350&fit=crop&q=80',
  191. gradientFrom: 'rgba(59,130,246,0.4)', gradientTo: 'rgba(17,24,39,0.95)',
  192. desc:t('platforms.engines.coze.desc'),
  193. useCases: [t('platforms.engines.coze.useCases.0'), t('platforms.engines.coze.useCases.1'), t('platforms.engines.coze.useCases.2')],
  194. metrics: [
  195. { value: '零代码', label: '快速搭建', color: 'text-blue-400' },
  196. { value: '10+', label: '接入渠道', color: 'text-green-400' },
  197. { value: '多模态', label: '能力支持', color: 'text-violet-400' }
  198. ],
  199. pros: [t('platforms.engines.coze.pros.0'), t('platforms.engines.coze.pros.1'),t('platforms.engines.coze.pros.2'), t('platforms.engines.coze.pros.3')],
  200. checkBg: 'bg-blue-100 text-blue-600',
  201. btnClass: 'bg-gradient-to-r from-blue-500 to-cyan-500 text-white shadow-lg shadow-blue-200/50'
  202. },
  203. {
  204. id: 'dify', name: 'Dify', logo: '🧠', tag: t('platforms.engines.dify.tag'), subtitle: t('platforms.engines.dify.subtitle'),
  205. color: 'emerald',
  206. img: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=600&h=350&fit=crop&q=80',
  207. gradientFrom: 'rgba(16,185,129,0.4)', gradientTo: 'rgba(17,24,39,0.95)',
  208. desc: t('platforms.engines.dify.desc'),
  209. useCases: [t('platforms.engines.dify.useCases.0'),t('platforms.engines.dify.useCases.1'), t('platforms.engines.dify.useCases.2')],
  210. metrics: [
  211. { value: 'RAG', label: t('platforms.engines.dify.metrics.0.label'), color: 'text-emerald-400' },
  212. { value: 'Agent', label: t('platforms.engines.dify.metrics.1.label'), color: 'text-green-400' },
  213. { value: '开源', label: t('platforms.engines.dify.metrics.2.value'), color: 'text-blue-400' }
  214. ],
  215. pros: [t('platforms.engines.dify.pros.0'), t('platforms.engines.dify.pros.1'), t('platforms.engines.dify.pros.2'), t('platforms.engines.dify.pros.3')],
  216. checkBg: 'bg-emerald-100 text-emerald-600',
  217. btnClass: 'bg-gradient-to-r from-emerald-500 to-teal-500 text-white shadow-lg shadow-emerald-200/50'
  218. },
  219. {
  220. id: 'fastgpt', name: 'FastGPT', logo: '⚡', tag: t('platforms.engines.fastgpt.tag'), subtitle: t('platforms.engines.fastgpt.subtitle'),
  221. color: 'amber',
  222. img: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=600&h=350&fit=crop&q=80',
  223. gradientFrom: 'rgba(245,158,11,0.4)', gradientTo: 'rgba(17,24,39,0.95)',
  224. desc: t('platforms.engines.fastgpt.desc'),
  225. useCases: [t('platforms.engines.fastgpt.useCases.0'), t('platforms.engines.fastgpt.useCases.1'), t('platforms.engines.fastgpt.useCases.2')],
  226. metrics: [
  227. { value: '95%+', label: t('platforms.engines.fastgpt.metrics.0.label'), color: 'text-amber-400' },
  228. { value: t('platforms.engines.fastgpt.metrics.1.value'), label: t('platforms.engines.fastgpt.metrics.1.label'), color: 'text-green-400' },
  229. { value: t('platforms.engines.fastgpt.metrics.2.value'), label: t('platforms.engines.fastgpt.metrics.2.label'), color: 'text-blue-400' }
  230. ],
  231. pros: [t('platforms.engines.fastgpt.pros.0'), t('platforms.engines.fastgpt.pros.1'),t('platforms.engines.fastgpt.pros.2'), t('platforms.engines.fastgpt.pros.3')],
  232. checkBg: 'bg-amber-100 text-amber-600',
  233. btnClass: 'bg-gradient-to-r from-amber-500 to-orange-500 text-white shadow-lg shadow-amber-200/50'
  234. }
  235. ]
  236. const currentEngine = computed(() => engines[activeEngine.value])
  237. const comparisonFeatures = [
  238. {
  239. icon: '🎨', name: t('platforms.comparison.features.0.name'), desc: t('platforms.comparison.features.0.desc'),
  240. tip: t('platforms.comparison.features.0.tip'),
  241. support: ['full', 'full', 'full', 'partial'],
  242. notes: ['', '', '', t('platforms.comparison.notes.basic')]
  243. },
  244. {
  245. icon: '🔌', name: t('platforms.comparison.features.1.name'), desc: t('platforms.comparison.features.1.desc'),
  246. tip: t('platforms.comparison.features.1.tip'),
  247. support: ['full', 'partial', 'partial', 'partial'],
  248. notes: ['400+', '50+', '100+', '30+']
  249. },
  250. {
  251. icon: '🧠', name: t('platforms.comparison.features.2.name'), desc: t('platforms.comparison.features.2.desc'),
  252. tip: t('platforms.comparison.features.2.tip'),
  253. support: ['partial', 'partial', 'full', 'full'],
  254. notes: [t('platforms.comparison.notes.basic'), t('platforms.comparison.notes.basic'), t('platforms.comparison.notes.complete'), t('platforms.comparison.notes.complete')]
  255. },
  256. {
  257. icon: '🤖', name: t('platforms.comparison.features.3.name'), desc: '智能体工作流',
  258. tip: t('platforms.comparison.features.3.tip'),
  259. support: ['full', 'full', 'full', 'partial'],
  260. notes: ['', '', '', t('platforms.comparison.notes.basic')]
  261. },
  262. {
  263. icon: '🏠', name: t('platforms.comparison.features.4.name'), desc: t('platforms.comparison.features.4.desc'),
  264. tip: t('platforms.comparison.features.4.tip'),
  265. support: ['full', 'none', 'full', 'full'],
  266. notes: ['', t('platforms.comparison.notes.cloudOnly'), '', '']
  267. },
  268. {
  269. icon: '📱', name: t('platforms.comparison.features.5.name'), desc: t('platforms.comparison.features.5.desc'),
  270. tip: t('platforms.comparison.features.5.tip'),
  271. support: ['partial', 'full', 'partial', 'partial'],
  272. notes: [t('platforms.comparison.notes.needConfig'), t('platforms.comparison.notes.nativeSupport'), t('platforms.comparison.notes.needConfig'), t('platforms.comparison.notes.needConfig')]
  273. },
  274. {
  275. icon: '💰', name: t('platforms.comparison.features.6.name'), desc: t('platforms.comparison.features.6.desc'),
  276. tip: t('platforms.comparison.features.6.tip'),
  277. support: ['full', 'full', 'full', 'full'],
  278. notes: [t('platforms.comparison.notes.openSourceFree'), t('platforms.comparison.notes.freeQuota'), t('platforms.comparison.notes.openSourceFree'), t('platforms.comparison.notes.openSourceFree')]
  279. }
  280. ]
  281. </script>
  282. <style scoped>
  283. .engine-slide-enter-active, .engine-slide-leave-active {
  284. transition: all 0.3s ease;
  285. }
  286. .engine-slide-enter-from {
  287. opacity: 0;
  288. transform: translateX(-20px);
  289. }
  290. .engine-slide-leave-to {
  291. opacity: 0;
  292. transform: translateX(20px);
  293. }
  294. /* ===== 响应式 ===== */
  295. /* 标题自适应 */
  296. .section-platforms h2 {
  297. font-size: clamp(1.75rem, 4.5vw, 3rem);
  298. }
  299. .section-platforms p {
  300. font-size: clamp(0.875rem, 2vw, 1.125rem);
  301. }
  302. /* 平板(≤1024px)*/
  303. @media (max-width: 1024px) {
  304. .section-platforms { padding-top: 4rem; padding-bottom: 4rem; }
  305. .section-platforms .max-w-7xl { padding-left: 1rem; padding-right: 1rem; }
  306. }
  307. /* 手机横屏 / 小平板(≤768px)*/
  308. @media (max-width: 768px) {
  309. .section-platforms { padding-top: 3rem; padding-bottom: 3rem; }
  310. /* 引擎选择器按钮 */
  311. .section-platforms button.group { padding: 8px 14px; font-size: 12px; gap: 8px; }
  312. /* 对比矩阵改为可滚动 */
  313. .section-platforms .lg\:col-span-3 > .bg-white {
  314. overflow-x: auto;
  315. -webkit-overflow-scrolling: touch;
  316. }
  317. .section-platforms .grid-cols-5 {
  318. min-width: 480px;
  319. }
  320. /* 封面图高度缩小 */
  321. .section-platforms .h-52 { height: 10rem; }
  322. /* 内容区域内边距 */
  323. .section-platforms .p-6 { padding: 1rem; }
  324. /* 指标卡片 */
  325. .section-platforms .grid-cols-3 { gap: 0.5rem; }
  326. }
  327. /* 手机竖屏(≤480px)*/
  328. @media (max-width: 480px) {
  329. .section-platforms { padding-top: 2.5rem; padding-bottom: 2.5rem; }
  330. /* 引擎选择器按钮隐藏 tag */
  331. .section-platforms button.group span:last-child { display: none; }
  332. .section-platforms button.group { padding: 7px 12px; font-size: 11px; gap: 6px; }
  333. /* 封面图 */
  334. .section-platforms .h-52 { height: 8rem; }
  335. /* 底部推荐框 */
  336. .section-platforms .mt-6.p-5 { padding: 0.75rem; }
  337. /* 对比矩阵单元格内边距 */
  338. .section-platforms .p-4 { padding: 0.5rem; }
  339. .section-platforms .text-sm { font-size: 0.75rem; }
  340. .section-platforms .text-xs { font-size: 0.65rem; }
  341. }
  342. /* 极小屏(≤360px)*/
  343. @media (max-width: 360px) {
  344. .section-platforms button.group span:nth-child(2) { display: none; }
  345. .section-platforms button.group { padding: 6px 10px; }
  346. }
  347. /* 对比表格 Tooltip */
  348. .compare-tooltip {
  349. position: absolute;
  350. left: 100%;
  351. top: 50%;
  352. transform: translateY(-50%);
  353. margin-left: 8px;
  354. background: rgba(15, 10, 35, 0.92);
  355. color: #fff;
  356. font-size: 12px;
  357. line-height: 1.5;
  358. padding: 6px 12px;
  359. border-radius: 8px;
  360. white-space: nowrap;
  361. max-width: 220px;
  362. white-space: normal;
  363. z-index: 100;
  364. pointer-events: none;
  365. opacity: 0;
  366. transition: opacity 0.2s ease;
  367. border: 1px solid rgba(99, 102, 241, 0.3);
  368. box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  369. }
  370. .group:hover .compare-tooltip {
  371. opacity: 1;
  372. }
  373. </style>