feat: 优化全局样式与组件视觉升级
- 更新 globals.css 全局样式 - 优化 not-found 404 页面 - 升级 footer, mega-dropdown, mobile-tab-bar 布局组件 - 改进 challenge, cta, hero 等核心 section 组件 - 优化 challenge-card, ink-glow-card, product-card 等 UI 组件 - 更新产品常量配置
This commit is contained in:
+11
-7
@@ -158,8 +158,8 @@
|
||||
--color-text-primary: #E5E5E5;
|
||||
--color-text-secondary: #B0B0B0;
|
||||
--color-text-tertiary: #A0A0A0;
|
||||
--color-text-muted: #8C8C8C;
|
||||
--color-text-subtle: #666666;
|
||||
--color-text-muted: #999999;
|
||||
--color-text-subtle: #777777;
|
||||
--color-text-placeholder: #737373;
|
||||
--color-text-hint: #5C5C5C;
|
||||
|
||||
@@ -197,10 +197,10 @@
|
||||
--color-footer-bg: #000000;
|
||||
--color-cta-bg: #141414;
|
||||
--color-hero-dark-end: #1A0A10;
|
||||
--color-footer-text: #8C8C8C;
|
||||
--color-footer-text-muted: #525252;
|
||||
--color-footer-text-dim: #737373;
|
||||
--color-footer-text-link: #B0B0B0;
|
||||
--color-footer-text: #999999;
|
||||
--color-footer-text-muted: #6B6B6B;
|
||||
--color-footer-text-dim: #858585;
|
||||
--color-footer-text-link: #C0C0C0;
|
||||
--color-footer-border: #262626;
|
||||
|
||||
--color-challenge-isolation: rgba(196, 30, 58, 0.12);
|
||||
@@ -536,7 +536,7 @@ body {
|
||||
}
|
||||
|
||||
.ink-glow-border {
|
||||
animation: rotateBorder 4s linear infinite;
|
||||
animation: rotateBorder 4s linear infinite paused;
|
||||
}
|
||||
|
||||
.ink-glow-border::before {
|
||||
@@ -573,6 +573,10 @@ body {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.ink-glow-border:hover {
|
||||
animation-play-state: running;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) and (max-width: 1023px) {
|
||||
.container-wide,
|
||||
.container-full {
|
||||
|
||||
+35
-58
@@ -3,34 +3,30 @@
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Home, ArrowLeft, Search } from 'lucide-react';
|
||||
import { COMPANY_INFO } from '@/lib/constants';
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[var(--color-bg-primary)] flex items-center justify-center">
|
||||
<div className="container-wide px-4 py-20">
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<div className="max-w-xl mx-auto text-center">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-[120px] font-bold text-[var(--color-brand-primary)] leading-none mb-4">
|
||||
<h1 className="text-8xl sm:text-[120px] font-bold text-[var(--color-brand-primary)] leading-none mb-4 opacity-20">
|
||||
404
|
||||
</h1>
|
||||
<div className="w-32 h-1 bg-[var(--color-brand-primary)] mx-auto mb-6" />
|
||||
</div>
|
||||
|
||||
<h2 className="text-3xl font-bold text-[var(--color-text-primary)] mb-4">
|
||||
<h2 className="text-2xl sm:text-3xl font-bold text-[var(--color-text-primary)] mb-4">
|
||||
页面未找到
|
||||
</h2>
|
||||
|
||||
<p className="text-lg text-[var(--color-text-placeholder)] mb-8 leading-relaxed">
|
||||
很抱歉,您访问的页面不存在或已被移动。
|
||||
请检查网址是否正确,或使用以下导航继续浏览。
|
||||
<p className="text-base text-[var(--color-text-muted)] mb-8 leading-relaxed">
|
||||
您访问的页面不存在或已被移动。请检查网址,或返回首页继续浏览。
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center mb-12">
|
||||
<Button
|
||||
size="lg"
|
||||
asChild
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
|
||||
>
|
||||
<StaticLink href="/">
|
||||
<Home className="w-5 h-5 mr-2" />
|
||||
@@ -48,72 +44,53 @@ export default function NotFound() {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="bg-[var(--color-bg-section)] rounded-lg p-8">
|
||||
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-6">
|
||||
<div className="bg-[var(--color-bg-section)] rounded-xl p-6 sm:p-8">
|
||||
<h3 className="text-lg font-semibold text-[var(--color-text-primary)] mb-5">
|
||||
您可能在寻找
|
||||
</h3>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<StaticLink
|
||||
href="/about"
|
||||
className="flex items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
|
||||
<Search className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-semibold text-[var(--color-text-primary)]">关于我们</div>
|
||||
<div className="text-sm text-[var(--color-text-placeholder)]">了解{COMPANY_INFO.displayName}</div>
|
||||
</div>
|
||||
</StaticLink>
|
||||
|
||||
<StaticLink
|
||||
href="/services"
|
||||
className="flex items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
|
||||
<Search className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-semibold text-[var(--color-text-primary)]">服务</div>
|
||||
<div className="text-sm text-[var(--color-text-placeholder)]">我们的服务</div>
|
||||
</div>
|
||||
</StaticLink>
|
||||
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<StaticLink
|
||||
href="/products"
|
||||
className="flex items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
|
||||
className="flex flex-col items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
|
||||
<Search className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-semibold text-[var(--color-text-primary)]">产品</div>
|
||||
<div className="text-sm text-[var(--color-text-placeholder)]">企业级产品</div>
|
||||
<div className="w-9 h-9 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mb-2 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
|
||||
<Search className="w-4 h-4 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<span className="font-medium text-sm text-[var(--color-text-primary)]">产品</span>
|
||||
</StaticLink>
|
||||
|
||||
<StaticLink
|
||||
href="/solutions"
|
||||
className="flex items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
|
||||
className="flex flex-col items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
|
||||
<Search className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
<div className="w-9 h-9 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mb-2 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
|
||||
<Search className="w-4 h-4 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-semibold text-[var(--color-text-primary)]">解决方案</div>
|
||||
<div className="text-sm text-[var(--color-text-placeholder)]">行业方案</div>
|
||||
<span className="font-medium text-sm text-[var(--color-text-primary)]">解决方案</span>
|
||||
</StaticLink>
|
||||
|
||||
<StaticLink
|
||||
href="/about"
|
||||
className="flex flex-col items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-9 h-9 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mb-2 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
|
||||
<Search className="w-4 h-4 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<span className="font-medium text-sm text-[var(--color-text-primary)]">关于我们</span>
|
||||
</StaticLink>
|
||||
|
||||
<StaticLink
|
||||
href="/contact"
|
||||
className="flex flex-col items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-9 h-9 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mb-2 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
|
||||
<Search className="w-4 h-4 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<span className="font-medium text-sm text-[var(--color-text-primary)]">联系我们</span>
|
||||
</StaticLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 text-sm text-[var(--color-text-placeholder)]">
|
||||
如果您认为这是一个错误,请{' '}
|
||||
<StaticLink href="/contact" className="text-[var(--color-brand-primary)] hover:underline">
|
||||
联系我们
|
||||
</StaticLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { COMPANY_INFO, NAVIGATION_V2, MEGA_DROPDOWN_DATA } from '@/lib/constants
|
||||
|
||||
export function Footer() {
|
||||
return (
|
||||
<footer className="bg-[var(--color-footer-bg)] text-white py-16" data-testid="footer" role="contentinfo">
|
||||
<footer className="bg-[var(--color-footer-bg)] text-white py-12 md:py-16" data-testid="footer" role="contentinfo">
|
||||
<div className="container-wide">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-10 lg:gap-8">
|
||||
<div data-testid="card-brand" className="lg:col-span-2">
|
||||
@@ -107,7 +107,7 @@ export function Footer() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-[var(--color-footer-border)] mt-12 pt-8 pb-24 md:pb-8">
|
||||
<div className="border-t border-[var(--color-footer-border)] mt-12 pt-8 pb-24 md:pb-8" style={{ paddingBottom: 'calc(5rem + env(safe-area-inset-bottom, 0px))' }}>
|
||||
<div className="flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<p className="text-[var(--color-footer-text-muted)] text-sm">
|
||||
© {new Date().getFullYear()} {COMPANY_INFO.name}. All rights reserved.
|
||||
|
||||
@@ -74,10 +74,15 @@ export function MegaDropdown({ label, items, isOpen, onToggle, onOpen, onClose }
|
||||
<StaticLink
|
||||
key={item.id}
|
||||
href={item.href}
|
||||
className="block p-4 rounded-lg border-l-[3px] border-l-[var(--color-brand-primary)] hover:bg-[var(--color-bg-secondary)] transition-colors duration-200"
|
||||
className="block p-4 rounded-lg border border-transparent hover:border-[var(--color-brand-primary)]/10 hover:bg-[var(--color-brand-primary-bg)] transition-all duration-200 group"
|
||||
>
|
||||
<div className="text-sm font-semibold text-[var(--color-text-primary)]">{item.title}</div>
|
||||
<div className="text-xs text-[var(--color-text-placeholder)] mt-1.5 leading-relaxed">{item.description}</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-1 h-8 rounded-full bg-[var(--color-border-primary)] group-hover:bg-[var(--color-brand-primary)] transition-colors duration-200 shrink-0" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="text-sm font-semibold text-[var(--color-text-primary)]">{item.title}</div>
|
||||
<div className="text-xs text-[var(--text-placeholder)] mt-1.5 leading-relaxed">{item.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
</StaticLink>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -37,7 +37,7 @@ export function MobileTabBar() {
|
||||
};
|
||||
|
||||
return (
|
||||
<nav className="fixed bottom-0 left-0 right-0 z-50 md:hidden bg-[var(--color-bg-primary)]/95 backdrop-blur-xl border-t border-[var(--color-border-primary)] safe-area-inset-bottom">
|
||||
<nav className="fixed bottom-0 left-0 right-0 z-50 md:hidden bg-[var(--color-bg-primary)]/95 backdrop-blur-xl border-t border-[var(--color-border-primary)]" style={{ paddingBottom: 'env(safe-area-inset-bottom, 0px)' }}>
|
||||
<div className="flex items-center justify-around h-16">
|
||||
{tabs.map((tab) => {
|
||||
const Icon = tab.icon;
|
||||
|
||||
@@ -56,21 +56,14 @@ export function ChallengeSection() {
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 md:gap-8">
|
||||
{CHALLENGES.map((challenge, index) => (
|
||||
<motion.div
|
||||
<ChallengeCard
|
||||
key={challenge.id}
|
||||
initial={shouldReduceMotion ? {} : { opacity: 0, x: index === 0 ? -32 : index === 1 ? 0 : 32 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true, margin: '-80px' }}
|
||||
transition={{ duration: 0.55, delay: index * 0.12, ease: [0.16, 1, 0.3, 1] }}
|
||||
>
|
||||
<ChallengeCard
|
||||
title={challenge.title}
|
||||
description={challenge.description}
|
||||
scenario={challenge.scenario}
|
||||
href={challenge.href}
|
||||
index={index}
|
||||
/>
|
||||
</motion.div>
|
||||
title={challenge.title}
|
||||
description={challenge.description}
|
||||
scenario={challenge.scenario}
|
||||
href={challenge.href}
|
||||
index={index}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -55,64 +55,18 @@ export function CTASection({
|
||||
style={{ backgroundColor: 'var(--color-cta-bg)' }}
|
||||
>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<svg className="absolute inset-0 w-full h-full" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||
<filter id="cta-grain">
|
||||
<feTurbulence
|
||||
type="fractalNoise"
|
||||
baseFrequency="0.75"
|
||||
numOctaves="4"
|
||||
stitchTiles="stitch"
|
||||
result="noise"
|
||||
/>
|
||||
<feColorMatrix type="saturate" values="0" in="noise" result="desaturated" />
|
||||
<feComponentTransfer in="desaturated" result="faded">
|
||||
<feFuncA type="linear" slope="0.04" />
|
||||
</feComponentTransfer>
|
||||
</filter>
|
||||
<rect width="100%" height="100%" filter="url(#cta-grain)" />
|
||||
</svg>
|
||||
|
||||
{!shouldReduceMotion && (
|
||||
<>
|
||||
<motion.div
|
||||
className="absolute inset-[-20%]"
|
||||
style={{
|
||||
background:
|
||||
'radial-gradient(circle at center, rgba(196, 30, 58, 0.08) 0%, transparent 50%)',
|
||||
x: glowX,
|
||||
y: glowY,
|
||||
opacity: isHovered ? 1 : 0.5,
|
||||
}}
|
||||
transition={{ opacity: { duration: 0.6 } }}
|
||||
/>
|
||||
<motion.div
|
||||
animate={{
|
||||
scale: [1, 1.15, 1],
|
||||
opacity: [0.06, 0.12, 0.06],
|
||||
}}
|
||||
transition={{
|
||||
duration: 8,
|
||||
repeat: Infinity,
|
||||
ease: 'easeInOut',
|
||||
}}
|
||||
className="absolute left-[10%] top-[20%] w-64 h-64 rounded-full"
|
||||
style={{ background: 'radial-gradient(circle, rgba(196,30,58,0.2), transparent 70%)' }}
|
||||
/>
|
||||
<motion.div
|
||||
animate={{
|
||||
scale: [1, 1.2, 1],
|
||||
opacity: [0.05, 0.1, 0.05],
|
||||
}}
|
||||
transition={{
|
||||
duration: 10,
|
||||
repeat: Infinity,
|
||||
ease: 'easeInOut',
|
||||
delay: 2,
|
||||
}}
|
||||
className="absolute right-[5%] bottom-[25%] w-80 h-80 rounded-full"
|
||||
style={{ background: 'radial-gradient(circle, rgba(196,30,58,0.15), transparent 70%)' }}
|
||||
/>
|
||||
</>
|
||||
<motion.div
|
||||
className="absolute inset-[-20%]"
|
||||
style={{
|
||||
background:
|
||||
'radial-gradient(circle at center, rgba(196, 30, 58, 0.08) 0%, transparent 50%)',
|
||||
x: glowX,
|
||||
y: glowY,
|
||||
opacity: isHovered ? 1 : 0.5,
|
||||
}}
|
||||
transition={{ opacity: { duration: 0.6 } }}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div
|
||||
@@ -122,13 +76,6 @@ export function CTASection({
|
||||
'linear-gradient(to top, rgba(196, 30, 58, 0.06) 0%, transparent 40%), linear-gradient(135deg, transparent 40%, rgba(196, 30, 58, 0.03) 100%)',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div
|
||||
className="absolute inset-0"
|
||||
style={{
|
||||
backgroundImage: `url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23C41E3A' fill-opacity='0.02'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="container-wide relative z-10">
|
||||
|
||||
@@ -54,61 +54,61 @@ export function HeroSectionV2() {
|
||||
>
|
||||
<HeroInkBackground />
|
||||
|
||||
<div className="container-wide py-24 md:py-32 lg:py-40 relative z-10 flex-1 flex items-center">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20 items-center w-full">
|
||||
<div className="container-wide py-16 md:py-24 lg:py-32 relative z-10 flex-1 flex items-center">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-10 lg:gap-16 items-center w-full">
|
||||
<div>
|
||||
<motion.div
|
||||
{...fadeUp(0)}
|
||||
className="mb-8"
|
||||
className="mb-6"
|
||||
>
|
||||
<span className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-[var(--color-brand-primary-bg)] text-[var(--color-brand-primary)] text-sm font-medium border border-[var(--color-brand-primary)]/10">
|
||||
<span className="inline-flex items-center gap-2 px-3 py-1.5 sm:px-4 sm:py-2 rounded-full bg-[var(--color-brand-primary-bg)] text-[var(--color-brand-primary)] text-xs sm:text-sm font-medium border border-[var(--color-brand-primary)]/10">
|
||||
{COMPANY_INFO.slogan}
|
||||
</span>
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
id="hero-heading"
|
||||
{...fadeUp(0.1)}
|
||||
className="text-6xl sm:text-7xl lg:text-8xl tracking-tight mb-6 font-brand"
|
||||
style={{ fontWeight: 'normal' }}
|
||||
>
|
||||
{COMPANY_INFO.shortName}
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
{...fadeUp(0.2)}
|
||||
className="text-xl sm:text-2xl text-[var(--color-text-primary)] mb-4"
|
||||
{...fadeUp(0.1)}
|
||||
className="text-lg sm:text-xl lg:text-2xl text-[var(--color-text-primary)] mb-3"
|
||||
>
|
||||
<span className="font-semibold text-[var(--color-brand-primary)] font-calligraphy">
|
||||
企业数字化转型服务商
|
||||
</span>
|
||||
</motion.p>
|
||||
|
||||
<motion.h1
|
||||
id="hero-heading"
|
||||
{...fadeUp(0.15)}
|
||||
className="text-5xl sm:text-6xl lg:text-7xl tracking-tight mb-5 font-brand leading-[1.1]"
|
||||
style={{ fontWeight: 'normal' }}
|
||||
>
|
||||
{COMPANY_INFO.shortName}
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
{...fadeUp(0.3)}
|
||||
className="text-lg text-[var(--color-text-muted)] max-w-xl leading-relaxed mb-10"
|
||||
{...fadeUp(0.25)}
|
||||
className="text-base sm:text-lg text-[var(--color-text-muted)] max-w-lg leading-relaxed mb-8"
|
||||
>
|
||||
{COMPANY_INFO.description}
|
||||
</motion.p>
|
||||
|
||||
<motion.div
|
||||
{...fadeUp(0.4)}
|
||||
{...fadeUp(0.35)}
|
||||
className="flex flex-col sm:flex-row items-start gap-4"
|
||||
>
|
||||
<Button size="lg" asChild>
|
||||
<Button size="lg" asChild className="min-h-[52px] px-8 text-base font-semibold shadow-lg shadow-[var(--color-brand-primary)]/20">
|
||||
<StaticLink href="/contact">
|
||||
免费获取定制方案
|
||||
<ArrowRight className="w-4 h-4 ml-2" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
<Button size="lg" variant="outline" asChild>
|
||||
<Button size="lg" variant="ghost" asChild className="text-[var(--color-text-muted)]">
|
||||
<StaticLink href="/products">探索产品</StaticLink>
|
||||
</Button>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
{...fadeUp(0.5)}
|
||||
className="flex flex-wrap gap-3 mt-10 lg:hidden"
|
||||
{...fadeUp(0.45)}
|
||||
className="flex flex-wrap gap-2 sm:gap-3 mt-8"
|
||||
>
|
||||
{CAPABILITIES.map((cap) => {
|
||||
const Icon = cap.icon;
|
||||
@@ -129,7 +129,6 @@ export function HeroSectionV2() {
|
||||
initial={shouldReduceMotion ? {} : { opacity: 0, y: 32 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.5, ease: EASE }}
|
||||
className="hidden lg:block"
|
||||
>
|
||||
<div
|
||||
ref={cardRef}
|
||||
@@ -152,35 +151,35 @@ export function HeroSectionV2() {
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="relative rounded-2xl bg-[var(--color-bg-primary)]/80 backdrop-blur-sm p-8 lg:p-10">
|
||||
<div className="w-14 h-14 rounded-xl bg-[var(--color-brand-primary-bg)] flex items-center justify-center mb-6">
|
||||
<Handshake className="w-6 h-6 text-[var(--color-brand-primary)]" strokeWidth={1.8} />
|
||||
<div className="relative rounded-2xl bg-[var(--color-bg-primary)]/80 backdrop-blur-sm p-6 sm:p-8 lg:p-10">
|
||||
<div className="w-12 h-12 lg:w-14 lg:h-14 rounded-xl bg-[var(--color-brand-primary-bg)] flex items-center justify-center mb-5 lg:mb-6">
|
||||
<Handshake className="w-5 h-5 lg:w-6 lg:h-6 text-[var(--color-brand-primary)]" strokeWidth={1.8} />
|
||||
</div>
|
||||
|
||||
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-2">
|
||||
<h3 className="text-lg lg:text-xl font-semibold text-[var(--color-text-primary)] mb-2">
|
||||
从沟通到落地,全程陪伴
|
||||
</h3>
|
||||
<p className="text-sm text-[var(--color-text-muted)] leading-relaxed mb-8">
|
||||
<p className="text-sm text-[var(--color-text-muted)] leading-relaxed mb-6 lg:mb-8">
|
||||
四步合作流程,确保每个项目科学推进、高效交付
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="grid grid-cols-2 gap-3 lg:gap-4 lg:space-y-0 lg:block lg:space-y-4">
|
||||
{JOURNEY_STEPS.map((step, idx) => {
|
||||
const Icon = step.icon;
|
||||
return (
|
||||
<div
|
||||
key={step.label}
|
||||
className="flex items-center gap-4 p-3 rounded-lg bg-[var(--color-bg-section)]/60"
|
||||
className="flex items-center gap-3 lg:gap-4 p-2.5 lg:p-3 rounded-lg bg-[var(--color-bg-section)]/60"
|
||||
>
|
||||
<div className="w-9 h-9 rounded-lg bg-[var(--color-brand-primary-bg)] flex items-center justify-center shrink-0">
|
||||
<Icon className="w-4 h-4 text-[var(--color-brand-primary)]" strokeWidth={2.2} />
|
||||
<div className="w-8 h-8 lg:w-9 lg:h-9 rounded-lg bg-[var(--color-brand-primary-bg)] flex items-center justify-center shrink-0">
|
||||
<Icon className="w-3.5 h-3.5 lg:w-4 lg:h-4 text-[var(--color-brand-primary)]" strokeWidth={2.2} />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-bold text-[var(--color-brand-primary)]">0{idx + 1}</span>
|
||||
<span className="text-sm font-medium text-[var(--color-text-primary)]">{step.label}</span>
|
||||
<div className="flex items-center gap-1.5 lg:gap-2">
|
||||
<span className="text-[10px] lg:text-xs font-bold text-[var(--color-brand-primary)]">0{idx + 1}</span>
|
||||
<span className="text-xs lg:text-sm font-medium text-[var(--color-text-primary)]">{step.label}</span>
|
||||
</div>
|
||||
<p className="text-xs text-[var(--color-text-muted)] mt-0.5">{step.desc}</p>
|
||||
<p className="text-[10px] lg:text-xs text-[var(--color-text-muted)] mt-0.5 hidden sm:block">{step.desc}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -7,12 +7,7 @@ import { METHODOLOGY } from '@/lib/constants/methodology';
|
||||
import { CheckCircle2 } from 'lucide-react';
|
||||
import { InkGlowCard } from '@/components/ui/ink-glow-card';
|
||||
|
||||
const phaseAccents: { rgb: string; glowStart: string; glowEnd: string }[] = [
|
||||
{ rgb: '196, 30, 58', glowStart: 'var(--color-brand-primary)', glowEnd: 'var(--color-warning)' },
|
||||
{ rgb: '217, 119, 6', glowStart: 'var(--color-warning)', glowEnd: 'var(--color-success)' },
|
||||
{ rgb: '22, 163, 74', glowStart: 'var(--color-success)', glowEnd: 'var(--color-accent-cyan)' },
|
||||
{ rgb: '37, 99, 235', glowStart: 'var(--color-accent-blue)', glowEnd: 'var(--color-accent-purple)' },
|
||||
];
|
||||
const phaseBgOpacities = [0.1, 0.08, 0.12, 0.06];
|
||||
|
||||
export function MethodologySection() {
|
||||
const ref = useRef(null);
|
||||
@@ -41,19 +36,16 @@ export function MethodologySection() {
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 md:gap-8">
|
||||
{METHODOLOGY.map((phase, idx) => {
|
||||
const accent = phaseAccents[idx % phaseAccents.length]!;
|
||||
const bgOpacity = phaseBgOpacities[idx % phaseBgOpacities.length];
|
||||
return (
|
||||
<InkGlowCard
|
||||
key={phase.id}
|
||||
index={idx}
|
||||
accentColorRgb={accent.rgb}
|
||||
glowStart={accent.glowStart}
|
||||
glowEnd={accent.glowEnd}
|
||||
>
|
||||
<div className="p-6 md:p-8">
|
||||
<div
|
||||
className="w-10 h-10 rounded-full flex items-center justify-center mb-5 text-sm font-bold"
|
||||
style={{ backgroundColor: accent.glowStart, color: 'var(--color-bg-primary)' }}
|
||||
style={{ backgroundColor: `rgba(var(--color-brand-primary-rgb), ${bgOpacity})`, color: 'var(--color-brand-primary)' }}
|
||||
>
|
||||
{phase.number}
|
||||
</div>
|
||||
|
||||
@@ -33,21 +33,14 @@ export function ProductMatrixSection() {
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-8">
|
||||
{PRODUCTS.map((product, index) => (
|
||||
<motion.div
|
||||
<ProductCard
|
||||
key={product.id}
|
||||
initial={shouldReduceMotion ? {} : { opacity: 0, y: 28 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-60px' }}
|
||||
transition={{ duration: 0.5, delay: index * 0.08, ease: [0.16, 1, 0.3, 1] }}
|
||||
>
|
||||
<ProductCard
|
||||
title={product.title}
|
||||
description={product.description}
|
||||
href={`/products/${product.id}`}
|
||||
index={index}
|
||||
status={product.status}
|
||||
/>
|
||||
</motion.div>
|
||||
title={product.title}
|
||||
description={product.description}
|
||||
href={`/products/${product.id}`}
|
||||
index={index}
|
||||
status={product.status}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -31,7 +31,7 @@ export function SocialProofSection() {
|
||||
const shouldReduceMotion = useReducedMotion();
|
||||
|
||||
return (
|
||||
<section id="social-proof" role="region" aria-labelledby="social-proof-heading" className="py-16 md:py-20 bg-[var(--color-bg-section)]">
|
||||
<section id="social-proof" role="region" aria-labelledby="social-proof-heading" className="py-12 md:py-16 lg:py-20 bg-[var(--color-bg-section)]">
|
||||
<div className="container-wide">
|
||||
<motion.div
|
||||
initial={shouldReduceMotion ? {} : { opacity: 0, y: 20 }}
|
||||
|
||||
@@ -14,34 +14,13 @@ interface ChallengeCardProps {
|
||||
|
||||
interface ScenarioConfig {
|
||||
icon: LucideIcon;
|
||||
accentColor: string;
|
||||
accentColorRgb: string;
|
||||
glowStart: string;
|
||||
glowEnd: string;
|
||||
iconBgOpacity: number;
|
||||
}
|
||||
|
||||
const scenarioConfig: Record<string, ScenarioConfig> = {
|
||||
isolation: {
|
||||
icon: Lock,
|
||||
accentColor: 'var(--color-brand-primary)',
|
||||
accentColorRgb: '196, 30, 58',
|
||||
glowStart: 'var(--color-brand-primary)',
|
||||
glowEnd: 'var(--color-accent-purple)',
|
||||
},
|
||||
growth: {
|
||||
icon: TrendingUp,
|
||||
accentColor: 'var(--color-warning)',
|
||||
accentColorRgb: '217, 119, 6',
|
||||
glowStart: 'var(--color-warning)',
|
||||
glowEnd: 'var(--color-success)',
|
||||
},
|
||||
compliance: {
|
||||
icon: Shield,
|
||||
accentColor: 'var(--color-success)',
|
||||
accentColorRgb: '22, 163, 74',
|
||||
glowStart: 'var(--color-success)',
|
||||
glowEnd: 'var(--color-accent-cyan)',
|
||||
},
|
||||
isolation: { icon: Lock, iconBgOpacity: 0.06 },
|
||||
growth: { icon: TrendingUp, iconBgOpacity: 0.08 },
|
||||
compliance: { icon: Shield, iconBgOpacity: 0.05 },
|
||||
};
|
||||
|
||||
export function ChallengeCard({ title, description, scenario, href, index }: ChallengeCardProps) {
|
||||
@@ -52,19 +31,15 @@ export function ChallengeCard({ title, description, scenario, href, index }: Cha
|
||||
<InkGlowCard
|
||||
index={index}
|
||||
href={href}
|
||||
accentColorRgb={config.accentColorRgb}
|
||||
glowStart={config.glowStart}
|
||||
glowEnd={config.glowEnd}
|
||||
>
|
||||
<div className="p-6 md:p-8">
|
||||
<div className="flex items-start justify-between mb-5">
|
||||
<div
|
||||
className="w-11 h-11 rounded-xl flex items-center justify-center"
|
||||
style={{ backgroundColor: `rgba(${config.accentColorRgb}, 0.06)` }}
|
||||
style={{ backgroundColor: `rgba(var(--color-brand-primary-rgb), ${config.iconBgOpacity})` }}
|
||||
>
|
||||
<IconComponent
|
||||
className="w-5 h-5"
|
||||
style={{ color: config.accentColor }}
|
||||
className="w-5 h-5 text-[var(--color-brand-primary)]"
|
||||
strokeWidth={1.8}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useEffect, useRef, useMemo, useSyncExternalStore } from 'react';
|
||||
import { motion, useScroll, useTransform } from 'framer-motion';
|
||||
import { useReducedMotion } from '@/hooks/use-reduced-motion';
|
||||
|
||||
const PARTICLE_COUNT = 24;
|
||||
const PARTICLE_COUNT = 12;
|
||||
|
||||
interface Particle {
|
||||
x: number;
|
||||
|
||||
@@ -7,24 +7,16 @@ import { StaticLink } from '@/components/ui/static-link';
|
||||
interface InkGlowCardProps {
|
||||
children: ReactNode;
|
||||
index?: number;
|
||||
accentColorRgb?: string;
|
||||
glowStart?: string;
|
||||
glowEnd?: string;
|
||||
className?: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
const DEFAULT_ACCENT = '196, 30, 58';
|
||||
const DEFAULT_GLOW_START = 'var(--color-brand-primary)';
|
||||
const DEFAULT_GLOW_END = 'var(--color-warning)';
|
||||
const DEFAULT_ACCENT_RGB = '196, 30, 58';
|
||||
|
||||
export function InkGlowCard({
|
||||
children,
|
||||
index = 0,
|
||||
accentColorRgb = DEFAULT_ACCENT,
|
||||
glowStart = DEFAULT_GLOW_START,
|
||||
glowEnd = DEFAULT_GLOW_END,
|
||||
className = '',
|
||||
href,
|
||||
onClick,
|
||||
@@ -48,7 +40,7 @@ export function InkGlowCard({
|
||||
className="absolute inset-0 pointer-events-none transition-opacity duration-500"
|
||||
style={{
|
||||
opacity: isHovered ? 1 : 0,
|
||||
background: `radial-gradient(400px circle at ${mousePos.x}px ${mousePos.y}px, rgba(${accentColorRgb}, 0.04), transparent 40%)`,
|
||||
background: `radial-gradient(400px circle at ${mousePos.x}px ${mousePos.y}px, rgba(${DEFAULT_ACCENT_RGB}, 0.04), transparent 40%)`,
|
||||
}}
|
||||
/>
|
||||
<div className="relative z-10">{children}</div>
|
||||
@@ -58,19 +50,21 @@ export function InkGlowCard({
|
||||
return (
|
||||
<motion.div
|
||||
ref={cardRef}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
initial={{ opacity: 0, scale: 0.96, y: 16 }}
|
||||
whileInView={{ opacity: 1, scale: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-60px' }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: index * 0.08,
|
||||
ease: [0.16, 1, 0.3, 1],
|
||||
}}
|
||||
className={`relative ink-glow-border rounded-2xl ${className}`}
|
||||
style={{
|
||||
'--glow-start': glowStart,
|
||||
'--glow-end': glowEnd,
|
||||
} as React.CSSProperties}
|
||||
style={
|
||||
{
|
||||
'--glow-start': 'var(--color-brand-primary)',
|
||||
'--glow-end': 'var(--color-warning)',
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
{href ? (
|
||||
<StaticLink
|
||||
@@ -78,7 +72,7 @@ export function InkGlowCard({
|
||||
className="relative block rounded-2xl bg-[var(--color-bg-primary)] overflow-hidden transition-all duration-500"
|
||||
style={{
|
||||
boxShadow: isHovered
|
||||
? `0 20px 40px rgba(0,0,0,0.1), 0 0 0 1px rgba(${accentColorRgb}, 0.12)`
|
||||
? `0 20px 40px rgba(0,0,0,0.1), 0 0 0 1px rgba(${DEFAULT_ACCENT_RGB}, 0.12)`
|
||||
: '0 1px 3px rgba(0,0,0,0.04), 0 0 0 1px rgba(0,0,0,0.06)',
|
||||
transform: isHovered ? 'translateY(-6px)' : 'translateY(0)',
|
||||
}}
|
||||
@@ -93,7 +87,7 @@ export function InkGlowCard({
|
||||
className="relative rounded-2xl bg-[var(--color-bg-primary)] overflow-hidden transition-all duration-500"
|
||||
style={{
|
||||
boxShadow: isHovered
|
||||
? `0 20px 40px rgba(0,0,0,0.1), 0 0 0 1px rgba(${accentColorRgb}, 0.12)`
|
||||
? `0 20px 40px rgba(0,0,0,0.1), 0 0 0 1px rgba(${DEFAULT_ACCENT_RGB}, 0.12)`
|
||||
: '0 1px 3px rgba(0,0,0,0.04), 0 0 0 1px rgba(0,0,0,0.06)',
|
||||
transform: isHovered ? 'translateY(-6px)' : 'translateY(0)',
|
||||
}}
|
||||
|
||||
@@ -14,29 +14,25 @@ interface ProductCardProps {
|
||||
|
||||
interface ProductStyleConfig {
|
||||
icon: LucideIcon;
|
||||
accentColor: string;
|
||||
accentColorRgb: string;
|
||||
glowStart: string;
|
||||
glowEnd: string;
|
||||
iconBgOpacity: number;
|
||||
}
|
||||
|
||||
const productConfig: ProductStyleConfig[] = [
|
||||
{ icon: Database, accentColor: 'var(--color-brand-primary)', accentColorRgb: '196, 30, 58', glowStart: 'var(--color-brand-primary)', glowEnd: 'var(--color-warning)' },
|
||||
{ icon: Users, accentColor: 'var(--color-warning)', accentColorRgb: '217, 119, 6', glowStart: 'var(--color-warning)', glowEnd: 'var(--color-success)' },
|
||||
{ icon: FileText, accentColor: 'var(--color-accent-blue)', accentColorRgb: '37, 99, 235', glowStart: 'var(--color-accent-blue)', glowEnd: 'var(--color-accent-purple)' },
|
||||
{ icon: BarChart3, accentColor: 'var(--color-success)', accentColorRgb: '22, 163, 74', glowStart: 'var(--color-success)', glowEnd: 'var(--color-accent-cyan)' },
|
||||
{ icon: Truck, accentColor: 'var(--color-accent-purple)', accentColorRgb: '124, 58, 237', glowStart: 'var(--color-accent-purple)', glowEnd: 'var(--color-brand-primary)' },
|
||||
{ icon: Building2, accentColor: 'var(--color-accent-cyan)', accentColorRgb: '8, 145, 178', glowStart: 'var(--color-accent-cyan)', glowEnd: 'var(--color-accent-blue)' },
|
||||
];
|
||||
const productIcons: LucideIcon[] = [Database, Users, FileText, BarChart3, Truck, Building2];
|
||||
|
||||
const productConfig: ProductStyleConfig[] = productIcons.map((icon, i) => ({
|
||||
icon,
|
||||
iconBgOpacity: 0.04 + i * 0.015,
|
||||
}));
|
||||
|
||||
const defaultConfig: ProductStyleConfig = {
|
||||
icon: Database, accentColor: 'var(--color-brand-primary)', accentColorRgb: '196, 30, 58', glowStart: 'var(--color-brand-primary)', glowEnd: 'var(--color-warning)',
|
||||
icon: Database,
|
||||
iconBgOpacity: 0.06,
|
||||
};
|
||||
|
||||
const statusConfig = {
|
||||
'研发中': { bg: 'rgba(var(--color-brand-primary-rgb), 0.08)', text: 'var(--color-brand-primary)', border: 'rgba(var(--color-brand-primary-rgb), 0.15)' },
|
||||
'内测中': { bg: 'rgba(var(--color-warning-rgb), 0.08)', text: 'var(--color-warning)', border: 'rgba(var(--color-warning-rgb), 0.15)' },
|
||||
'已发布': { bg: 'rgba(var(--color-success-rgb), 0.08)', text: 'var(--color-success)', border: 'rgba(var(--color-success-rgb), 0.15)' },
|
||||
'研发中': { bg: 'rgba(var(--color-brand-primary-rgb), 0.06)', text: 'var(--color-brand-primary)', border: 'rgba(var(--color-brand-primary-rgb), 0.12)' },
|
||||
'内测中': { bg: 'rgba(var(--color-warning-rgb), 0.06)', text: 'var(--color-warning)', border: 'rgba(var(--color-warning-rgb), 0.12)' },
|
||||
'已发布': { bg: 'rgba(var(--color-success-rgb), 0.06)', text: 'var(--color-success)', border: 'rgba(var(--color-success-rgb), 0.12)' },
|
||||
} as const;
|
||||
|
||||
export function ProductCard({ title, description, href, index, status }: ProductCardProps) {
|
||||
@@ -48,19 +44,15 @@ export function ProductCard({ title, description, href, index, status }: Product
|
||||
<InkGlowCard
|
||||
index={index}
|
||||
href={href}
|
||||
accentColorRgb={config.accentColorRgb}
|
||||
glowStart={config.glowStart}
|
||||
glowEnd={config.glowEnd}
|
||||
>
|
||||
<div className="p-6 md:p-8">
|
||||
<div className="flex items-start justify-between mb-5">
|
||||
<div
|
||||
className="w-11 h-11 rounded-xl flex items-center justify-center"
|
||||
style={{ backgroundColor: `rgba(${config.accentColorRgb}, 0.06)` }}
|
||||
style={{ backgroundColor: `rgba(var(--color-brand-primary-rgb), ${config.iconBgOpacity})` }}
|
||||
>
|
||||
<IconComponent
|
||||
className="w-5 h-5"
|
||||
style={{ color: config.accentColor }}
|
||||
className="w-5 h-5 text-[var(--color-brand-primary)]"
|
||||
strokeWidth={1.8}
|
||||
/>
|
||||
</div>
|
||||
@@ -91,7 +83,7 @@ export function ProductCard({ title, description, href, index, status }: Product
|
||||
{description}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-1.5 text-sm font-medium text-[var(--color-text-subtle)] group-hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
<div className="flex items-center gap-1.5 text-sm font-medium text-[var(--color-text-subtle)] group-hover:text-[var(--color-brand-primary)] transition-colors min-h-[44px]">
|
||||
<span>了解规划</span>
|
||||
<ArrowUpRight className="w-4 h-4" strokeWidth={2} />
|
||||
</div>
|
||||
|
||||
@@ -28,58 +28,22 @@ export function ScrollProgress() {
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={shouldReduceMotion ? {} : { opacity: 0, y: -4 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={shouldReduceMotion ? {} : { opacity: 0, y: -4 }}
|
||||
transition={{ duration: 0.25 }}
|
||||
className="fixed top-0 left-0 right-0 h-[3px] z-[100] bg-transparent"
|
||||
initial={shouldReduceMotion ? {} : { opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={shouldReduceMotion ? {} : { opacity: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className="fixed top-0 left-0 right-0 h-[2px] z-[100]"
|
||||
role="progressbar"
|
||||
aria-label="页面滚动进度"
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<motion.div
|
||||
className="h-full origin-left relative"
|
||||
className="h-full origin-left"
|
||||
style={{
|
||||
scaleX,
|
||||
background:
|
||||
'linear-gradient(90deg, #C41E3A 0%, #E04A68 50%, #C41E3A 100%)',
|
||||
backgroundSize: '200% 100%',
|
||||
background: 'var(--color-brand-primary)',
|
||||
}}
|
||||
>
|
||||
<motion.div
|
||||
className="absolute inset-y-0 right-0 w-6 -mr-[2px]"
|
||||
style={{
|
||||
background: 'linear-gradient(90deg, transparent, rgba(196,30,58,0.6))',
|
||||
filter: 'blur(4px)',
|
||||
opacity: shouldReduceMotion ? 0 : 1,
|
||||
}}
|
||||
/>
|
||||
{!shouldReduceMotion && (
|
||||
<>
|
||||
<motion.div
|
||||
className="absolute top-1/2 -translate-y-1/2 right-0 w-2 h-2 rounded-full"
|
||||
style={{ background: '#fff', boxShadow: '0 0 6px rgba(196,30,58,0.8)' }}
|
||||
animate={{ scale: [1, 1.5, 1], opacity: [0.8, 1, 0.8] }}
|
||||
transition={{ duration: 1.5, repeat: Infinity, ease: 'easeInOut' }}
|
||||
/>
|
||||
<motion.div
|
||||
className="absolute bottom-0 left-0 right-0 h-[1px]"
|
||||
style={{
|
||||
background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.15), transparent)',
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</motion.div>
|
||||
<div
|
||||
className="absolute inset-0 pointer-events-none"
|
||||
style={{
|
||||
background: 'linear-gradient(90deg, transparent, rgba(196,30,58,0.08), transparent)',
|
||||
filter: 'blur(8px)',
|
||||
transform: `scaleX(${typeof scaleX === 'object' ? 'var(--progress, 0)' : 1})`,
|
||||
}}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</motion.div>
|
||||
);
|
||||
|
||||
@@ -16,23 +16,23 @@ export const PRODUCTS: Product[] = [
|
||||
{
|
||||
id: 'erp',
|
||||
title: '睿新ERP管理系统',
|
||||
description: '集成财务、采购、销售、库存、生产等模块的企业资源计划系统,助力企业实现业务流程标准化、数据一体化管理。',
|
||||
description: '打通财务、采购、销售、库存、生产全链路,让各部门数据实时流转、业务流程自动协同。',
|
||||
image: '/images/products/erp.jpg',
|
||||
category: '企业软件',
|
||||
status: '研发中',
|
||||
overview: '睿新ERP管理系统是我们正在打造的企业资源计划系统,规划集成财务管理、采购管理、销售管理、库存管理、生产管理等核心模块,旨在帮助企业实现业务流程标准化、数据一体化管理,提升运营效率。',
|
||||
overview: '睿新ERP管理系统是我们正在打造的企业资源计划系统,旨在打通财务、采购、销售、库存、生产等核心模块,让各部门数据实时流转、业务流程自动协同,帮助企业告别信息孤岛。',
|
||||
features: [
|
||||
'财务管理:规划支持总账、应收应付、成本核算、固定资产管理',
|
||||
'采购管理:规划供应商管理、采购订单、入库验收、采购分析',
|
||||
'销售管理:规划客户管理、销售订单、发货管理、销售分析',
|
||||
'库存管理:规划库存查询、出入库管理、库存预警、盘点管理',
|
||||
'生产管理:规划生产计划、物料需求、生产订单、成本核算',
|
||||
'报表分析:规划丰富的报表模板,支持自定义报表',
|
||||
'财务管理:总账、应收应付、成本核算、固定资产管理',
|
||||
'采购管理:供应商管理、采购订单、入库验收、采购分析',
|
||||
'销售管理:客户管理、销售订单、发货管理、销售分析',
|
||||
'库存管理:库存查询、出入库管理、库存预警、盘点管理',
|
||||
'生产管理:生产计划、物料需求、生产订单、成本核算',
|
||||
'报表分析:丰富的报表模板,支持自定义报表',
|
||||
],
|
||||
benefits: [
|
||||
'数据完全自主可控,满足安全合规要求',
|
||||
'规划支持本地/私有云/混合云多种部署方式',
|
||||
'致力于提升企业运营效率,减少人工操作',
|
||||
'支持本地/私有云/混合云多种部署方式',
|
||||
'提升企业运营效率,减少人工操作',
|
||||
'灵活订阅按需付费,无隐性收费,成本可控',
|
||||
],
|
||||
process: [
|
||||
@@ -44,34 +44,34 @@ export const PRODUCTS: Product[] = [
|
||||
'培训交付:用户培训与正式交付上线',
|
||||
],
|
||||
specs: [
|
||||
'规划支持本地服务器、私有云、混合云部署',
|
||||
'规划支持多组织、多账套管理',
|
||||
'规划支持信创环境(国产操作系统/数据库)',
|
||||
'规划支持API接口集成,对接现有系统',
|
||||
'规划支持移动端访问(APP/微信/钉钉)',
|
||||
'规划支持数据加密存储与传输',
|
||||
'支持本地服务器、私有云、混合云部署',
|
||||
'支持多组织、多账套管理',
|
||||
'适配信创环境(国产操作系统/数据库)',
|
||||
'提供API接口,对接现有系统',
|
||||
'支持移动端访问(APP/微信/钉钉)',
|
||||
'数据加密存储与传输',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'crm',
|
||||
title: '睿新客户关系管理系统',
|
||||
description: '全渠道客户管理平台,整合客户信息、跟进销售机会、提升客户满意度和忠诚度,助力企业业绩增长。',
|
||||
description: '从线索到成交的全流程可视化管理,让销售团队清楚每一步该做什么、每个机会卡在哪里。',
|
||||
image: '/images/products/crm.jpg',
|
||||
category: '企业软件',
|
||||
status: '研发中',
|
||||
overview: '睿新客户关系管理系统是我们正在打造的全渠道客户管理平台,规划整合客户信息、跟进销售机会、提升客户满意度和忠诚度,助力企业业绩增长。系统规划支持多渠道客户数据整合,提供全面的客户画像和销售漏斗分析。',
|
||||
overview: '睿新客户关系管理系统是我们正在打造的全渠道客户管理平台,从线索到成交全流程可视化管理,让销售团队清楚每一步该做什么、每个机会卡在哪里。系统支持多渠道客户数据整合,提供全面的客户画像和销售漏斗分析。',
|
||||
features: [
|
||||
'客户档案:规划完整的客户信息管理,支持自定义字段',
|
||||
'销售漏斗:规划可视化的销售机会管理,实时跟进销售进度',
|
||||
'商机管理:规划商机创建、跟进、转化全流程管理',
|
||||
'合同管理:规划合同创建、审批、执行、归档全流程',
|
||||
'售后服务:规划工单管理、服务记录、客户满意度调查',
|
||||
'数据分析:规划客户分析、销售分析、业绩报表',
|
||||
'客户档案:完整的客户信息管理,支持自定义字段',
|
||||
'销售漏斗:可视化的销售机会管理,实时跟进销售进度',
|
||||
'商机管理:商机创建、跟进、转化全流程管理',
|
||||
'合同管理:合同创建、审批、执行、归档全流程',
|
||||
'售后服务:工单管理、服务记录、客户满意度调查',
|
||||
'数据分析:客户分析、销售分析、业绩报表',
|
||||
],
|
||||
benefits: [
|
||||
'客户数据私有化存储,保障商业机密',
|
||||
'规划支持与企业现有系统深度集成',
|
||||
'致力于提升销售转化率,提高销售效率',
|
||||
'与企业现有系统深度集成',
|
||||
'提升销售转化率,提高销售效率',
|
||||
'灵活定制销售流程,适配业务变化',
|
||||
],
|
||||
process: [
|
||||
@@ -83,34 +83,34 @@ export const PRODUCTS: Product[] = [
|
||||
'培训交付:销售团队培训与系统上线',
|
||||
],
|
||||
specs: [
|
||||
'规划支持本地服务器、私有云部署',
|
||||
'规划支持多渠道客户数据整合',
|
||||
'规划支持信创环境适配',
|
||||
'规划支持API接口,对接ERP/OA等系统',
|
||||
'规划支持移动端访问',
|
||||
'规划支持数据加密与权限隔离',
|
||||
'支持本地服务器、私有云部署',
|
||||
'支持多渠道客户数据整合',
|
||||
'适配信创环境',
|
||||
'提供API接口,对接ERP/OA等系统',
|
||||
'支持移动端访问',
|
||||
'数据加密与权限隔离',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'cms',
|
||||
title: '睿新内容管理系统',
|
||||
description: '灵活易用的企业级内容管理平台,支持多站点管理、内容发布、权限控制,助力企业高效管理各类数字内容。',
|
||||
description: '所见即所得的编辑体验,多站点统一管理,让内容发布像写文档一样简单。',
|
||||
image: '/images/products/cms.jpg',
|
||||
category: '企业软件',
|
||||
status: '研发中',
|
||||
overview: '睿新内容管理系统是我们正在打造的企业级内容管理平台,规划支持多站点管理、内容发布、权限控制,助力企业高效管理各类数字内容。系统规划提供强大的内容编辑功能和灵活的权限管理机制。',
|
||||
overview: '睿新内容管理系统是我们正在打造的企业级内容管理平台,提供所见即所得的编辑体验和多站点统一管理能力,让内容发布像写文档一样简单。系统提供强大的内容编辑功能和灵活的权限管理机制。',
|
||||
features: [
|
||||
'内容编辑:规划所见即所得的富文本编辑器,支持多媒体内容',
|
||||
'多站点管理:规划支持管理多个站点,统一内容管理',
|
||||
'权限控制:规划细粒度的权限管理,支持角色和用户权限',
|
||||
'版本管理:规划内容版本控制,支持版本对比和回滚',
|
||||
'内容发布:规划定时发布、工作流审批、多渠道分发',
|
||||
'SEO优化:规划内置SEO工具,优化搜索引擎排名',
|
||||
'内容编辑:所见即所得的富文本编辑器,支持多媒体内容',
|
||||
'多站点管理:统一管理多个站点的内容',
|
||||
'权限控制:细粒度的权限管理,支持角色和用户权限',
|
||||
'版本管理:内容版本控制,支持版本对比和回滚',
|
||||
'内容发布:定时发布、工作流审批、多渠道分发',
|
||||
'SEO优化:内置SEO工具,优化搜索引擎排名',
|
||||
],
|
||||
benefits: [
|
||||
'内容数据自主管理,支持等保合规',
|
||||
'规划支持私有化部署,内外网隔离访问',
|
||||
'致力于提升内容发布效率,加快内容更新',
|
||||
'支持私有化部署,内外网隔离访问',
|
||||
'提升内容发布效率,加快内容更新',
|
||||
'灵活的权限体系,满足多部门协作',
|
||||
],
|
||||
process: [
|
||||
@@ -122,34 +122,34 @@ export const PRODUCTS: Product[] = [
|
||||
'培训交付:内容团队培训与系统上线',
|
||||
],
|
||||
specs: [
|
||||
'规划支持本地服务器、私有云部署',
|
||||
'规划支持多站点统一管理',
|
||||
'规划支持信创环境适配',
|
||||
'规划支持API接口集成',
|
||||
'规划支持自定义模板与组件',
|
||||
'规划支持等保二级/三级安全要求',
|
||||
'支持本地服务器、私有云部署',
|
||||
'支持多站点统一管理',
|
||||
'适配信创环境',
|
||||
'提供API接口集成',
|
||||
'支持自定义模板与组件',
|
||||
'满足等保二级/三级安全要求',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'bi',
|
||||
title: '睿新商业智能平台',
|
||||
description: '数据可视化分析平台,整合多源数据,提供丰富的图表和报表,助力企业数据驱动决策,发现业务增长机会。',
|
||||
description: '拖拽式自助分析,让业务人员无需写SQL也能从数据中找到答案。',
|
||||
image: '/images/products/bi.jpg',
|
||||
category: '数据产品',
|
||||
status: '研发中',
|
||||
overview: '睿新商业智能平台是我们正在打造的数据可视化分析平台,规划整合多源数据,提供丰富的图表和报表,助力企业数据驱动决策,发现业务增长机会。平台规划支持自助式数据分析和实时数据监控。',
|
||||
overview: '睿新商业智能平台是我们正在打造的数据可视化分析平台,提供拖拽式自助分析能力,让业务人员无需写SQL也能从数据中找到答案。平台支持自助式数据分析和实时数据监控。',
|
||||
features: [
|
||||
'数据整合:规划支持多种数据源,统一数据平台',
|
||||
'可视化报表:规划丰富的图表类型,支持自定义报表',
|
||||
'自助分析:规划拖拽式数据分析,降低使用门槛',
|
||||
'实时监控:规划实时数据监控和智能预警',
|
||||
'智能预警:规划基于规则的智能预警,及时发现异常',
|
||||
'移动看板:规划支持移动端访问,随时随地查看数据',
|
||||
'数据整合:对接多种数据源,统一数据平台',
|
||||
'可视化报表:丰富的图表类型,支持自定义报表',
|
||||
'自助分析:拖拽式数据分析,降低使用门槛',
|
||||
'实时监控:实时数据监控和智能预警',
|
||||
'智能预警:基于规则的智能预警,及时发现异常',
|
||||
'移动看板:支持移动端访问,随时随地查看数据',
|
||||
],
|
||||
benefits: [
|
||||
'分析能力私有化部署,数据不出企业',
|
||||
'规划支持对接内部数据源,无需数据上云',
|
||||
'致力于提升决策效率,加快决策速度',
|
||||
'对接内部数据源,无需数据上云',
|
||||
'提升决策效率,加快决策速度',
|
||||
'自助式分析,降低数据使用门槛',
|
||||
],
|
||||
process: [
|
||||
@@ -161,32 +161,32 @@ export const PRODUCTS: Product[] = [
|
||||
'培训交付:数据分析培训与系统上线',
|
||||
],
|
||||
specs: [
|
||||
'规划支持本地服务器、私有云部署',
|
||||
'规划支持多种数据源(数据库/文件/API)',
|
||||
'规划支持信创环境适配',
|
||||
'规划支持实时与离线数据分析',
|
||||
'规划支持API接口集成',
|
||||
'规划支持数据加密与访问审计',
|
||||
'支持本地服务器、私有云部署',
|
||||
'支持多种数据源(数据库/文件/API)',
|
||||
'适配信创环境',
|
||||
'支持实时与离线数据分析',
|
||||
'提供API接口集成',
|
||||
'数据加密与访问审计',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'sds',
|
||||
title: '睿新供应链决策支持系统',
|
||||
description: '智能供应链管理平台,自动预测销量、优化库存、生成补货建议,帮助企业减少库存积压和缺货损失,让每一分钱都花在刀刃上。',
|
||||
description: '自动预测销量、智能补货建议,帮您把库存成本降下来、把缺货损失挽回来。',
|
||||
image: '/images/products/sds.jpg',
|
||||
category: '数据产品',
|
||||
status: '研发中',
|
||||
overview: '睿新供应链决策支持系统是我们正在打造的智能供应链管理平台,规划实现自动预测销量、优化库存、生成补货建议,帮助企业减少库存积压和缺货损失,让每一分钱都花在刀刃上。系统规划采用智能算法,实现从经验驱动到数据驱动的供应链管理升级。',
|
||||
overview: '睿新供应链决策支持系统是我们正在打造的智能供应链管理平台,自动预测销量、智能补货建议,帮您把库存成本降下来、把缺货损失挽回来。系统采用智能算法,实现从经验驱动到数据驱动的供应链管理升级。',
|
||||
features: [
|
||||
'智能销量预测:规划自动分析历史销售趋势、季节规律和促销影响,预测每个商品销量',
|
||||
'库存健康诊断:规划自动识别库存过多(积压资金)和即将缺货(错失销售)的商品',
|
||||
'精准补货建议:规划系统自动计算补货时机和数量,按紧急程度排好优先级',
|
||||
'原因追溯分析:规划提供预测偏差原因分析,帮助理解销量波动因素',
|
||||
'供应商协同:规划与供应商系统对接,实现采购订单自动推送和交期跟踪',
|
||||
'数据看板:规划实时展示库存周转率、缺货率、积压金额等关键指标',
|
||||
'智能销量预测:自动分析历史销售趋势、季节规律和促销影响,预测每个商品销量',
|
||||
'库存健康诊断:自动识别库存过多(积压资金)和即将缺货(错失销售)的商品',
|
||||
'精准补货建议:系统自动计算补货时机和数量,按紧急程度排好优先级',
|
||||
'原因追溯分析:提供预测偏差原因分析,帮助理解销量波动因素',
|
||||
'供应商协同:与供应商系统对接,实现采购订单自动推送和交期跟踪',
|
||||
'数据看板:实时展示库存周转率、缺货率、积压金额等关键指标',
|
||||
],
|
||||
benefits: [
|
||||
'致力于降低库存成本和缺货率,直接转化为利润提升',
|
||||
'降低库存成本和缺货率,直接转化为利润提升',
|
||||
'无需专业数据团队,采购员、库管员等日常操作人员即可独立使用',
|
||||
'简单三步完成核心操作,系统全程引导,零基础也能快速上手',
|
||||
'投入产出清晰可算,仪表盘实时展示节省了多少钱、挽回了多少销售',
|
||||
@@ -200,33 +200,33 @@ export const PRODUCTS: Product[] = [
|
||||
'培训交付:供应链团队培训与系统上线',
|
||||
],
|
||||
specs: [
|
||||
'规划支持本地服务器、私有云部署',
|
||||
'规划支持多种ERP/WMS系统数据对接',
|
||||
'规划支持信创环境适配',
|
||||
'规划支持多品类、多仓点并行管理',
|
||||
'规划支持API接口集成',
|
||||
'规划支持数据加密与访问审计',
|
||||
'支持本地服务器、私有云部署',
|
||||
'对接多种ERP/WMS系统数据',
|
||||
'适配信创环境',
|
||||
'支持多品类、多仓点并行管理',
|
||||
'提供API接口集成',
|
||||
'数据加密与访问审计',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'oa',
|
||||
title: '睿新协同办公系统',
|
||||
description: '一站式企业协同办公平台,集成流程审批、公文管理、智能协作、知识中心等功能,助力企业实现办公数字化、协作高效化。',
|
||||
description: '审批流程电子化、公文管理合规化、知识资产沉淀化,一站式解决办公协作难题。',
|
||||
image: '/images/products/oa.jpg',
|
||||
category: '企业软件',
|
||||
status: '研发中',
|
||||
overview: '睿新协同办公系统是我们正在打造的综合型企业协同办公平台,融合传统办公自动化与现代协作理念。系统规划集成流程审批、公文管理、即时通讯、知识管理、会议日程等核心模块,支持PC端与移动端全场景覆盖,帮助企业实现办公数字化、流程规范化、协作高效化。',
|
||||
overview: '睿新协同办公系统是我们正在打造的综合型企业协同办公平台,融合传统办公自动化与现代协作理念。集成流程审批、公文管理、即时通讯、知识管理、会议日程等核心模块,支持PC端与移动端全场景覆盖,帮助企业实现办公数字化、流程规范化、协作高效化。',
|
||||
features: [
|
||||
'流程审批:规划请假、报销、采购、合同等全流程电子化审批,支持自定义审批流程和条件分支',
|
||||
'公文管理:规划收文登记、发文审批、公文流转、归档管理,满足政务合规和档案管理要求',
|
||||
'智能协作:规划支持与钉钉、企业微信、飞书等主流平台深度整合,实现统一消息推送与协作',
|
||||
'知识中心:规划企业知识库、文档管理、知识检索、权限管控,沉淀组织智慧资产',
|
||||
'会议日程:规划会议室预约、会议通知、纪要管理、个人与团队日程同步',
|
||||
'移动办公:规划全功能移动端,支持APP、微信企业号、钉钉等多端接入',
|
||||
'流程审批:请假、报销、采购、合同等全流程电子化审批,支持自定义审批流程和条件分支',
|
||||
'公文管理:收文登记、发文审批、公文流转、归档管理,满足政务合规和档案管理要求',
|
||||
'智能协作:与钉钉、企业微信、飞书等主流平台深度整合,实现统一消息推送与协作',
|
||||
'知识中心:企业知识库、文档管理、知识检索、权限管控,沉淀组织智慧资产',
|
||||
'会议日程:会议室预约、会议通知、纪要管理、个人与团队日程同步',
|
||||
'移动办公:全功能移动端,支持APP、微信企业号、钉钉等多端接入',
|
||||
],
|
||||
benefits: [
|
||||
'致力于提升流程审批效率,告别纸质流转,降低管理成本',
|
||||
'知识资产沉淀共享,避免“人走知识丢”,提升组织学习能力',
|
||||
'提升流程审批效率,告别纸质流转,降低管理成本',
|
||||
'知识资产沉淀共享,避免"人走知识丢",提升组织学习能力',
|
||||
'移动办公全覆盖,决策不等待,响应更及时',
|
||||
'一站式办公平台,减少系统切换成本,提升工作效率',
|
||||
],
|
||||
@@ -239,12 +239,12 @@ export const PRODUCTS: Product[] = [
|
||||
'培训交付:全员培训与系统正式上线',
|
||||
],
|
||||
specs: [
|
||||
'规划支持本地服务器、私有云、混合云部署',
|
||||
'规划支持多组织、多层级组织架构管理',
|
||||
'规划支持信创环境(国产操作系统/数据库/中间件)',
|
||||
'规划支持API接口集成,对接ERP/CRM等业务系统',
|
||||
'规划支持移动端APP、微信企业号、钉钉等多端接入',
|
||||
'规划支持数据加密、访问审计、安全水印等安全特性',
|
||||
'支持本地服务器、私有云、混合云部署',
|
||||
'支持多组织、多层级组织架构管理',
|
||||
'适配信创环境(国产操作系统/数据库/中间件)',
|
||||
'提供API接口集成,对接ERP/CRM等业务系统',
|
||||
'支持移动端APP、微信企业号、钉钉等多端接入',
|
||||
'数据加密、访问审计、安全水印等安全特性',
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
|
||||
Reference in New Issue
Block a user