feat: 恢复深色主题版本,替换星空背景视频

This commit is contained in:
leisileken
2026-06-24 22:32:58 +08:00
parent 99deb970a0
commit 00eb7a3883
19 changed files with 2158 additions and 374 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 KiB

BIN
public/images/星云.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

BIN
public/videos/xingkong.mp4 Normal file

Binary file not shown.

View File

@@ -38,7 +38,7 @@ export const images = {
manufacturing: 'https://images.unsplash.com/photo-1581091226825-a6a2a5aee158?w=800&h=450&fit=crop',
finance: 'https://images.unsplash.com/photo-1563986768609-322da13575f3?w=800&h=450&fit=crop',
healthcare: 'https://images.unsplash.com/photo-1576091160399-112ba8d25d1d?w=800&h=450&fit=crop',
education: 'https://images.unsplash.com/photo-1523050854058-8df90110c9f1?w=800&h=450&fit=crop',
education: 'https://images.unsplash.com/photo-1522202176988-66273c2fd55f?w=800&h=450&fit=crop',
retail: 'https://images.unsplash.com/photo-1556742049-0cfed4f6a45d?w=800&h=450&fit=crop',
logistics: 'https://images.unsplash.com/photo-1489599849927-2ee91cede3ba?w=800&h=450&fit=crop',

View File

@@ -0,0 +1,372 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
interface Particle {
element: HTMLElement
angle: number
radius: number
speed: number
size: number
opacity: number
baseOpacity: number
color: string
centerX: number
centerY: number
twinkleSpeed: number
twinkleOffset: number
}
const particlesContainer = ref<HTMLDivElement | null>(null)
const particles: Particle[] = []
const mousePos = { x: 0, y: 0 }
let animationFrameId: number | null = null
let time = 0
const nebulaColors = [
'#6366f1',
'#8b5cf6',
'#a855f7',
'#d946ef',
'#ec4899',
'#f43f5e',
'#3b82f6',
'#60a5fa',
'#22d3ee',
'#14b8a6',
]
const createNebulaParticle = (centerX: number, centerY: number, maxRadius: number) => {
const particle = document.createElement('div')
particle.className = 'particle nebula'
particle.style.position = 'absolute'
particle.style.borderRadius = '50%'
particle.style.pointerEvents = 'none'
particle.style.transition = 'opacity 0.3s ease'
const angle = Math.random() * Math.PI * 2
const radius = Math.random() * maxRadius
const size = Math.random() * 3 + 1
const color = nebulaColors[Math.floor(Math.random() * nebulaColors.length)]
const baseOpacity = Math.random() * 0.4 + 0.2
particle.style.width = `${size}px`
particle.style.height = `${size}px`
particle.style.backgroundColor = color
particle.style.left = `${centerX + Math.cos(angle) * radius}px`
particle.style.top = `${centerY + Math.sin(angle) * radius}px`
particle.style.opacity = `${baseOpacity}`
if (particlesContainer.value) {
particlesContainer.value.appendChild(particle)
}
particles.push({
element: particle,
angle,
radius,
speed: (Math.random() * 0.001 + 0.0005) * (Math.random() > 0.5 ? 1 : -1),
size,
opacity: baseOpacity,
baseOpacity,
color,
centerX,
centerY,
twinkleSpeed: Math.random() * 0.005 + 0.002,
twinkleOffset: Math.random() * Math.PI * 2,
})
}
const createNebulaCenter = () => {
const centerX = window.innerWidth / 2
const centerY = window.innerHeight / 2
for (let i = 0; i < 150; i++) {
createNebulaParticle(centerX, centerY, Math.min(window.innerWidth, window.innerHeight) * 0.4)
}
for (let i = 0; i < 100; i++) {
createNebulaParticle(centerX, centerY, Math.min(window.innerWidth, window.innerHeight) * 0.6)
}
for (let i = 0; i < 50; i++) {
createNebulaParticle(centerX, centerY, Math.min(window.innerWidth, window.innerHeight) * 0.8)
}
}
const updateParticles = () => {
particles.forEach((particle) => {
const x = particle.centerX + Math.cos(particle.angle) * particle.radius
const y = particle.centerY + Math.sin(particle.angle) * particle.radius
particle.element.style.left = `${x}px`
particle.element.style.top = `${y}px`
particle.element.style.opacity = `${particle.baseOpacity}`
const glowSize = particle.size * 6
particle.element.style.boxShadow = `0 0 ${glowSize}px ${particle.color}40`
})
animationFrameId = requestAnimationFrame(updateParticles)
}
const handleMouseMove = (e: MouseEvent) => {
mousePos.x = e.clientX
mousePos.y = e.clientY
}
const handleResize = () => {
particles.forEach(p => {
p.element.remove()
})
particles.length = 0
createNebulaCenter()
}
onMounted(() => {
createNebulaCenter()
updateParticles()
window.addEventListener('mousemove', handleMouseMove)
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId)
}
window.removeEventListener('mousemove', handleMouseMove)
window.removeEventListener('resize', handleResize)
particles.forEach(p => {
p.element.remove()
})
})
</script>
<template>
<div class="cosmic-background">
<div ref="particlesContainer" class="particles-container"></div>
<div class="bg-gradient-radial-from-center"></div>
<div class="bg-gradient-radial-abyss"></div>
<div class="galaxy-core"></div>
<div class="galaxy-arms"></div>
<div class="cosmic-dust"></div>
</div>
</template>
<style scoped>
.cosmic-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
background: #000;
overflow: hidden;
}
.cosmic-background::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('/images/星云.png');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
opacity: 0.6;
z-index: 0;
}
.particles-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 1;
}
.bg-gradient-radial-from-center {
position: absolute;
inset: 0;
background: radial-gradient(
ellipse at center,
rgba(30, 30, 60, 0.4) 0%,
rgba(20, 20, 40, 0.3) 30%,
rgba(10, 10, 20, 0.2) 60%,
rgba(0, 0, 0, 0) 100%
);
z-index: 2;
}
.bg-gradient-radial-abyss {
position: absolute;
inset: 0;
background: radial-gradient(
ellipse 80% 50% at 50% 100%,
rgba(0, 0, 0, 0.85) 0%,
rgba(5, 5, 15, 0.7) 40%,
rgba(10, 10, 30, 0.5) 70%,
rgba(0, 0, 0, 0.8) 100%
);
z-index: 3;
}
.galaxy-core {
display: none;
}
.galaxy-arms {
position: absolute;
top: 50%;
left: 50%;
width: 800px;
height: 800px;
transform: translate(-50%, -50%);
animation: rotate-arms 120s linear infinite;
z-index: 4;
}
.galaxy-arms::before,
.galaxy-arms::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
transform-origin: center;
}
.galaxy-arms::before {
background: conic-gradient(
from 0deg,
transparent 0deg,
rgba(100, 100, 200, 0.02) 10deg,
rgba(150, 150, 255, 0.04) 20deg,
rgba(100, 100, 200, 0.02) 30deg,
transparent 40deg,
transparent 90deg,
rgba(100, 100, 200, 0.02) 100deg,
rgba(150, 150, 255, 0.04) 110deg,
rgba(100, 100, 200, 0.02) 120deg,
transparent 130deg,
transparent 180deg,
rgba(100, 100, 200, 0.02) 190deg,
rgba(150, 150, 255, 0.04) 200deg,
rgba(100, 100, 200, 0.02) 210deg,
transparent 220deg,
transparent 270deg,
rgba(100, 100, 200, 0.02) 280deg,
rgba(150, 150, 255, 0.04) 290deg,
rgba(100, 100, 200, 0.02) 300deg,
transparent 310deg,
transparent 360deg
);
border-radius: 50%;
}
.galaxy-arms::after {
background: conic-gradient(
from 45deg,
transparent 0deg,
rgba(180, 180, 255, 0.015) 15deg,
rgba(200, 200, 255, 0.03) 30deg,
rgba(180, 180, 255, 0.015) 45deg,
transparent 60deg,
transparent 150deg,
rgba(180, 180, 255, 0.015) 165deg,
rgba(200, 200, 255, 0.03) 180deg,
rgba(180, 180, 255, 0.015) 195deg,
transparent 210deg,
transparent 300deg,
rgba(180, 180, 255, 0.015) 315deg,
rgba(200, 200, 255, 0.03) 330deg,
rgba(180, 180, 255, 0.015) 345deg,
transparent 360deg
);
border-radius: 50%;
}
.cosmic-dust {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
radial-gradient(1px 1px at 20px 30px, rgba(255,255,255,0.3), transparent),
radial-gradient(1px 1px at 40px 70px, rgba(255,255,255,0.2), transparent),
radial-gradient(2px 2px at 90px 40px, rgba(255,255,255,0.4), transparent),
radial-gradient(1px 1px at 160px 120px, rgba(255,255,255,0.2), transparent),
radial-gradient(2px 2px at 230px 80px, rgba(255,255,255,0.3), transparent),
radial-gradient(1px 1px at 300px 150px, rgba(255,255,255,0.2), transparent),
radial-gradient(1px 1px at 370px 60px, rgba(255,255,255,0.3), transparent),
radial-gradient(2px 2px at 450px 200px, rgba(255,255,255,0.4), transparent),
radial-gradient(1px 1px at 520px 100px, rgba(255,255,255,0.2), transparent),
radial-gradient(1px 1px at 600px 180px, rgba(255,255,255,0.3), transparent),
radial-gradient(2px 2px at 680px 90px, rgba(255,255,255,0.4), transparent),
radial-gradient(1px 1px at 750px 250px, rgba(255,255,255,0.2), transparent),
radial-gradient(1px 1px at 830px 130px, rgba(255,255,255,0.3), transparent),
radial-gradient(2px 2px at 900px 300px, rgba(255,255,255,0.4), transparent),
radial-gradient(1px 1px at 980px 160px, rgba(255,255,255,0.2), transparent),
radial-gradient(1px 1px at 20px 280px, rgba(255,255,255,0.3), transparent),
radial-gradient(2px 2px at 100px 350px, rgba(255,255,255,0.4), transparent),
radial-gradient(1px 1px at 180px 420px, rgba(255,255,255,0.2), transparent),
radial-gradient(1px 1px at 260px 300px, rgba(255,255,255,0.3), transparent),
radial-gradient(2px 2px at 340px 480px, rgba(255,255,255,0.4), transparent),
radial-gradient(1px 1px at 420px 360px, rgba(255,255,255,0.2), transparent),
radial-gradient(1px 1px at 500px 440px, rgba(255,255,255,0.3), transparent),
radial-gradient(2px 2px at 580px 320px, rgba(255,255,255,0.4), transparent),
radial-gradient(1px 1px at 660px 500px, rgba(255,255,255,0.2), transparent),
radial-gradient(1px 1px at 740px 380px, rgba(255,255,255,0.3), transparent),
radial-gradient(2px 2px at 820px 560px, rgba(255,255,255,0.4), transparent),
radial-gradient(1px 1px at 900px 450px, rgba(255,255,255,0.2), transparent),
radial-gradient(1px 1px at 980px 520px, rgba(255,255,255,0.3), transparent);
background-size: 1000px 600px;
animation: float-dust 60s linear infinite;
z-index: 5;
}
@keyframes rotate-core {
from {
transform: translate(-50%, -50%) rotate(0deg);
}
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
@keyframes rotate-arms {
from {
transform: translate(-50%, -50%) rotate(0deg);
}
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
@keyframes pulse-core {
0%, 100% {
transform: translate(-50%, -50%) scale(1);
opacity: 0.5;
}
50% {
transform: translate(-50%, -50%) scale(1.2);
opacity: 0.2;
}
}
@keyframes float-dust {
from {
background-position: 0 0;
}
to {
background-position: 1000px 600px;
}
}
</style>

View File

@@ -25,7 +25,7 @@ const currentYear = new Date().getFullYear()
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<span>陕西省西安市高新区科技二路65号清华科技园E座</span>
<span>西安市未央区立讯未来中心</span>
</div>
<div class="flex items-center space-x-3 text-gray-400">
<svg class="w-5 h-5 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">

View File

@@ -0,0 +1,227 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
interface TrailPoint {
id: number
x: number
y: number
opacity: number
size: number
life: number
}
const isVisible = ref(false)
const trailPoints = ref<TrailPoint[]>([])
const mouseX = ref(0)
const mouseY = ref(0)
let animationFrameId: number | null = null
let pointId = 0
let lastX = 0
let lastY = 0
let lastTime = 0
let moveSpeed = 0
let lastTrailTime = 0
const handleMouseMove = (e: MouseEvent) => {
const currentTime = Date.now()
const deltaTime = currentTime - lastTime
const dx = e.clientX - lastX
const dy = e.clientY - lastY
mouseX.value = e.clientX
mouseY.value = e.clientY
if (deltaTime > 0) {
moveSpeed = Math.sqrt(dx * dx + dy * dy) / deltaTime
}
const distance = Math.sqrt(dx * dx + dy * dy)
if (distance > 5 && currentTime - lastTrailTime > 20) {
const trailLength = Math.min(Math.floor(moveSpeed * 1.5), 5)
for (let i = 0; i < trailLength; i++) {
const ratio = i / trailLength
const wave = Math.sin(ratio * Math.PI)
const sizeVariation = Math.sin(ratio * Math.PI * 3) * 2
trailPoints.value.push({
id: pointId++,
x: e.clientX - dx * ratio,
y: e.clientY - dy * ratio,
opacity: wave * (1 - ratio * 0.4),
size: 6 + wave * 3 + sizeVariation,
life: 1
})
}
lastTrailTime = currentTime
}
lastX = e.clientX
lastY = e.clientY
lastTime = currentTime
if (!isVisible.value) {
isVisible.value = true
}
}
const animate = () => {
const decaySpeed = moveSpeed > 0.5 ? 0.015 : 0.03
trailPoints.value = trailPoints.value
.map(p => ({
...p,
life: p.life - decaySpeed,
opacity: p.opacity * (1 - decaySpeed * 0.5),
size: p.size * (1 - decaySpeed * 0.3)
}))
.filter(p => p.life > 0 && p.opacity > 0)
if (moveSpeed < 0.1) {
moveSpeed *= 0.95
}
animationFrameId = requestAnimationFrame(animate)
}
const handleMouseLeave = () => {
isVisible.value = false
trailPoints.value = []
}
onMounted(() => {
if (window.matchMedia('(pointer: fine)').matches) {
document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseleave', handleMouseLeave)
animate()
}
})
onUnmounted(() => {
document.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseleave', handleMouseLeave)
if (animationFrameId) {
cancelAnimationFrame(animationFrameId)
}
})
</script>
<template>
<div
v-show="isVisible"
class="comet-trail-container"
>
<div
v-for="point in trailPoints"
:key="point.id"
class="comet-trail-point"
:style="{
left: `${point.x}px`,
top: `${point.y}px`,
opacity: point.opacity,
width: `${point.size}px`,
height: `${point.size}px`
}"
></div>
<div
class="comet-head"
:style="{
left: `${mouseX}px`,
top: `${mouseY}px`
}"
></div>
<div
class="comet-glow"
:style="{
left: `${mouseX}px`,
top: `${mouseY}px`
}"
></div>
</div>
</template>
<style scoped>
.comet-trail-container {
position: fixed;
inset: 0;
pointer-events: none;
z-index: 9999;
overflow: hidden;
}
.comet-trail-point {
position: absolute;
border-radius: 50%;
transform: translate(-50%, -50%);
background: radial-gradient(
circle,
rgba(147, 197, 253, 1) 0%,
rgba(139, 92, 246, 0.8) 40%,
rgba(99, 102, 241, 0.5) 70%,
transparent 100%
);
box-shadow:
0 0 6px rgba(147, 197, 253, 0.9),
0 0 12px rgba(139, 92, 246, 0.6),
0 0 18px rgba(99, 102, 241, 0.4);
filter: blur(1px);
}
.comet-head {
position: absolute;
width: 12px;
height: 12px;
border-radius: 50%;
transform: translate(-50%, -50%);
background: radial-gradient(
circle,
rgba(255, 255, 255, 1) 0%,
rgba(200, 220, 255, 1) 30%,
rgba(147, 197, 253, 0.9) 60%,
transparent 100%
);
box-shadow:
0 0 15px rgba(255, 255, 255, 1),
0 0 30px rgba(147, 197, 253, 0.9),
0 0 45px rgba(59, 130, 246, 0.6),
0 0 60px rgba(139, 92, 246, 0.4);
}
.comet-glow {
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
transform: translate(-50%, -50%);
background: radial-gradient(
circle,
rgba(147, 197, 253, 0.4) 0%,
rgba(59, 130, 246, 0.2) 40%,
transparent 70%
);
filter: blur(10px);
animation: glow-pulse 1s ease-in-out infinite;
}
@keyframes glow-pulse {
0%, 100% {
transform: translate(-50%, -50%) scale(1);
opacity: 0.8;
}
50% {
transform: translate(-50%, -50%) scale(1.2);
opacity: 1;
}
}
@media (pointer: coarse) {
.comet-trail-container {
display: none !important;
}
}
</style>

