46 KiB
Novalon 官网重新设计实施计划
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: 将 Novalon 官网从现有设计升级为深色科技风格的现代化企业网站
Architecture: 采用 Next.js 16 App Router + React 19 + TypeScript + Tailwind CSS v4 技术栈,基于组件化设计,实现深色科技风格的视觉系统和流畅的用户体验
Tech Stack: Next.js 16, React 19, TypeScript 5, Tailwind CSS v4, Framer Motion, AntV G2, shadcn/ui
前置准备
Task 0: 创建开发分支
Files:
- None
Step 1: 检查当前分支状态
Run: git status
Expected: 工作目录干净,在 main 或 develop 分支
Step 2: 创建新的功能分支
Run: git checkout -b feature/website-redesign
Expected: 切换到新分支 feature/website-redesign
Step 3: 推送分支到远程
Run: git push -u origin feature/website-redesign
Expected: 分支推送到远程仓库
阶段一:基础架构搭建
Task 1: 安装必要依赖
Files:
- Modify:
package.json
Step 1: 安装动画库
Run: npm install framer-motion
Expected: framer-motion 安装成功
Step 2: 安装图表库
Run: npm install @antv/g2
Expected: @antv/g2 安装成功
Step 3: 安装 CVA(如果尚未安装)
Run: npm install class-variance-authority
Expected: class-variance-authority 安装成功
Step 4: 验证安装
Run: npm list framer-motion @antv/g2 class-variance-authority
Expected: 显示已安装的版本信息
Step 5: 提交依赖更新
Run:
git add package.json package-lock.json
git commit -m "chore: add framer-motion, @antv/g2, and class-variance-authority dependencies"
Expected: 提交成功
Task 2: 扩展 Tailwind 配置
Files:
- Modify:
tailwind.config.ts(如果不存在则创建)
Step 1: 检查 Tailwind 配置文件
Run: ls -la | grep tailwind
Expected: 显示 tailwind 配置文件
Step 2: 读取现有配置
Read: tailwind.config.ts
Step 3: 扩展配置添加深色主题色彩
Modify: tailwind.config.ts
import type { Config } from "tailwindcss";
export default {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
colors: {
dark: {
DEFAULT: "#0A0A0A",
secondary: "#1A1A1A",
tertiary: "#2A2A2A",
},
tech: {
blue: "#00D9FF",
purple: "#A855F7",
cyan: "#06B6D4",
},
},
fontFamily: {
sans: ["Inter", "system-ui", "sans-serif"],
mono: ["JetBrains Mono", "monospace"],
},
animation: {
"fade-in-up": "fadeInUp 0.6s ease-out",
"fade-in-scale": "fadeInScale 0.6s ease-out",
glow: "glow 2s ease-in-out infinite",
float: "float 3s ease-in-out infinite",
},
keyframes: {
fadeInUp: {
"0%": { opacity: "0", transform: "translateY(20px)" },
"100%": { opacity: "1", transform: "translateY(0)" },
},
fadeInScale: {
"0%": { opacity: "0", transform: "scale(0.95)" },
"100%": { opacity: "1", transform: "scale(1)" },
},
glow: {
"0%, 100%": { boxShadow: "0 0 20px rgba(0, 217, 255, 0.3)" },
"50%": { boxShadow: "0 0 40px rgba(0, 217, 255, 0.6)" },
},
float: {
"0%, 100%": { transform: "translateY(0px)" },
"50%": { transform: "translateY(-10px)" },
},
},
},
},
plugins: [],
} satisfies Config;
Step 4: 验证配置语法
Run: npx tsc --noEmit tailwind.config.ts
Expected: 无错误输出
Step 5: 提交配置更新
Run:
git add tailwind.config.ts
git commit -m "feat: extend Tailwind config with dark theme and tech colors"
Expected: 提交成功
Task 3: 更新全局样式
Files:
- Modify:
src/app/globals.css
Step 1: 读取现有全局样式
Read: src/app/globals.css
Step 2: 添加 CSS 变量和基础样式
Modify: src/app/globals.css
在文件顶部添加:
:root {
--color-dark: #0A0A0A;
--color-dark-secondary: #1A1A1A;
--color-dark-tertiary: #2A2A2A;
--color-tech-blue: #00D9FF;
--color-tech-purple: #A855F7;
--color-tech-cyan: #06B6D4;
--gradient-primary: linear-gradient(135deg, #00D9FF 0%, #A855F7 100%);
--gradient-dark: linear-gradient(180deg, #0A0A0A 0%, #1A1A1A 100%);
--gradient-glow: radial-gradient(circle, #00D9FF20 0%, transparent 70%);
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html {
scroll-behavior: smooth;
}
body {
background-color: var(--color-dark);
color: #FFFFFF;
font-family: 'Inter', system-ui, sans-serif;
line-height: 1.6;
}
a {
color: inherit;
text-decoration: none;
}
button {
font-family: inherit;
}
input, textarea {
font-family: inherit;
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: var(--color-dark-secondary);
}
::-webkit-scrollbar-thumb {
background: var(--color-tech-blue);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--color-tech-purple);
}
Step 3: 验证样式文件
Run: npm run build
Expected: 构建成功,无样式错误
Step 4: 提交样式更新
Run:
git add src/app/globals.css
git commit -m "feat: add CSS variables and base styles for dark theme"
Expected: 提交成功
Task 4: 创建工具函数
Files:
- Modify:
src/lib/utils.ts
Step 1: 读取现有工具函数
Read: src/lib/utils.ts
Step 2: 添加新的工具函数
Modify: src/lib/utils.ts
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function formatNumber(num: number): string {
return new Intl.NumberFormat("zh-CN").format(num);
}
export function formatCurrency(amount: number): string {
return new Intl.NumberFormat("zh-CN", {
style: "currency",
currency: "CNY",
}).format(amount);
}
export function debounce<T extends (...args: unknown[]) => unknown>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout | null = null;
return (...args: Parameters<T>) => {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
}
export function throttle<T extends (...args: unknown[]) => unknown>(
func: T,
limit: number
): (...args: Parameters<T>) => void {
let inThrottle: boolean;
return (...args: Parameters<T>) => {
if (!inThrottle) {
func(...args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}
export function randomBetween(min: number, max: number): number {
return Math.random() * (max - min) + min;
}
export function lerp(start: number, end: number, t: number): number {
return start + (end - start) * t;
}
export function clamp(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max);
}
Step 3: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 4: 提交工具函数
Run:
git add src/lib/utils.ts
git commit -m "feat: add utility functions for formatting and animation"
Expected: 提交成功
Task 5: 创建主题常量
Files:
- Modify:
src/lib/constants.ts
Step 1: 读取现有常量
Read: src/lib/constants.ts
Step 2: 添加主题相关常量
Modify: src/lib/constants.ts
在文件末尾添加:
export const THEME = {
colors: {
dark: {
DEFAULT: "#0A0A0A",
secondary: "#1A1A1A",
tertiary: "#2A2A2A",
},
tech: {
blue: "#00D9FF",
purple: "#A855F7",
cyan: "#06B6D4",
},
text: {
primary: "#FFFFFF",
secondary: "#A0A0A0",
disabled: "#606060",
},
},
gradients: {
primary: "linear-gradient(135deg, #00D9FF 0%, #A855F7 100%)",
dark: "linear-gradient(180deg, #0A0A0A 0%, #1A1A1A 100%)",
glow: "radial-gradient(circle, #00D9FF20 0%, transparent 70%)",
},
spacing: {
xs: "4px",
sm: "8px",
md: "16px",
lg: "24px",
xl: "32px",
"2xl": "48px",
"3xl": "64px",
},
borderRadius: {
sm: "8px",
md: "12px",
lg: "16px",
full: "9999px",
},
animation: {
fast: "150ms",
standard: "300ms",
slow: "500ms",
verySlow: "1000ms",
},
breakpoints: {
sm: "640px",
md: "768px",
lg: "1024px",
xl: "1280px",
"2xl": "1536px",
},
} as const;
export const ANIMATION_VARIANTS = {
fadeInUp: {
initial: { opacity: 0, y: 20 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -20 },
},
fadeInScale: {
initial: { opacity: 0, scale: 0.95 },
animate: { opacity: 1, scale: 1 },
exit: { opacity: 0, scale: 0.95 },
},
slideInLeft: {
initial: { opacity: 0, x: -20 },
animate: { opacity: 1, x: 0 },
exit: { opacity: 0, x: 20 },
},
slideInRight: {
initial: { opacity: 0, x: 20 },
animate: { opacity: 1, x: 0 },
exit: { opacity: 0, x: -20 },
},
} as const;
Step 3: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 4: 提交常量更新
Run:
git add src/lib/constants.ts
git commit -m "feat: add theme constants and animation variants"
Expected: 提交成功
阶段二:基础UI组件开发
Task 6: 创建增强版按钮组件
Files:
- Modify:
src/components/ui/button.tsx
Step 1: 读取现有按钮组件
Read: src/components/ui/button.tsx
Step 2: 重写按钮组件以支持深色主题
Modify: src/components/ui/button.tsx
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-lg text-sm font-medium transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-tech-blue focus-visible:ring-offset-2 focus-visible:ring-offset-dark disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default:
"bg-gradient-to-r from-tech-blue to-tech-purple text-white hover:shadow-lg hover:shadow-tech-blue/50 hover:scale-105 active:scale-95",
secondary:
"bg-dark-tertiary text-white border border-gray-700 hover:border-tech-blue hover:shadow-lg hover:shadow-tech-blue/20 hover:scale-105 active:scale-95",
outline:
"border border-tech-blue text-tech-blue hover:bg-tech-blue/10 hover:shadow-lg hover:shadow-tech-blue/20",
ghost:
"text-gray-300 hover:text-tech-blue hover:bg-dark-tertiary",
link: "text-tech-blue underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-6 py-2",
sm: "h-8 px-4 text-xs",
lg: "h-12 px-8 text-base",
xl: "h-14 px-10 text-lg",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, ...props }, ref) => {
return (
<button
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
}
);
Button.displayName = "Button";
export { Button, buttonVariants };
Step 3: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 4: 提交按钮组件
Run:
git add src/components/ui/button.tsx
git commit -m "feat: enhance button component with dark theme variants"
Expected: 提交成功
Task 7: 创建增强版卡片组件
Files:
- Modify:
src/components/ui/card.tsx
Step 1: 读取现有卡片组件
Read: src/components/ui/card.tsx
Step 2: 重写卡片组件以支持深色主题和悬停效果
Modify: src/components/ui/card.tsx
import * as React from "react";
import { cn } from "@/lib/utils";
const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & {
variant?: "default" | "hover" | "glow";
}
>(({ className, variant = "default", ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-xl border border-gray-800 bg-dark-tertiary text-white transition-all duration-300",
{
"hover:border-tech-blue hover:shadow-lg hover:shadow-tech-blue/20 hover:-translate-y-2":
variant === "hover",
"hover:border-tech-blue hover:shadow-xl hover:shadow-tech-blue/30 hover:-translate-y-2 animate-glow":
variant === "glow",
},
className
)}
{...props}
/>
));
Card.displayName = "Card";
const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
));
CardHeader.displayName = "CardHeader";
const CardTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn(
"text-2xl font-bold leading-none tracking-tight text-white",
className
)}
{...props}
/>
));
CardTitle.displayName = "CardTitle";
const CardDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p
ref={ref}
className={cn("text-sm text-gray-400", className)}
{...props}
/>
));
CardDescription.displayName = "CardDescription";
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
));
CardContent.displayName = "CardContent";
const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
));
CardFooter.displayName = "CardFooter";
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
Step 3: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 4: 提交卡片组件
Run:
git add src/components/ui/card.tsx
git commit -m "feat: enhance card component with dark theme and hover effects"
Expected: 提交成功
Task 8: 创建输入框组件
Files:
- Modify:
src/components/ui/input.tsx
Step 1: 读取现有输入框组件
Read: src/components/ui/input.tsx
Step 2: 重写输入框组件以支持深色主题
Modify: src/components/ui/input.tsx
import * as React from "react";
import { cn } from "@/lib/utils";
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-lg border border-gray-700 bg-dark-secondary px-4 py-2 text-sm text-white placeholder:text-gray-500 transition-all duration-300",
"focus:border-tech-blue focus:outline-none focus:ring-2 focus:ring-tech-blue/20 focus:shadow-lg focus:shadow-tech-blue/10",
"disabled:cursor-not-allowed disabled:opacity-50",
"hover:border-gray-600",
className
)}
ref={ref}
{...props}
/>
);
}
);
Input.displayName = "Input";
export { Input };
Step 3: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 4: 提交输入框组件
Run:
git add src/components/ui/input.tsx
git commit -m "feat: enhance input component with dark theme styles"
Expected: 提交成功
Task 9: 创建徽章组件
Files:
- Modify:
src/components/ui/badge.tsx
Step 1: 读取现有徽章组件
Read: src/components/ui/badge.tsx
Step 2: 重写徽章组件以支持深色主题
Modify: src/components/ui/badge.tsx
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const badgeVariants = cva(
"inline-flex items-center rounded-full px-3 py-1 text-xs font-medium transition-colors duration-300",
{
variants: {
variant: {
default:
"bg-tech-blue/20 text-tech-blue border border-tech-blue/30",
secondary:
"bg-tech-purple/20 text-tech-purple border border-tech-purple/30",
success:
"bg-green-500/20 text-green-400 border border-green-500/30",
warning:
"bg-yellow-500/20 text-yellow-400 border border-yellow-500/30",
error:
"bg-red-500/20 text-red-400 border border-red-500/30",
outline:
"bg-transparent text-gray-300 border border-gray-600",
},
},
defaultVariants: {
variant: "default",
},
}
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
);
}
export { Badge, badgeVariants };
Step 3: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 4: 提交徽章组件
Run:
git add src/components/ui/badge.tsx
git commit -m "feat: enhance badge component with dark theme variants"
Expected: 提交成功
阶段三:布局组件重构
Task 10: 重构导航栏组件
Files:
- Modify:
src/components/layout/header.tsx
Step 1: 读取现有导航栏组件
Read: src/components/layout/header.tsx
Step 2: 重写导航栏组件以支持深色主题和下拉菜单
Modify: src/components/layout/header.tsx
"use client";
import { useState, useEffect } from "react";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { NAVIGATION, COMPANY_INFO } from "@/lib/constants";
import { cn } from "@/lib/utils";
import { ChevronDown, Menu, X } from "lucide-react";
export function Header() {
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [activeDropdown, setActiveDropdown] = useState<string | null>(null);
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 10);
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
return (
<header
className={cn(
"fixed top-0 left-0 right-0 z-50 transition-all duration-300",
isScrolled
? "bg-dark/95 backdrop-blur-md border-b border-gray-800 shadow-lg"
: "bg-transparent"
)}
>
<nav className="container-wide h-16 flex items-center justify-between">
<Link href="/" className="flex items-center gap-2 group">
<div className="relative">
<img
src="/logo.svg"
alt={COMPANY_INFO.shortName}
className="h-8 w-auto transition-all duration-300 group-hover:drop-shadow-[0_0_10px_rgba(0,217,255,0.5)]"
/>
</div>
<span className="text-lg font-bold text-white hidden sm:block">
{COMPANY_INFO.shortName}
</span>
</Link>
<div className="hidden lg:flex items-center gap-8">
{NAVIGATION.map((item) => (
<Link
key={item.id}
href={item.href}
className="text-gray-300 hover:text-tech-blue transition-colors duration-300 relative group"
>
{item.label}
<span className="absolute -bottom-1 left-0 w-0 h-0.5 bg-tech-blue transition-all duration-300 group-hover:w-full" />
</Link>
))}
</div>
<div className="hidden lg:flex items-center gap-4">
<Button variant="ghost" size="sm">
登录
</Button>
<Button variant="default" size="sm">
免费试用
</Button>
</div>
<button
className="lg:hidden text-white p-2"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
aria-label="Toggle menu"
>
{isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
</button>
</nav>
{isMobileMenuOpen && (
<div className="lg:hidden bg-dark-secondary border-t border-gray-800">
<div className="container-wide py-4 space-y-4">
{NAVIGATION.map((item) => (
<Link
key={item.id}
href={item.href}
className="block text-gray-300 hover:text-tech-blue transition-colors duration-300 py-2"
onClick={() => setIsMobileMenuOpen(false)}
>
{item.label}
</Link>
))}
<div className="flex flex-col gap-2 pt-4 border-t border-gray-800">
<Button variant="ghost" className="w-full">
登录
</Button>
<Button variant="default" className="w-full">
免费试用
</Button>
</div>
</div>
</div>
)}
</header>
);
}
Step 3: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 4: 提交导航栏组件
Run:
git add src/components/layout/header.tsx
git commit -m "feat: refactor header with dark theme and mobile menu"
Expected: 提交成功
Task 11: 重构页脚组件
Files:
- Modify:
src/components/layout/footer.tsx
Step 1: 读取现有页脚组件
Read: src/components/layout/footer.tsx
Step 2: 重写页脚组件以支持深色主题
Modify: src/components/layout/footer.tsx
import Link from "next/link";
import { COMPANY_INFO } from "@/lib/constants";
export function Footer() {
const currentYear = new Date().getFullYear();
const footerLinks = {
products: [
{ label: "ERP系统", href: "/products/erp" },
{ label: "CRM系统", href: "/products/crm" },
{ label: "OA平台", href: "/products/oa" },
{ label: "BI平台", href: "/products/bi" },
],
solutions: [
{ label: "金融行业", href: "/solutions/finance" },
{ label: "制造业", href: "/solutions/manufacturing" },
{ label: "零售行业", href: "/solutions/retail" },
{ label: "教育行业", href: "/solutions/education" },
],
company: [
{ label: "关于我们", href: "/about" },
{ label: "新闻动态", href: "/news" },
{ label: "成功案例", href: "/cases" },
{ label: "联系我们", href: "/contact" },
],
};
return (
<footer className="bg-dark-secondary border-t border-gray-800">
<div className="container-wide py-12">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
<div className="space-y-4">
<Link href="/" className="flex items-center gap-2">
<img
src="/logo.svg"
alt={COMPANY_INFO.shortName}
className="h-8 w-auto"
/>
<span className="text-lg font-bold text-white">
{COMPANY_INFO.shortName}
</span>
</Link>
<p className="text-sm text-gray-400">
{COMPANY_INFO.slogan}
</p>
<div className="flex gap-4">
<a
href="#"
className="text-gray-400 hover:text-tech-blue transition-colors duration-300"
aria-label="WeChat"
>
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 01.213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 00.167-.054l1.903-1.114a.864.864 0 01.717-.098 10.16 10.16 0 002.837.403c.276 0 .543-.027.811-.05-.857-2.578.157-4.972 1.932-6.446 1.703-1.415 3.882-1.98 5.853-1.838-.576-3.583-4.196-6.348-8.596-6.348zM5.785 5.991c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 01-1.162 1.178A1.17 1.17 0 014.623 7.17c0-.651.52-1.18 1.162-1.18zm5.813 0c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 01-1.162 1.178 1.17 1.17 0 01-1.162-1.178c0-.651.52-1.18 1.162-1.18zm5.34 2.867c-1.797-.052-3.746.512-5.28 1.786-1.72 1.428-2.687 3.72-1.78 6.22.942 2.453 3.666 4.229 6.884 4.229.826 0 1.622-.12 2.361-.336a.722.722 0 01.598.082l1.584.926a.272.272 0 00.14.047c.134 0 .24-.111.24-.247 0-.06-.023-.12-.038-.177l-.327-1.233a.582.582 0 01-.023-.156.49.49 0 01.201-.398C23.024 18.48 24 16.82 24 14.98c0-3.21-2.931-5.837-7.062-6.122zm-2.036 2.87c.535 0 .969.44.969.982a.976.976 0 01-.969.983.976.976 0 01-.969-.983c0-.542.434-.982.97-.982zm4.844 0c.535 0 .969.44.969.982a.976.976 0 01-.969.983.976.976 0 01-.969-.983c0-.542.434-.982.97-.982z" />
</svg>
</a>
<a
href="#"
className="text-gray-400 hover:text-tech-blue transition-colors duration-300"
aria-label="Weibo"
>
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M10.098 20.323c-3.977.391-7.414-1.406-7.672-4.02-.259-2.609 2.759-5.047 6.74-5.441 3.979-.394 7.413 1.404 7.671 4.018.259 2.6-2.759 5.049-6.737 5.439l-.002.004zM9.05 17.219c-.384.616-1.208.884-1.829.602-.612-.279-.793-.991-.406-1.593.379-.595 1.176-.861 1.793-.601.622.263.82.972.442 1.592zm1.27-1.627c-.141.237-.449.353-.689.253-.236-.09-.313-.361-.177-.586.138-.227.436-.346.672-.24.239.09.315.36.18.573h.014zm.176-2.719c-1.893-.493-4.033.45-4.857 2.118-.836 1.704-.026 3.591 1.886 4.21 1.983.64 4.318-.341 5.132-2.179.8-1.793-.201-3.642-2.161-4.149zm7.563-1.224c-.346-.105-.579-.18-.405-.649.381-1.017.422-1.896-.001-2.521-.792-1.163-2.951-1.102-5.418-.03 0 0-.776.34-.578-.275.381-1.217.324-2.236-.27-2.82-1.349-1.326-4.935.05-8.012 3.073C.417 11.473-.27 14.034-.27 16.218c0 4.179 5.37 6.717 10.624 6.717 6.886 0 11.469-3.997 11.469-7.169 0-1.917-1.618-3.004-3.764-3.617h.002zm2.029-5.47c-.439-.511-1.09-.744-1.741-.653-.651.091-1.178.488-1.434 1.065-.256.577-.197 1.23.157 1.742.354.512.941.812 1.592.812.651 0 1.238-.3 1.592-.812.354-.512.413-1.165.157-1.742-.256-.577-.783-.974-1.434-1.065-.651-.091-1.302.142-1.741.653h-.003v.003z" />
</svg>
</a>
</div>
</div>
<div>
<h3 className="text-white font-semibold mb-4">产品服务</h3>
<ul className="space-y-2">
{footerLinks.products.map((link) => (
<li key={link.href}>
<Link
href={link.href}
className="text-sm text-gray-400 hover:text-tech-blue transition-colors duration-300"
>
{link.label}
</Link>
</li>
))}
</ul>
</div>
<div>
<h3 className="text-white font-semibold mb-4">解决方案</h3>
<ul className="space-y-2">
{footerLinks.solutions.map((link) => (
<li key={link.href}>
<Link
href={link.href}
className="text-sm text-gray-400 hover:text-tech-blue transition-colors duration-300"
>
{link.label}
</Link>
</li>
))}
</ul>
</div>
<div>
<h3 className="text-white font-semibold mb-4">关于我们</h3>
<ul className="space-y-2">
{footerLinks.company.map((link) => (
<li key={link.href}>
<Link
href={link.href}
className="text-sm text-gray-400 hover:text-tech-blue transition-colors duration-300"
>
{link.label}
</Link>
</li>
))}
</ul>
</div>
</div>
<div className="mt-12 pt-8 border-t border-gray-800">
<div className="flex flex-col md:flex-row justify-between items-center gap-4">
<p className="text-sm text-gray-400">
© {currentYear} {COMPANY_INFO.name}. All rights reserved.
</p>
<div className="flex gap-6">
<Link
href="/privacy"
className="text-sm text-gray-400 hover:text-tech-blue transition-colors duration-300"
>
隐私政策
</Link>
<Link
href="/terms"
className="text-sm text-gray-400 hover:text-tech-blue transition-colors duration-300"
>
服务条款
</Link>
</div>
</div>
</div>
</div>
</footer>
);
}
Step 3: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 4: 提交页脚组件
Run:
git add src/components/layout/footer.tsx
git commit -m "feat: refactor footer with dark theme and improved layout"
Expected: 提交成功
阶段四:特效组件开发
Task 12: 创建粒子背景组件
Files:
- Create:
src/components/effects/particle-background.tsx
Step 1: 创建粒子背景组件
Create: src/components/effects/particle-background.tsx
"use client";
import { useEffect, useRef } from "react";
import { randomBetween } from "@/lib/utils";
interface Particle {
x: number;
y: number;
vx: number;
vy: number;
size: number;
color: string;
opacity: number;
}
interface ParticleBackgroundProps {
particleCount?: number;
colors?: string[];
minSize?: number;
maxSize?: number;
speed?: number;
className?: string;
}
export function ParticleBackground({
particleCount = 50,
colors = ["#00D9FF", "#A855F7", "#06B6D4"],
minSize = 1,
maxSize = 3,
speed = 0.5,
className = "",
}: ParticleBackgroundProps) {
const canvasRef = useRef<HTMLCanvasElement>(null);
const particlesRef = useRef<Particle[]>([]);
const animationRef = useRef<number>();
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext("2d");
if (!ctx) return;
const resizeCanvas = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
resizeCanvas();
window.addEventListener("resize", resizeCanvas);
particlesRef.current = Array.from({ length: particleCount }, () => ({
x: randomBetween(0, canvas.width),
y: randomBetween(0, canvas.height),
vx: randomBetween(-speed, speed),
vy: randomBetween(-speed, speed),
size: randomBetween(minSize, maxSize),
color: colors[Math.floor(Math.random() * colors.length)],
opacity: randomBetween(0.1, 0.5),
}));
const animate = () => {
if (!ctx || !canvas) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
particlesRef.current.forEach((particle) => {
particle.x += particle.vx;
particle.y += particle.vy;
if (particle.x < 0 || particle.x > canvas.width) particle.vx *= -1;
if (particle.y < 0 || particle.y > canvas.height) particle.vy *= -1;
ctx.beginPath();
ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
ctx.fillStyle = particle.color;
ctx.globalAlpha = particle.opacity;
ctx.fill();
});
ctx.globalAlpha = 1;
animationRef.current = requestAnimationFrame(animate);
};
animate();
return () => {
window.removeEventListener("resize", resizeCanvas);
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
};
}, [particleCount, colors, minSize, maxSize, speed]);
return (
<canvas
ref={canvasRef}
className={`absolute inset-0 pointer-events-none ${className}`}
style={{ zIndex: 0 }}
/>
);
}
Step 2: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 3: 提交粒子背景组件
Run:
git add src/components/effects/particle-background.tsx
git commit -m "feat: create particle background component for hero section"
Expected: 提交成功
Task 13: 创建发光效果组件
Files:
- Create:
src/components/effects/glow-effect.tsx
Step 1: 创建发光效果组件
Create: src/components/effects/glow-effect.tsx
"use client";
import { cn } from "@/lib/utils";
interface GlowEffectProps {
color?: string;
size?: "sm" | "md" | "lg" | "xl";
className?: string;
children?: React.ReactNode;
}
const sizeMap = {
sm: "w-32 h-32",
md: "w-48 h-48",
lg: "w-64 h-64",
xl: "w-96 h-96",
};
export function GlowEffect({
color = "#00D9FF",
size = "lg",
className,
children,
}: GlowEffectProps) {
return (
<div className={cn("relative", className)}>
<div
className={cn(
"absolute rounded-full blur-3xl opacity-20 animate-pulse",
sizeMap[size]
)}
style={{
background: `radial-gradient(circle, ${color}40 0%, transparent 70%)`,
}}
/>
{children}
</div>
);
}
interface GradientOrbProps {
position?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
color?: string;
className?: string;
}
const positionMap = {
"top-left": "top-0 left-0",
"top-right": "top-0 right-0",
"bottom-left": "bottom-0 left-0",
"bottom-right": "bottom-0 right-0",
};
export function GradientOrb({
position = "top-right",
color = "#00D9FF",
className,
}: GradientOrbProps) {
return (
<div
className={cn(
"absolute w-96 h-96 rounded-full blur-3xl opacity-5 pointer-events-none",
positionMap[position],
className
)}
style={{
background: `radial-gradient(circle, ${color} 0%, transparent 70%)`,
}}
/>
);
}
Step 2: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 3: 提交发光效果组件
Run:
git add src/components/effects/glow-effect.tsx
git commit -m "feat: create glow effect and gradient orb components"
Expected: 提交成功
阶段五:首页重构
Task 14: 重构 Hero Section
Files:
- Modify:
src/components/sections/hero-section.tsx
Step 1: 读取现有 Hero Section
Read: src/components/sections/hero-section.tsx
Step 2: 重写 Hero Section 以支持深色主题和动画
Modify: src/components/sections/hero-section.tsx
"use client";
import { motion } from "framer-motion";
import { Button } from "@/components/ui/button";
import { ParticleBackground } from "@/components/effects/particle-background";
import { GradientOrb } from "@/components/effects/glow-effect";
import { COMPANY_INFO } from "@/lib/constants";
import { ArrowRight, Sparkles } from "lucide-react";
export function HeroSection() {
return (
<section className="relative min-h-screen flex items-center justify-center overflow-hidden pt-16">
<ParticleBackground
particleCount={80}
colors={["#00D9FF", "#A855F7", "#06B6D4"]}
minSize={1}
maxSize={4}
speed={0.3}
/>
<GradientOrb position="top-right" color="#00D9FF" />
<GradientOrb position="bottom-left" color="#A855F7" />
<div className="container-wide relative z-10 py-24 md:py-32 lg:py-40">
<div className="max-w-4xl mx-auto text-center">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="mb-6"
>
<span className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-tech-blue/10 border border-tech-blue/20 text-tech-blue text-sm font-medium">
<Sparkles className="w-4 h-4" />
专注科技创新
</span>
</motion.div>
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.1 }}
className="text-4xl md:text-5xl lg:text-6xl font-bold text-white mb-6 leading-tight"
>
{COMPANY_INFO.slogan}
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.2 }}
className="text-lg md:text-xl text-gray-400 mb-8 max-w-2xl mx-auto"
>
{COMPANY_INFO.description}
</motion.p>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.3 }}
className="flex flex-col sm:flex-row gap-4 justify-center"
>
<Button size="lg" className="group">
立即体验
<ArrowRight className="ml-2 w-4 h-4 group-hover:translate-x-1 transition-transform" />
</Button>
<Button size="lg" variant="secondary">
了解更多
</Button>
</motion.div>
</div>
</div>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1, delay: 0.5 }}
className="absolute bottom-8 left-1/2 -translate-x-1/2"
>
<div className="flex flex-col items-center gap-2 text-gray-400">
<span className="text-sm">向下滚动</span>
<div className="w-6 h-10 rounded-full border-2 border-gray-600 flex justify-center pt-2">
<motion.div
animate={{ y: [0, 12, 0] }}
transition={{ duration: 1.5, repeat: Infinity }}
className="w-1.5 h-1.5 bg-tech-blue rounded-full"
/>
</div>
</div>
</motion.div>
</section>
);
}
Step 3: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 4: 提交 Hero Section
Run:
git add src/components/sections/hero-section.tsx
git commit -m "feat: refactor hero section with dark theme and animations"
Expected: 提交成功
Task 15: 创建统计数据 Section
Files:
- Create:
src/components/sections/stats-section.tsx
Step 1: 创建统计数据 Section
Create: src/components/sections/stats-section.tsx
"use client";
import { motion } from "framer-motion";
import { STATS } from "@/lib/constants";
export function StatsSection() {
return (
<section className="py-20 bg-dark-secondary">
<div className="container-wide">
<div className="grid grid-cols-2 md:grid-cols-4 gap-8">
{STATS.map((stat, index) => (
<motion.div
key={stat.label}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: index * 0.1 }}
className="text-center"
>
<div className="text-4xl md:text-5xl font-bold text-tech-blue mb-2">
{stat.value}
</div>
<div className="text-gray-400 text-sm md:text-base">
{stat.label}
</div>
</motion.div>
))}
</div>
</div>
</section>
);
}
Step 2: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 3: 提交统计数据 Section
Run:
git add src/components/sections/stats-section.tsx
git commit -m "feat: create stats section with animated counters"
Expected: 提交成功
Task 16: 重构产品展示 Section
Files:
- Modify:
src/components/sections/products-section.tsx
Step 1: 读取现有产品展示 Section
Read: src/components/sections/products-section.tsx
Step 2: 重写产品展示 Section 以支持深色主题和卡片效果
Modify: src/components/sections/products-section.tsx
"use client";
import { motion } from "framer-motion";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { PRODUCTS } from "@/lib/constants";
import { ArrowRight } from "lucide-react";
export function ProductsSection() {
return (
<section className="py-20 bg-dark">
<div className="container-wide">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h2 className="text-3xl md:text-4xl font-bold text-white mb-4">
产品服务
</h2>
<p className="text-gray-400 max-w-2xl mx-auto">
为企业提供全方位的数字化解决方案,助力业务增长
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{PRODUCTS.slice(0, 6).map((product, index) => (
<motion.div
key={product.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: index * 0.1 }}
>
<Card variant="hover" className="h-full">
<CardHeader>
<div className="flex items-start justify-between mb-2">
<Badge variant="default">{product.category}</Badge>
</div>
<CardTitle className="text-xl">{product.title}</CardTitle>
</CardHeader>
<CardContent>
<CardDescription className="mb-4">
{product.description}
</CardDescription>
<div className="flex flex-wrap gap-2 mb-4">
{product.features.slice(0, 3).map((feature) => (
<Badge key={feature} variant="outline" className="text-xs">
{feature}
</Badge>
))}
</div>
<a
href={`/products/${product.id}`}
className="inline-flex items-center text-tech-blue hover:text-tech-purple transition-colors duration-300 text-sm font-medium group"
>
了解更多
<ArrowRight className="ml-1 w-4 h-4 group-hover:translate-x-1 transition-transform" />
</a>
</CardContent>
</Card>
</motion.div>
))}
</div>
</div>
</section>
);
}
Step 3: 验证类型检查
Run: npx tsc --noEmit
Expected: 无类型错误
Step 4: 提交产品展示 Section
Run:
git add src/components/sections/products-section.tsx
git commit -m "feat: refactor products section with dark theme and card layout"
Expected: 提交成功
阶段六:测试与验证
Task 17: 运行开发服务器测试
Files:
- None
Step 1: 启动开发服务器
Run: npm run dev
Expected: 开发服务器成功启动在 http://localhost:3000
Step 2: 在浏览器中验证首页
手动测试:
- 访问 http://localhost:3000
- 验证深色主题是否正确应用
- 验证导航栏是否正常工作
- 验证 Hero Section 动画是否流畅
- 验证产品卡片悬停效果
- 验证响应式布局(移动端、平板、桌面)
Expected: 所有功能正常工作
Step 3: 停止开发服务器
按 Ctrl+C 停止服务器
Expected: 服务器成功停止
Task 18: 运行构建测试
Files:
- None
Step 1: 运行生产构建
Run: npm run build
Expected: 构建成功,无错误
Step 2: 检查构建输出
验证构建输出中:
- 页面是否正确生成
- 是否有优化建议
- 构建大小是否合理
Expected: 构建输出正常
Step 3: 运行代码检查
Run: npm run lint
Expected: 无 ESLint 错误
Task 19: 提交所有更改
Files:
- None
Step 1: 检查 Git 状态
Run: git status
Expected: 显示所有修改的文件
Step 2: 添加所有更改
Run: git add .
Expected: 所有更改已暂存
Step 3: 创建提交
Run:
git commit -m "feat: complete website redesign with dark tech theme
- Add dark theme color system and CSS variables
- Enhance UI components (Button, Card, Input, Badge)
- Refactor layout components (Header, Footer)
- Create effect components (ParticleBackground, GlowEffect)
- Refactor sections (Hero, Stats, Products)
- Add Framer Motion animations
- Improve responsive design
- Update Tailwind configuration"
Expected: 提交成功
Step 4: 推送到远程
Run: git push origin feature/website-redesign
Expected: 推送成功
完成清单
- 安装必要依赖(framer-motion, @antv/g2, class-variance-authority)
- 扩展 Tailwind 配置
- 更新全局样式
- 创建工具函数
- 创建主题常量
- 增强按钮组件
- 增强卡片组件
- 增强输入框组件
- 增强徽章组件
- 重构导航栏组件
- 重构页脚组件
- 创建粒子背景组件
- 创建发光效果组件
- 重构 Hero Section
- 创建统计数据 Section
- 重构产品展示 Section
- 运行开发服务器测试
- 运行构建测试
- 提交所有更改
注意事项
- 每个任务都应该独立完成并提交,便于版本控制和回滚
- 遇到错误立即停止,不要继续下一步
- 保持代码风格一致,遵循项目现有的代码规范
- 测试每个组件,确保在移动端和桌面端都能正常工作
- 关注性能,避免过度使用动画和特效
计划创建者: AI Assistant
创建日期: 2026-02-21
预计工期: 2-3天(基础架构 + 核心组件 + 首页重构)