فهرست منبع

feat(content): 添加内容未找到页面组件

- 新增 ContentNotFound 组件,包含趣味性提示信息- 实现随机选择幽默文案的功能
- 添加浮动粒子动画效果
- 设计返回首页的带动画按钮
- 支持响应式布局和多种设备适配

fix(footer): 优化底部信息展示逻辑- 将 FooterBlock 改为异步组件以支持服务端数据获取
- 从接口获取公司基本信息并动态渲染
- 替换硬编码电话号码和地址为动态数据
- 动态加载二维码图片路径
- 添加商务合作链接导航

refactor(development): 优化发展历程页面实现-为数据请求添加缓存策略和重新验证时间
- 调整时间轴在不同屏幕尺寸下的布局表现-优化时间节点在移动端的显示样式- 改进描述文字在小屏幕上的排版
- 微调整体间距和元素尺寸适配多端
nahida 7 ماه پیش
والد
کامیت
22b9559bd1
3فایلهای تغییر یافته به همراه170 افزوده شده و 18 حذف شده
  1. 117 0
      src/components/ContentNotFound.tsx
  2. 21 12
      src/components/about/Development.tsx
  3. 32 6
      src/components/footerBlock.tsx

+ 117 - 0
src/components/ContentNotFound.tsx

@@ -0,0 +1,117 @@
+"use client"
+
+import {Home, Newspaper, Sparkles} from "lucide-react"
+import Link from "next/link"
+import {useEffect, useState} from "react"
+
+const funnyMessages = [
+  {
+    title: "文章跑路了 🏃💨",
+    desc: "记者还在追赶中,请您稍安勿躁~",
+    iconClass: "text-purple-400",
+    bgGradient: "from-purple-400/20 to-pink-400/20",
+  },
+  {
+    title: "文章去摸鱼了 🐟",
+    desc: "估计一时半会儿也不会回来…",
+    iconClass: "text-sky-400",
+    bgGradient: "from-sky-400/20 to-blue-400/20",
+  },
+  {
+    title: "文章开小差了 🙈",
+    desc: "它可能在偷偷喝咖啡☕",
+    iconClass: "text-amber-400",
+    bgGradient: "from-amber-400/20 to-orange-400/20",
+  },
+  {
+    title: "文章掉线了 📡",
+    desc: "等信号回来再试试吧~",
+    iconClass: "text-rose-400",
+    bgGradient: "from-rose-400/20 to-red-400/20",
+  },
+  {
+    title: "文章请假了 📝",
+    desc: "理由:今天心情不太适合上班。",
+    iconClass: "text-green-400",
+    bgGradient: "from-green-400/20 to-emerald-400/20",
+  },
+]
+
+const FloatingParticles = () => {
+  return (
+    <div className="absolute inset-0 overflow-hidden pointer-events-none">
+      {[...Array(20)].map((_, i) => (
+        <div
+          key={i}
+          className="absolute animate-float opacity-30"
+          style={{
+            left: `${Math.random() * 100}%`,
+            top: `${Math.random() * 100}%`,
+            animationDelay: `${Math.random() * 3}s`,
+            animationDuration: `${3 + Math.random() * 4}s`,
+          }}
+        >
+          <Sparkles className="w-4 h-4 text-gray-400" />
+        </div>
+      ))}
+    </div>
+  )
+}
+
+export default function ContentNotFound() {
+  const [pick, setPick] = useState(funnyMessages[0])
+  const [mounted, setMounted] = useState(false)
+
+  useEffect(() => {
+    setMounted(true)
+    setPick(funnyMessages[Math.floor(Math.random() * funnyMessages.length)])
+  }, [])
+
+  if (!mounted) return null
+
+  return (
+    <div className="relative overflow-hidden">
+      <div className={`absolute inset-0 bg-gradient-to-br ${pick.bgGradient} animate-pulse`} />
+      <div className="absolute inset-0 bg-gradient-to-tr from-transparent via-white/5 to-transparent animate-shimmer" />
+
+      <FloatingParticles />
+
+      <div className="relative z-10 w-4/5 mx-auto flex flex-col items-center justify-center py-20 text-center">
+        <div className="relative mb-8">
+          <div className="absolute inset-0 animate-ping">
+            <Newspaper className={`w-20 h-20 ${pick.iconClass} opacity-20`} />
+          </div>
+          <Newspaper className={`w-20 h-20 ${pick.iconClass} animate-bounce relative z-10 drop-shadow-lg`} />
+        </div>
+
+        <h2 className="text-4xl font-bold text-gray-800 mb-4 animate-slideInUp">
+          <span className="bg-gradient-to-r from-gray-700 to-gray-900 bg-clip-text text-transparent">{pick.title}</span>
+        </h2>
+
+        <p className="text-lg text-gray-600 mb-8 animate-slideInUp animation-delay-200 max-w-md leading-relaxed">
+          {pick.desc}
+        </p>
+
+        <Link
+          href="/"
+          className="group relative inline-flex items-center gap-3 px-8 py-4 rounded-full bg-gradient-to-r from-blue-500 to-purple-600 text-white font-semibold shadow-xl hover:shadow-2xl transform hover:scale-105 transition-all duration-300 animate-slideInUp animation-delay-400 overflow-hidden"
+        >
+          <div className="absolute inset-0 bg-gradient-to-r from-purple-600 to-blue-500 opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
+          <Home className="w-5 h-5 relative z-10 group-hover:rotate-12 transition-transform duration-300" />
+          <span className="relative z-10">回到首页</span>
+          <div className="absolute inset-0 bg-white/20 translate-x-[-100%] group-hover:translate-x-[100%] transition-transform duration-700 skew-x-12" />
+        </Link>
+
+        <div className="mt-12 flex space-x-2 animate-slideInUp animation-delay-600">
+          {[...Array(3)].map((_, i) => (
+            <div
+              key={i}
+              className="w-2 h-2 rounded-full bg-gray-400 animate-pulse"
+              style={{ animationDelay: `${i * 0.2}s` }}
+            />
+          ))}
+        </div>
+      </div>
+    </div>
+  )
+}