View File

@@ -0,0 +1,120 @@
import type { Directive } from 'vue'
interface ActivatePoint {
id: number
x: number
y: number
progress: number
}
const vNeuralCard: Directive = {
mounted(el: HTMLElement) {
const points: ActivatePoint[] = []
let pointId = 0
let animationId: number | null = null
let isHovering = false
const createActivatePoint = () => {
const rect = el.getBoundingClientRect()
const edge = Math.floor(Math.random() * 4)
let x: number, y: number
switch (edge) {
case 0:
x = rect.left + Math.random() * rect.width
y = rect.top
break
case 1:
x = rect.right
y = rect.top + Math.random() * rect.height
break
case 2:
x = rect.left + Math.random() * rect.width
y = rect.bottom
break
default:
x = rect.left
y = rect.top + Math.random() * rect.height
}
points.push({
id: pointId++,
x,
y,
progress: 0
})
updateCSS()
}
const updateCSS = () => {
if (points.length === 0) {
el.style.setProperty('--neural-points', '')
return
}
const pointData = points
.map(p => `${p.x},${p.y},${p.progress}`)
.join('|')
el.style.setProperty('--neural-points', pointData)
el.style.setProperty('--neural-count', String(points.length))
}
const animate = () => {
points.forEach(p => {
p.progress += 0.02
})
const activePoints = points.filter(p => p.progress < 1)
points.length = 0
points.push(...activePoints)
updateCSS()
if (isHovering && points.length < 6) {
if (Math.random() > 0.7) {
createActivatePoint()
}
}
animationId = requestAnimationFrame(animate)
}
const handleMouseEnter = () => {
isHovering = true
el.classList.add('neural-active')
el.classList.add('neural-card-active')
}
const handleMouseLeave = () => {
isHovering = false
el.classList.remove('neural-active')
el.classList.remove('neural-card-active')
}
const handleMouseMove = (e: MouseEvent) => {
const rect = el.getBoundingClientRect()
const mouseX = ((e.clientX - rect.left) / rect.width) * 100
const mouseY = ((e.clientY - rect.top) / rect.height) * 100
el.style.setProperty('--mouse-x', `${mouseX}%`)
el.style.setProperty('--mouse-y', `${mouseY}%`)
}
el.addEventListener('mouseenter', handleMouseEnter)
el.addEventListener('mouseleave', handleMouseLeave)
el.addEventListener('mousemove', handleMouseMove)
animate()
el._neuralAnimationId = animationId
},
unmounted(el: HTMLElement) {
if (el._neuralAnimationId) {
cancelAnimationFrame(el._neuralAnimationId)
}
}
}
export default vNeuralCard

94
src/directives/ripple.ts Normal file
View File

@@ -0,0 +1,94 @@
import type { Directive, DirectiveBinding } from 'vue'
interface RippleEvent extends MouseEvent {
_ripple?: HTMLElement
}
const vRipple: Directive = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
el.style.position = 'relative'
el.style.overflow = 'hidden'
const handleClick = (e: RippleEvent) => {
const rect = el.getBoundingClientRect()
const x = e.clientX - rect.left
const y = e.clientY - rect.top
const maxSize = Math.max(rect.width, rect.height) * 2
const rippleOuter = document.createElement('span')
rippleOuter.style.position = 'absolute'
rippleOuter.style.borderRadius = '50%'
rippleOuter.style.background = 'rgba(59, 130, 246, 0.5)'
rippleOuter.style.width = '30px'
rippleOuter.style.height = '30px'
rippleOuter.style.left = `${x}px`
rippleOuter.style.top = `${y}px`
rippleOuter.style.transform = 'translate(-50%, -50%) scale(0)'
rippleOuter.style.transition = 'transform 0.6s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.6s ease-out'
rippleOuter.style.pointerEvents = 'none'
rippleOuter.style.zIndex = '100'
rippleOuter.style.boxShadow = '0 0 40px rgba(59, 130, 246, 0.8), 0 0 80px rgba(147, 197, 253, 0.6), 0 0 120px rgba(139, 92, 246, 0.4)'
const rippleMiddle = document.createElement('span')
rippleMiddle.style.position = 'absolute'
rippleMiddle.style.borderRadius = '50%'
rippleMiddle.style.background = 'rgba(147, 197, 253, 0.7)'
rippleMiddle.style.width = '20px'
rippleMiddle.style.height = '20px'
rippleMiddle.style.left = `${x}px`
rippleMiddle.style.top = `${y}px`
rippleMiddle.style.transform = 'translate(-50%, -50%) scale(0)'
rippleMiddle.style.transition = 'transform 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.5s ease-out'
rippleMiddle.style.pointerEvents = 'none'
rippleMiddle.style.zIndex = '101'
rippleMiddle.style.boxShadow = '0 0 30px rgba(147, 197, 253, 0.9), 0 0 60px rgba(59, 130, 246, 0.7), 0 0 90px rgba(255, 255, 255, 0.5)'
const rippleInner = document.createElement('span')
rippleInner.style.position = 'absolute'
rippleInner.style.borderRadius = '50%'
rippleInner.style.background = 'radial-gradient(circle, rgba(255, 255, 255, 1) 0%, rgba(147, 197, 253, 1) 30%, rgba(59, 130, 246, 0.8) 70%, transparent 100%)'
rippleInner.style.width = '15px'
rippleInner.style.height = '15px'
rippleInner.style.left = `${x}px`
rippleInner.style.top = `${y}px`
rippleInner.style.transform = 'translate(-50%, -50%) scale(0)'
rippleInner.style.transition = 'transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s ease-out'
rippleInner.style.pointerEvents = 'none'
rippleInner.style.zIndex = '102'
rippleInner.style.boxShadow = '0 0 25px rgba(255, 255, 255, 1), 0 0 50px rgba(147, 197, 253, 0.9), 0 0 80px rgba(59, 130, 246, 0.7), 0 0 110px rgba(139, 92, 246, 0.5)'
el.appendChild(rippleOuter)
el.appendChild(rippleMiddle)
el.appendChild(rippleInner)
requestAnimationFrame(() => {
rippleOuter.style.transform = `translate(-50%, -50%) scale(${maxSize / 15})`
rippleOuter.style.opacity = '0'
rippleMiddle.style.transform = `translate(-50%, -50%) scale(${maxSize / 10})`
rippleMiddle.style.opacity = '0'
rippleInner.style.transform = `translate(-50%, -50%) scale(${maxSize / 7})`
rippleInner.style.opacity = '0'
})
setTimeout(() => {
rippleOuter.remove()
rippleMiddle.remove()
rippleInner.remove()
}, 700)
}
el.addEventListener('click', handleClick)
el._rippleHandler = handleClick
},
unmounted(el: HTMLElement) {
if (el._rippleHandler) {
el.removeEventListener('click', el._rippleHandler)
}
}
}
export default vRipple

View File

@@ -4,8 +4,12 @@ import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import vRipple from './directives/ripple'
import vNeuralCard from './directives/neuralCard'
const app = createApp(App)
app.use(router)
app.use(ElementPlus)
app.directive('ripple', vRipple)
app.directive('neural-card', vNeuralCard)
app.mount('#app')

View File

