Explorar o código

首页中英文翻译及部分接口调试

liuqiwen hai 1 semana
pai
achega
608c4243a6

+ 4 - 0
src/api/publish.js

@@ -15,4 +15,8 @@ export function getPublishList(data = {}) {
 // 查询发布工作流列表
 // 查询发布工作流列表
 export function getPublishDetail(data = {}) {
 export function getPublishDetail(data = {}) {
   return request.get('/publish/'+data.id)
   return request.get('/publish/'+data.id)
+}
+// 查询工作流分类
+export function workflowCategoryStats(data = {}) {
+  return request.get('/index/workflowCategoryStats',data)
 }
 }

+ 77 - 6
src/locales/en.js

@@ -609,7 +609,10 @@ export default {
         "badgeText": "99.9%",
         "badgeText": "99.9%",
         "tags": ["Real-time Monitoring", "Automatic Alerts", "Execution Logs"]
         "tags": ["Real-time Monitoring", "Automatic Alerts", "Execution Logs"]
       }
       }
-    }
+    },
+    running: 'Running',
+    llmApplication: 'LLM App',
+    knowledgeBaseQA: 'Knowledge Base Q&A'
   },
   },
   "stats": {
   "stats": {
     "workflowTemplates": "Workflow Templates",
     "workflowTemplates": "Workflow Templates",
@@ -635,26 +638,31 @@ export default {
   "cards": {
   "cards": {
     "globalUsers": {
     "globalUsers": {
       "label": "Global Users",
       "label": "Global Users",
-      "sub": "From 120+ countries and regions"
+      "sub": "From 120+ countries and regions",
+      displayNum: '50,000+'
     },
     },
     "workflowExecutions": {
     "workflowExecutions": {
       "label": "Workflow Executions",
       "label": "Workflow Executions",
-      "sub": "Cumulative automated executions"
+      "sub": "Cumulative automated executions",
+      displayNum: '12M+'
     },
     },
     "timeSaved": {
     "timeSaved": {
       "label": "Time Saved",
       "label": "Time Saved",
-      "sub": "Cumulative manual time saved by users"
+      "sub": "Cumulative manual time saved by users",
+      displayNum: '3.2M hours'
     },
     },
     "workflowTemplates": {
     "workflowTemplates": {
       "label": "Workflow Templates",
       "label": "Workflow Templates",
-      "sub": "Curated templates contributed by the community"
+      "sub": "Curated templates contributed by the community",
+      displayNum: '8,000+'
     }
     }
   },
   },
   "systemMetrics": {
   "systemMetrics": {
     "uptime": "Uptime",
     "uptime": "Uptime",
     "peakTraffic": "Peak Traffic",
     "peakTraffic": "Peak Traffic",
     "avgResponseTime": "Average Response Time",
     "avgResponseTime": "Average Response Time",
-    "todayExecutions": "Today's Executions"
+    "todayExecutions": "Today's Executions",
+     todayExecutionsValue: '15,750 times'
   },
   },
   "flowSteps": {
   "flowSteps": {
     "dataInput": "Data Input",
     "dataInput": "Data Input",
@@ -1133,6 +1141,69 @@ export default {
   },
   },
   "featured": {
   "featured": {
     "title": "Featured Popular Courses"
     "title": "Featured Popular Courses"
+  },
+  levels: {
+    beginner: 'Beginner',
+    intermediate: 'Intermediate',
+    advanced: 'Advanced',
+    senior: 'Senior',
+    expert: 'Expert'
+  },
+  unit: {
+    lessons: 'lessons'
+  },
+  content: 'Course Content',
+  paths: {
+    n8nBasic: {
+      title: 'n8n Basic',
+      subtitle: 'Automation Beginner',
+      items: [
+        'What is AI Workflow',
+        'n8n Quick Start',
+        'First Automation Task',
+        'Common Nodes Usage'
+      ]
+    },
+    n8nAdvanced: {
+      title: 'n8n Advanced',
+      subtitle: 'Automation Expert',
+      items: [
+        'Complex Workflow Design',
+        'HTTP Node Deep Dive',
+        'Error Handling & Debugging',
+        'API Integration Practice'
+      ]
+    },
+    cozeBot: {
+      title: 'Coze Bot Development',
+      subtitle: 'AI Assistant Building',
+      items: [
+        'Coze Platform Overview',
+        'Multi-model Integration',
+        'Plugin Development',
+        'Enterprise Bot Deployment'
+      ]
+    },
+    difyRag: {
+      title: 'Dify RAG Application',
+      subtitle: 'Knowledge Base Building',
+      items: [
+        'RAG Principle Deep Dive',
+        'Vector Database Configuration',
+        'Prompt Engineering',
+        'Agent Orchestration'
+      ]
+    },
+    enterprise: {
+      title: 'Enterprise Workflow',
+      subtitle: 'Architect Certification',
+      items: [
+        'Enterprise Architecture Design',
+        'Multi-engine Collaboration',
+        'Security & Compliance',
+        'Performance Optimization'
+      ]
+    }
   }
   }
   },
   },
   "reviews": {
   "reviews": {

+ 77 - 6
src/locales/zh-CN.js

@@ -611,7 +611,10 @@ export default {
         "badgeText": "99.9%",
         "badgeText": "99.9%",
         "tags": ["实时监控", "自动告警", "执行日志"]
         "tags": ["实时监控", "自动告警", "执行日志"]
       }
       }
-    }
+    },
+    running: '实时运行中',
+    llmApplication: 'LLM 应用',
+    knowledgeBaseQA: '知识库问答'
   },
   },
   "stats": {
   "stats": {
     "workflowTemplates": "工作流模板",
     "workflowTemplates": "工作流模板",
@@ -637,26 +640,31 @@ export default {
   "cards": {
   "cards": {
     "globalUsers": {
     "globalUsers": {
       "label": "全球用户",
       "label": "全球用户",
-      "sub": "来自 120+ 国家和地区"
+      "sub": "来自 120+ 国家和地区",
+      displayNum: '50,000+'
     },
     },
     "workflowExecutions": {
     "workflowExecutions": {
       "label": "工作流执行",
       "label": "工作流执行",
-      "sub": "累计自动化执行次数"
+      "sub": "累计自动化执行次数",
+      displayNum: '1,200万+'
     },
     },
     "timeSaved": {
     "timeSaved": {
       "label": "节省工时",
       "label": "节省工时",
-      "sub": "用户累计节省的人工时间"
+      "sub": "用户累计节省的人工时间",
+      displayNum: '320万小时'
     },
     },
     "workflowTemplates": {
     "workflowTemplates": {
       "label": "工作流模板",
       "label": "工作流模板",
-      "sub": "社区贡献的精选模板"
+      "sub": "社区贡献的精选模板",
+      displayNum: '8,000+'
     }
     }
   },
   },
   "systemMetrics": {
   "systemMetrics": {
     "uptime": "在线率",
     "uptime": "在线率",
     "peakTraffic": "流量峰值",
     "peakTraffic": "流量峰值",
     "avgResponseTime": "平均响应时间",
     "avgResponseTime": "平均响应时间",
-    "todayExecutions": "今日执行次数"
+    "todayExecutions": "今日执行次数",
+    todayExecutionsValue: '15,750次'
   },
   },
   "flowSteps": {
   "flowSteps": {
     "dataInput": "数据输入",
     "dataInput": "数据输入",
@@ -1135,6 +1143,69 @@ export default {
   },
   },
   "featured": {
   "featured": {
     "title": "精选热门课程"
     "title": "精选热门课程"
+  },
+  levels: {
+    beginner: '入门',
+    intermediate: '中级',
+    advanced: '进阶',
+    senior: '高级',
+    expert: '专家'
+  },
+  unit: {
+    lessons: '节课'
+  },
+  content: '课程内容',
+  paths: {
+    n8nBasic: {
+      title: 'n8n 基础入门',
+      subtitle: '自动化入门',
+      items: [
+        '什么是AI工作流',
+        'n8n 快速入门',
+        '第一个自动化任务',
+        '常见节点使用'
+      ]
+    },
+    n8nAdvanced: {
+      title: 'n8n 进阶实战',
+      subtitle: '自动化专家',
+      items: [
+        '复杂工作流设计',
+        'HTTP 节点深度使用',
+        '错误处理与调试',
+        'API 集成实战'
+      ]
+    },
+    cozeBot: {
+      title: 'Coze Bot 开发',
+      subtitle: 'AI 助手构建',
+      items: [
+        'Coze 平台全解析',
+        '多模型接入',
+        '插件开发',
+        '企业Bot部署'
+      ]
+    },
+    difyRag: {
+      title: 'Dify RAG 应用',
+      subtitle: '知识库构建',
+      items: [
+        'RAG 原理深度解析',
+        '向量数据库配置',
+        'Prompt 工程',
+        'Agent 编排'
+      ]
+    },
+    enterprise: {
+      title: '企业级工作流',
+      subtitle: '架构师认证',
+      items: [
+        '企业架构设计',
+        '多引擎协同',
+        '安全与合规',
+        '性能优化'
+      ]
+    }
   }
   }
   },
   },
   "reviews": {
   "reviews": {

+ 58 - 17
src/pages/Home.vue

@@ -1098,21 +1098,20 @@
                 </svg>
                 </svg>
               </div>
               </div>
               <input
               <input
-                v-model="searchQuery"
+                v-model="workflowTitle"
                 type="text"
                 type="text"
                 :placeholder="$t('home.search.placeholder')"
                 :placeholder="$t('home.search.placeholder')"
                 :aria-label="$t('home.search.ariaLabel')"
                 :aria-label="$t('home.search.ariaLabel')"
                 class="flex-1 py-3.5 text-sm text-slate-700 placeholder-slate-400 outline-none bg-transparent min-w-0"
                 class="flex-1 py-3.5 text-sm text-slate-700 placeholder-slate-400 outline-none bg-transparent min-w-0"
-                @keyup.enter="handleSearch"
               />
               />
               <div class="hidden sm:flex items-center gap-1 px-2 flex-shrink-0">
               <div class="hidden sm:flex items-center gap-1 px-2 flex-shrink-0">
-                <button v-for="p in [$t('home.search.all'), 'n8n', 'Coze', 'Dify']" :key="p"
-                  class="px-2 py-1 text-xs font-semibold rounded-lg transition-all duration-200"
-                  :class="searchPlatform === p ? 'text-white shadow-sm' : 'text-slate-500 hover:bg-slate-100'"
-                  :style="searchPlatform === p ? 'background: linear-gradient(135deg, #3b82f6, #6366f1);' : ''"
-                  @click="searchPlatform = p">{{ p }}</button>
+                <button  v-for="item in categoryListTree" :key="item.categoryId"
+                  class="px-2 py-1 text-xs font-semibold rounded-lg transition-all duration-200 cursor-pointer"
+                  :class="categoryId === item.categoryId ? 'text-white shadow-sm' : 'text-slate-500 hover:bg-slate-100'"
+                  :style="categoryId === item.categoryId ? 'background: linear-gradient(135deg, #3b82f6, #6366f1);' : ''"
+                  @click="activePlatform = item.categoryName; categoryId = item.categoryId; platformUrl = item.categoryUrl;">{{item.categoryName}}</button>
               </div>
               </div>
-              <button @click="handleSearch"
+              <button  @click.stop.prevent="goSearchPlatform"
                 class="m-1.5 px-4 py-2.5 text-sm font-bold text-white rounded-xl transition-all duration-200 hover:shadow-lg hover:-translate-y-0.5 flex-shrink-0"
                 class="m-1.5 px-4 py-2.5 text-sm font-bold text-white rounded-xl transition-all duration-200 hover:shadow-lg hover:-translate-y-0.5 flex-shrink-0"
                 style="background: linear-gradient(135deg, #3b82f6, #6366f1);">
                 style="background: linear-gradient(135deg, #3b82f6, #6366f1);">
                 {{$t('common.shousuo')}}
                 {{$t('common.shousuo')}}
@@ -1121,22 +1120,24 @@
             <!-- 热门搜索标签 -->
             <!-- 热门搜索标签 -->
             <div class="flex items-center gap-2 mt-2.5 justify-center flex-wrap">
             <div class="flex items-center gap-2 mt-2.5 justify-center flex-wrap">
               <span class="text-xs text-slate-400">{{$t('home.search.hot')}}:</span>
               <span class="text-xs text-slate-400">{{$t('home.search.hot')}}:</span>
-              <button v-for="tag in [$t('home.search.tags.aiContent'),$t('home.search.tags.customerService'), $t('home.search.tags.dataReport'), $t('home.search.tags.fgmService'),$t('home.search.tags.emailMarketing'), $t('home.search.tags.socialMedia')]" :key="tag"
-                class="px-2.5 py-1 text-xs text-slate-600 rounded-lg transition-all duration-200 cursor-pointer hover:text-blue-600"
+              <button v-for="tag in hotTagList" :key="tag.dictValue"
+                class="px-2.5 py-1 text-xs text-slate-600 rounded-lg transition-all duration-200 hover:text-blue-600"
                 style="background: rgba(255,255,255,0.65); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border: 1px solid rgba(255,255,255,0.8);"
                 style="background: rgba(255,255,255,0.65); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border: 1px solid rgba(255,255,255,0.8);"
-                @click="searchQuery = tag; handleSearch()">{{ tag }}</button>
+              >{{ tag.dictLabel }}</button>
             </div>
             </div>
           </div>
           </div>
 
 
           <!-- CTA 按鈕 -->
           <!-- CTA 按鈕 -->
           <div class="flex items-center justify-center gap-3 flex-wrap hero-stagger" style="margin-bottom: clamp(4px, 0.8vh, 14px); animation-delay: 0.55s;">
           <div class="flex items-center justify-center gap-3 flex-wrap hero-stagger" style="margin-bottom: clamp(4px, 0.8vh, 14px); animation-delay: 0.55s;">
             <button class="flex items-center gap-2 px-6 py-3 text-sm font-bold text-white rounded-xl shadow-lg transition-all duration-300 hover:shadow-xl hover:-translate-y-1"
             <button class="flex items-center gap-2 px-6 py-3 text-sm font-bold text-white rounded-xl shadow-lg transition-all duration-300 hover:shadow-xl hover:-translate-y-1"
-                    style="background: linear-gradient(135deg, #3b82f6, #6366f1, #8b5cf6);">
+                    @click.stop.prevent="goWorkflowAdd"
+            style="background: linear-gradient(135deg, #3b82f6, #6366f1, #8b5cf6);">
               <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/></svg>
               <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/></svg>
               {{$t('common.chuangjiangongzuoliu')}}
               {{$t('common.chuangjiangongzuoliu')}}
               <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
               <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
             </button>
             </button>
             <button class="flex items-center gap-2 px-6 py-3 text-sm font-bold text-slate-700 rounded-xl transition-all duration-300 hover:text-blue-600 hover:shadow-md hover:-translate-y-1"
             <button class="flex items-center gap-2 px-6 py-3 text-sm font-bold text-slate-700 rounded-xl transition-all duration-300 hover:text-blue-600 hover:shadow-md hover:-translate-y-1"
+                    @click.stop.prevent="goWorkflowMarket"
                     style="background: rgba(255,255,255,0.68); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border: 1px solid rgba(255,255,255,0.85); box-shadow: 0 2px 12px rgba(0,0,0,0.06);">
                     style="background: rgba(255,255,255,0.68); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border: 1px solid rgba(255,255,255,0.85); box-shadow: 0 2px 12px rgba(0,0,0,0.06);">
               <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h8"/></svg>
               <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h8"/></svg>
               {{$t('home.cta.browse')}}
               {{$t('home.cta.browse')}}
@@ -1237,7 +1238,7 @@
             <span class="sticky-cta-logo">⚡</span>
             <span class="sticky-cta-logo">⚡</span>
             <span>{{ $t('home.stickyCta.text') }}</span>
             <span>{{ $t('home.stickyCta.text') }}</span>
           </div>
           </div>
-          <button class="sticky-cta-btn" @click="goWorkflowAdd">
+          <button class="sticky-cta-btn" @click="goWorkflowMarket">
             <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/></svg>
             <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/></svg>
             {{ $t('home.stickyCta.button') }}
             {{ $t('home.stickyCta.button') }}
           </button>
           </button>
@@ -1264,7 +1265,7 @@
 <script setup>
 <script setup>
 import { ref, computed, inject, onMounted, onUnmounted, nextTick } from 'vue';
 import { ref, computed, inject, onMounted, onUnmounted, nextTick } from 'vue';
 import { useRouter } from 'vue-router';
 import { useRouter } from 'vue-router';
-import { isLogin } from '@/utils/util.js';
+import { isLogin, openFullScreenLoading } from '@/utils/util.js'
 import { useI18n } from 'vue-i18n';
 import { useI18n } from 'vue-i18n';
 
 
 import cozeLogo from '@/assets/imgs/coze.png';
 import cozeLogo from '@/assets/imgs/coze.png';
@@ -1286,8 +1287,13 @@ import SectionWorkflowDemo from './Home/SectionWorkflowDemo.vue';
 import SectionWhatIsWorkflow from './Home/SectionWhatIsWorkflow.vue';
 import SectionWhatIsWorkflow from './Home/SectionWhatIsWorkflow.vue';
 import SectionLiveActivity from './Home/SectionLiveActivity.vue';
 import SectionLiveActivity from './Home/SectionLiveActivity.vue';
 
 
+import { getCategoryListTree } from '@/api/category.js'
+import { getDictList } from '@/api/common.js'
+import { getPublishList } from '@/api/publish.js'
+
 const router = useRouter();
 const router = useRouter();
 const { t } = useI18n();
 const { t } = useI18n();
+const categoryListTree = ref([])
 const openLoginDialog = inject('openLoginDialog');
 const openLoginDialog = inject('openLoginDialog');
 
 
 // 当前激活的平台(用于 hover 交互)
 // 当前激活的平台(用于 hover 交互)
@@ -1531,6 +1537,9 @@ onMounted(async () => {
     activeSideNav.value = current;
     activeSideNav.value = current;
   };
   };
   window.addEventListener('scroll', scrollHandler, { passive: true });
   window.addEventListener('scroll', scrollHandler, { passive: true });
+
+  getCategoryListTreeFn();
+  getDictListFn();
 });
 });
 onUnmounted(() => {
 onUnmounted(() => {
   if (heroCarouselTimer) clearInterval(heroCarouselTimer);
   if (heroCarouselTimer) clearInterval(heroCarouselTimer);
@@ -1538,7 +1547,15 @@ onUnmounted(() => {
   window.removeEventListener('resize', calcSvgPaths);
   window.removeEventListener('resize', calcSvgPaths);
   if (scrollHandler) window.removeEventListener('scroll', scrollHandler);
   if (scrollHandler) window.removeEventListener('scroll', scrollHandler);
 });
 });
-
+const getCategoryListTreeFn = () => {
+  getCategoryListTree().then(res => {
+    console.log(res)
+    categoryListTree.value = res.rows || [];
+    activePlatform.value = categoryListTree.value[0]?.categoryName || '';
+    categoryId.value = categoryListTree.value[0]?.categoryId || '';
+    platformUrl.value = categoryListTree.value[0]?.categoryUrl || '';
+  })
+};
 // 搜索 + 分类
 // 搜索 + 分类
 const searchKeyword = ref('');
 const searchKeyword = ref('');
 const activeCategory = ref('all');
 const activeCategory = ref('all');
@@ -1632,16 +1649,40 @@ const reviews = ref([
 
 
 // Hero 搜索
 // Hero 搜索
 const searchQuery = ref('');
 const searchQuery = ref('');
+const workflowTitle = ref('');
 const searchPlatform = ref('全部');
 const searchPlatform = ref('全部');
-const handleSearch = () => { if (searchQuery.value) goSearchPlatform(); };
+const platformUrl = ref('');
+
+const categoryId = ref('');
 
 
 // 跳转方法
 // 跳转方法
-const goSearchPlatform = () => { router.push({ path: '/search-platform', query: { workflowTitle: searchQuery.value || searchKeyword.value } }); };
+const goSearchPlatform = () => {
+  //增加参数名称
+  router.push({
+    path: `/search-platform`,
+    query: {
+      categoryId: categoryId.value,
+      activePlatform: activePlatform.value,
+      metaTitle: activePlatform.value ,
+      workflowTitle: workflowTitle.value,
+      platformUrl:platformUrl.value
+    }
+  })
+};
 const goWorkflowAdd = () => {
 const goWorkflowAdd = () => {
   if (!isLogin({ callback: openLoginDialog, t })) return;
   if (!isLogin({ callback: openLoginDialog, t })) return;
   router.push({ path: 'workflow-add' });
   router.push({ path: 'workflow-add' });
 };
 };
 const goDetail = (item) => { router.push({ path: `/workflow-detail/${item.id}` }); };
 const goDetail = (item) => { router.push({ path: `/workflow-detail/${item.id}` }); };
+const goWorkflowMarket = () => { router.push({ path: '/workflow-trade' }); };
+// 首页第一屏 热门标签
+const hotTagList = ref([])
+const getDictListFn = () => {
+  getDictList({dictType:'bus_hot_word'}).then(res => {
+    console.log('bus_hot_word',res)
+    hotTagList.value = res.rows;
+  })
+}
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 11 - 11
src/pages/Home/SectionAbout.vue

@@ -42,7 +42,7 @@
               </div>
               </div>
               <span class="text-green-600 text-xs font-medium flex items-center gap-1">
               <span class="text-green-600 text-xs font-medium flex items-center gap-1">
                 <span class="w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse"></span>
                 <span class="w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse"></span>
-                实时运行中
+                {{ $t('about.running') }}
               </span>
               </span>
             </div>
             </div>
             <!-- SVG 画布 -->
             <!-- SVG 画布 -->
@@ -98,14 +98,14 @@
                   <circle cx="150" cy="285" r="34" fill="white" stroke="rgba(16,185,129,0.25)" stroke-width="1.5" filter="url(#glow1)"/>
                   <circle cx="150" cy="285" r="34" fill="white" stroke="rgba(16,185,129,0.25)" stroke-width="1.5" filter="url(#glow1)"/>
                   <circle cx="150" cy="285" r="26" fill="rgba(16,185,129,0.08)"/>
                   <circle cx="150" cy="285" r="26" fill="rgba(16,185,129,0.08)"/>
                   <text x="150" y="280" text-anchor="middle" fill="#059669" font-size="12" font-weight="900">Dify</text>
                   <text x="150" y="280" text-anchor="middle" fill="#059669" font-size="12" font-weight="900">Dify</text>
-                  <text x="150" y="296" text-anchor="middle" fill="rgba(5,150,105,0.7)" font-size="8">LLM 应用</text>
+                  <text x="150" y="296" text-anchor="middle" fill="rgba(5,150,105,0.7)" font-size="8"> {{ $t('about.llmApplication') }}</text>
                 </g>
                 </g>
                 <!-- FastGPT 节点 -->
                 <!-- FastGPT 节点 -->
                 <g class="float-node" style="transform-origin: 530px 285px; animation-delay: 2.1s;">
                 <g class="float-node" style="transform-origin: 530px 285px; animation-delay: 2.1s;">
                   <circle cx="530" cy="285" r="34" fill="white" stroke="rgba(245,158,11,0.25)" stroke-width="1.5" filter="url(#glow1)"/>
                   <circle cx="530" cy="285" r="34" fill="white" stroke="rgba(245,158,11,0.25)" stroke-width="1.5" filter="url(#glow1)"/>
                   <circle cx="530" cy="285" r="26" fill="rgba(245,158,11,0.08)"/>
                   <circle cx="530" cy="285" r="26" fill="rgba(245,158,11,0.08)"/>
                   <text x="530" y="278" text-anchor="middle" fill="#d97706" font-size="10" font-weight="900">FastGPT</text>
                   <text x="530" y="278" text-anchor="middle" fill="#d97706" font-size="10" font-weight="900">FastGPT</text>
-                  <text x="530" y="294" text-anchor="middle" fill="rgba(217,119,6,0.7)" font-size="8">知识库问答</text>
+                  <text x="530" y="294" text-anchor="middle" fill="rgba(217,119,6,0.7)" font-size="8">{{ $t('about.knowledgeBaseQA') }}</text>
                 </g>
                 </g>
                 <!-- 浮动数据标签 -->
                 <!-- 浮动数据标签 -->
                 <rect x="240" y="55" width="200" height="28" rx="14" fill="white" stroke="rgba(139,92,246,0.2)" stroke-width="1" filter="url(#glow1)"/>
                 <rect x="240" y="55" width="200" height="28" rx="14" fill="white" stroke="rgba(139,92,246,0.2)" stroke-width="1" filter="url(#glow1)"/>
@@ -147,14 +147,14 @@
               </svg>
               </svg>
             </div>
             </div>
           </div>
           </div>
-          <div class="mt-2 flex gap-3">
-            <button class="flex-1 bg-gradient-to-r from-violet-600 to-blue-600 text-white text-sm font-bold py-3 px-6 rounded-2xl hover:shadow-lg hover:shadow-violet-500/30 transition-all duration-300 hover:-translate-y-0.5 active:scale-95">
-              {{$t('about.experiencePlatform')}} →
-            </button>
-            <button class="px-5 py-3 rounded-2xl border border-gray-200 text-gray-600 text-sm font-medium hover:border-violet-300 hover:text-violet-600 transition-all duration-300 active:scale-95">
-              {{$t('about.viewCases')}}
-            </button>
-          </div>
+<!--          <div class="mt-2 flex gap-3">-->
+<!--            <button class="flex-1 bg-gradient-to-r from-violet-600 to-blue-600 text-white text-sm font-bold py-3 px-6 rounded-2xl hover:shadow-lg hover:shadow-violet-500/30 transition-all duration-300 hover:-translate-y-0.5 active:scale-95">-->
+<!--              {{$t('about.experiencePlatform')}} →-->
+<!--            </button>-->
+<!--            <button class="px-5 py-3 rounded-2xl border border-gray-200 text-gray-600 text-sm font-medium hover:border-violet-300 hover:text-violet-600 transition-all duration-300 active:scale-95">-->
+<!--              {{$t('about.viewCases')}}-->
+<!--            </button>-->
+<!--          </div>-->
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>

+ 15 - 4
src/pages/Home/SectionCTA.vue

@@ -63,7 +63,7 @@
       <!-- 按钮组 -->
       <!-- 按钮组 -->
       <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;">
       <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;">
         <!-- 主按钮 -->
         <!-- 主按钮 -->
-        <button class="cta-btn-primary group" @mouseenter="primaryHover = true" @mouseleave="primaryHover = false">
+        <button class="cta-btn-primary group" @mouseenter="primaryHover = true" @mouseleave="primaryHover = false" @click="goWorkflowMarket">
           <div class="cta-btn-shine" :class="{ 'cta-btn-shine-active': primaryHover }"></div>
           <div class="cta-btn-shine" :class="{ 'cta-btn-shine-active': primaryHover }"></div>
           <span class="relative z-10 flex items-center gap-2">
           <span class="relative z-10 flex items-center gap-2">
             <span>🚀</span>
             <span>🚀</span>
@@ -72,7 +72,7 @@
         </button>
         </button>
 
 
         <!-- 次按钮 -->
         <!-- 次按钮 -->
-        <button class="cta-btn-secondary group">
+        <button class="cta-btn-secondary group" @click="goDetail">
           <div class="cta-btn-play">
           <div class="cta-btn-play">
             <svg class="w-4 h-4 ml-0.5" fill="currentColor" viewBox="0 0 20 20">
             <svg class="w-4 h-4 ml-0.5" fill="currentColor" viewBox="0 0 20 20">
               <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"/>
               <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"/>
@@ -102,10 +102,13 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { ref, onMounted } from 'vue'
+import {ref, onMounted, inject} from 'vue'
 import { useI18n } from 'vue-i18n'
 import { useI18n } from 'vue-i18n'
-
+import { useRouter } from 'vue-router'
+import {isLogin} from "@/utils/util.js";
+const router = useRouter()
 const { t } = useI18n()
 const { t } = useI18n()
+const openLoginDialog = inject('openLoginDialog')
 const isVisible = ref(false)
 const isVisible = ref(false)
 const ctaRef = ref(null)
 const ctaRef = ref(null)
 const primaryHover = ref(false)
 const primaryHover = ref(false)
@@ -147,6 +150,14 @@ const bottomStats = [
   { value: '99.9%', key: 'uptime', color: '#34d399' },
   { value: '99.9%', key: 'uptime', color: '#34d399' },
   { value: '4.9★', key: 'userRating', color: '#fbbf24' }
   { value: '4.9★', key: 'userRating', color: '#fbbf24' }
 ]
 ]
+const goWorkflowMarket = () => { router.push({ path: '/workflow-trade' }); };
+const goDetail = () => {
+  if (!isLogin({ callback: openLoginDialog, t })) return
+  router.push({
+    path: `/learning-system/detail/1`,
+    query: { courseId: 1 }
+  })
+}
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 120 - 84
src/pages/Home/SectionCourses.vue

@@ -75,22 +75,22 @@
                   <span class="text-xs font-bold text-gray-700">{{ path.progress }}%</span>
                   <span class="text-xs font-bold text-gray-700">{{ path.progress }}%</span>
                 </div>
                 </div>
               </div>
               </div>
-              <div class="text-gray-500 text-xs">{{ path.courseCount }} 节课</div>
+              <div class="text-gray-500 text-xs">{{ path.courseCount }} {{ $t('courses.unit.lessons') }}</div>
 
 
               <!-- 展开内容 -->
               <!-- 展开内容 -->
               <Transition name="expand">
               <Transition name="expand">
                 <div v-if="activePath === idx" class="mt-4 w-full text-left border-t border-gray-100 pt-4">
                 <div v-if="activePath === idx" class="mt-4 w-full text-left border-t border-gray-100 pt-4">
-                  <div class="text-xs text-gray-400 mb-2 font-medium">课程内容</div>
+                  <div class="text-xs text-gray-400 mb-2 font-medium">{{ $t('courses.content') }}</div>
                   <div class="space-y-1.5">
                   <div class="space-y-1.5">
                     <div v-for="item in path.items" :key="item" class="flex items-center gap-2 text-xs text-gray-700">
                     <div v-for="item in path.items" :key="item" class="flex items-center gap-2 text-xs text-gray-700">
                       <span class="w-1.5 h-1.5 rounded-full flex-shrink-0" :class="`bg-${path.color}-400`"></span>
                       <span class="w-1.5 h-1.5 rounded-full flex-shrink-0" :class="`bg-${path.color}-400`"></span>
                       {{ item }}
                       {{ item }}
                     </div>
                     </div>
                   </div>
                   </div>
-                  <button class="mt-3 w-full text-xs font-bold py-2 rounded-xl transition-all duration-200"
+                  <!-- <button class="mt-3 w-full text-xs font-bold py-2 rounded-xl transition-all duration-200"
                     :class="path.btnClass">
                     :class="path.btnClass">
                     {{ $t('courses.cta.startLearning') }} →
                     {{ $t('courses.cta.startLearning') }} →
-                  </button>
+                  </button> -->
                 </div>
                 </div>
               </Transition>
               </Transition>
             </div>
             </div>
@@ -109,20 +109,20 @@
             class="group relative bg-white border border-gray-100 rounded-2xl overflow-hidden hover:border-amber-300 shadow-sm hover:-translate-y-1 transition-all duration-300 cursor-pointer">
             class="group relative bg-white border border-gray-100 rounded-2xl overflow-hidden hover:border-amber-300 shadow-sm hover:-translate-y-1 transition-all duration-300 cursor-pointer">
             <!-- 封面 -->
             <!-- 封面 -->
             <div class="relative h-36 overflow-hidden">
             <div class="relative h-36 overflow-hidden">
-              <img :src="course.img" :alt="course.title" class="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700 opacity-90 group-hover:opacity-100"/>
+              <img :src="course.coverImageUrl" :alt="course.courseTitle" class="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700 opacity-90 group-hover:opacity-100"/>
               <div class="absolute inset-0 bg-gradient-to-t from-gray-800/60 to-transparent"></div>
               <div class="absolute inset-0 bg-gradient-to-t from-gray-800/60 to-transparent"></div>
               <!-- 难度 -->
               <!-- 难度 -->
-              <div class="absolute top-3 left-3 text-xs font-bold px-2.5 py-1 rounded-full" :class="course.levelClass">{{ course.level }}</div>
+              <div class="absolute top-3 left-3 text-xs font-bold px-2.5 py-1 rounded-full" :class="course.levelClass">{{ course.studyStageName }}</div>
               <!-- 引擎标签 -->
               <!-- 引擎标签 -->
-              <div class="absolute top-3 right-3 text-xs font-bold px-2.5 py-1 rounded-full bg-gray-900/80 text-gray-300 border border-gray-700">{{ course.engine }}</div>
+              <div class="absolute top-3 right-3 text-xs font-bold px-2.5 py-1 rounded-full bg-gray-900/80 text-gray-300 border border-gray-700">{{ course.skillTagName }}</div>
             </div>
             </div>
             <!-- 信息 -->
             <!-- 信息 -->
             <div class="p-4">
             <div class="p-4">
-              <div class="text-gray-900 text-sm font-bold mb-1 line-clamp-2">{{ course.title }}</div>
+              <div class="text-gray-900 text-sm font-bold mb-1 line-clamp-2">{{ course.courseTitle }}</div>
               <!-- 成果标签 -->
               <!-- 成果标签 -->
-              <div v-if="course.badge" class="inline-flex items-center gap-1 text-xs font-bold px-2 py-0.5 rounded-full mb-2" :class="course.badgeClass">
-                <span>{{ course.badgeIcon }}</span>
-                <span>{{ course.badge }}</span>
+              <div v-if="course.courseIntro" class="inline-flex items-center gap-1 text-xs font-bold px-2 py-0.5 rounded-full mb-2" :class="course.badgeClass">
+<!--                <span>{{ course.badgeIcon }}</span>-->
+                <span>{{ course.courseIntro }}</span>
               </div>
               </div>
               <div class="flex items-center justify-between mt-2">
               <div class="flex items-center justify-between mt-2">
                 <div class="flex items-center gap-1.5">
                 <div class="flex items-center gap-1.5">
@@ -136,19 +136,27 @@
               </div>
               </div>
               <div class="flex items-center justify-between mt-2">
               <div class="flex items-center justify-between mt-2">
                 <div class="flex items-center gap-1">
                 <div class="flex items-center gap-1">
-                  <span class="text-gray-500 text-xs">{{ course.students }} 人学习</span>
+                  <span class="text-gray-500 text-xs">{{ course.viewCount|| 0 }}  {{ $t('common.renkanguo') }}</span>
                   <!-- 学员头像堆叠 -->
                   <!-- 学员头像堆叠 -->
-                  <div class="flex -space-x-1 ml-1">
-                    <div v-for="n in 3" :key="n" class="w-4 h-4 rounded-full bg-gradient-to-br from-violet-400 to-indigo-500 border border-white text-white text-xs flex items-center justify-center" style="font-size:8px">{{ n }}</div>
+                  <div class="flex -space-x-1 ml-1" v-if="(course.viewCount || 0) > 0">
+                    <div 
+                      v-for="n in Math.min(3, course.viewCount || 0)" 
+                      :key="n" 
+                      class="w-4 h-4 rounded-full bg-gradient-to-br from-violet-400 to-indigo-500 border border-white text-white text-xs flex items-center justify-center"
+                      style="font-size:8px"
+                    >
+                      <img :src="avatars[n - 1]" class="w-5 h-5 rounded-full object-cover"/>
+                    </div>
+                    
                   </div>
                   </div>
                 </div>
                 </div>
-                <span class="text-xs font-bold" :class="course.free ? 'text-green-500' : 'text-amber-500'">{{ course.price }}</span>
+                <span class="text-xs font-bold" :class="course.free ? 'text-green-500' : 'text-amber-500'">{{ course.coursePrice }}</span>
               </div>
               </div>
               <!-- 进度条 -->
               <!-- 进度条 -->
               <div class="mt-3">
               <div class="mt-3">
-                <div class="flex items-center justify-between mb-1">
-                  <span class="text-gray-400 text-xs">{{ course.outcome }}</span>
-                </div>
+<!--                <div class="flex items-center justify-between mb-1">-->
+<!--                  <span class="text-gray-400 text-xs">{{ course.courseIntro }}</span>-->
+<!--                </div>-->
                 <div class="h-1 bg-gray-100 rounded-full overflow-hidden">
                 <div class="h-1 bg-gray-100 rounded-full overflow-hidden">
                   <div class="h-full rounded-full transition-all duration-700 bg-gradient-to-r from-amber-400 to-orange-400" :style="{ width: course.completionRate + '%' }"></div>
                   <div class="h-full rounded-full transition-all duration-700 bg-gradient-to-r from-amber-400 to-orange-400" :style="{ width: course.completionRate + '%' }"></div>
                 </div>
                 </div>
@@ -156,7 +164,7 @@
             </div>
             </div>
             <!-- Hover 立即开始按钒 -->
             <!-- Hover 立即开始按钒 -->
             <div class="absolute inset-0 bg-gradient-to-t from-gray-900/80 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end justify-center pb-4">
             <div class="absolute inset-0 bg-gradient-to-t from-gray-900/80 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end justify-center pb-4">
-              <button class="bg-amber-400 text-gray-900 text-xs font-bold px-5 py-2 rounded-full shadow-lg transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300">
+              <button class="bg-amber-400 text-gray-900 text-xs font-bold px-5 py-2 rounded-full shadow-lg transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300" @click="goDetail(course)">
                 {{ $t('courses.cta.startLearningNow') }} →
                 {{ $t('courses.cta.startLearningNow') }} →
               </button>
               </button>
             </div>
             </div>
@@ -168,18 +176,20 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { ref } from 'vue'
+import {ref , onMounted, reactive} from 'vue'
 import { useI18n } from 'vue-i18n'
 import { useI18n } from 'vue-i18n'
-
+import { getCourseList } from '@/api/course.js'
 const { t } = useI18n()
 const { t } = useI18n()
+import { useRouter } from 'vue-router'
+const router = useRouter()
 const activePath = ref(null)
 const activePath = ref(null)
 
 
-const learningPaths = [
+const learningPaths = ref([
   {
   {
     icon: '🌱',
     icon: '🌱',
-    title: 'AI 工作流入门',
-    subtitle: '零基础启蒙',
-    level: '入门',
+    title: t('courses.paths.n8nBasic.title'),
+    subtitle: t('courses.paths.n8nBasic.subtitle'),
+    level: t('courses.levels.beginner'),
     levelClass: 'bg-green-500/20 text-green-400 border-green-500/30',
     levelClass: 'bg-green-500/20 text-green-400 border-green-500/30',
     color: 'green',
     color: 'green',
     progress: 100,
     progress: 100,
@@ -187,14 +197,14 @@ const learningPaths = [
     courseCount: 12,
     courseCount: 12,
     iconBg: 'bg-green-500/20',
     iconBg: 'bg-green-500/20',
     iconActiveBg: 'bg-green-500/30',
     iconActiveBg: 'bg-green-500/30',
-    items: ['什么是AI工作流', 'n8n 快速入门', '第一个自动化任务', '常见节点使用'],
+    items: [t('courses.paths.n8nBasic.items.0'), t('courses.paths.n8nBasic.items.1'), t('courses.paths.n8nBasic.items.2'), t('courses.paths.n8nBasic.items.3')],
     btnClass: 'bg-green-500/20 text-green-400 hover:bg-green-500/30'
     btnClass: 'bg-green-500/20 text-green-400 hover:bg-green-500/30'
   },
   },
   {
   {
     icon: '⚡',
     icon: '⚡',
-    title: 'n8n 进阶实战',
-    subtitle: '自动化专家',
-    level: '进阶',
+    title: t('courses.paths.n8nAdvanced.title'),
+    subtitle: t('courses.paths.n8nAdvanced.subtitle'),
+    level: t('courses.levels.advanced'),
     levelClass: 'bg-violet-500/20 text-violet-400 border-violet-500/30',
     levelClass: 'bg-violet-500/20 text-violet-400 border-violet-500/30',
     color: 'violet',
     color: 'violet',
     progress: 78,
     progress: 78,
@@ -202,14 +212,14 @@ const learningPaths = [
     courseCount: 24,
     courseCount: 24,
     iconBg: 'bg-violet-500/20',
     iconBg: 'bg-violet-500/20',
     iconActiveBg: 'bg-violet-500/30',
     iconActiveBg: 'bg-violet-500/30',
-    items: ['复杂工作流设计', 'HTTP 节点深度使用', '错误处理与调试', 'API 集成实战'],
+    items: [t('courses.paths.n8nAdvanced.items.0'), t('courses.paths.n8nAdvanced.items.1'), t('courses.paths.n8nAdvanced.items.2'), t('courses.paths.n8nAdvanced.items.3')],
     btnClass: 'bg-violet-500/20 text-violet-400 hover:bg-violet-500/30'
     btnClass: 'bg-violet-500/20 text-violet-400 hover:bg-violet-500/30'
   },
   },
   {
   {
     icon: '🤖',
     icon: '🤖',
-    title: 'Coze Bot 开发',
-    subtitle: 'AI 助手构建',
-    level: '中级',
+    title: t('courses.paths.cozeBot.title'),
+    subtitle: t('courses.paths.cozeBot.subtitle'),
+    level: t('courses.levels.intermediate'),
     levelClass: 'bg-blue-500/20 text-blue-400 border-blue-500/30',
     levelClass: 'bg-blue-500/20 text-blue-400 border-blue-500/30',
     color: 'blue',
     color: 'blue',
     progress: 65,
     progress: 65,
@@ -217,14 +227,14 @@ const learningPaths = [
     courseCount: 18,
     courseCount: 18,
     iconBg: 'bg-blue-500/20',
     iconBg: 'bg-blue-500/20',
     iconActiveBg: 'bg-blue-500/30',
     iconActiveBg: 'bg-blue-500/30',
-    items: ['Coze 平台全解析', '多模型接入', '插件开发', '企业Bot部署'],
+    items: [t('courses.paths.cozeBot.items.0'), t('courses.paths.cozeBot.items.1'), t('courses.paths.cozeBot.items.2'), t('courses.paths.cozeBot.items.3')],
     btnClass: 'bg-blue-500/20 text-blue-400 hover:bg-blue-500/30'
     btnClass: 'bg-blue-500/20 text-blue-400 hover:bg-blue-500/30'
   },
   },
   {
   {
     icon: '🧠',
     icon: '🧠',
-    title: 'Dify RAG 应用',
-    subtitle: '知识库构建',
-    level: '高级',
+    title: t('courses.paths.difyRag.title'),
+    subtitle: t('courses.paths.difyRag.subtitle'),
+    level: t('courses.paths.difyRag.subtitle'),
     levelClass: 'bg-emerald-500/20 text-emerald-400 border-emerald-500/30',
     levelClass: 'bg-emerald-500/20 text-emerald-400 border-emerald-500/30',
     color: 'emerald',
     color: 'emerald',
     progress: 45,
     progress: 45,
@@ -232,14 +242,14 @@ const learningPaths = [
     courseCount: 20,
     courseCount: 20,
     iconBg: 'bg-emerald-500/20',
     iconBg: 'bg-emerald-500/20',
     iconActiveBg: 'bg-emerald-500/30',
     iconActiveBg: 'bg-emerald-500/30',
-    items: ['RAG 原理深度解析', '向量数据库配置', 'Prompt 工程', 'Agent 编排'],
+    items: [t('courses.paths.difyRag.items.0'), t('courses.paths.difyRag.items.1'), t('courses.paths.difyRag.items.2'), t('courses.paths.difyRag.items.3')],
     btnClass: 'bg-emerald-500/20 text-emerald-400 hover:bg-emerald-500/30'
     btnClass: 'bg-emerald-500/20 text-emerald-400 hover:bg-emerald-500/30'
   },
   },
   {
   {
     icon: '🏆',
     icon: '🏆',
-    title: '企业级工作流',
-    subtitle: '架构师认证',
-    level: '专家',
+    title: t('courses.paths.enterprise.title'),
+    subtitle: t('courses.paths.enterprise.subtitle'),
+    level: t('courses.levels.expert'),
     levelClass: 'bg-amber-500/20 text-amber-400 border-amber-500/30',
     levelClass: 'bg-amber-500/20 text-amber-400 border-amber-500/30',
     color: 'amber',
     color: 'amber',
     progress: 30,
     progress: 30,
@@ -247,53 +257,79 @@ const learningPaths = [
     courseCount: 32,
     courseCount: 32,
     iconBg: 'bg-amber-500/20',
     iconBg: 'bg-amber-500/20',
     iconActiveBg: 'bg-amber-500/30',
     iconActiveBg: 'bg-amber-500/30',
-    items: ['企业架构设计', '多引擎协同', '安全与合规', '性能优化'],
+    items: [t('courses.paths.enterprise.items.0'), t('courses.paths.enterprise.items.1'), t('courses.paths.enterprise.items.2'), t('courses.paths.enterprise.items.3')],
     btnClass: 'bg-amber-500/20 text-amber-400 hover:bg-amber-500/30'
     btnClass: 'bg-amber-500/20 text-amber-400 hover:bg-amber-500/30'
   }
   }
-]
+])
 
 
-const featuredCourses = [
-  {
-    title: 'n8n 从零到精通:构建你的第一个 AI 自动化工作流',
-    img: 'https://images.unsplash.com/photo-1518770660439-4636190af475?w=400&h=250&fit=crop&q=80',
-    level: '入门', levelClass: 'bg-green-500/80 text-white',
-    engine: 'n8n',
-    teacher: '暴米讲师', avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&h=40&fit=crop',
-    rating: '4.9', students: '12,500', price: '免费', free: true,
-    badge: '最受欢迎', badgeIcon: '🔥', badgeClass: 'bg-orange-100 text-orange-600',
-    outcome: '完成后可独立构建工作流', completionRate: 92
-  },
-  {
-    title: 'Coze 智能 Bot 开发:从对话到多模态 AI 助手',
-    img: 'https://images.unsplash.com/photo-1677442135703-1787eea5ce01?w=400&h=250&fit=crop&q=80',
-    level: '中级', levelClass: 'bg-blue-500/80 text-white',
-    engine: 'Coze',
-    teacher: 'AI 导师', avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=40&h=40&fit=crop',
-    rating: '4.8', students: '8,200', price: '¥199', free: false,
-    badge: '新人首选', badgeIcon: '⭐', badgeClass: 'bg-blue-100 text-blue-600',
-    outcome: '掌握 Bot 开发全流程', completionRate: 78
-  },
-  {
-    title: 'Dify RAG 知识库:让 AI 精准回答你的业务问题',
-    img: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=400&h=250&fit=crop&q=80',
-    level: '高级', levelClass: 'bg-emerald-500/80 text-white',
-    engine: 'Dify',
-    teacher: '技术专家', avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&h=40&fit=crop',
-    rating: '4.9', students: '5,600', price: '¥299', free: false,
-    badge: '高分好评', badgeIcon: '🏆', badgeClass: 'bg-emerald-100 text-emerald-600',
-    outcome: '构建企业级知识问答系统', completionRate: 85
-  },
-  {
-    title: 'FastGPT 企业知识库:私有化部署与高精度问答',
-    img: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=400&h=250&fit=crop&q=80',
-    level: '专家', levelClass: 'bg-amber-500/80 text-white',
-    engine: 'FastGPT',
-    teacher: '架构师', avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&h=40&fit=crop',
-    rating: '4.7', students: '3,800', price: '¥399', free: false,
-    badge: '企业首选', badgeIcon: '🏢', badgeClass: 'bg-amber-100 text-amber-600',
-    outcome: '私有化部署全掌握', completionRate: 70
+const featuredCourses = ref([
+  // {
+  //   title: 'n8n 从零到精通:构建你的第一个 AI 自动化工作流',
+  //   img: 'https://images.unsplash.com/photo-1518770660439-4636190af475?w=400&h=250&fit=crop&q=80',
+  //   level: '入门', levelClass: 'bg-green-500/80 text-white',
+  //   engine: 'n8n',
+  //   teacher: '暴米讲师', avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&h=40&fit=crop',
+  //   rating: '4.9', students: '12,500', price: '免费', free: true,
+  //   badge: '最受欢迎', badgeIcon: '🔥', badgeClass: 'bg-orange-100 text-orange-600',
+  //   outcome: '完成后可独立构建工作流', completionRate: 92
+  // },
+  // {
+  //   title: 'Coze 智能 Bot 开发:从对话到多模态 AI 助手',
+  //   img: 'https://images.unsplash.com/photo-1677442135703-1787eea5ce01?w=400&h=250&fit=crop&q=80',
+  //   level: '中级', levelClass: 'bg-blue-500/80 text-white',
+  //   engine: 'Coze',
+  //   teacher: 'AI 导师', avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=40&h=40&fit=crop',
+  //   rating: '4.8', students: '8,200', price: '¥199', free: false,
+  //   badge: '新人首选', badgeIcon: '⭐', badgeClass: 'bg-blue-100 text-blue-600',
+  //   outcome: '掌握 Bot 开发全流程', completionRate: 78
+  // },
+  // {
+  //   title: 'Dify RAG 知识库:让 AI 精准回答你的业务问题',
+  //   img: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=400&h=250&fit=crop&q=80',
+  //   level: '高级', levelClass: 'bg-emerald-500/80 text-white',
+  //   engine: 'Dify',
+  //   teacher: '技术专家', avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&h=40&fit=crop',
+  //   rating: '4.9', students: '5,600', price: '¥299', free: false,
+  //   badge: '高分好评', badgeIcon: '🏆', badgeClass: 'bg-emerald-100 text-emerald-600',
+  //   outcome: '构建企业级知识问答系统', completionRate: 85
+  // },
+  // {
+  //   title: 'FastGPT 企业知识库:私有化部署与高精度问答',
+  //   img: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=400&h=250&fit=crop&q=80',
+  //   level: '专家', levelClass: 'bg-amber-500/80 text-white',
+  //   engine: 'FastGPT',
+  //   teacher: '架构师', avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&h=40&fit=crop',
+  //   rating: '4.7', students: '3,800', price: '¥399', free: false,
+  //   badge: '企业首选', badgeIcon: '🏢', badgeClass: 'bg-amber-100 text-amber-600',
+  //   outcome: '私有化部署全掌握', completionRate: 70
+  // }
+])
+const avatars = ref(['https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&h=40&fit=crop','https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&h=40&fit=crop','https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=40&h=40&fit=crop'])
+const searchFom = reactive({
+  skillTag: '',
+  pageNum: 1,
+  pageSize: 4,
+})
+
+const getList = async (type) => {
+  const res = await getCourseList(searchFom)
+  if(res.code === 200){
+    featuredCourses.value = res.rows || [];
   }
   }
-]
+};
+const goDetail = (item) => {
+  //增加参数名称
+  router.push({
+    path: `/learning-system/detail/${item.courseId}`,
+    query: {
+      courseId: item.courseId,
+      metaTitle: item.courseTitle || '课程详情'
+    }
+  })
+};
+onMounted(() => {
+  getList();
+})
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 188 - 103
src/pages/Home/SectionHotWorkflows.vue

@@ -13,7 +13,7 @@
     <div class="scroll-track-wrapper">
     <div class="scroll-track-wrapper">
       <div class="scroll-track track-forward" ref="track1" @mouseenter="pauseTrack1 = true" @mouseleave="pauseTrack1 = false">
       <div class="scroll-track track-forward" ref="track1" @mouseenter="pauseTrack1 = true" @mouseleave="pauseTrack1 = false">
         <div
         <div
-          v-for="(wf, i) in [...workflows, ...workflows]"
+          v-for="(wf, i) in displayWorkflows"
           :key="'a' + i"
           :key="'a' + i"
           class="workflow-card"
           class="workflow-card"
           @mouseenter="hoveredCard = 'a' + i"
           @mouseenter="hoveredCard = 'a' + i"
@@ -24,29 +24,29 @@
             <img :src="wf.coverImage" :alt="wf.title" class="cover-img" />
             <img :src="wf.coverImage" :alt="wf.title" class="cover-img" />
             <div class="cover-overlay"></div>
             <div class="cover-overlay"></div>
             <!-- 平台标签 -->
             <!-- 平台标签 -->
-            <div class="platform-chip" :style="{ background: wf.platformColor }">{{ wf.platform }}</div>
+            <div class="platform-chip" :style="{ background: wf.platformColor }">{{ wf.categoryName1 }}</div>
             <!-- 播放量 -->
             <!-- 播放量 -->
-            <div class="view-count">▶ {{ wf.views }}</div>
+            <div class="view-count">▶ {{ wf.downCount }}</div>
           </div>
           </div>
           <!-- 卡片内容 -->
           <!-- 卡片内容 -->
           <div class="card-info">
           <div class="card-info">
             <div class="card-title-row">
             <div class="card-title-row">
-              <h4 class="card-title">{{ wf.title }}</h4>
-              <div class="card-rating">⭐{{ wf.rating }}</div>
+              <h4 class="card-title">{{ wf.workflowTitle }}</h4>
+<!--              <div class="card-rating">⭐{{ wf.rating }}</div>-->
             </div>
             </div>
-            <p class="card-desc">{{ wf.desc }}</p>
+            <p class="card-desc">{{ wf.description }}</p>
             <div class="card-footer">
             <div class="card-footer">
               <div class="author-info">
               <div class="author-info">
-                <img :src="wf.authorAvatar" :alt="wf.author" class="author-avatar" />
-                <span class="author-name">{{ wf.author }}</span>
+                <img :src="wf.userAvatar" :alt="wf.nickName" class="author-avatar" />
+                <span class="author-name">{{ wf.nickName }}</span>
               </div>
               </div>
               <span class="card-category">{{ wf.category }}</span>
               <span class="card-category">{{ wf.category }}</span>
             </div>
             </div>
           </div>
           </div>
           <!-- 悬停操作 -->
           <!-- 悬停操作 -->
           <div class="card-hover-actions" :class="{ visible: hoveredCard === 'a' + i }">
           <div class="card-hover-actions" :class="{ visible: hoveredCard === 'a' + i }">
-            <button class="action-btn primary">立即使用</button>
-            <button class="action-btn secondary">预览</button>
+            <button class="action-btn primary" @click="handleUseClick($event, wf)">{{ $t('hotWorkflows.cta.use') }}</button>
+            <button class="action-btn secondary" @click="handlePreviewClick($event, wf)">{{ $t('hotWorkflows.cta.preview') }}</button>
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
@@ -56,7 +56,7 @@
     <div class="scroll-track-wrapper">
     <div class="scroll-track-wrapper">
       <div class="scroll-track track-reverse" ref="track2" @mouseenter="pauseTrack2 = true" @mouseleave="pauseTrack2 = false">
       <div class="scroll-track track-reverse" ref="track2" @mouseenter="pauseTrack2 = true" @mouseleave="pauseTrack2 = false">
         <div
         <div
-          v-for="(wf, i) in [...workflowsB, ...workflowsB]"
+          v-for="(wf, i) in displayWorkflowsB"
           :key="'b' + i"
           :key="'b' + i"
           class="workflow-card"
           class="workflow-card"
           @mouseenter="hoveredCard = 'b' + i"
           @mouseenter="hoveredCard = 'b' + i"
@@ -65,26 +65,26 @@
           <div class="card-cover">
           <div class="card-cover">
             <img :src="wf.coverImage" :alt="wf.title" class="cover-img" />
             <img :src="wf.coverImage" :alt="wf.title" class="cover-img" />
             <div class="cover-overlay"></div>
             <div class="cover-overlay"></div>
-            <div class="platform-chip" :style="{ background: wf.platformColor }">{{ wf.platform }}</div>
-            <div class="view-count">▶ {{ wf.views }}</div>
+            <div class="platform-chip" :style="{ background: wf.platformColor }">{{ wf.categoryName1 }}</div>
+            <div class="view-count">▶ {{ wf.downCount }}</div>
           </div>
           </div>
           <div class="card-info">
           <div class="card-info">
             <div class="card-title-row">
             <div class="card-title-row">
-              <h4 class="card-title">{{ wf.title }}</h4>
-              <div class="card-rating">⭐{{ wf.rating }}</div>
+              <h4 class="card-title">{{ wf.workflowTitle }}</h4>
+<!--              <div class="card-rating">⭐{{ wf.rating }}</div>-->
             </div>
             </div>
-            <p class="card-desc">{{ wf.desc }}</p>
+            <p class="card-desc">{{ wf.description }}</p>
             <div class="card-footer">
             <div class="card-footer">
               <div class="author-info">
               <div class="author-info">
-                <img :src="wf.authorAvatar" :alt="wf.author" class="author-avatar" />
-                <span class="author-name">{{ wf.author }}</span>
+                <img :src="wf.userAvatar" :alt="wf.nickName" class="author-avatar" />
+                <span class="author-name">{{ wf.nickName }}</span>
               </div>
               </div>
-              <span class="card-category">{{ wf.category }}</span>
+              <span class="card-category">{{ wf.categoryName2 }}</span>
             </div>
             </div>
           </div>
           </div>
           <div class="card-hover-actions" :class="{ visible: hoveredCard === 'b' + i }">
           <div class="card-hover-actions" :class="{ visible: hoveredCard === 'b' + i }">
-            <button class="action-btn primary">{{ $t('hotWorkflows.cta.use') }}</button>
-            <button class="action-btn secondary">{{ $t('hotWorkflows.cta.preview') }}</button>
+            <button class="action-btn primary" @click="handleUseClick($event, wf)">{{ $t('hotWorkflows.cta.use') }}</button>
+            <button class="action-btn secondary" @click="handlePreviewClick($event, wf)">{{ $t('hotWorkflows.cta.preview') }}</button>
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
@@ -93,147 +93,232 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { ref } from 'vue'
+import {onMounted, reactive, ref, computed, inject} from 'vue'
 import { useI18n } from 'vue-i18n'
 import { useI18n } from 'vue-i18n'
-
+import { useRouter } from 'vue-router'
+import { getPublishList } from '@/api/publish.js'
+import {isLogin, openNewTab} from "@/utils/util.js";
 const { t } = useI18n()
 const { t } = useI18n()
+const router = useRouter()
 const hoveredCard = ref(null)
 const hoveredCard = ref(null)
 const pauseTrack1 = ref(false)
 const pauseTrack1 = ref(false)
 const pauseTrack2 = ref(false)
 const pauseTrack2 = ref(false)
 
 
 const workflows = [
 const workflows = [
   {
   {
-    title: 'AI 文章批量生产流水线', platform: 'n8n', platformColor: '#EA4B71',
-    rating: '4.9', views: '12.3K', category: '内容创作',
-    desc: '一键生成高质量文章,自动配图排版,多平台发布',
-    author: 'Alex Chen',
-    authorAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&q=80',
+    workflowTitle: 'AI 文章批量生产流水线', categoryName1: 'n8n', platformColor: '#EA4B71',
+    rating: '4.9', downCount: '12.3K', categoryName2: '内容创作',
+    description: '一键生成高质量文章,自动配图排版,多平台发布',
+    nickName: 'Alex Chen',
+    userAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1499750310107-5fef28a66643?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1499750310107-5fef28a66643?w=300&q=80'
   },
   },
   {
   {
-    title: 'GPT-4 智能客服机器人', platform: 'Coze', platformColor: '#1B6EF3',
-    rating: '4.8', views: '8.7K', category: '客服自动化',
-    desc: '基于知识库的智能问答,支持多轮对话和情感识别',
-    author: 'Sarah Liu',
-    authorAvatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=40&q=80',
+    workflowTitle: 'GPT-4 智能客服机器人', categoryName1: 'Coze', platformColor: '#1B6EF3',
+    rating: '4.8', downCount: '8.7K', categoryName2: '客服自动化',
+    description: '基于知识库的智能问答,支持多轮对话和情感识别',
+    nickName: 'Sarah Liu',
+    userAvatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=300&q=80'
   },
   },
   {
   {
-    title: '企业知识库问答系统', platform: 'FastGPT', platformColor: '#059669',
-    rating: '5.0', views: '15.2K', category: '知识管理',
-    desc: '多格式文档导入,精准语义检索,企业知识管理',
-    author: 'Mike Wang',
-    authorAvatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&q=80',
+    workflowTitle: '企业知识库问答系统', categoryName1: 'FastGPT', platformColor: '#059669',
+    rating: '5.0', downCount: '15.2K', categoryName2: '知识管理',
+    description: '多格式文档导入,精准语义检索,企业知识管理',
+    nickName: 'Mike Wang',
+    userAvatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=300&q=80'
   },
   },
   {
   {
-    title: '数据报告自动生成', platform: 'Dify', platformColor: '#7C3AED',
-    rating: '4.7', views: '6.4K', category: '数据分析',
-    desc: '连接多数据源,自动分析可视化,定时推送报告',
-    author: 'Lisa Zhang',
-    authorAvatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=40&q=80',
+    workflowTitle: '数据报告自动生成', categoryName1: 'Dify', platformColor: '#7C3AED',
+    rating: '4.7', downCount: '6.4K', categoryName2: '数据分析',
+    description: '连接多数据源,自动分析可视化,定时推送报告',
+    nickName: 'Lisa Zhang',
+    userAvatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=300&q=80'
   },
   },
   {
   {
-    title: '社交媒体内容矩阵', platform: 'n8n', platformColor: '#EA4B71',
-    rating: '4.8', views: '9.1K', category: '内容创作',
-    desc: '一个主题,自动生成适配各平台的差异化内容',
-    author: 'Tom Li',
-    authorAvatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&q=80',
+    workflowTitle: '社交媒体内容矩阵', categoryName1: 'n8n', platformColor: '#EA4B71',
+    rating: '4.8', downCount: '9.1K', categoryName2: '内容创作',
+    description: '一个主题,自动生成适配各平台的差异化内容',
+    nickName: 'Tom Li',
+    userAvatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1553877522-43269d4ea984?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1553877522-43269d4ea984?w=300&q=80'
   },
   },
   {
   {
-    title: 'AI 邮件营销自动化', platform: 'Coze', platformColor: '#1B6EF3',
-    rating: '4.6', views: '7.3K', category: '营销运营',
-    desc: '个性化邮件生成,智能发送时机,效果追踪分析',
-    author: 'Emma Zhou',
-    authorAvatar: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=40&q=80',
+    workflowTitle: 'AI 邮件营销自动化', categoryName1: 'Coze', platformColor: '#1B6EF3',
+    rating: '4.6', downCount: '7.3K', categoryName2: '营销运营',
+    description: '个性化邮件生成,智能发送时机,效果追踪分析',
+    nickName: 'Emma Zhou',
+    userAvatar: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=300&q=80'
   },
   },
   {
   {
-    title: '会议纪要自动整理', platform: 'n8n', platformColor: '#EA4B71',
-    rating: '5.0', views: '13.7K', category: '效率工具',
-    desc: '语音转文字,AI 提炼要点,自动分配任务到项目管理',
-    author: 'Zhang Wei',
-    authorAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&q=80',
+    workflowTitle: '会议纪要自动整理', categoryName1: 'n8n', platformColor: '#EA4B71',
+    rating: '5.0', downCount: '13.7K', categoryName2: '效率工具',
+    description: '语音转文字,AI 提炼要点,自动分配任务到项目管理',
+    nickName: 'Zhang Wei',
+    userAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=300&q=80'
   },
   },
   {
   {
-    title: '电商选品智能分析', platform: 'Dify', platformColor: '#7C3AED',
-    rating: '4.7', views: '5.8K', category: '数据分析',
-    desc: '多平台数据爬取,AI 分析趋势,自动生成选品报告',
-    author: 'Jack Wu',
-    authorAvatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&q=80',
+    workflowTitle: '电商选品智能分析', categoryName1: 'Dify', platformColor: '#7C3AED',
+    rating: '4.7', downCount: '5.8K', categoryName2: '数据分析',
+    description: '多平台数据爬取,AI 分析趋势,自动生成选品报告',
+    nickName: 'Jack Wu',
+    userAvatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1677442135703-1787eea5ce01?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1677442135703-1787eea5ce01?w=300&q=80'
   }
   }
 ]
 ]
 
 
 const workflowsB = [
 const workflowsB = [
   {
   {
-    title: '多语言翻译工作流', platform: 'Coze', platformColor: '#1B6EF3',
-    rating: '4.9', views: '11.5K', category: '内容创作',
-    desc: '支持 50+ 语言,保留格式,批量处理文档翻译',
-    author: 'Wang Fang',
-    authorAvatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=40&q=80',
+    workflowTitle: '多语言翻译工作流', categoryName1: 'Coze', platformColor: '#1B6EF3',
+    rating: '4.9', downCount: '11.5K', categoryName2: '内容创作',
+    description: '支持 50+ 语言,保留格式,批量处理文档翻译',
+    nickName: 'Wang Fang',
+    userAvatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1455390582262-044cdead277a?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1455390582262-044cdead277a?w=300&q=80'
   },
   },
   {
   {
-    title: 'SEO 内容优化助手', platform: 'Dify', platformColor: '#7C3AED',
-    rating: '4.7', views: '6.2K', category: '内容创作',
-    desc: '关键词分析,竞品对比,AI 生成 SEO 优化建议',
-    author: 'Li Ming',
-    authorAvatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&q=80',
+    workflowTitle: 'SEO 内容优化助手', categoryName1: 'Dify', platformColor: '#7C3AED',
+    rating: '4.7', downCount: '6.2K', categoryName2: '内容创作',
+    description: '关键词分析,竞品对比,AI 生成 SEO 优化建议',
+    nickName: 'Li Ming',
+    userAvatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1499750310107-5fef28a66643?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1499750310107-5fef28a66643?w=300&q=80'
   },
   },
   {
   {
-    title: '用户反馈情感分析', platform: 'FastGPT', platformColor: '#059669',
-    rating: '4.8', views: '8.1K', category: '客服自动化',
-    desc: '多渠道收集反馈,AI 情感分类,自动生成改进建议',
-    author: 'Liu Yang',
-    authorAvatar: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=40&q=80',
+    workflowTitle: '用户反馈情感分析', categoryName1: 'FastGPT', platformColor: '#059669',
+    rating: '4.8', downCount: '8.1K', categoryName2: '客服自动化',
+    description: '多渠道收集反馈,AI 情感分类,自动生成改进建议',
+    nickName: 'Liu Yang',
+    userAvatar: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=300&q=80'
   },
   },
   {
   {
-    title: 'AI 直播脚本生成', platform: 'Coze', platformColor: '#1B6EF3',
-    rating: '4.7', views: '7.8K', category: '内容创作',
-    desc: '根据产品信息自动生成直播话术,实时提词',
-    author: 'Xu Ming',
-    authorAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&q=80',
+    workflowTitle: 'AI 直播脚本生成', categoryName1: 'Coze', platformColor: '#1B6EF3',
+    rating: '4.7', downCount: '7.8K', categoryName2: '内容创作',
+    description: '根据产品信息自动生成直播话术,实时提词',
+    nickName: 'Xu Ming',
+    userAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=300&q=80'
   },
   },
   {
   {
-    title: '供应链风险预警', platform: 'n8n', platformColor: '#EA4B71',
-    rating: '4.8', views: '5.3K', category: '数据分析',
-    desc: '实时监控供应链数据,AI 预测风险,自动发出预警',
-    author: 'Zhang San',
-    authorAvatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&q=80',
+    workflowTitle: '供应链风险预警', categoryName1: 'n8n', platformColor: '#EA4B71',
+    rating: '4.8', downCount: '5.3K', categoryName2: '数据分析',
+    description: '实时监控供应链数据,AI 预测风险,自动发出预警',
+    nickName: 'Zhang San',
+    userAvatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=300&q=80'
   },
   },
   {
   {
-    title: '财务数据智能汇总', platform: 'FastGPT', platformColor: '#059669',
-    rating: '4.6', views: '4.5K', category: '数据分析',
-    desc: '多账户数据整合,自动对账,生成财务分析报告',
-    author: 'Zhao Yan',
-    authorAvatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=40&q=80',
+    workflowTitle: '财务数据智能汇总', categoryName1: 'FastGPT', platformColor: '#059669',
+    rating: '4.6', downCount: '4.5K', categoryName2: '数据分析',
+    description: '多账户数据整合,自动对账,生成财务分析报告',
+    nickName: 'Zhao Yan',
+    userAvatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=300&q=80'
   },
   },
   {
   {
-    title: '简历筛选自动化', platform: 'n8n', platformColor: '#EA4B71',
-    rating: '4.5', views: '4.2K', category: 'HR自动化',
-    desc: 'AI 智能匹配岗位要求,自动评分排序,发送面试邀请',
-    author: 'Nina Zhao',
-    authorAvatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&q=80',
+    workflowTitle: '简历筛选自动化', categoryName1: 'n8n', platformColor: '#EA4B71',
+    rating: '4.5', downCount: '4.2K', categoryName2: 'HR自动化',
+    description: 'AI 智能匹配岗位要求,自动评分排序,发送面试邀请',
+    nickName: 'Nina Zhao',
+    userAvatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=300&q=80'
   },
   },
   {
   {
-    title: '竞品监控与分析', platform: 'Dify', platformColor: '#7C3AED',
-    rating: '4.6', views: '3.9K', category: '数据分析',
-    desc: '自动追踪竞品动态,AI 分析策略变化,生成洞察报告',
-    author: 'Chen Jing',
-    authorAvatar: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=40&q=80',
+    workflowTitle: '竞品监控与分析', categoryName1: 'Dify', platformColor: '#7C3AED',
+    rating: '4.6', downCount: '3.9K', categoryName2: '数据分析',
+    description: '自动追踪竞品动态,AI 分析策略变化,生成洞察报告',
+    nickName: 'Chen Jing',
+    userAvatar: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=40&q=80',
     coverImage: 'https://images.unsplash.com/photo-1677442135703-1787eea5ce01?w=300&q=80'
     coverImage: 'https://images.unsplash.com/photo-1677442135703-1787eea5ce01?w=300&q=80'
   }
   }
 ]
 ]
+const openLoginDialog = inject('openLoginDialog')
+const searchFom = reactive({
+  pageNum: 0,
+  pageSize: 16,
+  orderByColumn: 'downCount',
+  isAsc: 'desc'
+})
+const workflowsList = ref([]);
+const getList = async (type) => {
+  const res = await getPublishList(searchFom)
+  console.log(res);
+  workflowsList.value = res.rows || [];
+};
+// 准备工作流列表,确保有指定数量的数据
+const prepareWorkflowList = (realData, fakeData, requiredCount) => {
+  // 复制真实数据
+  const result = [...realData];
+  
+   // 去重判断函数
+   const isDuplicate = (item) =>
+    result.some(r => r.workflowTitle === item.workflowTitle)
+
+  // 从假数据中补充
+  for (const fakeItem of fakeData) {
+    if (result.length >= requiredCount) break
+    if (!isDuplicate(fakeItem)) {
+      result.push({ ...fakeItem })
+    }
+  }
+
+  // 极端情况下仍不足,允许重复假数据(兜底)
+  let index = 0
+  while (result.length < requiredCount) {
+    result.push({ ...fakeData[index % fakeData.length] })
+    index++
+  }
+
+  return result
+};
+// 计算实际显示的工作流列表
+const displayWorkflows = computed(() => {
+  return prepareWorkflowList(workflowsList.value, workflows, 8);
+});
+const displayWorkflowsB = computed(() => {
+  return prepareWorkflowList(workflowsList.value, workflowsB, 8);
+});
+// 检查是否为真实数据
+const isRealData = (item) => {
+  return workflowsList.value.some(workflow => workflow.workflowTitle === item.workflowTitle);
+};
+// 处理立即使用按钮点击
+const handleUseClick = (event, item) => {
+  event.stopPropagation(); // 阻止冒泡
+  if(!isLogin({callback: openLoginDialog,t})){
+    return;
+  }
+  if (isRealData(item)) {
+    openNewTab(item.categoryUrl);
+  }
+};
+// 处理预览按钮点击
+const handlePreviewClick = (event, item) => {
+  event.stopPropagation(); // 阻止冒泡
+  //判断是否登录
+  if(!isLogin({callback: openLoginDialog,t})){
+    return;
+  }
+  if (isRealData(item)) {
+    let path = `/workflow-detail`
+    //增加参数名称
+    router.push({
+      path: path,
+      query: {
+        publishId: item.publishId,
+        metaTitle: 'route.WorkflowDetail'
+      }
+    })
+  }
+};
+onMounted(() => {
+  getList();
+})
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 4 - 2
src/pages/Home/SectionHowItWorks.vue

@@ -119,7 +119,7 @@
             <span class="w-px h-4 bg-gray-200"></span>
             <span class="w-px h-4 bg-gray-200"></span>
             <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>
             <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>
           </div>
           </div>
-          <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">
+          <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" @click="goWorkflowMarket">
             {{ $t('howItWorks.cta.startFree') }} →
             {{ $t('howItWorks.cta.startFree') }} →
           </button>
           </button>
         </div>
         </div>
@@ -130,8 +130,9 @@
 
 
 <script setup>
 <script setup>
 import { useI18n } from 'vue-i18n'
 import { useI18n } from 'vue-i18n'
-
+import { useRouter } from 'vue-router'
 const { t } = useI18n()
 const { t } = useI18n()
+const router = useRouter()
 const steps = [
 const steps = [
   {
   {
     icon: '🎯',
     icon: '🎯',
@@ -198,6 +199,7 @@ const steps = [
     previewSub: t('howItWorks.steps.2.previewSub')
     previewSub: t('howItWorks.steps.2.previewSub')
   }
   }
 ]
 ]
+const goWorkflowMarket = () => { router.push({ path: '/workflow-trade' }); };
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 111 - 116
src/pages/Home/SectionMarketplace.vue

@@ -21,7 +21,7 @@
           class="search-input"
           class="search-input"
           @input="filterWorkflows"
           @input="filterWorkflows"
         />
         />
-        <button class="search-btn">{{ $t('marketplace.search.button') }}</button>
+        <button class="search-btn" @click="filterWorkflows">{{ $t('marketplace.search.button') }}</button>
       </div>
       </div>
     </div>
     </div>
 
 
@@ -29,14 +29,14 @@
     <div class="category-tabs">
     <div class="category-tabs">
       <button
       <button
         v-for="cat in categories"
         v-for="cat in categories"
-        :key="cat.label"
+        :key="cat.category2Name"
         class="cat-tab"
         class="cat-tab"
-        :class="{ active: activeCategory === cat.label }"
-        @click="selectCategory(cat.label)"
+        :class="{ active: activeCategory === cat.categoryId2 }"
+        @click="selectCategory(cat.categoryId2)"
       >
       >
         <span>{{ cat.icon }}</span>
         <span>{{ cat.icon }}</span>
-        <span>{{ cat.label }}</span>
-        <span class="cat-count">{{ cat.count }}</span>
+        <span>{{ cat.category2Name }}</span>
+        <span class="cat-count">{{ cat.downCount }}</span>
       </button>
       </button>
     </div>
     </div>
 
 
@@ -46,7 +46,6 @@
         v-for="(wf, i) in filteredWorkflows"
         v-for="(wf, i) in filteredWorkflows"
         :key="i"
         :key="i"
         class="market-card"
         class="market-card"
-        :class="{ hidden: !wf.visible }"
         @mouseenter="hoveredCard = i"
         @mouseenter="hoveredCard = i"
         @mouseleave="hoveredCard = null"
         @mouseleave="hoveredCard = null"
       >
       >
@@ -54,24 +53,24 @@
         <div class="market-card-cover">
         <div class="market-card-cover">
           <img :src="wf.coverImage" :alt="wf.title" class="market-cover-img" />
           <img :src="wf.coverImage" :alt="wf.title" class="market-cover-img" />
           <div class="market-cover-overlay"></div>
           <div class="market-cover-overlay"></div>
-          <div class="market-platform-chip" :style="{ background: wf.platformColor }">{{ wf.platform }}</div>
-          <div class="market-views">▶ {{ wf.views }}</div>
+          <div class="market-platform-chip" :style="{ background: wf.platformColor }">{{ wf.categoryName1 }}</div>
+          <div class="market-views">▶ {{ wf.downCount }}</div>
         </div>
         </div>
 
 
         <!-- 卡片内容 -->
         <!-- 卡片内容 -->
         <div class="market-card-body">
         <div class="market-card-body">
           <div class="market-card-top">
           <div class="market-card-top">
-            <h4 class="market-title">{{ wf.title }}</h4>
-            <div class="market-rating">⭐ {{ wf.rating }}</div>
+            <h4 class="market-title">{{ wf.workflowTitle }}</h4>
+            <!-- <div class="market-rating">⭐ {{ wf.rating }}</div> -->
           </div>
           </div>
-          <p class="market-desc">{{ wf.desc }}</p>
-          <div class="market-tags">
+          <p class="market-desc">{{ wf.description }}</p>
+          <!-- <div class="market-tags">
             <span class="market-tag" v-for="tag in wf.tags" :key="tag">{{ tag }}</span>
             <span class="market-tag" v-for="tag in wf.tags" :key="tag">{{ tag }}</span>
-          </div>
+          </div> -->
           <div class="market-footer">
           <div class="market-footer">
             <div class="market-author">
             <div class="market-author">
-              <img :src="wf.authorAvatar" :alt="wf.author" class="market-avatar" />
-              <span>{{ wf.author }}</span>
+              <img :src="wf.userAvatar" :alt="wf.author" class="market-avatar" />
+              <span>{{ wf.nickName }}</span>
             </div>
             </div>
             <button class="market-use-btn">{{ $t('marketplace.cta.use') }} →</button>
             <button class="market-use-btn">{{ $t('marketplace.cta.use') }} →</button>
           </div>
           </div>
@@ -79,135 +78,131 @@
 
 
         <!-- 悬停遮罩 -->
         <!-- 悬停遮罩 -->
         <div class="market-hover-overlay" :class="{ visible: hoveredCard === i }">
         <div class="market-hover-overlay" :class="{ visible: hoveredCard === i }">
-          <button class="overlay-btn primary">{{ $t('marketplace.cta.use2') }}</button>
-          <button class="overlay-btn secondary">{{ $t('marketplace.cta.details') }}</button>
+          <button class="overlay-btn primary" @click="handleUseClick($event, wf)">{{ $t('marketplace.cta.use2') }}</button>
+          <button class="overlay-btn secondary" @click="handlePreviewClick($event, wf)">{{ $t('marketplace.cta.details') }}</button>
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>
 
 
     <!-- 查看更多 -->
     <!-- 查看更多 -->
     <div class="marketplace-footer">
     <div class="marketplace-footer">
-      <button class="view-all-btn">{{ $t('marketplace.cta.viewAll') }} →</button>
+      <button class="view-all-btn" @click="goWorkflowMarket">{{ $t('marketplace.cta.viewAll') }} →</button>
     </div>
     </div>
     </div><!-- /.marketplace-inner -->
     </div><!-- /.marketplace-inner -->
   </section>
   </section>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { ref, computed } from 'vue'
+import {ref, computed, onMounted, inject} from 'vue'
 import { useI18n } from 'vue-i18n'
 import { useI18n } from 'vue-i18n'
-
+import { useRouter } from 'vue-router'
+import {isLogin, openNewTab} from "@/utils/util.js";
+import { getPublishList,workflowCategoryStats } from '@/api/publish.js'
 const { t } = useI18n()
 const { t } = useI18n()
+const router = useRouter()
 const searchQuery = ref('')
 const searchQuery = ref('')
-const activeCategory = ref('全部')
+const activeCategory = ref('')
 const hoveredCard = ref(null)
 const hoveredCard = ref(null)
-
-const categories = [
-  { label: '全部', icon: '🌟', count: '200K+' },
-  { label: '内容创作', icon: '✍️', count: '45K+' },
-  { label: '数据分析', icon: '📊', count: '38K+' },
-  { label: '客服自动化', icon: '🤖', count: '52K+' },
-  { label: '销售运营', icon: '💼', count: '29K+' },
-  { label: '效率工具', icon: '⚡', count: '36K+' }
-]
-
-const allWorkflows = ref([
-  {
-    title: 'AI 文章批量生产流水线', platform: 'n8n', platformColor: '#EA4B71',
-    rating: '4.9', views: '12.3K', category: '内容创作',
-    desc: '一键生成高质量文章,自动配图排版,多平台发布',
-    tags: ['GPT-4', '内容创作', '自动化'],
-    author: 'Alex Chen',
-    authorAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&q=80',
-    coverImage: 'https://images.unsplash.com/photo-1499750310107-5fef28a66643?w=400&q=80',
-    visible: true
-  },
-  {
-    title: 'GPT-4 智能客服机器人', platform: 'Coze', platformColor: '#1B6EF3',
-    rating: '4.8', views: '8.7K', category: '客服自动化',
-    desc: '基于知识库的智能问答,支持多轮对话和情感识别',
-    tags: ['知识库', '多轮对话', 'NLP'],
-    author: 'Sarah Liu',
-    authorAvatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=40&q=80',
-    coverImage: 'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=400&q=80',
-    visible: true
-  },
-  {
-    title: '企业知识库问答系统', platform: 'FastGPT', platformColor: '#059669',
-    rating: '5.0', views: '15.2K', category: '客服自动化',
-    desc: '多格式文档导入,精准语义检索,企业知识管理',
-    tags: ['RAG', '语义检索', '企业级'],
-    author: 'Mike Wang',
-    authorAvatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&q=80',
-    coverImage: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=400&q=80',
-    visible: true
-  },
-  {
-    title: '数据报告自动生成', platform: 'Dify', platformColor: '#7C3AED',
-    rating: '4.7', views: '6.4K', category: '数据分析',
-    desc: '连接多数据源,自动分析可视化,定时推送报告',
-    tags: ['数据可视化', '自动报告', '多数据源'],
-    author: 'Lisa Zhang',
-    authorAvatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=40&q=80',
-    coverImage: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=400&q=80',
-    visible: true
-  },
-  {
-    title: '社交媒体内容矩阵', platform: 'n8n', platformColor: '#EA4B71',
-    rating: '4.8', views: '9.1K', category: '内容创作',
-    desc: '一个主题,自动生成适配各平台的差异化内容',
-    tags: ['多平台', '内容矩阵', '自动化'],
-    author: 'Tom Li',
-    authorAvatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=40&q=80',
-    coverImage: 'https://images.unsplash.com/photo-1553877522-43269d4ea984?w=400&q=80',
-    visible: true
-  },
-  {
-    title: 'AI 邮件营销自动化', platform: 'Coze', platformColor: '#1B6EF3',
-    rating: '4.6', views: '7.3K', category: '销售运营',
-    desc: '个性化邮件生成,智能发送时机,效果追踪分析',
-    tags: ['邮件营销', '个性化', 'A/B测试'],
-    author: 'Emma Zhou',
-    authorAvatar: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=40&q=80',
-    coverImage: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=400&q=80',
-    visible: true
-  },
-  {
-    title: '会议纪要自动整理', platform: 'n8n', platformColor: '#EA4B71',
-    rating: '5.0', views: '13.7K', category: '效率工具',
-    desc: '语音转文字,AI 提炼要点,自动分配任务到项目管理',
-    tags: ['语音识别', '会议管理', '任务分配'],
-    author: 'Zhang Wei',
-    authorAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=40&q=80',
-    coverImage: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&q=80',
-    visible: true
-  },
-  {
-    title: '电商选品智能分析', platform: 'Dify', platformColor: '#7C3AED',
-    rating: '4.7', views: '5.8K', category: '数据分析',
-    desc: '多平台数据爬取,AI 分析趋势,自动生成选品报告',
-    tags: ['电商', '选品分析', '趋势预测'],
-    author: 'Jack Wu',
-    authorAvatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=40&q=80',
-    coverImage: 'https://images.unsplash.com/photo-1677442135703-1787eea5ce01?w=400&q=80',
-    visible: true
-  }
+const icons = ['🌟','✍️','📊','🤖','💼','⚡']
+const categories = ref([
+  // { label: '全部', icon: '🌟', count: '200K+' },
+  // { label: '内容创作', icon: '✍️', count: '45K+' },
+  // { label: '数据分析', icon: '📊', count: '38K+' },
+  // { label: '客服自动化', icon: '🤖', count: '52K+' },
+  // { label: '销售运营', icon: '💼', count: '29K+' },
+  // { label: '效率工具', icon: '⚡', count: '36K+' }
 ])
 ])
 
 
+const allWorkflows = ref([])
+
 const filteredWorkflows = computed(() => {
 const filteredWorkflows = computed(() => {
   return allWorkflows.value.filter(wf => {
   return allWorkflows.value.filter(wf => {
-    const matchCategory = activeCategory.value === '全部' || wf.category === activeCategory.value
-    const matchSearch = !searchQuery.value || wf.title.includes(searchQuery.value) || wf.desc.includes(searchQuery.value)
+    const matchCategory = wf.categoryId2 === activeCategory.value
+    const matchSearch = !searchQuery.value || 
+      (wf.workflowTitle && wf.workflowTitle.includes(searchQuery.value)) || 
+      (wf.description && wf.description.includes(searchQuery.value))
     return matchCategory && matchSearch
     return matchCategory && matchSearch
   })
   })
 })
 })
 
 
 function selectCategory(cat) {
 function selectCategory(cat) {
-  activeCategory.value = cat
+  activeCategory.value = cat;
+  searchFom.value.categoryId2=activeCategory.value;
+    getList();
 }
 }
 function filterWorkflows() {
 function filterWorkflows() {
   // 搜索过滤由 computed 处理
   // 搜索过滤由 computed 处理
 }
 }
+const searchFom = ref({
+  pageNum: 0,
+  pageSize: 8,
+  orderByColumn: 'downCount',
+  isAsc: 'desc',
+})
+const getWorkflowCategoryStats =async () => {
+  let obj ={
+    pageNum: 0,
+        pageSize: 50}
+  const res = await workflowCategoryStats(obj);
+  if (res && res.rows) {
+      // 处理数据,添加图标
+      const processedCategories = res.rows.map((category, index) => ({
+        ...category,
+        icon: icons[index % icons.length] // 循环使用图标数组
+      }));
+      categories.value = processedCategories;
+    activeCategory.value=categories.value[0].categoryId2;
+      console.log(activeCategory.value)
+    searchFom.value.categoryId2=activeCategory.value;
+    getList()
+    } else {
+      console.error('Invalid response from workflowCategoryStats');
+    }
+}
+
+const getList = async () => {
+  try {
+    const res = await getPublishList(searchFom.value);
+    if (res && res.rows) {
+      // 转换真实数据格式
+      allWorkflows.value = res.rows;
+    }
+  } catch (error) {
+    console.error('Error loading workflows:', error);
+    // 加载失败时使用假数据
+    allWorkflows.value = [];
+  }
+};
+const openLoginDialog = inject('openLoginDialog')
+const handleUseClick = (event, item) => {
+  event.stopPropagation(); // 阻止冒泡
+  if(!isLogin({callback: openLoginDialog,t})){
+    return;
+  }
+  openNewTab(item.categoryUrl);
+};
+// 处理预览按钮点击
+const handlePreviewClick = (event, item) => {
+  event.stopPropagation(); // 阻止冒泡
+  //判断是否登录
+  if(!isLogin({callback: openLoginDialog,t})){
+    return;
+  }
+  let path = `/workflow-detail`
+    //增加参数名称
+    router.push({
+      path: path,
+      query: {
+        publishId: item.publishId,
+        metaTitle: 'route.WorkflowDetail'
+      }
+    })
+};
+const goWorkflowMarket = () => { router.push({ path: '/workflow-trade' }); };
+onMounted(() => {
+  getWorkflowCategoryStats();
+
+})
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 11 - 5
src/pages/Home/SectionPlatforms.vue

@@ -91,7 +91,8 @@
 
 
                 <!-- CTA -->
                 <!-- CTA -->
                 <button class="w-full py-3 rounded-2xl font-bold text-sm transition-all duration-300 hover:-translate-y-0.5 hover:shadow-lg"
                 <button class="w-full py-3 rounded-2xl font-bold text-sm transition-all duration-300 hover:-translate-y-0.5 hover:shadow-lg"
-                  :class="currentEngine.btnClass">
+                  :class="currentEngine.btnClass"
+                @click="goPlatform(currentEngine.name)">
                   {{ $t('platforms.cta.learn') }} {{ currentEngine.name }} →
                   {{ $t('platforms.cta.learn') }} {{ currentEngine.name }} →
                 </button>
                 </button>
               </div>
               </div>
@@ -118,7 +119,7 @@
               class="grid grid-cols-5 border-b border-gray-50 transition-all duration-200 cursor-default"
               class="grid grid-cols-5 border-b border-gray-50 transition-all duration-200 cursor-default"
               :class="[
               :class="[
                 fIdx % 2 === 0 ? '' : 'bg-gray-50/30',
                 fIdx % 2 === 0 ? '' : 'bg-gray-50/30',
-                hoveredRow === fIdx ? 'bg-indigo-50/60 shadow-sm' : 'hover:bg-gray-50/50'
+                hoveredRow === fIdx ? 'bg-indigo-50/60 shadow-sm' : 'hover:bg-gray-50/50',
               ]"
               ]"
               @mouseenter="hoveredRow = fIdx"
               @mouseenter="hoveredRow = fIdx"
               @mouseleave="hoveredRow = null">
               @mouseleave="hoveredRow = null">
@@ -140,7 +141,7 @@
               <!-- 各引擎支持情况 -->
               <!-- 各引擎支持情况 -->
               <div v-for="(engine, eIdx) in engines" :key="engine.id"
               <div v-for="(engine, eIdx) in engines" :key="engine.id"
                 class="p-4 flex items-center justify-center transition-all duration-300"
                 class="p-4 flex items-center justify-center transition-all duration-300"
-                :class="activeEngine === eIdx ? `bg-${engine.color}-50/50` : ''">
+                :class="activeEngine === eIdx ? `bg-${engine.color}-50` : ''">
                 <div class="flex flex-col items-center gap-1">
                 <div class="flex flex-col items-center gap-1">
                   <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>
                   <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>
                   <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>
                   <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>
@@ -162,7 +163,7 @@
                   <span class="font-semibold text-gray-700">Coze</span>  {{ $t('platforms.engineSelection.coze') }};
                   <span class="font-semibold text-gray-700">Coze</span>  {{ $t('platforms.engineSelection.coze') }};
                   <span class="font-semibold text-gray-700">Dify</span>  {{ $t('platforms.engineSelection.dify') }};
                   <span class="font-semibold text-gray-700">Dify</span>  {{ $t('platforms.engineSelection.dify') }};
                   <span class="font-semibold text-gray-700">FastGPT</span> {{ $t('platforms.engineSelection.fastgpt') }}。
                   <span class="font-semibold text-gray-700">FastGPT</span> {{ $t('platforms.engineSelection.fastgpt') }}。
-                  <a href="#" class="text-indigo-600 font-semibold ml-1 hover:underline">{{ $t('platforms.engineSelection.guide') }} →</a>
+<!--                  <a href="#" class="text-indigo-600 font-semibold ml-1 hover:underline">{{ $t('platforms.engineSelection.guide') }} →</a>-->
                 </div>
                 </div>
               </div>
               </div>
             </div>
             </div>
@@ -178,6 +179,8 @@ import { ref, computed } from 'vue'
 import { useI18n } from 'vue-i18n'
 import { useI18n } from 'vue-i18n'
 
 
 const { t } = useI18n()
 const { t } = useI18n()
+import {useRouter} from "vue-router";
+const router = useRouter();
 
 
 const activeEngine = ref(0)
 const activeEngine = ref(0)
 const hoveredRow = ref(null)
 const hoveredRow = ref(null)
@@ -256,7 +259,8 @@ const comparisonFeatures = [
     icon: '🎨', name: t('platforms.comparison.features.0.name'), desc: t('platforms.comparison.features.0.desc'),
     icon: '🎨', name: t('platforms.comparison.features.0.name'), desc: t('platforms.comparison.features.0.desc'),
     tip: t('platforms.comparison.features.0.tip'),
     tip: t('platforms.comparison.features.0.tip'),
     support: ['full', 'full', 'full', 'partial'],
     support: ['full', 'full', 'full', 'partial'],
-    notes: ['', '', '', t('platforms.comparison.notes.basic')]
+    notes: ['', '', '', t('platforms.comparison.notes.basic')],
+    color: 'red',
   },
   },
   {
   {
     icon: '🔌', name: t('platforms.comparison.features.1.name'), desc: t('platforms.comparison.features.1.desc'),
     icon: '🔌', name: t('platforms.comparison.features.1.name'), desc: t('platforms.comparison.features.1.desc'),
@@ -295,6 +299,8 @@ const comparisonFeatures = [
     notes: [t('platforms.comparison.notes.openSourceFree'), t('platforms.comparison.notes.freeQuota'), t('platforms.comparison.notes.openSourceFree'), t('platforms.comparison.notes.openSourceFree')]
     notes: [t('platforms.comparison.notes.openSourceFree'), t('platforms.comparison.notes.freeQuota'), t('platforms.comparison.notes.openSourceFree'), t('platforms.comparison.notes.openSourceFree')]
   }
   }
 ]
 ]
+
+const goPlatform = () => { router.push({ path: '/learning-system' }); };
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 8 - 8
src/pages/Home/SectionScenes.vue

@@ -167,14 +167,14 @@
           </div>
           </div>
 
 
           <!-- CTA 按钮 -->
           <!-- CTA 按钮 -->
-          <div class="mt-6 flex gap-3">
-            <button class="scene-cta-primary flex-1">
-              {{ $t('scenes.cta.experience') }} · {{ currentScene.name }} →
-            </button>
-            <button class="scene-cta-secondary px-5">
-              {{ $t('scenes.cta.viewCases') }} 
-            </button>
-          </div>
+<!--          <div class="mt-6 flex gap-3">-->
+<!--            <button class="scene-cta-primary flex-1">-->
+<!--              {{ $t('scenes.cta.experience') }} · {{ currentScene.name }} →-->
+<!--            </button>-->
+<!--            <button class="scene-cta-secondary px-5">-->
+<!--              {{ $t('scenes.cta.viewCases') }}-->
+<!--            </button>-->
+<!--          </div>-->
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>

+ 3 - 3
src/pages/Home/SectionStats.vue

@@ -133,8 +133,8 @@ onMounted(() => {
 
 
 const stats = [
 const stats = [
   { icon: '🌍', label: t('stats.cards.globalUsers.label'), sub: t('stats.cards.globalUsers.sub'), displayNum: '50,000+', growth: '↑ 23%', numColor: '#c084fc', lineGradient: 'linear-gradient(90deg, #8b5cf6, #a78bfa)', glowColor: 'radial-gradient(circle at 50% 0%, rgba(139,92,246,0.3) 0%, transparent 70%)', progress: '75%' },
   { icon: '🌍', label: t('stats.cards.globalUsers.label'), sub: t('stats.cards.globalUsers.sub'), displayNum: '50,000+', growth: '↑ 23%', numColor: '#c084fc', lineGradient: 'linear-gradient(90deg, #8b5cf6, #a78bfa)', glowColor: 'radial-gradient(circle at 50% 0%, rgba(139,92,246,0.3) 0%, transparent 70%)', progress: '75%' },
-  { icon: '⚡', label: t('stats.cards.workflowExecutions.label'), sub: t('stats.cards.workflowExecutions.sub'), displayNum: '1,200万+', growth: '↑ 41%', numColor: '#60a5fa', lineGradient: 'linear-gradient(90deg, #3b82f6, #60a5fa)', glowColor: 'radial-gradient(circle at 50% 0%, rgba(59,130,246,0.3) 0%, transparent 70%)', progress: '88%' },
-  { icon: '⏱️', label: t('stats.cards.timeSaved.label'), sub: t('stats.cards.timeSaved.sub'), displayNum: '320万小时', growth: '↑ 58%', numColor: '#22d3ee', lineGradient: 'linear-gradient(90deg, #06b6d4, #22d3ee)', glowColor: 'radial-gradient(circle at 50% 0%, rgba(6,182,212,0.3) 0%, transparent 70%)', progress: '92%' },
+  { icon: '⚡', label: t('stats.cards.workflowExecutions.label'), sub: t('stats.cards.workflowExecutions.sub'), displayNum: t('stats.cards.workflowExecutions.displayNum'), growth: '↑ 41%', numColor: '#60a5fa', lineGradient: 'linear-gradient(90deg, #3b82f6, #60a5fa)', glowColor: 'radial-gradient(circle at 50% 0%, rgba(59,130,246,0.3) 0%, transparent 70%)', progress: '88%' },
+  { icon: '⏱️', label: t('stats.cards.timeSaved.label'), sub: t('stats.cards.timeSaved.sub'), displayNum: t('stats.cards.timeSaved.displayNum'), growth: '↑ 58%', numColor: '#22d3ee', lineGradient: 'linear-gradient(90deg, #06b6d4, #22d3ee)', glowColor: 'radial-gradient(circle at 50% 0%, rgba(6,182,212,0.3) 0%, transparent 70%)', progress: '92%' },
   { icon: '📦', label: t('stats.cards.workflowTemplates.label'), sub: t('stats.cards.workflowTemplates.sub'), displayNum: '8,000+', growth: '↑ 35%', numColor: '#34d399', lineGradient: 'linear-gradient(90deg, #10b981, #34d399)', glowColor: 'radial-gradient(circle at 50% 0%, rgba(16,185,129,0.3) 0%, transparent 70%)', progress: '65%' }
   { icon: '📦', label: t('stats.cards.workflowTemplates.label'), sub: t('stats.cards.workflowTemplates.sub'), displayNum: '8,000+', growth: '↑ 35%', numColor: '#34d399', lineGradient: 'linear-gradient(90deg, #10b981, #34d399)', glowColor: 'radial-gradient(circle at 50% 0%, rgba(16,185,129,0.3) 0%, transparent 70%)', progress: '65%' }
 ]
 ]
 
 
@@ -142,7 +142,7 @@ const systemMetrics = [
   { icon: '✅', label: t('stats.systemMetrics.uptime'), value: '99.9%', width: '99%', barGradient: 'linear-gradient(90deg, #10b981, #34d399)', numColor: '#34d399' },
   { icon: '✅', label: t('stats.systemMetrics.uptime'), value: '99.9%', width: '99%', barGradient: 'linear-gradient(90deg, #10b981, #34d399)', numColor: '#34d399' },
   { icon: '📈', label:t('stats.systemMetrics.peakTraffic'), value: '60%', width: '60%', barGradient: 'linear-gradient(90deg, #3b82f6, #60a5fa)', numColor: '#60a5fa' },
   { icon: '📈', label:t('stats.systemMetrics.peakTraffic'), value: '60%', width: '60%', barGradient: 'linear-gradient(90deg, #3b82f6, #60a5fa)', numColor: '#60a5fa' },
   { icon: '⚡', label: t('stats.systemMetrics.avgResponseTime'), value: '180ms', width: '82%', barGradient: 'linear-gradient(90deg, #8b5cf6, #a78bfa)', numColor: '#a78bfa' },
   { icon: '⚡', label: t('stats.systemMetrics.avgResponseTime'), value: '180ms', width: '82%', barGradient: 'linear-gradient(90deg, #8b5cf6, #a78bfa)', numColor: '#a78bfa' },
-  { icon: '🔄', label: t('stats.systemMetrics.todayExecutions'), value: '15,750次', width: '78%', barGradient: 'linear-gradient(90deg, #f59e0b, #fbbf24)', numColor: '#fbbf24' }
+  { icon: '🔄', label: t('stats.systemMetrics.todayExecutions'), value: t('stats.systemMetrics.todayExecutionsValue'), width: '78%', barGradient: 'linear-gradient(90deg, #f59e0b, #fbbf24)', numColor: '#fbbf24' }
 ]
 ]
 
 
 const flowSteps = [
 const flowSteps = [

+ 5 - 3
src/pages/Home/SectionWhatIsWorkflow.vue

@@ -46,7 +46,8 @@
       <!-- 底部 CTA -->
       <!-- 底部 CTA -->
       <div class="text-center observe-fade">
       <div class="text-center observe-fade">
         <p class="text-gray-400 text-sm mb-4" v-html="$t('whatIsWorkflow.userCount', { count: '50,000+' })"></p>
         <p class="text-gray-400 text-sm mb-4" v-html="$t('whatIsWorkflow.userCount', { count: '50,000+' })"></p>
-        <button class="inline-flex items-center gap-2 bg-gradient-to-r from-violet-600 to-indigo-600 text-white font-bold px-8 py-3.5 rounded-2xl shadow-lg shadow-violet-200 hover:shadow-violet-300 hover:-translate-y-0.5 transition-all duration-300">
+        <button class="inline-flex items-center gap-2 bg-gradient-to-r from-violet-600 to-indigo-600 text-white font-bold px-8 py-3.5 rounded-2xl shadow-lg shadow-violet-200 hover:shadow-violet-300 hover:-translate-y-0.5 transition-all duration-300" style="cursor: pointer;"
+                @click.stop.prevent="goWorkflowMarket">
           <span>{{$t('whatIsWorkflow.ctaButton')}}</span>
           <span>{{$t('whatIsWorkflow.ctaButton')}}</span>
           <span class="text-lg">→</span>
           <span class="text-lg">→</span>
         </button>
         </button>
@@ -58,7 +59,8 @@
 <script setup>
 <script setup>
 import { onMounted } from 'vue'
 import { onMounted } from 'vue'
 import { useI18n } from 'vue-i18n'
 import { useI18n } from 'vue-i18n'
-
+import {useRouter} from "vue-router";
+const router = useRouter();
 const { t } = useI18n()
 const { t } = useI18n()
 const steps = [
 const steps = [
 {
 {
@@ -89,7 +91,7 @@ const steps = [
     tagColor: '#059669'
     tagColor: '#059669'
   }
   }
 ]
 ]
-
+const goWorkflowMarket = () => { router.push({ path: '/workflow-trade' }); };
 onMounted(() => {
 onMounted(() => {
   const observer = new IntersectionObserver((entries) => {
   const observer = new IntersectionObserver((entries) => {
     entries.forEach(entry => {
     entries.forEach(entry => {

+ 8 - 1
src/router/index.js

@@ -1,5 +1,6 @@
 import { createRouter, createWebHistory } from 'vue-router'
 import { createRouter, createWebHistory } from 'vue-router'
 import Home from '../pages/Home.vue'
 import Home from '../pages/Home.vue'
+import Home2 from '../pages/Home2.vue'
 
 
 const routes = [
 const routes = [
   {
   {
@@ -14,9 +15,15 @@ const routes = [
         name: 'Index',
         name: 'Index',
         component: Home,
         component: Home,
         meta: { title: 'route.home' }
         meta: { title: 'route.home' }
-      }
+      },
     ]
     ]
   },
   },
+  {
+    path: '/index2',
+    name: 'Index2',
+    component: Home2,
+    meta: { title: 'route.home' }
+  },
   {
   {
     path: '/search-platform',
     path: '/search-platform',
     name: 'SearchPlatformHome',
     name: 'SearchPlatformHome',