瀏覽代碼

产品和案例接口对接等

gcz 1 周之前
父節點
當前提交
486890138f
共有 8 個文件被更改,包括 537 次插入202 次删除
  1. 4 3
      .env
  2. 2 1
      .env.production
  3. 47 12
      src/api/modules/home.js
  4. 二進制
      src/assets/index-about-img.png
  5. 43 9
      src/pages/cases/Index.vue
  6. 259 117
      src/pages/home/Index.vue
  7. 90 60
      src/pages/products/Index.vue
  8. 92 0
      src/utils/numberAnimation.js

+ 4 - 3
.env

@@ -1,4 +1,5 @@
-#
-VITE_APP_TITLE 'development'
+# Development Environment
+VITE_APP_TITLE='development'
 VITE_APP_BASE_URL=/stage-api
-VITE_APP_ENV=development
+VITE_APP_ENV=development
+VITE_APP_IMG_HOST=https://miniores.dev.dazesoft.cn/dzkj/

+ 2 - 1
.env.production

@@ -1,4 +1,5 @@
 # 
 VITE_APP_TITLE='production'
 VITE_APP_BASE_URL=/prod-api
-VITE_APP_ENV=production
+VITE_APP_ENV=production
+VITE_APP_IMG_HOST=https://miniores.dev.dazesoft.cn/dzkj/

+ 47 - 12
src/api/modules/home.js

@@ -1,33 +1,68 @@
 import request from '@/utils/request'
 
 // 获取首页数据