@@ -8,6 +8,11 @@ const router = createRouter({
name: 'Home',
component: () => import('@/views/Home.vue')
},
{
path: '/landing',
name: 'Landing',
component: () => import('@/views/LandingPage.vue')
},
{
path: '/products',
name: 'Products',

View File

@@ -90,6 +90,21 @@ body {
animation: float 6s ease-in-out infinite;
}
.page-visible {
animation: page-fade-in 1s ease-out forwards;
}
@keyframes page-fade-in {
0% {
opacity: 0;
transform: scale(0.98);
}
100% {
opacity: 1;
transform: scale(1);
}
}
/* 渐变背景 */
.bg-gradient-primary {
background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 50%, #60a5fa 100%);
@@ -143,3 +158,102 @@ body {
.text-gradient {
@apply bg-gradient-to-r from-primary-600 to-accent-500 bg-clip-text text-transparent;
}
/* 神经网络卡片激活效果 - 旋转光效 */
.neural-card-active {
position: relative;
transform: translateY(-6px) scale(1.02);
box-shadow:
0 0 30px rgba(59, 130, 246, 0.4),
0 0 60px rgba(147, 197, 253, 0.3),
inset 0 0 20px rgba(147, 197, 253, 0.1);
}
.neural-card-active::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: conic-gradient(
from 0deg,
transparent 0deg,
rgba(147, 197, 253, 0.3) 30deg,
rgba(59, 130, 246, 0.6) 60deg,
rgba(139, 92, 246, 0.8) 90deg,
rgba(59, 130, 246, 0.6) 120deg,
rgba(147, 197, 253, 0.3) 150deg,
transparent 180deg,
transparent 360deg
);
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
padding: 3px;
animation: neural-rotate 3s linear infinite;
}
@keyframes neural-rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.neural-card-active::after {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: conic-gradient(
from 180deg,
transparent 0deg,
rgba(59, 130, 246, 0.4) 45deg,
rgba(147, 197, 253, 0.7) 90deg,
rgba(255, 255, 255, 0.9) 110deg,
rgba(147, 197, 253, 0.7) 130deg,
rgba(59, 130, 246, 0.4) 180deg,
transparent 360deg
);
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
padding: 3px;
animation: neural-rotate-reverse 4s linear infinite;
opacity: 0.7;
}
@keyframes neural-rotate-reverse {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
.neural-card-active .card-inner-glow {
position: absolute;
inset: 0;
border-radius: inherit;
background: radial-gradient(
circle at var(--mouse-x, 50%) var(--mouse-y, 50%),
rgba(147, 197, 253, 0.2) 0%,
rgba(59, 130, 246, 0.1) 30%,
transparent 60%
);
pointer-events: none;
animation: neural-flicker 2s ease-in-out infinite;
}
@keyframes neural-flicker {
0%, 100% {
opacity: 0.5;
transform: scale(1);
}
50% {
opacity: 1;
transform: scale(1.02);
}
}

View File

@@ -54,20 +54,19 @@ const advantages = [
</script>
<template>
<div class="min-h-screen bg-white">
<section class="relative py-20 overflow-hidden">
<video
src="/videos/tech3.mp4"
class="absolute inset-0 w-full h-full object-cover"
autoplay loop muted playsinline
></video>
<div class="absolute inset-0 bg-gradient-to-br from-primary-900/90 via-primary-800/80 to-accent-900/90"></div>
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="min-h-screen relative">
<video
class="fixed inset-0 w-full h-full object-cover z-0"
autoplay loop muted playsinline
>
<source src="/videos/xingkong.mp4" type="video/mp4" />
</video>
<div class="fixed inset-0 bg-black/30 z-0"></div>
<section class="relative min-h-screen flex items-center overflow-hidden z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 pt-20">
<div class="text-center">
<span class="inline-block px-4 py-2 bg-white/10 text-white/90 rounded-full text-sm font-medium mb-4">
关于我们
</span>
<h1 class="text-4xl sm:text-5xl font-bold text-white mb-4">
<h1 class="text-5xl sm:text-6xl font-bold bg-gradient-to-r from-green-400 via-cyan-400 to-blue-500 bg-clip-text text-transparent mb-4">
西安云阶智元信息科技有限公司
</h1>
<p class="text-lg text-white/80 max-w-2xl mx-auto">
@@ -77,12 +76,12 @@ const advantages = [
</div>
</section>
<section class="py-20">
<section class="py-20 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid lg:grid-cols-2 gap-12 items-center">
<div>
<h2 class="text-3xl font-bold text-gray-900 mb-6">公司简介</h2>
<p class="text-gray-600 mb-8 leading-relaxed">
<h2 class="text-3xl font-bold text-white mb-6">公司简介</h2>
<p class="text-white/70 mb-8 leading-relaxed">
西安云阶智元信息科技有限公司简称"云阶智元"成立于2026年坐落于西安市未央区立讯未来中心是一家以智能体Agent技术为核心驱动致力于为实体产业注入智能化增长动能的新型科技企业公司自助研发智能体架构"启元"公司拥有自主可控的研发团队核心成员10余人精通智能体架构设计高可用运维保障零信任安全防护等关键技术公司主业聚焦Agent定制开发智能运维托管全链路安全防护三大板块同时拓展跨境电商平台科研协同智慧规划产教融合等衍生服务灵活适配制造业农业文旅水利政务等多行业智能化需求公司已成功落地某零食厂家智能运营体西安市某乡村自媒体无人运营系统长江流域水文科研平台产业发展推演模型等标杆项目切实助力客户实现管理效率提升决策模式优化与运营成本降低未来云阶智元将持续深耕Agent底层技术强化场景化赋能能力致力成为西北地区产业智能化升级最值得信赖的合作伙伴
</p>
<ul class="space-y-3">
@@ -91,14 +90,14 @@ const advantages = [
:key="index"
class="flex items-center"
>
<svg class="w-5 h-5 text-accent-500 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-5 h-5 text-accent-400 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<span class="text-gray-700">{{ advantage }}</span>
<span class="text-white/80">{{ advantage }}</span>
</li>
</ul>
</div>
<div class="relative">
<div class="relative self-start mt-16">
<div class="absolute -inset-4 bg-gradient-to-r from-primary-400 to-accent-400 rounded-2xl blur-xl opacity-20"></div>
<video
src="/videos/001.mp4"
@@ -111,87 +110,89 @@ const advantages = [
</div>
</section>
<section class="py-16 bg-gray-50">
<section class="py-16 bg-white/5 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-2 md:grid-cols-4 gap-6">
<div class="text-center">
<div class="w-16 h-16 bg-primary-100 rounded-xl flex items-center justify-center mx-auto mb-4">
<svg class="w-8 h-8 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="text-center group">
<div class="w-16 h-16 bg-gradient-to-br from-primary-500/30 to-accent-500/30 rounded-xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-primary-500/30 transition-all duration-300">
<svg class="w-8 h-8 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"/>
</svg>
</div>
<p class="text-3xl font-bold text-gray-900 mb-1">{{ companyInfo.employees }}</p>
<p class="text-gray-600">核心团队</p>
<p class="text-3xl font-bold text-white mb-1">{{ companyInfo.employees }}</p>
<p class="text-white/60">核心团队</p>
</div>
<div class="text-center">
<div class="w-16 h-16 bg-accent-100 rounded-xl flex items-center justify-center mx-auto mb-4">
<svg class="w-8 h-8 text-accent-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="text-center group">
<div class="w-16 h-16 bg-gradient-to-br from-accent-500/30 to-purple-500/30 rounded-xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-accent-500/30 transition-all duration-300">
<svg class="w-8 h-8 text-accent-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</div>
<p class="text-3xl font-bold text-gray-900 mb-1">{{ companyInfo.clients }}</p>
<p class="text-gray-600">标杆项目</p>
<p class="text-3xl font-bold text-white mb-1">{{ companyInfo.clients }}</p>
<p class="text-white/60">标杆项目</p>
</div>
<div class="text-center">
<div class="w-16 h-16 bg-purple-100 rounded-xl flex items-center justify-center mx-auto mb-4">
<svg class="w-8 h-8 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="text-center group">
<div class="w-16 h-16 bg-gradient-to-br from-purple-500/30 to-pink-500/30 rounded-xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-purple-500/30 transition-all duration-300">
<svg class="w-8 h-8 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-5 0h-5m-5 0H2m2 0v-4a2 2 0 012-2h10a2 2 0 012 2v4M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"/>
</svg>
</div>
<p class="text-3xl font-bold text-gray-900 mb-1">20+</p>
<p class="text-gray-600">行业覆盖</p>
<p class="text-3xl font-bold text-white mb-1">20+</p>
<p class="text-white/60">行业覆盖</p>
</div>
<div class="text-center">
<div class="w-16 h-16 bg-orange-100 rounded-xl flex items-center justify-center mx-auto mb-4">
<svg class="w-8 h-8 text-orange-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="text-center group">
<div class="w-16 h-16 bg-gradient-to-br from-orange-500/30 to-red-500/30 rounded-xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-orange-500/30 transition-all duration-300">
<svg class="w-8 h-8 text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/>
</svg>
</div>
<p class="text-3xl font-bold text-gray-900 mb-1">信息安全</p>
<p class="text-gray-600">核心技术</p>
<p class="text-3xl font-bold text-white mb-1">信息安全</p>
<p class="text-white/60">核心技术</p>
</div>
</div>
</div>
</section>
<section class="py-20">
<section class="py-20 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-gray-900 mb-4">核心价值观</h2>
<p class="text-gray-600">我们坚信的理念指引我们不断前行</p>
<h2 class="text-3xl font-bold text-white mb-4">核心价值观</h2>
<p class="text-white/70">我们坚信的理念指引我们不断前行</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
<div
v-for="(value, index) in coreValues"
:key="index"
class="bg-gray-50 rounded-xl p-6 text-center"
class="bg-white/10 backdrop-blur-sm rounded-xl p-6 text-center border border-white/10 hover:border-white/30 hover:shadow-lg hover:shadow-primary-500/20 transition-all duration-300 group cursor-pointer"
v-ripple
v-neural-card
>
<div class="w-14 h-14 bg-primary-100 rounded-xl flex items-center justify-center mx-auto mb-4">
<svg v-if="value.icon === 'target'" class="w-7 h-7 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="w-14 h-14 bg-gradient-to-br from-primary-500/30 to-accent-500/30 rounded-xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
<svg v-if="value.icon === 'target'" class="w-7 h-7 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<svg v-else-if="value.icon === 'lightbulb'" class="w-7 h-7 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="value.icon === 'lightbulb'" class="w-7 h-7 text-accent-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/>
</svg>
<svg v-else-if="value.icon === 'users'" class="w-7 h-7 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="value.icon === 'users'" class="w-7 h-7 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"/>
</svg>
<svg v-else-if="value.icon === 'trending'" class="w-7 h-7 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="value.icon === 'trending'" class="w-7 h-7 text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/>
</svg>
</div>
<h3 class="font-semibold text-gray-900 mb-2">{{ value.title }}</h3>
<p class="text-gray-600 text-sm">{{ value.desc }}</p>
<h3 class="font-semibold text-white mb-2">{{ value.title }}</h3>
<p class="text-white/60 text-sm">{{ value.desc }}</p>
</div>
</div>
</div>
</section>
<section class="py-20 bg-gradient-to-br from-gray-50 via-primary-50/50 to-accent-50/50">
<section class="py-20 bg-white/5 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-gray-900 mb-4">公司来历</h2>
<p class="text-gray-600">从技术研发到公司成立我们的成长之路</p>
<h2 class="text-3xl font-bold text-white mb-4">公司来历</h2>
<p class="text-white/70">从技术研发到公司成立我们的成长之路</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
@@ -201,28 +202,28 @@ const advantages = [
class="relative group"
>
<div class="absolute inset-0 bg-gradient-to-br from-primary-500 to-accent-500 rounded-2xl blur-lg opacity-0 group-hover:opacity-20 transition-opacity duration-500"></div>
<div class="relative bg-white rounded-2xl p-6 shadow-lg border border-gray-100 hover:shadow-xl transition-all duration-300 h-full flex flex-col">
<div class="w-14 h-14 bg-gradient-to-br from-primary-100 to-accent-100 rounded-xl flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
<svg v-if="index === 0" class="w-7 h-7 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="relative bg-white/10 backdrop-blur-sm rounded-2xl p-6 border border-white/10 hover:border-white/30 hover:shadow-lg hover:shadow-primary-500/20 transition-all duration-300 h-full flex flex-col cursor-pointer" v-ripple v-neural-card>
<div class="w-14 h-14 bg-gradient-to-br from-primary-500/30 to-accent-500/30 rounded-xl flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
<svg v-if="index === 0" class="w-7 h-7 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/>
</svg>
<svg v-else-if="index === 1" class="w-7 h-7 text-accent-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="index === 1" class="w-7 h-7 text-accent-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"/>
</svg>
<svg v-else-if="index === 2" class="w-7 h-7 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="index === 2" class="w-7 h-7 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
</svg>
<svg v-else class="w-7 h-7 text-orange-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else class="w-7 h-7 text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"/>
</svg>
</div>
<p class="text-xl font-bold text-gray-900 mb-2">{{ milestone.year }}</p>
<p class="text-gray-600 text-sm flex-grow mb-4">{{ milestone.event }}</p>
<p class="text-xl font-bold text-white mb-2">{{ milestone.year }}</p>
<p class="text-white/70 text-sm flex-grow mb-4">{{ milestone.event }}</p>
<div class="flex flex-wrap gap-2">
<span
v-for="(tag, tagIndex) in milestone.tags"
:key="tagIndex"
class="px-2 py-1 bg-primary-50 text-primary-600 text-xs rounded-full font-medium"
class="px-2 py-1 bg-primary-500/20 text-primary-400 text-xs rounded-full font-medium"
>
{{ tag }}
</span>
@@ -232,87 +233,87 @@ const advantages = [
v-if="index < milestones.length - 1"
class="hidden lg:block absolute top-1/2 -right-3 transform -translate-y-1/2 z-10"
>
<svg class="w-6 h-6 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-6 h-6 text-white/30" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</div>
</div>
</div>
<div class="mt-12 bg-white rounded-2xl p-8 shadow-lg border border-gray-100">
<div class="mt-12 bg-white/10 backdrop-blur-sm rounded-2xl p-8 border border-white/10">
<div class="text-center mb-6">
<h3 class="text-2xl font-bold text-gray-900 mb-2">核心Agent产品矩阵</h3>
<p class="text-gray-600">基于多年技术积累打造全方位智能体解决方案</p>
<h3 class="text-2xl font-bold text-white mb-2">核心Agent产品矩阵</h3>
<p class="text-white/70">基于多年技术积累打造全方位智能体解决方案</p>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="bg-gradient-to-br from-primary-50 to-primary-100/50 rounded-xl p-4 text-center">
<div class="w-12 h-12 bg-white rounded-full flex items-center justify-center mx-auto mb-3 shadow-sm">
<svg class="w-6 h-6 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="bg-white/5 rounded-xl p-4 text-center border border-white/10 hover:border-white/30 transition-colors cursor-pointer" v-ripple v-neural-card>
<div class="w-12 h-12 bg-gradient-to-br from-primary-500/30 to-accent-500/30 rounded-full flex items-center justify-center mx-auto mb-3">
<svg class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
</svg>
</div>
<p class="font-semibold text-gray-900 text-sm">企业智能体中枢</p>
<p class="text-gray-500 text-xs mt-1">集群核心大脑</p>
<p class="font-semibold text-white text-sm">企业智能体中枢</p>
<p class="text-white/60 text-xs mt-1">集群核心大脑</p>
</div>
<div class="bg-gradient-to-br from-accent-50 to-accent-100/50 rounded-xl p-4 text-center">
<div class="w-12 h-12 bg-white rounded-full flex items-center justify-center mx-auto mb-3 shadow-sm">
<svg class="w-6 h-6 text-accent-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="bg-white/5 rounded-xl p-4 text-center border border-white/10 hover:border-white/30 transition-colors cursor-pointer" v-ripple v-neural-card>
<div class="w-12 h-12 bg-gradient-to-br from-accent-500/30 to-purple-500/30 rounded-full flex items-center justify-center mx-auto mb-3">
<svg class="w-6 h-6 text-accent-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
</div>
<p class="font-semibold text-gray-900 text-sm">智能客服助手</p>
<p class="text-gray-500 text-xs mt-1">7x24服务</p>
<p class="font-semibold text-white text-sm">智能客服助手</p>
<p class="text-white/60 text-xs mt-1">7x24服务</p>
</div>
<div class="bg-gradient-to-br from-purple-50 to-purple-100/50 rounded-xl p-4 text-center">
<div class="w-12 h-12 bg-white rounded-full flex items-center justify-center mx-auto mb-3 shadow-sm">
<svg class="w-6 h-6 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="bg-white/5 rounded-xl p-4 text-center border border-white/10 hover:border-white/30 transition-colors cursor-pointer" v-ripple v-neural-card>
<div class="w-12 h-12 bg-gradient-to-br from-purple-500/30 to-pink-500/30 rounded-full flex items-center justify-center mx-auto mb-3">
<svg class="w-6 h-6 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
</div>
<p class="font-semibold text-gray-900 text-sm">智能营销助手</p>
<p class="text-gray-500 text-xs mt-1">精准获客</p>
<p class="font-semibold text-white text-sm">智能营销助手</p>
<p class="text-white/60 text-xs mt-1">精准获客</p>
</div>
<div class="bg-gradient-to-br from-orange-50 to-orange-100/50 rounded-xl p-4 text-center">
<div class="w-12 h-12 bg-white rounded-full flex items-center justify-center mx-auto mb-3 shadow-sm">
<svg class="w-6 h-6 text-orange-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="bg-white/5 rounded-xl p-4 text-center border border-white/10 hover:border-white/30 transition-colors cursor-pointer" v-ripple v-neural-card>
<div class="w-12 h-12 bg-gradient-to-br from-orange-500/30 to-red-500/30 rounded-full flex items-center justify-center mx-auto mb-3">
<svg class="w-6 h-6 text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
</div>
<p class="font-semibold text-gray-900 text-sm">智能办公助手</p>
<p class="text-gray-500 text-xs mt-1">效率提升</p>
<p class="font-semibold text-white text-sm">智能办公助手</p>
<p class="text-white/60 text-xs mt-1">效率提升</p>
</div>
</div>
</div>
</div>
</section>
<section class="py-20" id="team">
<section class="py-20 relative z-10" id="team">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-gray-900 mb-4">核心团队</h2>
<p class="text-gray-600">专业的领导团队带领公司不断发展</p>
<h2 class="text-3xl font-bold text-white mb-4">核心团队</h2>
<p class="text-white/70">专业的领导团队带领公司不断发展</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
<div
v-for="(member, index) in team"
:key="index"
class="text-center"
class="text-center group"
>
<div class="relative mb-4">
<img
:src="member.avatar"
:alt="member.name"
class="w-32 h-32 rounded-full mx-auto object-cover ring-4 ring-primary-100"
class="w-32 h-32 rounded-full mx-auto object-cover ring-4 ring-primary-500/30 group-hover:ring-primary-500/60 group-hover:scale-105 transition-all duration-300"
/>
</div>
<h3 class="font-semibold text-gray-900 mb-1">{{ member.name }}</h3>
<p class="text-primary-600 text-sm">{{ member.role }}</p>
<h3 class="font-semibold text-white mb-1">{{ member.name }}</h3>
<p class="text-primary-400 text-sm">{{ member.role }}</p>
</div>
</div>
</div>
</section>
<section class="bg-gradient-to-br from-primary-900 to-accent-900 py-20">
<section class="bg-white/5 backdrop-blur-sm border-t border-white/10 py-20 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-4">
加入我们
@@ -320,7 +321,7 @@ const advantages = [
<p class="text-white/80 mb-8 max-w-2xl mx-auto">
我们正在寻找优秀的人才加入我们的团队共同推动技术创新和企业发展
</p>
<button @click="openRecruitment" class="btn-primary">
<button @click="openRecruitment" class="px-8 py-4 bg-gradient-to-r from-primary-600 to-accent-500 text-white font-medium rounded-xl hover:from-primary-500 hover:to-accent-400 transition-all duration-300 shadow-lg shadow-primary-500/30">
查看招聘信息
</button>
</div>
@@ -329,10 +330,10 @@ const advantages = [
<Teleport to="body">
<div
v-if="showRecruitment"
class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4"
class="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center z-50 p-4"
@click.self="closeRecruitment"
>
<div class="bg-white rounded-2xl shadow-2xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
<div class="bg-gray-900/95 backdrop-blur-xl border border-white/20 rounded-2xl shadow-2xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
<div class="bg-gradient-to-r from-primary-600 to-accent-600 p-6 rounded-t-2xl">
<div class="flex items-center justify-between">
<h3 class="text-2xl font-bold text-white">西安云阶智元科技AI Agent方向招聘</h3>
@@ -347,79 +348,79 @@ const advantages = [
</div>
</div>
<div class="p-8">
<p class="text-gray-700 mb-6 leading-relaxed">
<p class="text-white/80 mb-6 leading-relaxed">
云阶智元是一家专注于 AI Agent企业智能体中枢与行业智能化解决方案的科技公司致力于推动智能体在企业流程知识管理业务协同和自动化运营中的落地应用
</p>
<div class="mb-6">
<h4 class="text-lg font-semibold text-gray-900 mb-3 flex items-center">
<svg class="w-5 h-5 text-primary-600 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<h4 class="text-lg font-semibold text-white mb-3 flex items-center">
<svg class="w-5 h-5 text-primary-400 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"/>
</svg>
招聘岗位
</h4>
<div class="flex flex-wrap gap-2">
<span class="px-3 py-1 bg-primary-50 text-primary-700 rounded-full text-sm font-medium">AI产品经理</span>
<span class="px-3 py-1 bg-accent-50 text-accent-700 rounded-full text-sm font-medium">Agent应用开发工程师</span>
<span class="px-3 py-1 bg-purple-50 text-purple-700 rounded-full text-sm font-medium">前端开发工程师</span>
<span class="px-3 py-1 bg-blue-50 text-blue-700 rounded-full text-sm font-medium">后端开发工程师</span>
<span class="px-3 py-1 bg-green-50 text-green-700 rounded-full text-sm font-medium">AI解决方案顾问</span>
<span class="px-3 py-1 bg-orange-50 text-orange-700 rounded-full text-sm font-medium">内容/市场运营</span>
<span class="px-3 py-1 bg-primary-500/20 text-primary-400 rounded-full text-sm font-medium">AI产品经理</span>
<span class="px-3 py-1 bg-accent-500/20 text-accent-400 rounded-full text-sm font-medium">Agent应用开发工程师</span>
<span class="px-3 py-1 bg-purple-500/20 text-purple-400 rounded-full text-sm font-medium">前端开发工程师</span>
<span class="px-3 py-1 bg-blue-500/20 text-blue-400 rounded-full text-sm font-medium">后端开发工程师</span>
<span class="px-3 py-1 bg-green-500/20 text-green-400 rounded-full text-sm font-medium">AI解决方案顾问</span>
<span class="px-3 py-1 bg-orange-500/20 text-orange-400 rounded-full text-sm font-medium">内容/市场运营</span>
</div>
</div>
<div class="mb-6">
<h4 class="text-lg font-semibold text-gray-900 mb-3 flex items-center">
<svg class="w-5 h-5 text-primary-600 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<h4 class="text-lg font-semibold text-white mb-3 flex items-center">
<svg class="w-5 h-5 text-primary-400 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
</svg>
岗位要求
</h4>
<ul class="space-y-2">
<li class="flex items-start text-gray-700">
<span class="w-6 h-6 bg-primary-100 text-primary-600 rounded-full flex items-center justify-center text-xs font-bold mr-3 flex-shrink-0">1</span>
<li class="flex items-start text-white/70">
<span class="w-6 h-6 bg-primary-500/30 text-primary-400 rounded-full flex items-center justify-center text-xs font-bold mr-3 flex-shrink-0">1</span>
关注AI Agent大模型应用企业数字化方向
</li>
<li class="flex items-start text-gray-700">
<span class="w-6 h-6 bg-primary-100 text-primary-600 rounded-full flex items-center justify-center text-xs font-bold mr-3 flex-shrink-0">2</span>
<li class="flex items-start text-white/70">
<span class="w-6 h-6 bg-primary-500/30 text-primary-400 rounded-full flex items-center justify-center text-xs font-bold mr-3 flex-shrink-0">2</span>
具备较强的学习能力执行力和项目推进能力
</li>
<li class="flex items-start text-gray-700">
<span class="w-6 h-6 bg-primary-100 text-primary-600 rounded-full flex items-center justify-center text-xs font-bold mr-3 flex-shrink-0">3</span>
<li class="flex items-start text-white/70">
<span class="w-6 h-6 bg-primary-500/30 text-primary-400 rounded-full flex items-center justify-center text-xs font-bold mr-3 flex-shrink-0">3</span>
有产品研发SaaS企业服务或AI应用经验者优先
</li>
<li class="flex items-start text-gray-700">
<span class="w-6 h-6 bg-primary-100 text-primary-600 rounded-full flex items-center justify-center text-xs font-bold mr-3 flex-shrink-0">4</span>
<li class="flex items-start text-white/70">
<span class="w-6 h-6 bg-primary-500/30 text-primary-400 rounded-full flex items-center justify-center text-xs font-bold mr-3 flex-shrink-0">4</span>
能适应创业团队节奏愿意参与从0到1的产品建设
</li>
</ul>
</div>
<div class="mb-6">
<h4 class="text-lg font-semibold text-gray-900 mb-3 flex items-center">
<svg class="w-5 h-5 text-primary-600 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<h4 class="text-lg font-semibold text-white mb-3 flex items-center">
<svg class="w-5 h-5 text-primary-400 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
薪资待遇
</h4>
<p class="text-gray-700">
<p class="text-white/70">
基础薪资8K-25K/核心岗位可面议优秀者可享项目奖金绩效激励及长期发展权益
</p>
</div>
<div class="grid grid-cols-2 gap-4 mb-6">
<div class="bg-gray-50 rounded-xl p-4">
<p class="text-sm text-gray-500 mb-1">工作地点</p>
<p class="font-semibold text-gray-900">西安</p>
<div class="bg-white/10 rounded-xl p-4 border border-white/10">
<p class="text-sm text-white/60 mb-1">工作地点</p>
<p class="font-semibold text-white">西安</p>
</div>
<div class="bg-gray-50 rounded-xl p-4">
<p class="text-sm text-gray-500 mb-1">联系方式</p>
<p class="font-semibold text-gray-900">15515659613</p>
<div class="bg-white/10 rounded-xl p-4 border border-white/10">
<p class="text-sm text-white/60 mb-1">联系方式</p>
<p class="font-semibold text-white">15515659613</p>
</div>
</div>
<div class="bg-primary-50 rounded-xl p-4">
<p class="text-primary-800 text-center font-medium">
<div class="bg-primary-500/20 rounded-xl p-4 border border-primary-500/30">
<p class="text-primary-400 text-center font-medium">
欢迎真正看好AI时代愿意一起做长期事业的伙伴加入
</p>
</div>

View File

@@ -42,27 +42,26 @@ const handleSubmit = () => {
}
const contactInfo = [
{ icon: 'map', title: '公司地址', content: '陕西省西安市高新区科技二路65号清华科技园E座' },
{ icon: 'map', title: '公司地址', content: '西安市未央区立讯未来中心' },
{ icon: 'mail', title: '电子邮箱', content: '492265466@qq.com' },
{ icon: 'clock', title: '营业时间', content: '周一至周五 9:00-18:00' }
]
</script>
<template>
<div class="min-h-screen bg-white">
<section class="relative py-20 overflow-hidden">
<video
src="/videos/tech3.mp4"
class="absolute inset-0 w-full h-full object-cover"
autoplay loop muted playsinline
></video>
<div class="absolute inset-0 bg-gradient-to-br from-primary-900/90 via-primary-800/80 to-accent-900/90"></div>
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="min-h-screen relative">
<video
class="fixed inset-0 w-full h-full object-cover z-0"
autoplay loop muted playsinline
>
<source src="/videos/xingkong.mp4" type="video/mp4" />
</video>
<div class="fixed inset-0 bg-black/30 z-0"></div>
<section class="relative min-h-screen flex items-center overflow-hidden z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 pt-20">
<div class="text-center">
<span class="inline-block px-4 py-2 bg-white/10 text-white/90 rounded-full text-sm font-medium mb-4">
联系我们
</span>
<h1 class="text-4xl sm:text-5xl font-bold text-white mb-4">
<h1 class="text-5xl sm:text-6xl font-bold bg-gradient-to-r from-green-400 via-cyan-400 to-blue-500 bg-clip-text text-transparent mb-4">
与我们取得联系
</h1>
<p class="text-lg text-white/80 max-w-2xl mx-auto">
@@ -72,77 +71,79 @@ const contactInfo = [
</div>
</section>
<section class="py-16 bg-gray-50">
<section class="py-16 bg-white/5 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-2 md:grid-cols-4 gap-6">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div
v-for="(info, index) in contactInfo"
:key="index"
class="bg-white rounded-xl p-6 text-center"
class="bg-white/10 backdrop-blur-sm rounded-xl p-6 text-center border border-white/10 hover:border-white/30 hover:shadow-lg hover:shadow-primary-500/20 transition-all duration-300 group cursor-pointer"
v-ripple
v-neural-card
>
<div class="w-12 h-12 bg-primary-100 rounded-xl flex items-center justify-center mx-auto mb-4">
<svg v-if="info.icon === 'map'" class="w-6 h-6 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="w-12 h-12 bg-gradient-to-br from-primary-500/30 to-accent-500/30 rounded-xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
<svg v-if="info.icon === 'map'" class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<svg v-else-if="info.icon === 'phone'" class="w-6 h-6 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="info.icon === 'phone'" class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"/>
</svg>
<svg v-else-if="info.icon === 'mail'" class="w-6 h-6 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="info.icon === 'mail'" class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
</svg>
<svg v-else-if="info.icon === 'clock'" class="w-6 h-6 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="info.icon === 'clock'" class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</div>
<h3 class="font-semibold text-gray-900 mb-2">{{ info.title }}</h3>
<p class="text-gray-600 text-sm">{{ info.content }}</p>
<h3 class="font-semibold text-white mb-2">{{ info.title }}</h3>
<p class="text-white/60 text-sm">{{ info.content }}</p>
</div>
</div>
</div>
</section>
<section class="py-20">
<section id="consultation" class="py-20 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid lg:grid-cols-2 gap-12">
<div>
<h2 class="text-3xl font-bold text-gray-900 mb-6">获取免费咨询</h2>
<p class="text-gray-600 mb-8">
<h2 class="text-3xl font-bold text-white mb-6">获取免费咨询</h2>
<p class="text-white/70 mb-8">
填写以下表单我们的专业团队将在24小时内与您联系为您提供定制化的解决方案
</p>
<div class="space-y-6 mb-8">
<div class="flex items-start space-x-4">
<div class="w-12 h-12 bg-accent-100 rounded-xl flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-accent-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="w-12 h-12 bg-accent-500/20 rounded-xl flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-accent-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div>
<h4 class="font-semibold text-gray-900">专业团队</h4>
<p class="text-gray-600 text-sm">资深技术顾问一对一服务深入了解您的需求</p>
<h4 class="font-semibold text-white">专业团队</h4>
<p class="text-white/60 text-sm">资深技术顾问一对一服务深入了解您的需求</p>
</div>
</div>
<div class="flex items-start space-x-4">
<div class="w-12 h-12 bg-accent-100 rounded-xl flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-accent-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="w-12 h-12 bg-accent-500/20 rounded-xl flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-accent-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div>
<h4 class="font-semibold text-gray-900">定制方案</h4>
<p class="text-gray-600 text-sm">根据您的业务需求提供专属解决方案</p>
<h4 class="font-semibold text-white">定制方案</h4>
<p class="text-white/60 text-sm">根据您的业务需求提供专属解决方案</p>
</div>
</div>
<div class="flex items-start space-x-4">
<div class="w-12 h-12 bg-accent-100 rounded-xl flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-accent-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="w-12 h-12 bg-accent-500/20 rounded-xl flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-accent-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div>
<h4 class="font-semibold text-gray-900">免费评估</h4>
<p class="text-gray-600 text-sm">免费提供项目评估和报价服务</p>
<h4 class="font-semibold text-white">免费评估</h4>
<p class="text-white/60 text-sm">免费提供项目评估和报价服务</p>
</div>
</div>
</div>
@@ -153,44 +154,44 @@ const contactInfo = [
alt="公司环境"
class="w-full h-full object-cover"
/>
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent"></div>
<div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
<div class="absolute bottom-4 left-4 text-white">
<p class="font-semibold">欢迎来访</p>
<p class="text-sm text-white/80">陕西省西安市高新区科技二路65号清华科技园E座</p>
<p class="text-sm text-white/80">西安市未央区立讯未来中心</p>
</div>
</div>
</div>
<div class="bg-gray-50 rounded-2xl p-8">
<div class="bg-white/10 backdrop-blur-sm rounded-2xl p-8 border border-white/10">
<div v-if="isSubmitted" class="text-center py-12">
<div class="w-20 h-20 bg-accent-100 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="w-10 h-10 text-accent-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="w-20 h-20 bg-accent-500/20 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="w-10 h-10 text-accent-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
</div>
<h3 class="text-2xl font-bold text-gray-900 mb-2">提交成功!</h3>
<p class="text-gray-600">我们将在24小时内与您联系</p>
<h3 class="text-2xl font-bold text-white mb-2">提交成功!</h3>
<p class="text-white/70">我们将在24小时内与您联系</p>
</div>
<form v-else class="space-y-5" @submit.prevent="handleSubmit">
<div class="grid md:grid-cols-2 gap-5">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
<label class="block text-sm font-medium text-white/80 mb-2">
<svg class="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
</svg>
姓名 <span class="text-red-500">*</span>
姓名 <span class="text-red-400">*</span>
</label>
<input
v-model="form.name"
type="text"
required
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all"
class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all text-white placeholder-white/40"
placeholder="请输入您的姓名"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
<label class="block text-sm font-medium text-white/80 mb-2">
<svg class="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"/>
</svg>
@@ -199,7 +200,7 @@ const contactInfo = [
<input
v-model="form.company"
type="text"
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all"
class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all text-white placeholder-white/40"
placeholder="请输入公司名称"
/>
</div>
@@ -207,7 +208,7 @@ const contactInfo = [
<div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
<label class="block text-sm font-medium text-white/80 mb-2">
<svg class="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
</svg>
@@ -216,44 +217,44 @@ const contactInfo = [
<input
v-model="form.email"
type="email"
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all"
class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all text-white placeholder-white/40"
placeholder="请输入电子邮箱"
/>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">咨询服务</label>
<label class="block text-sm font-medium text-white/80 mb-2">咨询服务</label>
<select
v-model="form.service"
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all bg-white"
class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all text-white"
>
<option value="">请选择服务类型</option>
<option v-for="service in services" :key="service" :value="service">
<option value="" class="text-gray-900">请选择服务类型</option>
<option v-for="service in services" :key="service" :value="service" class="text-gray-900">
{{ service }}
</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
<label class="block text-sm font-medium text-white/80 mb-2">
<svg class="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-3.582 8-8 8a8.013 8.013 0 01-5.45-2.132L2.5 19l1.132-3.238A7.956 7.956 0 014 12c0-4.418 3.582-8 8-8s8 3.582 8 8z"/>
</svg>
需求描述 <span class="text-red-500">*</span>
需求描述 <span class="text-red-400">*</span>
</label>
<textarea
v-model="form.message"
rows="4"
required
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all resize-none"
class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all resize-none text-white placeholder-white/40"
placeholder="请简要描述您的需求..."
></textarea>
</div>
<button
type="submit"
class="btn-primary w-full flex items-center justify-center"
class="w-full flex items-center justify-center px-8 py-4 bg-gradient-to-r from-primary-600 to-accent-500 text-white font-medium rounded-xl hover:from-primary-500 hover:to-accent-400 transition-all duration-300 shadow-lg shadow-primary-500/30"
:disabled="isSubmitting"
>
<span v-if="isSubmitting">提交中...</span>
@@ -270,20 +271,20 @@ const contactInfo = [
</div>
</section>
<section class="bg-gray-50 py-16">
<section class="bg-white/5 py-16 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid md:grid-cols-3 gap-8">
<div class="text-center">
<div class="text-4xl font-bold text-primary-600 mb-2">24小时</div>
<p class="text-gray-600">快速响应</p>
<div class="text-4xl font-bold text-primary-400 mb-2">24小时</div>
<p class="text-white/70">快速响应</p>
</div>
<div class="text-center">
<div class="text-4xl font-bold text-accent-600 mb-2">1对1</div>
<p class="text-gray-600">专属服务</p>
<div class="text-4xl font-bold text-accent-400 mb-2">1对1</div>
<p class="text-white/70">专属服务</p>
</div>
<div class="text-center">
<div class="text-4xl font-bold text-purple-600 mb-2">免费</div>
<p class="text-gray-600">方案评估</p>
<div class="text-4xl font-bold text-purple-400 mb-2">免费</div>
<p class="text-white/70">方案评估</p>
</div>
</div>
</div>

View File

@@ -1,14 +1,37 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { images } from '@/assets/images'
const router = useRouter()
const bgVideoRef = ref<HTMLVideoElement | null>(null)
const isVisible = ref(false)
const initScrollAnimation = () => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('visible')
}
})
},
{
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
}
)
document.querySelectorAll('.scroll-animate, .scroll-animate-left, .scroll-animate-right, .scroll-animate-scale').forEach((el) => {
observer.observe(el)
})
}
onMounted(() => {
setTimeout(() => {
isVisible.value = true
}, 100)
if (bgVideoRef.value) {
bgVideoRef.value.currentTime = 2
bgVideoRef.value.addEventListener('timeupdate', () => {
@@ -19,6 +42,11 @@ onMounted(() => {
}
})
}
setTimeout(initScrollAnimation, 100)
})
onUnmounted(() => {
})
const stats = [
@@ -58,19 +86,22 @@ const services = [
const products = [
{
name: '云智通平台',
description: '企业级智能化管理平台',
shortDescription: '企业级智能化管理平台',
description: '云智通平台是一款专为企业打造的一体化智能管理解决方案。平台整合了先进的人工智能技术与丰富的行业经验提供从数据采集、分析到决策支持的全链路服务。通过智能化的流程引擎企业可以实现业务流程的自动化编排与优化大幅降低运营成本。平台内置的实时监控系统能够7×24小时追踪企业关键指标及时发现异常并推送预警。强大的数据可视化模块让复杂数据一目了然支持多种图表类型和自定义报表。同时平台采用微服务架构支持弹性扩展能够随业务增长灵活扩容。我们提供完整的API接口和SDK工具包便于与企业现有系统无缝集成。',
features: ['智能数据分析', '流程自动化', '实时监控'],
image: images.enterprise
},
{
name: 'AI智能助手',
description: '基于大语言模型的智能客服系统',
shortDescription: '基于大语言模型的智能客服系统',
description: 'AI智能助手是基于最新大语言模型技术打造的下一代智能客服解决方案。它能够理解用户的自然语言表达实现流畅的多轮对话交互准确把握用户意图并给出专业的解答。系统内置了强大的知识图谱引擎支持结构化与非结构化知识的统一管理可以快速构建企业专属的知识库。与传统客服相比AI助手可以同时处理海量并发请求大幅缩短响应时间提升客户满意度。支持多渠道接入包括网页、APP、微信公众号、企业微信等。系统具备自我学习能力能够从对话中持续优化不断提升回答的准确性和专业度。我们提供完整的部署方案既支持云端SaaS模式快速上线也支持私有化部署保障数据安全。',
features: ['自然语言交互', '多轮对话', '知识图谱'],
image: images.aiChatbot
},
{
name: '数据中台',
description: '统一数据管理与分析平台',
shortDescription: '统一数据管理与分析平台',
description: '数据中台是企业数字化转型的基础设施提供从数据采集、清洗、存储到分析、应用的全生命周期管理。平台支持多种异构数据源的快速接入包括关系型数据库、NoSQL数据库、文件系统、API接口等实现数据的统一汇聚。强大的实时计算引擎支持流式数据处理能够满足金融风控、物联网监控等场景的毫秒级响应需求。智能数据挖掘模块内置了丰富的机器学习算法可以帮助企业从海量数据中发现潜在规律预测市场趋势。完善的数据治理功能确保数据质量支持数据血缘追踪、安全脱敏、分级分类等需求。平台提供可视化的数据开发环境让数据工程师可以快速构建数据管道。同时开放的数据服务层让业务系统能够便捷地获取所需数据资产。',
features: ['数据集成', '实时计算', '智能洞察'],
image: images.dataCenter
}
@@ -92,27 +123,39 @@ const testimonials = [
]
const activeTestimonial = ref(0)
const expandedProduct = ref<number | null>(null)
const showProductModal = ref(false)
const selectedProduct = ref<any>(null)
const toggleProduct = (index: number) => {
expandedProduct.value = expandedProduct.value === index ? null : index
}
const openProductDetail = (product: any) => {
selectedProduct.value = product
showProductModal.value = true
}
const closeProductDetail = () => {
showProductModal.value = false
selectedProduct.value = null
}
</script>
<template>
<div class="min-h-screen">
<section class="relative min-h-screen flex items-center overflow-hidden">
<div class="min-h-screen" :class="{ 'page-visible': isVisible }">
<section class="relative min-h-screen flex items-center overflow-hidden bg-black">
<video
ref="bgVideoRef"
src="/videos/tech3.mp4"
class="absolute inset-0 w-full h-full object-cover"
autoplay loop muted playsinline
></video>
<div class="absolute inset-0 bg-gradient-to-br from-primary-900/90 via-primary-800/80 to-accent-900/90"></div>
<div class="absolute inset-0 overflow-hidden">
<div class="absolute top-20 left-20 w-72 h-72 bg-primary-500/20 rounded-full blur-3xl animate-pulse-slow"></div>
<div class="absolute bottom-20 right-20 w-96 h-96 bg-accent-500/20 rounded-full blur-3xl animate-pulse-slow" style="animation-delay: 1s;"></div>
<div class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-[600px] h-[600px] bg-primary-400/10 rounded-full blur-3xl"></div>
</div>
>
<source src="/videos/xingkong.mp4" type="video/mp4" />
</video>
<div class="absolute inset-0 bg-black/30"></div>
<div class="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10 pt-20">
<div class="grid lg:grid-cols-2 gap-12 items-center">
<div class="animate-fadeInUp">
<div class="scroll-animate-left">
<div class="inline-flex items-center px-4 py-2 bg-white/10 rounded-full text-white/90 text-sm mb-6">
<span class="w-2 h-2 bg-accent-400 rounded-full mr-2 animate-pulse"></span>
专注数字化转型赋能企业创新
@@ -136,38 +179,16 @@ const activeTestimonial = ref(0)
</button>
</div>
</div>
<div class="animate-slideInRight">
<div class="relative">
<div class="absolute -inset-4 bg-gradient-to-r from-primary-400 to-accent-400 rounded-2xl blur-xl opacity-20"></div>
<video
src="/videos/001.mp4"
class="relative rounded-2xl shadow-2xl w-full"
autoplay loop muted playsinline
></video>
<div class="absolute -bottom-6 -left-6 bg-white rounded-xl p-4 shadow-xl animate-float">
<div class="flex items-center space-x-3">
<div class="w-12 h-12 bg-accent-100 rounded-full flex items-center justify-center">
<svg class="w-6 h-6 text-accent-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div>
<p class="font-semibold text-gray-900">项目交付</p>
<p class="text-sm text-gray-500">100%准时交付</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="grid grid-cols-2 lg:grid-cols-4 gap-6 mt-20">
<div
v-for="(stat, index) in stats"
:key="index"
class="bg-white/10 backdrop-blur-sm rounded-xl p-6 text-center"
:style="{ animationDelay: `${index * 0.1}s` }"
class="scroll-animate shimmer-card-dark bg-white/10 backdrop-blur-sm rounded-xl p-6 text-center cursor-pointer"
:style="{ transitionDelay: `${index * 0.1}s` }"
v-ripple
v-neural-card
>
<p class="text-3xl lg:text-4xl font-bold text-white mb-2">{{ stat.value }}</p>
<p class="text-white/70">{{ stat.label }}</p>
@@ -178,7 +199,7 @@ const activeTestimonial = ref(0)
<section id="services" class="py-20 bg-white">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<div class="text-center mb-16 scroll-animate">
<span class="inline-block px-4 py-2 bg-primary-100 text-primary-700 rounded-full text-sm font-medium mb-4">
核心服务
</span>
@@ -194,7 +215,10 @@ const activeTestimonial = ref(0)
<div
v-for="(service, index) in services"
:key="index"
class="card-hover bg-gray-50 rounded-xl p-6 text-center"
class="scroll-animate shimmer-card bg-gray-50 rounded-xl p-6 text-center cursor-pointer"
:style="{ transitionDelay: `${index * 0.1}s` }"
v-ripple
v-neural-card
>
<div :class="[service.color, 'w-16 h-16 rounded-xl flex items-center justify-center mx-auto mb-4']">
<svg v-if="service.icon === 'zap'" class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -219,7 +243,7 @@ const activeTestimonial = ref(0)
<section id="products" class="py-20 bg-gray-50">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<div class="text-center mb-16 scroll-animate">
<span class="inline-block px-4 py-2 bg-accent-100 text-accent-700 rounded-full text-sm font-medium mb-4">
产品中心
</span>
@@ -235,14 +259,15 @@ const activeTestimonial = ref(0)
<div
v-for="(product, index) in products"
:key="index"
class="card-hover bg-white rounded-2xl overflow-hidden shadow-lg"
class="scroll-animate shimmer-card bg-white rounded-2xl overflow-hidden shadow-lg"
:style="{ transitionDelay: `${index * 0.15}s` }"
>
<div class="aspect-video overflow-hidden">
<img :src="product.image" :alt="product.name" class="w-full h-full object-cover" />
<img :src="product.image" :alt="product.name" class="w-full h-full object-cover transition-transform duration-500 hover:scale-110" />
</div>
<div class="p-6">
<h3 class="text-xl font-semibold text-gray-900 mb-2">{{ product.name }}</h3>
<p class="text-gray-600 mb-4">{{ product.description }}</p>
<p class="text-gray-600 mb-4">{{ product.shortDescription }}</p>
<ul class="space-y-2 mb-6">
<li
v-for="(feature, fIndex) in product.features"
@@ -255,8 +280,17 @@ const activeTestimonial = ref(0)
{{ feature }}
</li>
</ul>
<button class="btn-secondary w-full" @click="router.push('/products')">
了解详情
<button
class="btn-secondary w-full flex items-center justify-center gap-2"
@click="openProductDetail(product)"
>
<span>了解详情</span>
<svg
class="w-4 h-4"
fill="none" stroke="currentColor" viewBox="0 0 24 24"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</button>
</div>
</div>
@@ -264,9 +298,17 @@ const activeTestimonial = ref(0)
</div>
</section>
<section id="testimonials" class="py-20 bg-gradient-to-br from-primary-900 to-accent-900">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<section id="testimonials" class="relative py-20 overflow-hidden">
<video
class="absolute inset-0 w-full h-full object-cover"
autoplay loop muted playsinline
>
<source src="/videos/xingkong.mp4" type="video/mp4" />
</video>
<div class="absolute inset-0 bg-black/30"></div>
<div class="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
<div class="text-center mb-16 scroll-animate">
<span class="inline-block px-4 py-2 bg-white/10 text-white/90 rounded-full text-sm font-medium mb-4">
客户评价
</span>
@@ -279,7 +321,7 @@ const activeTestimonial = ref(0)
</div>
<div class="max-w-4xl mx-auto">
<div class="bg-white/10 backdrop-blur-sm rounded-2xl p-8 lg:p-12">
<div class="scroll-animate-scale shimmer-card-dark bg-white/10 backdrop-blur-sm rounded-2xl p-8 lg:p-12 cursor-pointer" v-ripple>
<div class="text-center">
<div class="flex justify-center mb-6">
<div class="w-16 h-16 bg-white/20 rounded-full flex items-center justify-center">
@@ -315,7 +357,7 @@ const activeTestimonial = ref(0)
<section id="contact" class="py-20 bg-white">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid lg:grid-cols-2 gap-12 items-center">
<div>
<div class="scroll-animate-left">
<span class="inline-block px-4 py-2 bg-primary-100 text-primary-700 rounded-full text-sm font-medium mb-4">
联系我们
</span>
@@ -335,7 +377,7 @@ const activeTestimonial = ref(0)
</div>
<div>
<p class="font-semibold text-gray-900">公司地址</p>
<p class="text-gray-600">陕西省西安市高新区科技二路65号清华科技园E座</p>
<p class="text-gray-600">西安市未央区立讯未来中心</p>
</div>
</div>
<div class="flex items-start space-x-4">
@@ -352,7 +394,7 @@ const activeTestimonial = ref(0)
</div>
</div>
<div class="bg-gray-50 rounded-2xl p-8">
<div class="scroll-animate-right bg-gray-50 rounded-2xl p-8">
<h3 class="text-xl font-semibold text-gray-900 mb-6">获取免费咨询</h3>
<form class="space-y-4">
<div class="grid md:grid-cols-2 gap-4">
@@ -381,7 +423,7 @@ const activeTestimonial = ref(0)
placeholder="请简要描述您的需求..."
></textarea>
</div>
<button type="submit" class="btn-primary w-full">
<button type="submit" class="btn-primary w-full cursor-pointer">
提交咨询
</button>
</form>
@@ -389,5 +431,85 @@ const activeTestimonial = ref(0)
</div>
</div>
</section>
<!-- 产品详情模态框 -->
<Transition name="modal">
<div
v-if="showProductModal"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
@click.self="closeProductDetail"
>
<!-- 背景遮罩 -->
<div class="absolute inset-0 bg-black/60 backdrop-blur-sm"></div>
<!-- 模态框内容 -->
<div class="relative bg-white rounded-2xl shadow-2xl max-w-2xl w-full max-h-[80vh] overflow-hidden">
<!-- 头部 -->
<div class="bg-gradient-to-r from-primary-600 to-accent-500 p-6 text-white">
<div class="flex items-center justify-between">
<h3 class="text-2xl font-bold">{{ selectedProduct?.name }}</h3>
<button
@click="closeProductDetail"
class="w-10 h-10 rounded-full bg-white/20 hover:bg-white/30 transition-colors flex items-center justify-center"
>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<p class="text-white/80 mt-2">{{ selectedProduct?.shortDescription }}</p>
</div>
<!-- 内容区域 -->
<div class="p-6 overflow-y-auto max-h-[calc(80vh-140px)]">
<!-- 产品图片 -->
<div v-if="selectedProduct?.image" class="mb-6 rounded-xl overflow-hidden">
<img :src="selectedProduct.image" :alt="selectedProduct?.name" class="w-full h-48 object-cover" />
</div>
<!-- 核心功能 -->
<div class="mb-6">
<h4 class="text-lg font-semibold text-gray-900 mb-3">核心功能</h4>
<div class="grid grid-cols-3 gap-3">
<div
v-for="(feature, index) in selectedProduct?.features"
:key="index"
class="bg-gradient-to-br from-primary-50 to-accent-50 rounded-lg p-3 text-center"
>
<svg class="w-5 h-5 text-primary-600 mx-auto mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<span class="text-sm text-gray-700">{{ feature }}</span>
</div>
</div>
</div>
<!-- 详细介绍 -->
<div>
<h4 class="text-lg font-semibold text-gray-900 mb-3">详细介绍</h4>
<p class="text-gray-600 leading-relaxed whitespace-pre-line">{{ selectedProduct?.description }}</p>
</div>
</div>
<!-- 底部按钮 -->
<div class="border-t border-gray-200 p-4 bg-gray-50">
<div class="flex gap-3">
<button
@click="closeProductDetail"
class="flex-1 px-6 py-3 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-100 transition-colors"
>
关闭
</button>
<button
@click="router.push('/contact')"
class="flex-1 btn-primary"
>
获取方案
</button>
</div>
</div>
</div>
</div>
</Transition>
</div>
</template>

653
src/views/LandingPage.vue Normal file
View File

@@ -0,0 +1,653 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
interface Particle {
id: number
x: number
y: number
size: number
opacity: number
speedX: number
speedY: number
depth: number
}
interface FloatRing {
id: number
radius: number
speed: number
opacity: number
rotation: number
}
const isLoaded = ref(false)
const isEntering = ref(false)
const particles = ref<Particle[]>([])
const floatRings = ref<FloatRing[]>([])
const mouseX = ref(0)
const mouseY = ref(0)
const rotationX = ref(0)
const rotationY = ref(0)
let animationFrameId: number | null = null
let particleId = 0
const createParticles = () => {
for (let i = 0; i < 80; i++) {
particles.value.push({
id: particleId++,
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
size: Math.random() * 3 + 1,
opacity: Math.random() * 0.6 + 0.1,
speedX: (Math.random() - 0.5) * 0.3,
speedY: (Math.random() - 0.5) * 0.3,
depth: Math.random() * 2 + 1
})
}
for (let i = 0; i < 5; i++) {
floatRings.value.push({
id: i,
radius: 120 + i * 40,
speed: 0.5 + i * 0.2,
opacity: 0.1 + i * 0.05,
rotation: Math.random() * 360
})
}
}
const animate = () => {
particles.value = particles.value.map(p => ({
...p,
x: (p.x + p.speedX) % window.innerWidth,
y: (p.y + p.speedY) % window.innerHeight,
opacity: p.opacity + (Math.random() - 0.5) * 0.02,
size: p.size + (Math.random() - 0.5) * 0.1
}))
floatRings.value = floatRings.value.map(r => ({
...r,
rotation: (r.rotation + r.speed * 0.1) % 360
}))
rotationY.value += 0.05
rotationX.value = Math.sin(Date.now() / 2000) * 5
animationFrameId = requestAnimationFrame(animate)
}
const handleMouseMove = (e: MouseEvent) => {
mouseX.value = (e.clientX - window.innerWidth / 2) / window.innerWidth
mouseY.value = (e.clientY - window.innerHeight / 2) / window.innerHeight
}
const enterWebsite = () => {
isEntering.value = true
setTimeout(() => {
router.push('/')
}, 1500)
}
onMounted(() => {
createParticles()
animate()
document.addEventListener('mousemove', handleMouseMove)
setTimeout(() => {
isLoaded.value = true
}, 300)
})
onUnmounted(() => {
document.removeEventListener('mousemove', handleMouseMove)
if (animationFrameId) {
cancelAnimationFrame(animationFrameId)
}
})
</script>
<template>
<div
class="landing-page"
:class="{ entering: isEntering }"
>
<div class="gradient-bg"></div>
<div class="particles-container">
<div
v-for="particle in particles"
:key="particle.id"
class="particle"
:style="{
left: `${particle.x}px`,
top: `${particle.y}px`,
width: `${particle.size}px`,
height: `${particle.size}px`,
opacity: Math.max(0.1, Math.min(0.8, particle.opacity)),
transform: `translate(-50%, -50%) translate(${mouseX * particle.depth * 20}px, ${mouseY * particle.depth * 20}px)`
}"
></div>
</div>
<div
class="center-content"
:style="{
transform: `translate(${mouseX * 30}px, ${mouseY * 30}px)`
}"
>
<div
class="tech-structure"
:style="{
transform: `rotateX(${rotationX + mouseY * 10}deg) rotateY(${rotationY + mouseX * 10}deg)`
}"
>
<div class="core-sphere">
<div class="inner-core"></div>
<div class="energy-ring ring-1"></div>
<div class="energy-ring ring-2"></div>
<div class="energy-ring ring-3"></div>
<svg class="neural-network" viewBox="0 0 300 300">
<defs>
<linearGradient id="lineGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="rgba(147, 197, 253, 0)" />
<stop offset="50%" stop-color="rgba(147, 197, 253, 0.6)" />
<stop offset="100%" stop-color="rgba(147, 197, 253, 0)" />
</linearGradient>
<filter id="neuralGlow">
<feGaussianBlur stdDeviation="2" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<circle cx="150" cy="150" r="4" fill="rgba(147, 197, 253, 1)" filter="url(#neuralGlow)" />
<circle cx="150" cy="80" r="3" fill="rgba(139, 92, 246, 0.8)" filter="url(#neuralGlow)" />
<circle cx="220" cy="110" r="3" fill="rgba(139, 92, 246, 0.8)" filter="url(#neuralGlow)" />
<circle cx="220" cy="190" r="3" fill="rgba(139, 92, 246, 0.8)" filter="url(#neuralGlow)" />
<circle cx="150" cy="220" r="3" fill="rgba(139, 92, 246, 0.8)" filter="url(#neuralGlow)" />
<circle cx="80" cy="190" r="3" fill="rgba(139, 92, 246, 0.8)" filter="url(#neuralGlow)" />
<circle cx="80" cy="110" r="3" fill="rgba(139, 92, 246, 0.8)" filter="url(#neuralGlow)" />
<circle cx="150" cy="40" r="2" fill="rgba(0, 229, 255, 0.6)" filter="url(#neuralGlow)" />
<circle cx="250" cy="90" r="2" fill="rgba(0, 229, 255, 0.6)" filter="url(#neuralGlow)" />
<circle cx="250" cy="210" r="2" fill="rgba(0, 229, 255, 0.6)" filter="url(#neuralGlow)" />
<circle cx="150" cy="260" r="2" fill="rgba(0, 229, 255, 0.6)" filter="url(#neuralGlow)" />
<circle cx="50" cy="210" r="2" fill="rgba(0, 229, 255, 0.6)" filter="url(#neuralGlow)" />
<circle cx="50" cy="90" r="2" fill="rgba(0, 229, 255, 0.6)" filter="url(#neuralGlow)" />
<line x1="150" y1="150" x2="150" y2="80" stroke="url(#lineGrad)" stroke-width="1" stroke-opacity="0.5" />
<line x1="150" y1="150" x2="220" y2="110" stroke="url(#lineGrad)" stroke-width="1" stroke-opacity="0.5" />
<line x1="150" y1="150" x2="220" y2="190" stroke="url(#lineGrad)" stroke-width="1" stroke-opacity="0.5" />
<line x1="150" y1="150" x2="150" y2="220" stroke="url(#lineGrad)" stroke-width="1" stroke-opacity="0.5" />
<line x1="150" y1="150" x2="80" y2="190" stroke="url(#lineGrad)" stroke-width="1" stroke-opacity="0.5" />
<line x1="150" y1="150" x2="80" y2="110" stroke="url(#lineGrad)" stroke-width="1" stroke-opacity="0.5" />
<line x1="150" y1="80" x2="150" y2="40" stroke="url(#lineGrad)" stroke-width="0.5" stroke-opacity="0.3" />
<line x1="220" y1="110" x2="250" y2="90" stroke="url(#lineGrad)" stroke-width="0.5" stroke-opacity="0.3" />
<line x1="220" y1="190" x2="250" y2="210" stroke="url(#lineGrad)" stroke-width="0.5" stroke-opacity="0.3" />
<line x1="150" y1="220" x2="150" y2="260" stroke="url(#lineGrad)" stroke-width="0.5" stroke-opacity="0.3" />
<line x1="80" y1="190" x2="50" y2="210" stroke="url(#lineGrad)" stroke-width="0.5" stroke-opacity="0.3" />
<line x1="80" y1="110" x2="50" y2="90" stroke="url(#lineGrad)" stroke-width="0.5" stroke-opacity="0.3" />
</svg>
</div>
<div
v-for="ring in floatRings"
:key="ring.id"
class="float-ring"
:style="{
width: `${ring.radius * 2}px`,
height: `${ring.radius * 2}px`,
opacity: ring.opacity,
transform: `rotateX(${30 + ring.id * 10}deg) rotate(${ring.rotation}deg)`
}"
></div>
<div class="data-beams">
<div class="beam beam-1"></div>
<div class="beam beam-2"></div>
<div class="beam beam-3"></div>
<div class="beam beam-4"></div>
</div>
</div>
<div
class="brand-section"
:class="{ visible: isLoaded }"
>
<h1 class="brand-name">云阶智元</h1>
<p class="brand-english">AI Agent Intelligence Hub</p>
<p class="brand-slogan">让智能体成为企业增长的新引擎</p>
<p class="brand-tagline">AI Agent · 企业智能体中枢 · 数字化协同进化</p>
</div>
<button
class="enter-btn"
@click="enterWebsite"
>
<span class="btn-text">开启智能之门</span>
<span class="btn-glow"></span>
<span class="btn-pulse"></span>
</button>
</div>
<div class="transition-overlay" :class="{ active: isEntering }"></div>
</div>
</template>
<style scoped>
.landing-page {
position: fixed;
inset: 0;
overflow: hidden;
background: #05070D;
z-index: 99999;
}
.gradient-bg {
position: absolute;
inset: 0;
background:
radial-gradient(ellipse at 20% 20%, rgba(30, 107, 255, 0.15) 0%, transparent 50%),
radial-gradient(ellipse at 80% 80%, rgba(138, 63, 252, 0.15) 0%, transparent 50%),
radial-gradient(ellipse at 50% 50%, rgba(0, 229, 255, 0.05) 0%, transparent 60%),
linear-gradient(180deg, #05070D 0%, #0a0f1a 50%, #0d1225 100%);
}
.particles-container {
position: absolute;
inset: 0;
pointer-events: none;
}
.particle {
position: absolute;
border-radius: 50%;
background: radial-gradient(
circle,
rgba(147, 197, 253, 1) 0%,
rgba(59, 130, 246, 0.5) 50%,
transparent 100%
);
box-shadow: 0 0 6px rgba(147, 197, 253, 0.5);
transition: transform 0.3s ease-out;
}
.center-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 40px;
z-index: 10;
}
.tech-structure {
position: relative;
width: 300px;
height: 300px;
perspective: 800px;
transform-style: preserve-3d;
}
.core-sphere {
position: absolute;
top: 50%;
left: 50%;
width: 150px;
height: 150px;
transform: translate(-50%, -50%);
}
.inner-core {
position: absolute;
top: 50%;
left: 50%;
width: 60px;
height: 60px;
transform: translate(-50%, -50%);
border-radius: 50%;
background: radial-gradient(
circle,
rgba(255, 255, 255, 0.9) 0%,
rgba(147, 197, 253, 0.7) 30%,
rgba(59, 130, 246, 0.4) 60%,
transparent 100%
);
box-shadow:
0 0 30px rgba(147, 197, 253, 0.8),
0 0 60px rgba(59, 130, 246, 0.5),
0 0 90px rgba(139, 92, 246, 0.3);
animation: core-pulse 3s ease-in-out infinite;
}
@keyframes core-pulse {
0%, 100% {
transform: translate(-50%, -50%) scale(1);
opacity: 0.8;
}
50% {
transform: translate(-50%, -50%) scale(1.1);
opacity: 1;
}
}
.energy-ring {
position: absolute;
top: 50%;
left: 50%;
border-radius: 50%;
border: 1px solid;
transform-style: preserve-3d;
}
.ring-1 {
width: 100px;
height: 100px;
transform: translate(-50%, -50%) rotateX(70deg);
border-color: rgba(147, 197, 253, 0.5);
animation: ring-rotate 10s linear infinite;
}
.ring-2 {
width: 120px;
height: 120px;
transform: translate(-50%, -50%) rotateX(50deg);
border-color: rgba(139, 92, 246, 0.4);
animation: ring-rotate 12s linear infinite reverse;
}
.ring-3 {
width: 140px;
height: 140px;
transform: translate(-50%, -50%) rotateX(30deg);
border-color: rgba(0, 229, 255, 0.3);
animation: ring-rotate 8s linear infinite;
}
@keyframes ring-rotate {
from { transform: translate(-50%, -50%) rotateX(var(--rx, 70deg)) rotate(0deg); }
to { transform: translate(-50%, -50%) rotateX(var(--rx, 70deg)) rotate(360deg); }
}
.ring-1 { --rx: 70deg; }
.ring-2 { --rx: 50deg; }
.ring-3 { --rx: 30deg; }
.neural-network {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
transform: translate(-50%, -50%);
}
.float-ring {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
border: 1px solid rgba(147, 197, 253, 0.3);
transform-style: preserve-3d;
}
.data-beams {
position: absolute;
top: 50%;
left: 50%;
width: 200px;
height: 200px;
transform: translate(-50%, -50%);
}
.beam {
position: absolute;
top: 50%;
left: 50%;
width: 2px;
height: 80px;
background: linear-gradient(
to top,
rgba(147, 197, 253, 0) 0%,
rgba(147, 197, 253, 0.8) 50%,
rgba(147, 197, 253, 0) 100%
);
transform-origin: bottom center;
animation: beam-pulse 2s ease-in-out infinite;
}
.beam-1 { transform: translate(-50%, -50%) rotate(0deg); animation-delay: 0s; }
.beam-2 { transform: translate(-50%, -50%) rotate(90deg); animation-delay: 0.5s; }
.beam-3 { transform: translate(-50%, -50%) rotate(180deg); animation-delay: 1s; }
.beam-4 { transform: translate(-50%, -50%) rotate(270deg); animation-delay: 1.5s; }
@keyframes beam-pulse {
0%, 100% { opacity: 0.3; height: 60px; }
50% { opacity: 0.8; height: 100px; }
}
.brand-section {
text-align: center;
opacity: 0;
transform: translateY(30px);
transition: all 1s ease-out;
}
.brand-section.visible {
opacity: 1;
transform: translateY(0);
}
.brand-name {
font-size: 4rem;
font-weight: 700;
background: linear-gradient(
135deg,
rgba(255, 255, 255, 1) 0%,
rgba(147, 197, 253, 1) 30%,
rgba(0, 229, 255, 1) 50%,
rgba(139, 92, 246, 1) 70%,
rgba(147, 197, 253, 1) 100%
);
background-size: 200% 200%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-shadow:
0 0 30px rgba(147, 197, 253, 0.5),
0 0 60px rgba(59, 130, 246, 0.3);
animation: gradient-shift 4s ease-in-out infinite;
margin-bottom: 12px;
}
@keyframes gradient-shift {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
.brand-english {
font-size: 1rem;
color: rgba(147, 197, 253, 0.6);
letter-spacing: 0.3em;
margin-bottom: 16px;
}
.brand-slogan {
font-size: 1.25rem;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 8px;
}
.brand-tagline {
font-size: 0.9rem;
color: rgba(147, 197, 253, 0.5);
letter-spacing: 0.1em;
}
.enter-btn {
position: relative;
padding: 16px 48px;
font-size: 1.1rem;
font-weight: 600;
color: white;
background: linear-gradient(135deg, rgba(30, 107, 255, 0.2), rgba(138, 63, 252, 0.2));
border: 1px solid rgba(147, 197, 253, 0.4);
border-radius: 50px;
cursor: pointer;
overflow: hidden;
transition: all 0.3s ease;
}
.enter-btn:hover {
background: linear-gradient(135deg, rgba(30, 107, 255, 0.3), rgba(138, 63, 252, 0.3));
border-color: rgba(147, 197, 253, 0.8);
transform: translateY(-2px);
}
.btn-text {
position: relative;
z-index: 2;
}
.btn-glow {
position: absolute;
inset: 0;
background: radial-gradient(
circle at center,
rgba(147, 197, 253, 0.3) 0%,
transparent 70%
);
opacity: 0;
transition: opacity 0.3s ease;
}
.enter-btn:hover .btn-glow {
opacity: 1;
}
.btn-pulse {
position: absolute;
inset: -2px;
border-radius: 50px;
border: 2px solid transparent;
background: linear-gradient(#05070D, #05070D) padding-box,
linear-gradient(135deg, rgba(147, 197, 255, 0), rgba(138, 63, 252, 0)) border-box;
opacity: 0;
transition: all 0.3s ease;
}
.enter-btn:hover .btn-pulse {
opacity: 1;
background: linear-gradient(#05070D, #05070D) padding-box,
linear-gradient(135deg, rgba(147, 197, 255, 0.8), rgba(138, 63, 252, 0.8)) border-box;
}
.transition-overlay {
position: absolute;
inset: 0;
background: radial-gradient(
circle at center,
rgba(147, 197, 253, 0) 0%,
rgba(59, 130, 246, 0) 30%,
#05070D 100%
);
opacity: 0;
pointer-events: none;
transition: opacity 1.5s ease;
}
.transition-overlay.active {
opacity: 1;
}
.landing-page.entering {
animation: page-transition 1.5s ease forwards;
}
@keyframes page-transition {
0% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.8;
transform: scale(1.05);
}
100% {
opacity: 0;
transform: scale(0.95);
pointer-events: none;
}
}
@media (max-width: 768px) {
.tech-structure {
width: 220px;
height: 220px;
}
.core-sphere {
width: 110px;
height: 110px;
}
.inner-core {
width: 45px;
height: 45px;
}
.brand-name {
font-size: 2.5rem;
}
.brand-slogan {
font-size: 1rem;
}
.brand-tagline {
font-size: 0.75rem;
}
.enter-btn {
padding: 14px 36px;
font-size: 1rem;
}
}
@media (max-width: 480px) {
.tech-structure {
width: 180px;
height: 180px;
}
.brand-name {
font-size: 2rem;
}
.brand-slogan {
font-size: 0.9rem;
}
.brand-tagline {
font-size: 0.65rem;
}
.enter-btn {
padding: 12px 28px;
font-size: 0.9rem;
}
}
</style>

View File

@@ -1,7 +1,10 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { images, videos } from '@/assets/images'
const router = useRouter()
const activeTab = ref('enterprise')
const selectedProduct = ref<{ name: string; details: string; video: string } | null>(null)
const isSpeaking = ref(false)
@@ -225,27 +228,26 @@ const products = {
const features = [
{ icon: 'shield', title: '安全可靠', desc: '企业级安全防护' },
{ icon: 'globe', title: '全部署', desc: '多地域节点支持' },
{ icon: 'globe', title: '全部署', desc: '多地域节点支持' },
{ icon: 'database', title: '数据安全', desc: '加密存储保障' },
{ icon: 'layers', title: '灵活扩展', desc: '弹性架构设计' }
]
</script>
<template>
<div class="min-h-screen bg-white">
<section class="relative py-20 overflow-hidden">
<video
src="/videos/tech3.mp4"
class="absolute inset-0 w-full h-full object-cover"
autoplay loop muted playsinline
></video>
<div class="absolute inset-0 bg-gradient-to-br from-primary-900/90 via-primary-800/80 to-accent-900/90"></div>
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="min-h-screen relative">
<video
class="fixed inset-0 w-full h-full object-cover z-0"
autoplay loop muted playsinline
>
<source src="/videos/xingkong.mp4" type="video/mp4" />
</video>
<div class="fixed inset-0 bg-black/30 z-0"></div>
<section class="relative min-h-screen flex items-center overflow-hidden z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 pt-20">
<div class="text-center">
<span class="inline-block px-4 py-2 bg-white/10 text-white/90 rounded-full text-sm font-medium mb-4">
产品中心
</span>
<h1 class="text-4xl sm:text-5xl font-bold text-white mb-4">
<h1 class="text-5xl sm:text-6xl font-bold bg-gradient-to-r from-green-400 via-cyan-400 to-blue-500 bg-clip-text text-transparent mb-4">
智能产品矩阵
</h1>
<p class="text-lg text-white/80 max-w-2xl mx-auto">
@@ -255,45 +257,47 @@ const features = [
</div>
</section>
<section class="py-16 bg-gray-50">
<section class="py-16 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-2 md:grid-cols-4 gap-6">
<div
v-for="(feature, index) in features"
:key="index"
class="bg-white rounded-xl p-6 text-center"
class="bg-white/10 backdrop-blur-sm border border-white/20 rounded-xl p-6 text-center cursor-pointer hover:bg-white/15 transition-all duration-300"
v-ripple
v-neural-card
>
<div class="w-12 h-12 bg-primary-100 rounded-xl flex items-center justify-center mx-auto mb-4">
<svg v-if="feature.icon === 'shield'" class="w-6 h-6 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="w-12 h-12 bg-gradient-to-br from-primary-500/30 to-accent-500/30 rounded-xl flex items-center justify-center mx-auto mb-4">
<svg v-if="feature.icon === 'shield'" class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
</svg>
<svg v-else-if="feature.icon === 'globe'" class="w-6 h-6 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="feature.icon === 'globe'" class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<svg v-else-if="feature.icon === 'database'" class="w-6 h-6 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="feature.icon === 'database'" class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"/>
</svg>
<svg v-else-if="feature.icon === 'layers'" class="w-6 h-6 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="feature.icon === 'layers'" class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"/>
</svg>
</div>
<h3 class="font-semibold text-gray-900 mb-1">{{ feature.title }}</h3>
<p class="text-sm text-gray-600">{{ feature.desc }}</p>
<h3 class="font-semibold text-white mb-1">{{ feature.title }}</h3>
<p class="text-sm text-white/60">{{ feature.desc }}</p>
</div>
</div>
</div>
</section>
<section class="py-20">
<section class="py-20 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex flex-wrap justify-center gap-4 mb-12">
<button
v-for="tab in tabs"
:key="tab.id"
class="flex items-center space-x-2 px-6 py-3 rounded-xl font-medium transition-all duration-300"
class="btn-glow flex items-center space-x-2 px-6 py-3 rounded-xl font-medium transition-all duration-300"
:class="activeTab === tab.id
? 'bg-primary-600 text-white shadow-lg'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'"
? 'bg-gradient-to-r from-primary-600 to-accent-500 text-white shadow-lg shadow-primary-500/30'
: 'bg-white/10 text-white/80 hover:bg-white/20 border border-white/10'"
@click="activeTab = tab.id"
>
<svg v-if="tab.icon === 'layers'" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -320,22 +324,22 @@ const features = [
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
<div
v-for="(product, index) in products[activeTab as keyof typeof products]"
:key="index"
class="card-hover bg-gray-50 rounded-2xl overflow-hidden"
>
<div class="aspect-video overflow-hidden">
<img :src="product.image" :alt="product.name" class="w-full h-full object-cover" />
</div>
<div class="p-6">
<h3 class="text-xl font-semibold text-gray-900 mb-2">{{ product.name }}</h3>
<p class="text-gray-600 mb-4">{{ product.description }}</p>
<ul class="space-y-2 mb-6">
<li
v-for="(feature, fIndex) in product.features"
:key="fIndex"
class="flex items-center text-sm text-gray-700"
>
v-for="(product, index) in products[activeTab as keyof typeof products]"
:key="index"
class="card-hover bg-white/10 backdrop-blur-sm border border-white/20 rounded-2xl overflow-hidden hover:border-white/30 flex flex-col h-full"
>
<div class="aspect-video overflow-hidden flex-shrink-0">
<img :src="product.image" :alt="product.name" class="w-full h-full object-cover" />
</div>
<div class="p-6 flex flex-col flex-1">
<h3 class="text-xl font-semibold text-white mb-2">{{ product.name }}</h3>
<p class="text-white/70 mb-4 flex-1">{{ product.description }}</p>
<ul class="space-y-2 mb-6">
<li
v-for="(feature, fIndex) in product.features"
:key="fIndex"
class="flex items-center text-sm text-white/80"
>
<svg class="w-4 h-4 text-accent-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
@@ -343,7 +347,7 @@ const features = [
</li>
</ul>
<button
class="btn-secondary w-full flex items-center justify-center"
class="btn-glow w-full flex items-center justify-center px-6 py-3 border-2 border-white/30 text-white font-medium rounded-lg hover:bg-white/10 hover:border-white/50 transition-all duration-300 cursor-pointer mt-auto"
@click="openDetail(product)"
>
了解详情
@@ -357,42 +361,42 @@ const features = [
</div>
</section>
<section class="bg-gradient-to-br from-primary-900 to-accent-900 py-20">
<section class="bg-white/5 backdrop-blur-sm border-t border-white/10 py-20 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-4">
找不到合适的产品
</h2>
<p class="text-white/80 mb-8 max-w-2xl mx-auto">
<p class="text-white/70 mb-8 max-w-2xl mx-auto">
我们提供定制化开发服务根据您的具体需求为您量身打造专属解决方案
</p>
<button class="btn-primary">
<button
class="btn-glow px-8 py-4 bg-gradient-to-r from-primary-600 to-accent-500 text-white font-medium rounded-xl hover:from-primary-500 hover:to-accent-400 transition-all duration-300 shadow-lg shadow-primary-500/30"
@click="router.push('/contact')"
>
预约定制咨询
<svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/>
</svg>
</button>
</div>
</section>
<div
v-if="selectedProduct"
class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4"
class="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center z-50 p-4"
@click.self="closeDetail"
>
<div class="bg-white rounded-2xl max-w-2xl w-full max-h-[80vh] overflow-y-auto shadow-2xl">
<div class="sticky top-0 bg-white border-b border-gray-100 px-6 py-4 flex items-center justify-between">
<h3 class="text-xl font-semibold text-gray-900">{{ selectedProduct.name }}</h3>
<div class="bg-gray-900/95 backdrop-blur-xl border border-white/20 rounded-2xl max-w-2xl w-full max-h-[80vh] overflow-y-auto shadow-2xl">
<div class="sticky top-0 bg-gray-900/95 border-b border-white/10 px-6 py-4 flex items-center justify-between">
<h3 class="text-xl font-semibold text-white">{{ selectedProduct.name }}</h3>
<button
class="w-8 h-8 rounded-full hover:bg-gray-100 flex items-center justify-center transition-colors"
class="btn-glow w-8 h-8 rounded-full hover:bg-white/10 flex items-center justify-center transition-colors"
@click="closeDetail"
>
<svg class="w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-5 h-5 text-white/70" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<div class="p-6">
<div class="aspect-video rounded-xl overflow-hidden mb-6 bg-gray-900">
<div class="aspect-video rounded-xl overflow-hidden mb-6 bg-black">
<video
:src="selectedProduct.video"
controls
@@ -405,10 +409,10 @@ const features = [
</div>
<div class="flex items-center justify-between mb-4">
<h4 class="text-lg font-semibold text-gray-900">产品介绍</h4>
<h4 class="text-lg font-semibold text-white">产品介绍</h4>
<button
class="flex items-center space-x-2 px-4 py-2 rounded-lg transition-colors"
:class="isSpeaking ? 'bg-red-100 text-red-600 hover:bg-red-200' : 'bg-primary-100 text-primary-600 hover:bg-primary-200'"
class="btn-glow flex items-center space-x-2 px-4 py-2 rounded-lg transition-colors"
:class="isSpeaking ? 'bg-red-500/20 text-red-400 hover:bg-red-500/30' : 'bg-primary-500/20 text-primary-400 hover:bg-primary-500/30'"
@click="toggleSpeaking"
>
<svg v-if="!isSpeaking" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -422,13 +426,13 @@ const features = [
</button>
</div>
<p class="text-gray-700 leading-relaxed text-lg">
<p class="text-white/80 leading-relaxed text-lg">
{{ selectedProduct.details }}
</p>
</div>
<div class="bg-gray-50 border-t border-gray-100 px-6 py-4">
<div class="bg-white/5 border-t border-white/10 px-6 py-4">
<button
class="btn-primary w-full"
class="w-full px-6 py-3 bg-gradient-to-r from-primary-600 to-accent-500 text-white font-medium rounded-lg hover:from-primary-500 hover:to-accent-400 transition-all duration-300"
@click="closeDetail"
>
关闭
@@ -437,4 +441,68 @@ const features = [
</div>
</div>
</div>
</template>
</template>
<style scoped>
@keyframes glow-pulse {
0% {
box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7), 0 0 0 0 rgba(139, 92, 246, 0.5);
}
50% {
box-shadow: 0 0 20px 10px rgba(59, 130, 246, 0.5), 0 0 40px 20px rgba(139, 92, 246, 0.3);
}
100% {
box-shadow: 0 0 0 0 rgba(59, 130, 246, 0), 0 0 0 0 rgba(139, 92, 246, 0);
}
}
@keyframes ripple {
0% {
transform: scale(0);
opacity: 1;
}
100% {
transform: scale(4);
opacity: 0;
}
}
.btn-glow {
position: relative;
overflow: visible;
transition: all 0.3s ease;
}
.btn-glow:active {
animation: glow-pulse 0.6s ease-out;
transform: scale(0.98);
}
.btn-glow::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
background: radial-gradient(circle, rgba(59, 130, 246, 0.6) 0%, rgba(139, 92, 246, 0.4) 40%, transparent 70%);
transform: translate(-50%, -50%) scale(0);
transition: transform 0.4s ease-out, opacity 0.4s ease-out;
opacity: 0;
pointer-events: none;
}
.btn-glow:active::after {
transform: translate(-50%, -50%) scale(2);
opacity: 1;
}
.card-hover {
transition: all 0.3s ease;
}
.card-hover:hover {
transform: translateY(-4px);
box-shadow: 0 20px 40px rgba(59, 130, 246, 0.2), 0 10px 20px rgba(139, 92, 246, 0.1);
}
</style>

View File

@@ -1,7 +1,9 @@
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { images } from '@/assets/images'
const router = useRouter()
const activeSolution = ref('manufacturing')
@@ -161,20 +163,19 @@ const closeCaseDetail = () => {
</script>
<template>
<div class="min-h-screen bg-white">
<section class="relative py-20 overflow-hidden">
<video
src="/videos/tech3.mp4"
class="absolute inset-0 w-full h-full object-cover"
autoplay loop muted playsinline
></video>
<div class="absolute inset-0 bg-gradient-to-br from-primary-900/90 via-primary-800/80 to-accent-900/90"></div>
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="min-h-screen relative">
<video
class="fixed inset-0 w-full h-full object-cover z-0"
autoplay loop muted playsinline
>
<source src="/videos/xingkong.mp4" type="video/mp4" />
</video>
<div class="fixed inset-0 bg-black/30 z-0"></div>
<section class="relative min-h-screen flex items-center overflow-hidden z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 pt-20">
<div class="text-center">
<span class="inline-block px-4 py-2 bg-white/10 text-white/90 rounded-full text-sm font-medium mb-4">
解决方案
</span>
<h1 class="text-4xl sm:text-5xl font-bold text-white mb-4">
<h1 class="text-5xl sm:text-6xl font-bold bg-gradient-to-r from-green-400 via-cyan-400 to-blue-500 bg-clip-text text-transparent mb-4">
行业解决方案
</h1>
<p class="text-lg text-white/80 max-w-2xl mx-auto">
@@ -184,20 +185,22 @@ const closeCaseDetail = () => {
</div>
</section>
<section class="py-16">
<section class="py-16 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4">
<button
v-for="solution in solutions"
:key="solution.id"
class="flex flex-col items-center p-6 rounded-xl transition-all duration-300"
class="flex flex-col items-center p-6 rounded-xl transition-all duration-300 border border-white/10 hover:border-white/30 group"
:class="activeSolution === solution.id
? 'bg-primary-100 ring-2 ring-primary-500'
: 'bg-gray-50 hover:bg-gray-100'"
? 'bg-white/20 shadow-lg shadow-primary-500/20 scale-105'
: 'bg-white/5 hover:bg-white/10'"
@click="setActiveSolution(solution)"
v-ripple
v-neural-card
>
<div
class="w-14 h-14 rounded-xl flex items-center justify-center mb-3"
class="w-14 h-14 rounded-xl flex items-center justify-center mb-3 transition-all duration-300 group-hover:scale-110"
:class="solution.color"
>
<svg v-if="solution.icon === 'factory'" class="w-7 h-7 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -219,7 +222,7 @@ const closeCaseDetail = () => {
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/>
</svg>
</div>
<span class="font-medium" :class="activeSolution === solution.id ? 'text-primary-700' : 'text-gray-700'">
<span class="font-medium" :class="activeSolution === solution.id ? 'text-white' : 'text-white/70'">
{{ solution.name }}
</span>
</button>
@@ -227,20 +230,20 @@ const closeCaseDetail = () => {
</div>
</section>
<section class="py-16 bg-gray-50">
<section class="py-16 bg-white/5 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid lg:grid-cols-2 gap-12 items-center">
<div>
<span
class="inline-block px-3 py-1 rounded-full text-sm font-medium mb-4"
:class="currentSolution.color.replace('500', '100') + ' ' + currentSolution.color.replace('bg-', 'text-')"
:class="currentSolution.color.replace('500', '200') + ' ' + currentSolution.color.replace('bg-', 'text-') + ' bg-opacity-20'"
>
{{ currentSolution.name }}
</span>
<h2 class="text-3xl font-bold text-gray-900 mb-4">
<h2 class="text-3xl font-bold text-white mb-4">
{{ currentSolution.name }}解决方案
</h2>
<p class="text-gray-600 mb-6">
<p class="text-white/70 mb-6">
{{ currentSolution.description }}
</p>
<ul class="space-y-3 mb-8">
@@ -249,13 +252,13 @@ const closeCaseDetail = () => {
:key="index"
class="flex items-center"
>
<svg class="w-5 h-5 text-accent-500 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg class="w-5 h-5 text-accent-400 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<span class="text-gray-700">{{ feature }}</span>
<span class="text-white/80">{{ feature }}</span>
</li>
</ul>
<button class="btn-primary flex items-center">
<button class="px-8 py-4 bg-gradient-to-r from-primary-600 to-accent-500 text-white font-medium rounded-xl hover:from-primary-500 hover:to-accent-400 transition-all duration-300 shadow-lg shadow-primary-500/30 flex items-center">
获取方案详情
<svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/>
@@ -277,11 +280,11 @@ const closeCaseDetail = () => {
</div>
</section>
<section class="py-16">
<section class="py-16 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-gray-900 mb-4">成功案例</h2>
<p class="text-gray-600">我们在各行业的成功实践</p>
<h2 class="text-3xl font-bold text-white mb-4">成功案例</h2>
<p class="text-white/70">我们在各行业的成功实践</p>
</div>
<div class="relative h-32 overflow-hidden">
<div
@@ -294,18 +297,18 @@ const closeCaseDetail = () => {
class="flex-shrink-0 w-1/3 px-3"
>
<div
class="bg-gray-50 rounded-xl p-6 border border-gray-100 hover:border-primary-200 hover:shadow-lg transition-all duration-300 cursor-pointer h-full flex items-center justify-center"
class="bg-white/10 backdrop-blur-sm rounded-xl p-6 border border-white/10 hover:border-white/30 hover:shadow-lg hover:shadow-primary-500/20 transition-all duration-300 cursor-pointer h-full flex items-center justify-center group"
@click="openCaseDetail(caseItem)"
>
<div class="flex items-center space-x-4">
<div class="w-10 h-10 bg-accent-100 rounded-lg flex items-center justify-center flex-shrink-0">
<svg class="w-5 h-5 text-accent-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="w-10 h-10 bg-gradient-to-br from-accent-500/30 to-primary-500/30 rounded-lg flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform">
<svg class="w-5 h-5 text-accent-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div class="text-center">
<h4 class="font-semibold text-gray-900 mb-1">{{ caseItem.name }}</h4>
<p class="text-sm text-gray-600">基于Agent技术的智能解决方案</p>
<h4 class="font-semibold text-white mb-1">{{ caseItem.name }}</h4>
<p class="text-sm text-white/60">基于Agent技术的智能解决方案</p>
</div>
</div>
</div>
@@ -315,46 +318,46 @@ const closeCaseDetail = () => {
</div>
</section>
<section class="py-16 bg-gray-50">
<section class="py-16 bg-white/5 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-gray-900 mb-4">服务流程</h2>
<p class="text-gray-600">标准化的服务流程确保项目高质量交付</p>
<h2 class="text-3xl font-bold text-white mb-4">服务流程</h2>
<p class="text-white/70">标准化的服务流程确保项目高质量交付</p>
</div>
<div class="grid md:grid-cols-4 gap-6">
<div
v-for="(step, index) in steps"
:key="index"
class="text-center"
class="text-center group"
>
<div class="relative">
<div class="w-16 h-16 bg-primary-100 rounded-xl flex items-center justify-center mx-auto mb-4">
<svg v-if="step.icon === 'users'" class="w-8 h-8 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="w-16 h-16 bg-gradient-to-br from-primary-500/30 to-accent-500/30 rounded-xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 group-hover:shadow-lg group-hover:shadow-primary-500/30 transition-all duration-300">
<svg v-if="step.icon === 'users'" class="w-8 h-8 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"/>
</svg>
<svg v-else-if="step.icon === 'settings'" class="w-8 h-8 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="step.icon === 'settings'" class="w-8 h-8 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<svg v-else-if="step.icon === 'factory'" class="w-8 h-8 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="step.icon === 'factory'" class="w-8 h-8 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"/>
</svg>
<svg v-else-if="step.icon === 'check'" class="w-8 h-8 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg v-else-if="step.icon === 'check'" class="w-8 h-8 text-accent-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
</div>
<div class="absolute -top-2 -right-2 w-6 h-6 bg-accent-500 rounded-full flex items-center justify-center text-white text-sm font-bold">
<div class="absolute -top-2 -right-2 w-6 h-6 bg-accent-500 rounded-full flex items-center justify-center text-white text-sm font-bold shadow-lg">
{{ index + 1 }}
</div>
</div>
<h3 class="font-semibold text-gray-900 mb-1">{{ step.title }}</h3>
<p class="text-sm text-gray-600">{{ step.desc }}</p>
<h3 class="font-semibold text-white mb-1">{{ step.title }}</h3>
<p class="text-sm text-white/60">{{ step.desc }}</p>
</div>
</div>
</div>
</section>
<section class="bg-gradient-to-br from-primary-900 to-accent-900 py-20">
<section class="bg-white/5 backdrop-blur-sm border-t border-white/10 py-20 relative z-10">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-4">
开启您的数字化转型之旅
@@ -362,11 +365,11 @@ const closeCaseDetail = () => {
<p class="text-white/80 mb-8 max-w-2xl mx-auto">
无论您处于数字化转型的哪个阶段我们都能为您提供专业的解决方案和技术支持
</p>
<button class="btn-primary">
<button
class="px-8 py-4 bg-gradient-to-r from-primary-600 to-accent-500 text-white font-medium rounded-xl hover:from-primary-500 hover:to-accent-400 transition-all duration-300 shadow-lg shadow-primary-500/30"
@click="router.push('/contact')"
>
预约方案咨询
<svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/>
</svg>
</button>
</div>
</section>