+ 21 - 12
src/components/about/Development.tsx

@@ -2,7 +2,12 @@ import React from 'react';
 import {serverGet} from "@/utils/request";
 
 async function Development() {
-  const res = await serverGet<{year:number,processDescription:string}[]>("/webSite/getDevelopmentHistory")
+  const res = await serverGet<{year:number,processDescription:string}[]>("/webSite/getDevelopmentHistory",null,{
+    next: {
+      revalidate: 180
+    },
+    cache: "force-cache"
+  })
   const list = res.data.map(item => ({
     year: item.year,
     description: item.processDescription
@@ -22,26 +27,29 @@ async function Development() {
         </div>
 
         {/* Timeline container */}
-        <div className="relative z-10 flex items-center justify-center px-8 py-16">
+        <div className="relative z-10 flex items-center justify-center px-4 sm:px-8 py-10 sm:py-16">
           <div className="w-full max-w-7xl">
-            {/* Timeline line and dots */}
-            <div className="relative mb-16">
-              {/* Horizontal line */}
-              {/*<div className="absolute top-1/2 left-0 right-0 h-0.5 bg-white/30 transform -translate-y-1/2"></div>*/}
-
+            <div className="relative mb-10 sm:mb-16">
               {/* Timeline items */}
-              <div className="flex justify-between items-center relative flex-wrap">
+              <div
+                className="flex flex-col sm:flex-row sm:justify-between sm:items-start relative flex-wrap gap-10 sm:gap-0">
                 {list.map((item, index) => (
-                  <div key={index} className="flex flex-col items-center relative w-1/4">
+                  <div
+                    key={index}
+                    className="flex flex-col items-center relative w-full sm:w-1/4"
+                  >
                     {/* Dot */}
                     <div
-                      className="w-4 h-4 bg-white rounded-full border-4 border-blue-600 relative z-10 mb-8"></div>
+                      className="w-3 h-3 sm:w-4 sm:h-4 bg-white rounded-full border-2 sm:border-4 border-blue-600 relative z-10 mb-4 sm:mb-8"></div>
 
                     {/* Year */}
-                    <div className="text-white text-2xl font-bold mb-4 text-center">{item.year}</div>
+                    <div className="text-white text-lg sm:text-2xl font-bold mb-2 sm:mb-4 text-center">
+                      {item.year}
+                    </div>
 
                     {/* Description */}
-                    <div className="text-white/90 w-full h-40 text-sm leading-relaxed max-w-xs text-center px-4 border-t-2 border-solid border-gray-300 pt-2">
+                    <div
+                      className="text-white/90 w-full h-auto sm:h-40 text-sm leading-relaxed max-w-xs text-center px-2 sm:px-4 border-t-2 border-solid border-gray-300 pt-2">
                       {item.description}
                     </div>
                   </div>
@@ -51,6 +59,7 @@ async function Development() {
           </div>
         </div>
       </div>
+
     </>
   );
 }

+ 32 - 6
src/components/footerBlock.tsx

@@ -1,7 +1,30 @@
 import Link from "next/link"
 import Image from "next/image";
+import {serverGet} from "@/utils/request";
 
-export default function FooterBlock() {
+export default async function FooterBlock() {
+  const BASE_URL:string = process.env.NEXT_PUBLIC_BASE_URL as string;
+  const basicInfoRes = await serverGet<BasicInfo[]>("/webSite/getBasicInfo",{
+    next: {
+      revalidate: 1800
+    },
+    cache: "force-cache"
+  })
+  const basicInfo = basicInfoRes.data[0] || {
+    address: "",
+    companyProfile: "",
+    companyProfileUrl: "",
+    consultationHotline: "",
+    email: "",
+    hardwareIntroduction: "",
+    id: "",
+    qrCodeUrl: "",
+    serviceHotline: "",
+    softwareIntroduction: "",
+    telephone: ""
+  };
+
+  const qrCodeUrl = BASE_URL + basicInfo.qrCodeUrl;
   return (
     <footer className="bg-[url('/assets/home/27.jpg')] bg-cover text-white py-12 px-6">
       <div className="max-w-6xl mx-auto">
@@ -35,6 +58,11 @@ export default function FooterBlock() {
                   服务支持
                 </Link>
               </li>
+              <li>
+                <Link href="/business" className="text-blue-200 hover:text-white transition-colors">
+                  商务合作
+                </Link>
+              </li>
               <li>
                 <Link href="/about" className="text-blue-200 hover:text-white transition-colors">
                   关于我们
@@ -47,13 +75,11 @@ export default function FooterBlock() {
           <div>
             <h3 className="text-lg font-semibold mb-4">联系方式</h3>
             <div className="space-y-3">
-              <p className="text-blue-200">0731-85315153</p>
+              <p className="text-blue-200">{basicInfo.telephone}</p>
               <div>
                 <h4 className="font-medium mb-2">公司地址</h4>
                 <p className="text-blue-200 text-sm leading-relaxed">
-                  湖南省长沙市岳麓区梅溪湖街道泉水路461号
-                  <br />
-                  长沙健康医疗大数据产业孵化基地1-2#楼 未来楼5楼左侧
+                  {basicInfo.address}
                 </p>
               </div>
             </div>
@@ -65,7 +91,7 @@ export default function FooterBlock() {
             <div className="space-y-4">
               {/* QR Code placeholder - using a colored block */}
               <div className="w-28 h-28 bg-white border-2 border-gray-300 flex items-center justify-center">
-                  <Image src={"/assets/home/26.jpg"} alt={"qrCode"} width={500} height={500} />
+                  <Image src={qrCodeUrl} alt={"qrCode"} width={500} height={500} />
               </div>
               <div className="text-sm text-blue-200">
                 <p>- 版权所有 -</p>