-export const getHomeData = () => {
+export const getHomeData = (params) => {
   return request({
     url: '/website/companyInfo',
-    method: 'get'
+    method: 'get',
+    params
   })
 }
 
-// 获取产品列表
-export const getProducts = () => {
+// 产品/案例信息
+// 分类列表
+// 请求Query参数
+// classifyType类型:1:产品中心 2:行业案例
+export const getProjectClassifyList = (params) => {
   return request({
-    url: '/home/products',
-    method: 'get'
+    url: '/website/dzProjectClassify/list',
+    method: 'get',
+    params
+  })
+}
+
+// 产品/案例信息
+// 请求Query参数
+// classifyId分类ID
+// projectType类型:1:产品中心 2:行业案例
+export const getProjectList= (params) => {
+  return request({
+    url: '/website/dzProject/list',
+    method: 'get',
+    params
+  })
+}
+// 联系我们
+// 提交留言
+export const addDzNotes = (data) => {
+  return request({
+    url: '/website/dzNotes/addDzNotes',
+    method: 'post',
+    data
   })
 }
 
-// 获取技术优势
-export const getAdvantages = () => {
+// 联系我们
+export const getContacts= (params) => {
   return request({
-    url: '/home/advantages',
+    url: '/website/companyInfo/getContacts',
+    method: 'get',
+    params
+  })
+}
+
+// 企业介绍
+export const getCompanyInfo= () => {
+  return request({
+    url: '/website/companyInfo',
     method: 'get'
   })
 }
 
-// 获取统计数据
-export const getStats = () => {
+// 企业资质
+export const getCompanyCertList= () => {
   return request({
-    url: '/home/stats',
+    url: '/website/dzCompanyCert/list',
     method: 'get'
   })
 }

二進制
src/assets/index-about-img.png


+ 43 - 9
src/pages/cases/Index.vue

@@ -17,7 +17,7 @@
 
         <!-- 解决方案列表 -->
         <div class="solutions-grid">
-          <div v-for="(solution, index) in visibleSolutions" :key="solution.id" class="solution-card">
+          <div v-for="solution in visibleSolutions" :key="solution.id" @click="goToCaseDetail(solution.id)" class="solution-card">
             <div class="card-image">
               <img :src="solution.image" :alt="solution.title" />
             </div>
@@ -53,8 +53,8 @@
 
         <!-- 案例列表 -->
         <div class="cases-list">
-          <div v-for="(caseItem, index) in casesList" :key="caseItem.id" class="case-item"
-            :class="{ 'fifth-row': Math.floor(index / 2) === 4 }" @click="goToCaseDetail(caseItem.id)">
+          <div v-for="(caseItem, caseIndex) in casesList" :key="caseItem.id" class="case-item"
+            :class="{ 'fifth-row': Math.floor(caseIndex / 2) === 4 }" @click="goToCaseDetail(caseItem.id)">
             <div class="case-content">
               <h3 class="case-title">{{ caseItem.title }}</h3>
             </div>
@@ -67,9 +67,9 @@
 
 <script>
 import { ref, computed, onMounted } from 'vue'
+import { getProjectClassifyList, getProjectList } from '@/api/modules/home'
 import { useRouter } from 'vue-router'
 import DefaultLayout from '@/layouts/DefaultLayout.vue'
-import { getProductsData } from '@/api/modules/products'
 
 export default {
   name: 'ProductsPage',
@@ -78,11 +78,13 @@ export default {
   },
   setup() {
     const router = useRouter()
+    // 环境变量
+    const imgHost = import.meta.env.VITE_APP_IMG_HOST || ''
     const currentPage = ref(0)
     const itemsPerPage = 6 // 每页显示6个(2行 × 3列)
 
     // 解决方案数据
-    const solutions = ref([
+    let solutions = ref([
       {
         id: 1,
         title: '智慧农业(种植+养殖)',
@@ -134,7 +136,7 @@ export default {
     ])
 
     // 更多案例数据
-    const casesList = ref([
+    let casesList = ref([
       { id: 1, title: '海南教育局大数据中心建设项目' },
       { id: 2, title: '贵阳某龙新区疫情网络安全监测项目' },
       { id: 3, title: '六盘水区民法院网络安全项目' },
@@ -194,8 +196,39 @@ export default {
     // API调用方法
     const loadProductsData = async () => {
       try {
-        const data = await getProductsData()
-        console.log('产品数据:', data)
+        // 获取产品分类列表 (用于solutions)
+        // const classifyData = await getProjectClassifyList({ classifyType: 1 })
+        // console.log('产品分类数据:', classifyData)
+
+        // if (classifyData && classifyData.rows && classifyData.rows.length > 0) {
+        //   // 更新solutions数据
+        //   solutions.value = classifyData.rows.map(item => ({
+        //     id: item.id,
+        //     title: item.classifyName,
+        //     description: item.classifyDesc || '为您提供专业的解决方案',
+        //     image: item.projectImage ? imgHost + item.projectImage : '/src/assets/products-youshi-01.png'
+        //   }))
+        // }
+
+        // 获取案例列表 (用于casesList)
+        const casesData = await getProjectList({ projectType: 2 })
+        console.log('案例数据:', casesData)
+
+        if (casesData && casesData.rows && casesData.rows.length > 0) {
+          // 更新casesList数据
+          casesList.value = casesData.rows.map(item => ({
+            id: item.id,
+            title: item.projectName || item.title
+          }))
+
+          // 更新solutions数据
+          solutions.value = casesData.rows.map(item => ({
+            id: item.id,
+            title: item.classifyName,
+            description: item.classifyDesc || '为您提供专业的解决方案',
+            image: item.projectImage ? imgHost + item.projectImage : '/src/assets/products-youshi-01.png'
+          }))
+        }
       } catch (error) {
         console.error('加载产品数据失败:', error)
       }
@@ -399,7 +432,8 @@ export default {
   padding: 80px 0;
   background: #fff;
   position: relative;
-  &::before{
+
+  &::before {
     position: absolute;
     content: '';
     left: 0;

+ 259 - 117
src/pages/home/Index.vue

@@ -6,16 +6,16 @@
       <div class="info-row">
         <div class="info-item">
           <span class="text">覆盖</span>
-          <span class="number">10+</span>
+          <span class="number" ref="number1">{{ animatedNumbers.number1 }}+</span>
           <span class="text">垂直行业</span>
         </div>
         <div class="info-item">
-          <span class="number">72</span>
+          <span class="number" ref="number2">{{ animatedNumbers.number2 }}</span>
           <span class="text">小时原型交付</span>
         </div>
         <div class="info-item">
           <span class="text">定制成本降低</span>
-          <span class="number">30%</span>
+          <span class="number" ref="number3">{{ animatedNumbers.number3 }}%</span>
         </div>
       </div>
     </section>
@@ -33,17 +33,18 @@
           <div class="products-nav">
             <div v-for="product in productList" :key="product.id" class="nav-item"
               :class="{ active: activeProductId === product.id }" @click="setActiveProduct(product.id)">
-              {{ product.title }}
+              {{ product.classifyName }}
             </div>
           </div>
 
-          <div class="product-detail">
+          <div class="product-detail" v-if="activeProduct">
             <div class="detail-content">
-              <h3 class="product-title">{{ activeProduct.title }}</h3>
-              <p class="product-description">{{ activeProduct.description }}</p>
+              <h3 class="product-title">{{ activeProduct.classifyName }}</h3>
+              <p class="product-description">{{ activeProduct.description || activeProduct.classifyDesc || '为您提供专业的解决方案'
+              }}</p>
             </div>
             <div class="detail-image">
-              <img :src="activeProduct.image" :alt="activeProduct.title" />
+              <img :src="imgHost + activeProduct.projectImage" :alt="activeProduct.classifyName" />
             </div>
           </div>
         </div>
@@ -68,13 +69,14 @@
           <div class="cases-container">
             <div class="cases-wrapper"
               :style="{ transform: `translateX(-${currentCaseIndex * (100 / visibleCases)}%)` }">
-              <div v-for="caseItem in casesList" :key="caseItem.id" class="case-item">
+              <div v-for="caseItem in casesList" :key="caseItem.id" @click="goToCaseDetail(caseItem.id)"
+                class="case-item">
                 <div class="case-image">
-                  <img :src="caseItem.image" :alt="caseItem.title" />
+                  <img :src="imgHost + caseItem.projectImage" :alt="caseItem.title" />
                 </div>
                 <div class="case-content">
-                  <h3 class="case-title">{{ caseItem.title }}</h3>
-                  <p class="case-description">{{ caseItem.description }}</p>
+                  <h3 class="case-title">{{ caseItem.projectName }}</h3>
+                  <p class="case-description">{{ caseItem.projectProfile }}</p>
                 </div>
               </div>
             </div>
@@ -115,7 +117,7 @@
                   <h3 class="content-title">{{ activeAboutContent.title }}</h3>
                   <div class="content-description" v-html="activeAboutContent.description"></div>
                   <div class="content-action">
-                    <button class="learn-more-btn">查看更多 →</button>
+                    <button class="learn-more-btn" @click="router.push({ name: 'About' })">查看更多 →</button>
                   </div>
                 </div>
               </div>
@@ -144,9 +146,13 @@
 </template>
 
 <script>
-import { ref, computed, onMounted, onUnmounted } from 'vue'
+import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
+import { useRouter } from 'vue-router'
 import DefaultLayout from '@/layouts/DefaultLayout.vue'
-import { getHomeData } from '@/api/modules/home'
+import { getHomeData, getProjectClassifyList, getProjectList, getCompanyCertList } from '@/api/modules/home'
+import { animateNumber, createNumberAnimationObserver } from '@/utils/numberAnimation'
+// 导入图片资源
+import indexAboutBg from '@/assets/index-about-img.png'
 
 export default {
   name: 'HomePage',
@@ -154,59 +160,78 @@ export default {
     DefaultLayout
   },
   setup() {
-    const activeProductId = ref(1)
+    const router = useRouter()
+    const activeProductId = ref(null)
 
-    const productList = ref([
-      {
-        id: 1,
-        title: '低代码平台',
-        description: '图形化界面和拖拽式组件,简化应用开发和部署,快速构建和迭代企业级应用。',
-        image: 'src/assets/index-products-01.png'
-      },
-      {
-        id: 2,
-        title: '物联网平台',
-        description: '连接和管理各种智能设备,实现设备数据采集、监控和远程控制。',
-        image: 'https://via.placeholder.com/400x300/0066cc/ffffff?text=物联网平台'
-      },
-      {
-        id: 3,
-        title: '统一权限系统',
-        description: '集中管理用户权限和访问控制,确保系统安全和数据保护。',
-        image: 'https://via.placeholder.com/400x300/0066cc/ffffff?text=统一权限系统'
-      },
-      {
-        id: 4,
-        title: '地图适配应用',
-        description: '提供地理信息服务和位置定位功能,支持多种地图数据源。',
-        image: 'https://via.placeholder.com/400x300/0066cc/ffffff?text=地图适配应用'
-      },
-      {
-        id: 5,
-        title: '数字学生',
-        description: '学生信息管理和学习行为分析,提供个性化教育服务。',
-        image: 'https://via.placeholder.com/400x300/0066cc/ffffff?text=数字学生'
-      },
-      {
-        id: 6,
-        title: '数据中台',
-        description: '统一数据管理和分析平台,提供数据治理和业务洞察。',
-        image: 'https://via.placeholder.com/400x300/0066cc/ffffff?text=数据中台'
-      },
-      {
-        id: 7,
-        title: 'AI大模型',
-        description: '集成人工智能技术,提供智能分析和决策支持服务。',
-        image: 'https://via.placeholder.com/400x300/0066cc/ffffff?text=AI大模型'
-      }
-    ])
+    // 环境变量
+    const imgHost = import.meta.env.VITE_APP_IMG_HOST
+
+    // 数字滚动动画相关
+    const animatedNumbers = ref({
+      number1: 0,
+      number2: 0,
+      number3: 0
+    })
+
+    const targetNumbers = {
+      number1: 10,
+      number2: 72,
+      number3: 30
+    }
+
+    // 启动所有数字动画
+    const startNumberAnimations = () => {
+      // 延迟启动,让页面加载完成后再开始动画
+      setTimeout(() => {
+        animateNumber(
+          (value) => animatedNumbers.value.number1 = value,
+          targetNumbers.number1,
+          2000
+        )
+      }, 200)
+
+      setTimeout(() => {
+        animateNumber(
+          (value) => animatedNumbers.value.number2 = value,
+          targetNumbers.number2,
+          2500
+        )
+      }, 500)
+
+      setTimeout(() => {
+        animateNumber(
+          (value) => animatedNumbers.value.number3 = value,
+          targetNumbers.number3,
+          2200
+        )
+      }, 800)
+    }
+
+    // 设置数字动画观察器
+    const setupIntersectionObserver = () => {
+      createNumberAnimationObserver('.info-row', startNumberAnimations, {
+        threshold: 0.5,
+        rootMargin: '0px 0px -100px 0px'
+      })
+    }
+
+    // 产品分类列表
+    let productList = ref([])
+    // 当前选中分类的产品列表
+    let currentProductList = ref([])
 
     const activeProduct = computed(() => {
+      if (productList.value.length === 0) return null
       return productList.value.find(product => product.id === activeProductId.value) || productList.value[0]
     })
 
-    const setActiveProduct = (id) => {
+    const setActiveProduct = async (id) => {
       activeProductId.value = id
+      // 获取选中分类的产品列表
+      const selectedCategory = productList.value.find(product => product.id === id)
+      if (selectedCategory && selectedCategory.id) {
+        await getProductsByClassify(selectedCategory.id)
+      }
     }
 
     // 行业案例数据和逻辑
@@ -222,38 +247,21 @@ export default {
       { id: 'qualification', title: '荣誉资质' }
     ])
 
-    const aboutContents = ref({
+    let aboutContents = ref({
       about: {
         title: '关于达泽',
-        description: `
-          <p>达泽科技是贵州省今日前沿信息技术有限责任公司旗下品牌,专业为软件开发及数字化商务的综合性企业。为政府、金融、保险、通讯、电力、教育、制造、零售、交通、教育、通信、水利、农业等领域的企业及机构提供了专业的信息化解决方案。</p>
-          <p>公司一直致力为客户内部管理,为用户至上的服务理念,为客户提供,合作共赢,服务至上的服务理念,为社会创造更高的价值。</p>
-        `,
-        image: 'src/assets/index-about-bg.png'
+        description: '<p>加载中...</p>',
+        image: indexAboutBg
       },
       history: {
         title: '发展历程',
-        description: `
-          <p><strong>2018年</strong> - 公司成立,专注于智慧校园解决方案</p>
-          <p><strong>2019年</strong> - 推出低代码开发平台,服务客户超过50家</p>
-          <p><strong>2020年</strong> - 获得高新技术企业认证,团队规模扩展至100人</p>
-          <p><strong>2021年</strong> - 业务拓展至智慧农业、智慧停车等多个领域</p>
-          <p><strong>2022年</strong> - 服务学校超过500所,用户突破100万</p>
-          <p><strong>2023年</strong> - 推出AI大模型解决方案,引领行业创新</p>
-        `,
-        image: 'src/assets/index-about-bg.png'
+        description: '<p>加载中...</p>',
+        image: indexAboutBg
       },
       qualification: {
         title: '荣誉资质',
-        description: `
-          <p><strong>国家高新技术企业</strong> - 2020年获得认证</p>
-          <p><strong>软件企业认证</strong> - 贵州省软件行业协会会员单位</p>
-          <p><strong>ISO9001质量管理体系认证</strong> - 2021年通过认证</p>
-          <p><strong>信息安全等级保护三级</strong> - 系统安全等级认证</p>
-          <p><strong>优秀合作伙伴奖</strong> - 多家知名企业颁发</p>
-          <p><strong>创新技术奖</strong> - 贵州省科技厅颁发</p>
-        `,
-        image: 'src/assets/index-about-bg.png'
+        description: '<p>加载中...</p>',
+        image: indexAboutBg
       }
     })
 
@@ -329,42 +337,42 @@ export default {
       }
     ])
 
-    const casesList = ref([
+    let casesList = ref([
       {
         id: 1,
-        title: '智慧农业(种植+养殖)',
-        description: '通过物联网技术实现农业自动化管理,利用传感器监控土壤、水质等环境参数,提高农业生产效率。',
-        image: 'https://unsplash.it/300/200'
+        projectName: '智慧农业(种植+养殖)',
+        projectProfile: '通过物联网技术实现农业自动化管理,利用传感器监控土壤、水质等环境参数,提高农业生产效率。',
+        projectImage: 'https://unsplash.it/300/200'
       },
       {
         id: 2,
-        title: '智慧停车',
-        description: '通过车牌识别技术及物联网设备实现停车场智能化管理,实现无感支付和车位引导等功能。',
-        image: 'https://unsplash.it/300/200'
+        projectName: '智慧停车',
+        projectProfile: '通过车牌识别技术及物联网设备实现停车场智能化管理,实现无感支付和车位引导等功能。',
+        projectImage: 'https://unsplash.it/300/200'
       },
       {
         id: 3,
-        title: '副控票务系统',
-        description: '为景区提供智能化票务管理,智能闸机一体化管理系统,提升游客体验,优化景区运营。',
-        image: 'https://unsplash.it/300/200'
+        projectName: '副控票务系统',
+        projectProfile: '为景区提供智能化票务管理,智能闸机一体化管理系统,提升游客体验,优化景区运营。',
+        projectImage: 'https://unsplash.it/300/200'
       },
       {
         id: 4,
-        title: '智慧校园',
-        description: '集成学生管理、教学管理、安全监控等功能,为教育机构提供全方位数字化解决方案。',
-        image: 'https://unsplash.it/300/200'
+        projectName: '智慧校园',
+        projectProfile: '集成学生管理、教学管理、安全监控等功能,为教育机构提供全方位数字化解决方案。',
+        projectImage: 'https://unsplash.it/300/200'
       },
       {
         id: 5,
-        title: '智慧医疗',
-        description: '通过数字化技术提升医疗服务效率,实现患者信息管理、远程诊疗等智能化医疗服务。',
-        image: 'https://unsplash.it/300/200'
+        projectName: '智慧医疗',
+        projectProfile: '通过数字化技术提升医疗服务效率,实现患者信息管理、远程诊疗等智能化医疗服务。',
+        projectImage: 'https://unsplash.it/300/200'
       },
       {
         id: 6,
-        title: '智慧物流',
-        description: '利用物联网和大数据技术优化物流配送,实现货物追踪、路径优化等智能化物流管理。',
-        image: 'https://unsplash.it/300/200'
+        projectName: '智慧物流',
+        projectProfile: '利用物联网和大数据技术优化物流配送,实现货物追踪、路径优化等智能化物流管理。',
+        projectImage: 'https://unsplash.it/300/200'
       }
     ])
 
@@ -387,14 +395,88 @@ export default {
     // API调用方法
     const loadHomeData = async () => {
       try {
-        const data = await getHomeData()
-        // 这里可以更新products和advantages数据
+        const result = await getHomeData()
+        const data = result.data
         console.log('首页数据:', data)
+
+        if (data) {
+          // 更新关于达泽的描述
+          if (data.companyDescribe) {
+            aboutContents.value.about.description = data.companyDescribe
+          }
+
+          // 更新发展历程的描述
+          if (data.courseList && Array.isArray(data.courseList)) {
+            const historyHtml = data.courseList.map(item => {
+              const time = item.createTime ? new Date(item.createTime).getFullYear() : '未知时间'
+              const description = item.courseDescribe || '暂无描述'
+              return `<p><strong>${time}年</strong> - ${description}</p>`
+            }).join('')
+            aboutContents.value.history.description = historyHtml || '<p>暂无发展历程数据</p>'
+          }
+        }
       } catch (error) {
         console.error('加载首页数据失败:', error)
       }
     }
 
+    // 获取产品分类列表
+    const handleGetProjectClassifyList1 = async () => {
+      try {
+        const data = await getProjectClassifyList({ classifyType: 1 })
+        console.log('产品中心分类列表:', data)
+
+        if (data && data.rows && data.rows.length > 0) {
+          productList.value = data.rows
+          // 默认选中第一个分类
+          activeProductId.value = data.rows[0].id
+          // 获取第一个分类的产品列表
+          await getProductsByClassify(data.rows[0].id)
+        }
+      } catch (error) {
+        console.error('加载产品中心分类列表失败:', error)
+      }
+    }
+
+    // 根据分类ID获取产品列表
+    const getProductsByClassify = async (classifyId) => {
+      try {
+        const data = await getProjectList({
+          classifyId: classifyId,
+          projectType: 1 // 1:产品中心 2:行业案例
+        })
+        console.log('产品列表:', data)
+
+        if (data && data.rows) {
+          currentProductList.value = data.rows
+          // 更新当前选中分类的描述信息
+          const currentCategory = productList.value.find(item => item.id === activeProductId.value)
+          if (currentCategory && data.rows.length > 0) {
+            // 可以根据API返回的数据更新分类的描述信息
+            currentCategory.description = data.rows[0].projectProfile || currentCategory.classifyDesc || '为您提供专业的解决方案';
+            currentCategory.projectImage = data.rows[0].projectImage
+            console.log('currentCategory', currentCategory)
+          }
+        }
+      } catch (error) {
+        console.error('加载产品列表失败:', error)
+      }
+    }
+
+
+    // 产品/案例信息-案例信息
+    const handleGetProjectList = async () => {
+      try {
+        const data = await getProjectList({ projectType: 2 })
+        // 这里可以更新products和advantages数据
+        console.log('案例信息:', data)
+        casesList.value = data.rows;
+        console.log('案例信息列表:', casesList.value)
+      } catch (error) {
+        console.error('加载案例信息失败:', error)
+      }
+    }
+
     // 响应式处理
     const updateVisibleCases = () => {
       if (window.innerWidth <= 768) {
@@ -408,10 +490,44 @@ export default {
       }
     }
 
+    // 跳转到案例详情页
+    const goToCaseDetail = (caseId) => {
+      router.push({
+        name: 'Casesdetails',
+        query: { id: caseId }
+      })
+    }
+
+    // 获取企业资质证书
+    const loadCompanyCertList = async () => {
+      try {
+        const data = await getCompanyCertList()
+        console.log('企业资质数据:', data)
+
+        if (data && data.rows && Array.isArray(data.rows)) {
+          const certHtml = data.rows.map(item => {
+            const certName = item.certName || '未知证书'
+            return `<p><strong>${certName}</strong></p>`
+          }).join('')
+          aboutContents.value.qualification.description = certHtml || '<p>暂无资质证书数据</p>'
+        }
+      } catch (error) {
+        console.error('加载企业资质失败:', error)
+      }
+    }
+
     onMounted(() => {
       loadHomeData()
+      loadCompanyCertList() // 获取企业资质证书
+      handleGetProjectClassifyList1() // 获取产品分类列表
+      handleGetProjectList() // 获取案例列表
       updateVisibleCases()
       window.addEventListener('resize', updateVisibleCases)
+
+      // 设置数字滚动动画的观察器
+      nextTick(() => {
+        setupIntersectionObserver()
+      })
     })
 
     onUnmounted(() => {
@@ -419,7 +535,9 @@ export default {
     })
 
     return {
+      router,
       productList,
+      currentProductList,
       activeProductId,
       activeProduct,
       setActiveProduct,
@@ -433,7 +551,10 @@ export default {
       activeAboutTab,
       activeAboutContent,
       setActiveAboutTab,
-      partnersList
+      partnersList,
+      goToCaseDetail,
+      imgHost,
+      animatedNumbers
     }
   }
 }
@@ -443,6 +564,7 @@ export default {
 // banner区域
 .banner-section {
   position: relative;
+
   img {
     width: 100%;
   }
@@ -484,6 +606,12 @@ export default {
     font-size: 32px;
     vertical-align: middle;
     margin: 0 5px;
+    font-family: 'Arial', monospace;
+    letter-spacing: 1px;
+    transition: all 0.1s ease;
+    display: inline-block;
+    min-width: 1.2em;
+    text-align: center;
   }
 
   .text {
@@ -704,6 +832,7 @@ export default {
       height: 200px;
       border-radius: 12px 12px 0 0;
       overflow: hidden;
+      background: #fff;
 
       img {
         width: 100%;
@@ -738,6 +867,12 @@ export default {
         color: #666;
         line-height: 1.6;
         margin: 0;
+        min-height: 45px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: -webkit-box;
+        -webkit-line-clamp:2;
+        -webkit-box-orient: vertical;
       }
     }
   }
@@ -914,14 +1049,16 @@ export default {
   background-size: cover;
   padding: 80px 0;
   position: relative;
-  &::before{
+
+  &::before {
     position: absolute;
     content: '';
     width: 1346px;
     height: 335px;
     right: 150px;
     top: 0;
-    background: url('@assets/index-cooperation-bg.png') no-repeat center center;;
+    background: url('@assets/index-cooperation-bg.png') no-repeat center center;
+    ;
     background-size: contain;
   }
 
@@ -1011,27 +1148,32 @@ export default {
 
 // 响应式设计
 @media (max-width: 768px) {
-  .cooperation-section{
-    &::before{
+  .cooperation-section {
+    &::before {
       width: 0;
     }
-    .section-header{
-      .section-subtitle{
+
+    .section-header {
+      .section-subtitle {
         margin-bottom: 10px;
       }
     }
   }
-  .info-row{
-    .info-item{
+
+  .info-row {
+    .info-item {
       padding: 0 10px;
     }
-    .text{
+
+    .text {
       font-size: 14px;
     }
-    .number{
+
+    .number {
       font-size: 14px;
     }
   }
+
   .products-section {
     padding: 40px 0;
 

+ 90 - 60
src/pages/products/Index.vue

@@ -23,13 +23,13 @@
       <!-- 内容部分 -->
       <div class="skills-content">
         <div class="container">
-          <div class="content-wrapper">
+          <div class="content-wrapper" v-if="platforms[activePlatform]">
             <h3 class="content-title">{{ platforms[activePlatform].title }}</h3>
             <img src="@assets/products-select.png" alt="" class="title-indicator">
             <p class="content-subtitle">{{ platforms[activePlatform].subtitle }}</p>
 
             <!-- 图片轮播 -->
-            <div class="carousel-container">
+            <div class="carousel-container" v-if="platforms[activePlatform] && platforms[activePlatform].images">
               <div class="carousel-wrapper" @mouseenter="pauseAutoPlay" @mouseleave="resumeAutoPlay">
                 <div class="carousel-track" :style="{ transform: `translateX(-${currentSlide * 100}%)` }">
                   <div v-for="(image, index) in platforms[activePlatform].images" :key="index" class="carousel-slide">
@@ -74,7 +74,7 @@
 <script>
 import { ref, onMounted, onUnmounted } from 'vue'
 import DefaultLayout from '@/layouts/DefaultLayout.vue'
-import { getProductsData } from '@/api/modules/products'
+import { getProjectClassifyList, getProjectList } from '@/api/modules/home'
 import productsBg01 from '@/assets/products-bg01.png'
 import productsBg02 from '@/assets/products-bg02.png'
 import productsYoushi01 from '@/assets/products-youshi-01.png'
@@ -90,56 +90,18 @@ export default {
     DefaultLayout
   },
   setup() {
+    // 环境变量
+    const imgHost = import.meta.env.VITE_APP_IMG_HOST || ''
+
     // 响应式数据
     const activePlatform = ref(0)
     const currentSlide = ref(0)
     let autoPlayTimer = null
 
-    // 平台数据
-    const platforms = ref([
-      {
-        name: '低代码平台',
-        title: '平台预览',
-        subtitle: '图形化界面和拖拽式组件,简化应用开发复杂度,快速构建和配置各类企业应用。',
-        images: [productsBg01, productsBg02, productsBg01]
-      },
-      {
-        name: '物联网平台',
-        title: '物联网解决方案',
-        subtitle: '全面的物联网设备管理和数据采集平台,实现设备互联和智能化管理。',
-        images: [productsBg02, productsBg01, productsBg02]
-      },
-      {
-        name: '统一权限登录系统',
-        title: '权限管理系统',
-        subtitle: '统一身份认证和权限管理,确保系统安全性和用户体验的完美平衡。',
-        images: [productsBg01, productsBg02, productsBg01]
-      },
-      {
-        name: '地图通感应用',
-        title: '地图通感平台',
-        subtitle: '基于地理信息的智能感知应用,提供精准的位置服务和空间数据分析。',
-        images: [productsBg02, productsBg01, productsBg02]
-      },
-      {
-        name: '数字学生',
-        title: '数字学生管理',
-        subtitle: '全方位的学生信息管理和学习行为分析,助力个性化教育发展。',
-        images: [productsBg01, productsBg02, productsBg01]
-      },
-      {
-        name: '数据中台',
-        title: '数据中台服务',
-        subtitle: '企业级数据治理和分析平台,实现数据资产的统一管理和价值挖掘。',
-        images: [productsBg02, productsBg01, productsBg02]
-      },
-      {
-        name: 'AI大模型',
-        title: 'AI智能服务',
-        subtitle: '先进的人工智能大模型技术,为企业提供智能化解决方案和服务。',
-        images: [productsBg01, productsBg02, productsBg01]
-      }
-    ])
+    // 平台数据 - 从API获取
+    const platforms = ref([])
+    // 产品列表数据
+    const productList = ref([])
 
     // 产品优势数据
     const advantages = ref([
@@ -176,10 +138,15 @@ export default {
     ])
 
     // 切换平台
-    const switchPlatform = (index) => {
+    const switchPlatform = async (index) => {
       activePlatform.value = index
       currentSlide.value = 0 // 切换平台时重置轮播
       resetAutoPlay()
+
+      // 获取选中分类的产品列表
+      if (platforms.value[index] && platforms.value[index].id) {
+        await getProductsByClassify(platforms.value[index].id)
+      }
     }
 
     // 切换轮播图
@@ -191,8 +158,10 @@ export default {
     // 自动播放
     const startAutoPlay = () => {
       autoPlayTimer = setInterval(() => {
-        const maxSlides = platforms.value[activePlatform.value].images.length
-        currentSlide.value = (currentSlide.value + 1) % maxSlides
+        if (platforms.value[activePlatform.value] && platforms.value[activePlatform.value].images) {
+          const maxSlides = platforms.value[activePlatform.value].images.length
+          currentSlide.value = (currentSlide.value + 1) % maxSlides
+        }
       }, 4000)
     }
 
@@ -216,18 +185,75 @@ export default {
       startAutoPlay()
     }
 
-    // API调用方法
-    const loadProductsData = async () => {
+    // 获取产品分类列表
+    const handleGetProjectClassifyList1 = async () => {
       try {
-        const data = await getProductsData()
-        console.log('产品数据:', data)
+        const data = await getProjectClassifyList({ classifyType: 1 })
+        console.log('产品中心分类列表:', data)
+
+        if (data && data.rows && data.rows.length > 0) {
+          // 处理分类数据,添加默认的展示信息
+          platforms.value = data.rows.map(item => ({
+            ...item,
+            name: item.classifyName || item.name,
+            title: item.classifyName || item.name,
+            subtitle: item.classifyDesc || '为您提供专业的解决方案',
+            images: [productsBg01, productsBg02, productsBg01] // 默认图片,后续可从API获取
+          }))
+
+          console.log('platforms.value', platforms.value)
+
+          // 默认选中第一条,获取对应的产品列表
+          if (platforms.value[0] && platforms.value[0].id) {
+            await getProductsByClassify(platforms.value[0].id)
+          }
+        }
       } catch (error) {
-        console.error('加载产品数据失败:', error)
+        console.error('加载产品中心分类列表失败:', error)
+      }
+    }
+
+    // 根据分类ID获取产品列表
+    const getProductsByClassify = async (classifyId) => {
+      try {
+        const data = await getProjectList({
+          classifyId: classifyId,
+          projectType: 1 // 1:产品中心 2:行业案例
+        })
+        console.log('产品列表:', data)
+
+        if (data && data.rows) {
+          productList.value = data.rows
+          // 更新当前选中平台的信息
+          if (platforms.value[activePlatform.value] && data.rows.length > 0) {
+            // 更新subtitle为第一条数据的projectProfile
+            if (data.rows[0].projectProfile) {
+              platforms.value[activePlatform.value].subtitle = data.rows[0].projectProfile
+            }
+
+            // 使用API返回的产品数据中的projectImage字段
+            const images = data.rows
+              .filter(item => item.projectImage) // 过滤掉没有图片的项目
+              .map(item => imgHost + item.projectImage)
+              .slice(0, 5) // 最多取5张图片
+
+            if (images.length > 0) {
+              platforms.value[activePlatform.value].images = images
+              // 重置轮播到第一张
+              currentSlide.value = 0
+            } else {
+              // 如果没有图片,使用默认图片
+              platforms.value[activePlatform.value].images = [productsBg01, productsBg02, productsBg01]
+            }
+          }
+        }
+      } catch (error) {
+        console.error('加载产品列表失败:', error)
       }
     }
 
     onMounted(() => {
-      loadProductsData()
+      handleGetProjectClassifyList1() // 获取产品分类列表
       startAutoPlay()
     })
 
@@ -241,11 +267,13 @@ export default {
       activePlatform,
       currentSlide,
       platforms,
+      productList,
       advantages,
       switchPlatform,
       goToSlide,
       pauseAutoPlay,
-      resumeAutoPlay
+      resumeAutoPlay,
+      imgHost
     }
   }
 }
@@ -428,7 +456,8 @@ export default {
   background: #f8f9fa;
   padding: 80px 0;
   position: relative;
-  &::before{
+
+  &::before {
     position: absolute;
     content: '';
     left: 0;
@@ -438,7 +467,8 @@ export default {
     background: url('@assets/products-bg02.png') no-repeat center center;
     background-size: cover;
   }
-  .container{
+
+  .container {
     position: relative;
   }
 

+ 92 - 0
src/utils/numberAnimation.js

@@ -0,0 +1,92 @@
+/**
+ * 数字滚动动画工具函数
+ * @param {Function} updateCallback - 更新数字的回调函数
+ * @param {number} target - 目标数字
+ * @param {number} duration - 动画持续时间(毫秒)
+ * @param {Function} easingFunction - 缓动函数
+ */
+export function animateNumber(updateCallback, target, duration = 2000, easingFunction = easeOutQuart) {
+  const start = 0
+  const startTime = performance.now()
+  
+  const animate = (currentTime) => {
+    const elapsed = currentTime - startTime
+    const progress = Math.min(elapsed / duration, 1)
+    
+    const easedProgress = easingFunction(progress)
+    const current = Math.floor(start + (target - start) * easedProgress)
+    
+    updateCallback(current)
+    
+    if (progress < 1) {
+      requestAnimationFrame(animate)
+    } else {
+      updateCallback(target)
+    }
+  }
+  
+  requestAnimationFrame(animate)
+}
+
+/**
+ * 缓动函数 - 四次方缓出
+ * @param {number} t - 进度值 (0-1)
+ * @returns {number} 缓动后的值
+ */
+export function easeOutQuart(t) {
+  return 1 - Math.pow(1 - t, 4)
+}
+
+/**
+ * 缓动函数 - 三次方缓出
+ * @param {number} t - 进度值 (0-1)
+ * @returns {number} 缓动后的值
+ */
+export function easeOutCubic(t) {
+  return 1 - Math.pow(1 - t, 3)
+}
+
+/**
+ * 缓动函数 - 二次方缓出
+ * @param {number} t - 进度值 (0-1)
+ * @returns {number} 缓动后的值
+ */
+export function easeOutQuad(t) {
+  return 1 - (1 - t) * (1 - t)
+}
+
+/**
+ * 创建 Intersection Observer 来触发数字动画
+ * @param {string} selector - 要观察的元素选择器
+ * @param {Function} callback - 当元素进入视口时的回调函数
+ * @param {Object} options - Intersection Observer 选项
+ */
+export function createNumberAnimationObserver(selector, callback, options = {}) {
+  const defaultOptions = {
+    threshold: 0.5,
+    rootMargin: '0px 0px -100px 0px'
+  }
+  
+  const observerOptions = { ...defaultOptions, ...options }
+  
+  const element = document.querySelector(selector)
+  if (!element) {
+    console.warn(`Element with selector "${selector}" not found`)
+    return null
+  }
+
+  const observer = new IntersectionObserver(
+    (entries) => {
+      entries.forEach((entry) => {
+        if (entry.isIntersecting) {
+          callback()
+          observer.unobserve(entry.target) // 只触发一次
+        }
+      })
+    },
+    observerOptions
+  )
+
+  observer.observe(element)
+  return observer
+}