This commit is contained in:
张成
2025-08-25 17:55:01 +08:00
parent 3fa80ef071
commit 2d0a8a4647
20 changed files with 673 additions and 544 deletions

View File

@@ -1,11 +1,6 @@
// 动画效果库 - LESS版本
/* 动画效果库 - 为项目添加丰富的动画效果 */
@import './variables.less';
// ===== 动画变量 =====
@animation-duration: @animation-duration-base;
@animation-timing: @animation-timing-base;
@animation-fill-mode: both;
// ===== 基础动画关键帧 =====
@keyframes fadeIn {
from { opacity: 0; }
@@ -58,45 +53,37 @@
@keyframes slideInUp {
from {
transform: translateY(100px);
opacity: 0;
transform: translateY(100%);
}
to {
transform: translateY(0);
opacity: 1;
}
}
@keyframes slideInDown {
from {
transform: translateY(-100px);
opacity: 0;
transform: translateY(-100%);
}
to {
transform: translateY(0);
opacity: 1;
}
}
@keyframes slideInLeft {
from {
transform: translateX(-100px);
opacity: 0;
transform: translateX(-100%);
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideInRight {
from {
transform: translateX(100px);
opacity: 0;
transform: translateX(100%);
}
to {
transform: translateX(0);
opacity: 1;
}
}
@@ -105,6 +92,9 @@
opacity: 0;
transform: scale(0.3);
}
50% {
opacity: 1;
}
to {
opacity: 1;
transform: scale(1);
@@ -116,6 +106,9 @@
opacity: 1;
transform: scale(1);
}
50% {
opacity: 1;
}
to {
opacity: 0;
transform: scale(0.3);
@@ -138,44 +131,38 @@
}
@keyframes pulse {
from {
transform: scale3d(1, 1, 1);
0% {
transform: scale(1);
}
50% {
transform: scale3d(1.05, 1.05, 1.05);
}
to {
transform: scale3d(1, 1, 1);
}
}
@keyframes shake {
0%, 100% {
transform: translate3d(0, 0, 0);
}
10%, 30%, 50%, 70%, 90% {
transform: translate3d(-10px, 0, 0);
}
20%, 40%, 60%, 80% {
transform: translate3d(10px, 0, 0);
}
}
@keyframes swing {
20% {
transform: rotate(15deg);
}
40% {
transform: rotate(-10deg);
}
60% {
transform: rotate(5deg);
}
80% {
transform: rotate(-5deg);
transform: scale(1.05);
}
100% {
transform: rotate(0deg);
transform: scale(1);
}
}
@keyframes wobble {
0% {
transform: translateX(0%);
}
15% {
transform: translateX(-25%) rotate(-5deg);
}
30% {
transform: translateX(20%) rotate(3deg);
}
45% {
transform: translateX(-15%) rotate(-3deg);
}
60% {
transform: translateX(10%) rotate(2deg);
}
75% {
transform: translateX(-5%) rotate(-1deg);
}
100% {
transform: translateX(0%);
}
}
@@ -206,88 +193,51 @@
}
}
@keyframes lightSpeedIn {
from {
transform: translate3d(100%, 0, 0) skewX(-30deg);
opacity: 0;
@keyframes shake {
0%, 100% {
transform: translateX(0);
}
60% {
transform: skewX(20deg);
opacity: 1;
10%, 30%, 50%, 70%, 90% {
transform: translateX(-10px);
}
80% {
transform: skewX(-5deg);
opacity: 1;
}
to {
transform: translate3d(0, 0, 0);
opacity: 1;
20%, 40%, 60%, 80% {
transform: translateX(10px);
}
}
@keyframes rubberBand {
from {
transform: scale3d(1, 1, 1);
}
30% {
transform: scale3d(1.25, 0.75, 1);
@keyframes swing {
20% {
transform: rotate(15deg);
}
40% {
transform: scale3d(0.75, 1.25, 1);
}
50% {
transform: scale3d(1.15, 0.85, 1);
}
65% {
transform: scale3d(0.95, 1.05, 1);
}
75% {
transform: scale3d(1.05, 0.95, 1);
}
to {
transform: scale3d(1, 1, 1);
}
}
@keyframes wobble {
0% {
transform: translate3d(0, 0, 0);
}
15% {
transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
}
30% {
transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
}
45% {
transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
transform: rotate(-10deg);
}
60% {
transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
transform: rotate(5deg);
}
75% {
transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
80% {
transform: rotate(-5deg);
}
100% {
transform: translate3d(0, 0, 0);
transform: rotate(0deg);
}
}
@keyframes tada {
0% {
transform: scale3d(1, 1, 1);
transform: scale(1);
}
10%, 20% {
transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
transform: scale(0.9) rotate(-3deg);
}
30%, 50%, 70%, 90% {
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
transform: scale(1.1) rotate(3deg);
}
40%, 60%, 80% {
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
transform: scale(1.1) rotate(-3deg);
}
100% {
transform: scale3d(1, 1, 1);
transform: scale(1) rotate(0);
}
}
@@ -324,335 +274,272 @@
transform: rotate(60deg);
transform-origin: top left;
animation-timing-function: ease-in-out;
}
100% {
transform: translateY(700px) rotate(60deg);
}
}
@keyframes rollIn {
0% {
opacity: 0;
transform: translate3d(-100%, 0, 0) rotate(-120deg);
}
100% {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
@keyframes rollOut {
0% {
opacity: 1;
}
100% {
transform: translate3d(0, 700px, 0);
opacity: 0;
transform: translate3d(100%, 0, 0) rotate(120deg);
}
}
@keyframes lightSpeedIn {
0% {
transform: translate3d(100%, 0, 0) skewX(-30deg);
opacity: 0;
}
60% {
transform: skewX(20deg);
opacity: 1;
}
80% {
transform: skewX(-5deg);
}
100% {
transform: translate3d(0, 0, 0);
}
}
@keyframes lightSpeedOut {
0% {
opacity: 1;
}
100% {
transform: translate3d(100%, 0, 0) skewX(-30deg);
opacity: 0;
}
}
@keyframes roll {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
// ===== 基础动画类 =====
// ===== 动画工具类 =====
.animate {
animation-duration: @animation-duration;
animation-fill-mode: @animation-fill-mode;
animation-timing-function: @animation-timing;
animation-duration: @animation-duration-base;
animation-fill-mode: both;
animation-timing-function: @animation-timing-base;
}
// 淡入动画
.fade-in { animation-name: fadeIn; }
.fade-in-up { animation-name: fadeInUp; }
.fade-in-down { animation-name: fadeInDown; }
.fade-in-left { animation-name: fadeInLeft; }
.fade-in-right { animation-name: fadeInRight; }
// 滑入动画
.slide-in-up { animation-name: slideInUp; }
.slide-in-down { animation-name: slideInDown; }
.slide-in-left { animation-name: slideInLeft; }
.slide-in-right { animation-name: slideInRight; }
// 缩放动画
.zoom-in { animation-name: zoomIn; }
.zoom-out { animation-name: zoomOut; }
// 特殊动画
.bounce { animation-name: bounce; }
.pulse { animation-name: pulse; }
.shake { animation-name: shake; }
.swing { animation-name: swing; }
.rotate { animation-name: rotate; }
.flip { animation-name: flip; }
.light-speed-in { animation-name: lightSpeedIn; }
.rubber-band { animation-name: rubberBand; }
.wobble { animation-name: wobble; }
.tada { animation-name: tada; }
.heart-beat { animation-name: heartBeat; }
.hinge { animation-name: hinge; }
.roll { animation-name: roll; }
// ===== 动画时长 =====
.duration-0_5s { animation-duration: 0.5s; }
.duration-1s { animation-duration: 1s; }
.duration-1_5s { animation-duration: 1.5s; }
.duration-2s { animation-duration: 2s; }
.duration-3s { animation-duration: 3s; }
// ===== 动画延迟 =====
.delay-0_5s { animation-delay: 0.5s; }
.delay-1s { animation-delay: 1s; }
.delay-1_5s { animation-delay: 1.5s; }
.delay-2s { animation-delay: 2s; }
.delay-3s { animation-delay: 3s; }
// ===== 动画重复 =====
.infinite { animation-iteration-count: infinite; }
.repeat-2 { animation-iteration-count: 2; }
.repeat-3 { animation-iteration-count: 3; }
// ===== 悬停动画效果 =====
.hover-lift {
transition: transform 0.3s ease, box-shadow 0.3s ease;
&:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
.animate.infinite {
animation-iteration-count: infinite;
}
.hover-scale {
transition: transform 0.3s ease;
&:hover {
transform: scale(1.05);
}
.animate.delay-1s {
animation-delay: 1s;
}
.hover-glow {
transition: box-shadow 0.3s ease;
&:hover {
box-shadow: 0 0 20px rgba(0, 123, 255, 0.5);
}
.animate.delay-2s {
animation-delay: 2s;
}
.hover-rotate {
transition: transform 0.3s ease;
&:hover {
transform: rotate(5deg);
}
.animate.delay-3s {
animation-delay: 3s;
}
.hover-bounce {
transition: transform 0.3s ease;
&:hover {
animation: bounce 0.6s ease;
.animate.delay-4s {
animation-delay: 4s;
}
.animate.delay-5s {
animation-delay: 5s;
}
// ===== 具体动画类 =====
.fade-in {
animation-name: fadeIn;
}
.fade-in-up {
animation-name: fadeInUp;
}
.fade-in-down {
animation-name: fadeInDown;
}
.fade-in-left {
animation-name: fadeInLeft;
}
.fade-in-right {
animation-name: fadeInRight;
}
.slide-in-up {
animation-name: slideInUp;
}
.slide-in-down {
animation-name: slideInDown;
}
.slide-in-left {
animation-name: slideInLeft;
}
.slide-in-right {
animation-name: slideInRight;
}
.zoom-in {
animation-name: zoomIn;
}
.zoom-out {
animation-name: zoomOut;
}
.bounce {
animation-name: bounce;
}
.pulse {
animation-name: pulse;
}
.wobble {
animation-name: wobble;
}
.rotate {
animation-name: rotate;
}
.flip {
animation-name: flip;
}
.shake {
animation-name: shake;
}
.swing {
animation-name: swing;
}
.tada {
animation-name: tada;
}
.heart-beat {
animation-name: heartBeat;
}
.hinge {
animation-name: hinge;
}
.roll-in {
animation-name: rollIn;
}
.roll-out {
animation-name: rollOut;
}
.light-speed-in {
animation-name: lightSpeedIn;
}
.light-speed-out {
animation-name: lightSpeedOut;
}
// ===== 滚动触发动画 =====
.scroll-animate {
.animate-on-scroll {
opacity: 0;
transform: translateY(30px);
transition: all 0.8s ease;
transition: all 0.6s @animation-timing-ease-out;
}
&.animate-in {
.animate-on-scroll.visible {
opacity: 1;
transform: translateY(0);
}
}
// ===== 交错动画 =====
.animate-stagger {
> * {
opacity: 0;
transform: translateY(20px);
transition: all 0.6s ease;
opacity: 1;
}
&:nth-child(1) { transition-delay: 0.1s; }
&:nth-child(2) { transition-delay: 0.2s; }
&:nth-child(3) { transition-delay: 0.3s; }
&:nth-child(4) { transition-delay: 0.4s; }
&:nth-child(5) { transition-delay: 0.5s; }
&:nth-child(6) { transition-delay: 0.6s; }
&.animate-in {
.animate-stagger.visible .animate-stagger-item {
opacity: 1;
transform: translateY(0);
}
}
.animate-stagger-item {
opacity: 0;
transform: translateY(30px);
transition: all 0.5s @animation-timing-ease-out;
}
// ===== 加载指示器 =====
.loading-spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
// ===== 悬停动画 =====
.hover-scale {
transition: transform 0.3s @animation-timing-base;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
.hover-scale:hover {
transform: scale(1.05);
}
// ===== 打字机效果 =====
.typewriter {
overflow: hidden;
border-right: 2px solid #000;
white-space: nowrap;
animation: typing 3.5s steps(40, end), blink-caret 0.75s step-end infinite;
.hover-lift {
transition: all 0.3s @animation-timing-base;
}
@keyframes typing {
from { width: 0; }
to { width: 100%; }
.hover-lift:hover {
transform: translateY(-5px);
box-shadow: @box-shadow-lg;
}
@keyframes blink-caret {
from, to { border-color: transparent; }
50% { border-color: #000; }
.hover-rotate {
transition: transform 0.3s @animation-timing-base;
}
// ===== 波浪效果 =====
.wave {
position: relative;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(45deg, transparent 30%, rgba(255, 255, 255, 0.3) 50%, transparent 70%);
animation: wave 2s infinite;
}
.hover-rotate:hover {
transform: rotate(5deg);
}
@keyframes wave {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
.hover-glow {
transition: all 0.3s @animation-timing-base;
}
// ===== 粒子效果 =====
.particles {
position: relative;
overflow: hidden;
&::before,
&::after {
content: '';
position: absolute;
width: 4px;
height: 4px;
background: rgba(255, 255, 255, 0.8);
border-radius: 50%;
animation: float 6s infinite;
.hover-glow:hover {
box-shadow: 0 0 20px rgba(52, 152, 219, 0.5);
}
&::before {
left: 20%;
animation-delay: 0s;
.hover-bounce {
transition: transform 0.3s @animation-timing-base;
}
&::after {
right: 20%;
animation-delay: 3s;
}
.hover-bounce:hover {
animation: bounce 0.6s;
}
@keyframes float {
0%, 100% { transform: translateY(0px) rotate(0deg); opacity: 1; }
50% { transform: translateY(-20px) rotate(180deg); opacity: 0.5; }
// ===== 文本发光效果 =====
.text-glow {
text-shadow: 0 0 10px rgba(52, 152, 219, 0.8);
}
// ===== 3D翻转卡片 =====
.flip-card {
perspective: 1000px;
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.6s;
transform-style: preserve-3d;
&:hover {
transform: rotateY(180deg);
}
.text-glow:hover {
text-shadow: 0 0 20px rgba(52, 152, 219, 1);
}
.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.flip-card-back {
transform: rotateY(180deg);
}
}
// ===== 渐变背景动画 =====
.gradient-bg {
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
background-size: 400% 400%;
animation: gradient 15s ease infinite;
}
@keyframes gradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
// ===== 霓虹文字效果 =====
.neon-text {
color: #fff;
text-shadow:
0 0 5px #fff,
0 0 10px #fff,
0 0 15px #0073e6,
0 0 20px #0073e6,
0 0 25px #0073e6,
0 0 30px #0073e6,
0 0 35px #0073e6;
animation: neon-pulse 1.5s ease-in-out infinite alternate;
}
@keyframes neon-pulse {
from { text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #0073e6, 0 0 20px #0073e6, 0 0 25px #0073e6, 0 0 30px #0073e6, 0 0 35px #0073e6; }
to { text-shadow: 0 0 2px #fff, 0 0 4px #fff, 0 0 6px #0073e6, 0 0 8px #0073e6, 0 0 10px #0073e6, 0 0 12px #0073e6, 0 0 14px #0073e6; }
}
// ===== 滚动进度条 =====
.scroll-progress-bar {
position: fixed;
top: 0;
left: 0;
width: 0%;
height: 3px;
background: linear-gradient(90deg, #0073e6, #00d4ff);
z-index: 9999;
transition: width 0.1s ease;
}
// ===== 视差滚动元素 =====
.parallax {
position: relative;
overflow: hidden;
.parallax-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 120%;
background-size: cover;
background-position: center;
transform: translateZ(0);
will-change: transform;
}
}
// ===== 浮动粒子 =====
// ===== 浮动粒子动画 =====
.floating-particles {
position: absolute;
top: 0;
@@ -662,6 +549,7 @@
overflow: hidden;
pointer-events: none;
z-index: 1;
}
.floating-particle {
position: absolute;
@@ -669,24 +557,82 @@
height: 4px;
background: rgba(255, 255, 255, 0.6);
border-radius: 50%;
animation: float-particle 8s infinite linear;
&:nth-child(1) { left: 10%; animation-delay: 0s; animation-duration: 8s; }
&:nth-child(2) { left: 20%; animation-delay: 1s; animation-duration: 10s; }
&:nth-child(3) { left: 30%; animation-delay: 2s; animation-duration: 12s; }
&:nth-child(4) { left: 40%; animation-delay: 3s; animation-duration: 9s; }
&:nth-child(5) { left: 50%; animation-delay: 4s; animation-duration: 11s; }
&:nth-child(6) { left: 60%; animation-delay: 5s; animation-duration: 7s; }
&:nth-child(7) { left: 70%; animation-delay: 6s; animation-duration: 13s; }
&:nth-child(8) { left: 80%; animation-delay: 7s; animation-duration: 8s; }
&:nth-child(9) { left: 90%; animation-delay: 8s; animation-duration: 10s; }
&:nth-child(10) { left: 95%; animation-delay: 9s; animation-duration: 12s; }
}
animation: float 6s infinite linear;
}
@keyframes float-particle {
.floating-particle:nth-child(1) {
top: 10%;
left: 10%;
animation-delay: 0s;
animation-duration: 8s;
}
.floating-particle:nth-child(2) {
top: 20%;
left: 80%;
animation-delay: 1s;
animation-duration: 10s;
}
.floating-particle:nth-child(3) {
top: 60%;
left: 20%;
animation-delay: 2s;
animation-duration: 7s;
}
.floating-particle:nth-child(4) {
top: 80%;
left: 70%;
animation-delay: 3s;
animation-duration: 9s;
}
.floating-particle:nth-child(5) {
top: 30%;
left: 60%;
animation-delay: 4s;
animation-duration: 6s;
}
.floating-particle:nth-child(6) {
top: 70%;
left: 40%;
animation-delay: 5s;
animation-duration: 8s;
}
.floating-particle:nth-child(7) {
top: 40%;
left: 90%;
animation-delay: 6s;
animation-duration: 7s;
}
.floating-particle:nth-child(8) {
top: 90%;
left: 30%;
animation-delay: 7s;
animation-duration: 9s;
}
.floating-particle:nth-child(9) {
top: 50%;
left: 10%;
animation-delay: 8s;
animation-duration: 6s;
}
.floating-particle:nth-child(10) {
top: 15%;
left: 50%;
animation-delay: 9s;
animation-duration: 8s;
}
@keyframes float {
0% {
transform: translateY(100vh) scale(0);
transform: translateY(0) rotate(0deg);
opacity: 0;
}
10% {
@@ -696,66 +642,46 @@
opacity: 1;
}
100% {
transform: translateY(-100px) scale(1);
transform: translateY(-100vh) rotate(360deg);
opacity: 0;
}
}
// ===== 文字发光效果 =====
.text-glow {
text-shadow:
0 0 5px currentColor,
0 0 10px currentColor,
0 0 15px currentColor,
0 0 20px currentColor;
animation: text-glow-pulse 2s ease-in-out infinite alternate;
// ===== 滚动进度条 =====
.scroll-progress-bar {
position: fixed;
top: 0;
left: 0;
width: 0%;
height: 3px;
background: linear-gradient(90deg, @primary-color, @success-color);
z-index: @zindex-fixed;
transition: width 0.1s ease;
}
@keyframes text-glow-pulse {
from { text-shadow: 0 0 5px currentColor, 0 0 10px currentColor, 0 0 15px currentColor, 0 0 20px currentColor; }
to { text-shadow: 0 0 10px currentColor, 0 0 20px currentColor, 0 0 30px currentColor, 0 0 40px currentColor; }
// ===== 视差效果 =====
[data-parallax] {
transform: translateZ(0);
will-change: transform;
}
// ===== 响应式动画考虑 =====
// ===== 性能优化 =====
.animate,
.animate-on-scroll,
.animate-stagger-item {
will-change: transform, opacity;
backface-visibility: hidden;
transform: translate3d(0, 0, 0);
}
// ===== 减少动画偏好支持 =====
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
.animate,
.animate-on-scroll,
.animate-stagger-item,
.floating-particle {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
// ===== 移动端动画优化 =====
@media (max-width: 768px) {
.floating-particles {
display: none; // 移动端隐藏浮动粒子以提升性能
}
.animate {
animation-duration: 0.8s; // 移动端减少动画时长
}
.scroll-animate {
transform: translateY(20px); // 移动端减少移动距离
}
}
// ===== 性能优化 =====
.animate,
.hover-lift,
.hover-scale,
.hover-glow,
.hover-rotate,
.hover-bounce {
will-change: transform, opacity;
transform: translate3d(0, 0, 0); // 启用硬件加速
}
// ===== 动画工具类 =====
.animation-paused { animation-play-state: paused; }
.animation-running { animation-play-state: running; }
.animation-reverse { animation-direction: reverse; }
.animation-alternate { animation-direction: alternate; }
.animation-alternate-reverse { animation-direction: alternate-reverse; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 347 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 471 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

BIN
src/assets/img/ic_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
src/assets/img/ic_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
src/assets/img/ic_3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -15,19 +15,18 @@
<div class="footer-section">
<h4>关于我们</h4>
<ul class="footer-links">
<li><router-link to="/aboutUs/aboutUs">公司简介</router-link></li>
<li><router-link to="/aboutUs/propystTechnology">技术优势</router-link></li>
<li><router-link to="/aboutUs/cooperateWithUs">合作共赢</router-link></li>
<li v-for="item in aboutUsMenu" :key="item.name">
<router-link :to="item.url">{{ item.name }}</router-link>
</li>
</ul>
</div>
<div class="footer-section">
<h4>解决方案</h4>
<ul class="footer-links">
<li><router-link to="/ourPlan/iot">物联网</router-link></li>
<li><router-link to="/ourPlan/smartbuildings">智能建筑</router-link></li>
<li><router-link to="/ourPlan/facilityManagement">设施管理</router-link></li>
<li><router-link to="/ourPlan/reaEstate">房地产</router-link></li>
<li v-for="solution in solutionsMenu" :key="solution.name">
<router-link :to="solution.url">{{ solution.name }}</router-link>
</li>
</ul>
</div>
@@ -35,19 +34,19 @@
<h4>联系我们</h4>
<div class="contact-info">
<div class="contact-item">
<span class="contact-icon">📍</span>
<span class="contact-icon">🏢</span>
<span>上海市宝山区高逸路112-118号3幢6422室</span>
</div>
<div class="contact-item">
<span class="contact-icon">📞</span>
<span class="contact-icon">📱</span>
<span>13817819452</span>
</div>
<div class="contact-item">
<span class="contact-icon"></span>
<span class="contact-icon">📧</span>
<span>bimwe@bimwe.com</span>
</div>
<div class="contact-item">
<span class="contact-icon">🌐</span>
<span class="contact-icon">💻</span>
<span>www.bimwe.com</span>
</div>
</div>
@@ -58,12 +57,12 @@
<div class="footer-bottom">
<div class="footer-bottom-content">
<div class="copyright">
<p>&copy; 2024 上海丙维数字科技有限公司. 保留所有权利.</p>
<p>&copy; © 2025 上海丙维数字科技有限公司. 保留所有权利.</p>
</div>
<div class="footer-extra">
<div class="beian">
<img :src="require('@/assets/img/beian_icon.png')" alt="备案" class="beian-icon">
<span>沪ICP备XXXXXXXX号</span>
<span class="beian-icon">🔒</span>
<span>沪ICP备19005870号-1</span>
</div>
</div>
</div>
@@ -79,11 +78,15 @@
</template>
<script>
import { getFooterAboutUsMenu, getFooterSolutionsMenu } from '../config/menu'
export default {
name: 'ifooter',
data() {
return {
showBackToTop: false
showBackToTop: false,
aboutUsMenu: getFooterAboutUsMenu(),
solutionsMenu: getFooterSolutionsMenu()
}
},
mounted() {
@@ -264,9 +267,10 @@ export default {
}
.beian-icon {
width: 16px;
height: 16px;
filter: brightness(0) invert(0.6);
font-size: 1.2rem;
width: 20px;
text-align: center;
color: #95a5a6;
}
/* 返回顶部按钮 */

View File

@@ -70,36 +70,14 @@
<script>
import { common } from '../static/common'
import { getMainMenu } from '../config/menu'
export default {
name: 'ihead',
data() {
return {
isMiniHeader: false,
menus: [
{
name: '首页',
url: '/index',
child: []
},
{
name: '关于我们',
url: '/aboutUs',
child: []
},
{
name: '我们的方案',
url: '/ourPlan',
child: [
{ name: 'AI集成', url: '/ourPlan/aiSolutions' },
{ name: '智能建筑', url: '/ourPlan/estateManagement' },
{ name: '物联网', url: '/ourPlan/iot' },
{ name: '设施管理', url: '/ourPlan/facilityManagement' },
{ name: '系统集成', url: '/ourPlan/technologyIntegration' }
]
},
]
menus: getMainMenu()
}
},
computed: {

59
src/config/menu.js Normal file
View File

@@ -0,0 +1,59 @@
/**
* 菜单配置文件 - 统一管理头部和页脚菜单
*/
export const menuConfig = {
// 主导航菜单
mainMenu: [
{
name: '首页',
url: '/index',
child: []
},
{
name: '关于我们',
url: '/aboutUs',
child: []
},
{
name: '我们的方案',
url: '/ourPlan',
child: [
{ name: 'AI集成', url: '/ourPlan/aiSolutions' },
{ name: '智能建筑', url: '/ourPlan/estateManagement' },
{ name: '物联网', url: '/ourPlan/iot' },
{ name: '设施管理', url: '/ourPlan/facilityManagement' },
{ name: '系统集成', url: '/ourPlan/technologyIntegration' }
]
}
],
// 页脚菜单配置
footerMenu: {
aboutUs: [
{ name: '公司简介', url: '/aboutUs' }
],
solutions: [
{ name: 'AI集成', url: '/ourPlan/aiSolutions' },
{ name: '智能建筑', url: '/ourPlan/estateManagement' },
{ name: '物联网', url: '/ourPlan/iot' },
{ name: '设施管理', url: '/ourPlan/facilityManagement' },
{ name: '系统集成', url: '/ourPlan/technologyIntegration' }
]
}
}
// 获取主导航菜单
export const getMainMenu = () => menuConfig.mainMenu
// 获取页脚关于我们菜单
export const getFooterAboutUsMenu = () => menuConfig.footerMenu.aboutUs
// 获取页脚解决方案菜单
export const getFooterSolutionsMenu = () => menuConfig.footerMenu.solutions
// 获取所有解决方案
export const getAllSolutions = () => {
const solutionMenu = menuConfig.mainMenu.find(menu => menu.name === '我们的方案');
return solutionMenu && solutionMenu.child ? solutionMenu.child : [];
}

View File

@@ -71,4 +71,12 @@ router.beforeEach((to, from, next) => {
next();
});
// 全局后置钩子 - 路由切换完成后触发动画重置
router.afterEach((to, from) => {
// 触发自定义路由变化事件
window.dispatchEvent(new CustomEvent('routeChange', {
detail: { to, from }
}));
});
export default router

View File

@@ -22,6 +22,9 @@ class AnimationHelper {
// 添加滚动事件监听
this.addScrollListeners();
// 监听路由变化
this.setupRouteListener();
// 初始化页面加载动画
this.initPageLoadAnimations();
@@ -61,6 +64,20 @@ class AnimationHelper {
window.addEventListener('resize', this.handleResize.bind(this), { passive: true });
}
/**
* 设置路由监听
*/
setupRouteListener() {
// 监听 popstate 事件(浏览器前进后退)
window.addEventListener('popstate', this.handleRouteChange.bind(this));
// 监听自定义路由变化事件
window.addEventListener('routeChange', this.handleRouteChange.bind(this));
// 监听页面可见性变化
document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this));
}
/**
* 处理滚动事件
*/
@@ -77,6 +94,30 @@ class AnimationHelper {
this.recalculateAnimations();
}
/**
* 处理路由变化
*/
handleRouteChange() {
// 延迟重置动画确保DOM已更新
setTimeout(() => {
this.resetAnimations();
this.initPageLoadAnimations();
}, 100);
}
/**
* 处理页面可见性变化
*/
handleVisibilityChange() {
if (!document.hidden) {
// 页面重新可见时,重置动画状态
setTimeout(() => {
this.resetAnimations();
this.initPageLoadAnimations();
}, 100);
}
}
/**
* 初始化页面加载动画
*/
@@ -276,6 +317,41 @@ class AnimationHelper {
});
}
/**
* 重置所有动画状态
*/
resetAnimations() {
// 重置所有动画元素的类
this.animatedElements.forEach(element => {
if (element.classList.contains('scroll-animate')) {
element.classList.remove('animate-in');
} else if (element.classList.contains('animate-stagger')) {
element.classList.remove('visible');
// 重置子元素状态
const children = Array.from(element.children);
children.forEach((child, index) => {
child.style.opacity = '0';
child.style.transform = 'translateY(30px)';
});
}
});
// 重置所有带有动画类的元素
const allAnimatedElements = document.querySelectorAll('.animate-on-scroll, .animate-stagger, .scroll-animate');
allAnimatedElements.forEach(element => {
element.classList.remove('visible', 'animate-in');
// 重置 transform 和 opacity
if (element.classList.contains('animate-on-scroll')) {
element.style.opacity = '0';
element.style.transform = 'translateY(30px)';
}
});
// 重新观察所有元素
this.recalculateAnimations();
}
/**
* 显示所有元素(降级处理)
*/
@@ -334,6 +410,9 @@ class AnimationHelper {
window.removeEventListener('scroll', this.handleScroll);
window.removeEventListener('resize', this.handleResize);
window.removeEventListener('popstate', this.handleRouteChange);
window.removeEventListener('routeChange', this.handleRouteChange);
document.removeEventListener('visibilitychange', this.handleVisibilityChange);
this.animatedElements = [];
this.isInitialized = false;

View File

@@ -60,7 +60,10 @@
<div class="advantages-grid">
<div class="advantage-card" v-for="advantage in advantages" :key="advantage.title">
<div class="advantage-icon">{{advantage.icon}}</div>
<div class="advantage-icon">
<img v-if="typeof advantage.icon === 'string' && advantage.icon.includes('.png')" :src="advantage.icon" :alt="advantage.title" class="icon-image">
<span v-else>{{advantage.icon}}</span>
</div>
<h3>{{advantage.title}}</h3>
<p>{{advantage.description}}</p>
<ul class="advantage-features">
@@ -103,7 +106,10 @@
<div class="areas-grid">
<div class="area-card" v-for="area in businessAreas" :key="area.name">
<div class="area-header">
<div class="area-icon">{{area.icon}}</div>
<div class="area-icon">
<img v-if="typeof area.icon === 'string' && area.icon.includes('.png')" :src="area.icon" :alt="area.name" class="icon-image">
<span v-else>{{area.icon}}</span>
</div>
<h3>{{area.name}}</h3>
</div>
<p class="area-description">{{area.description}}</p>
@@ -232,7 +238,7 @@ export default {
],
businessAreas: [
{
icon: '💻',
icon: require('../../assets/img/ic_1.png'),
name: '技术开发与服务',
description: '从事计算机软硬件、网络科技、信息科技领域的技术开发、咨询、转让和服务,致力于推动行业技术进步。',
services: [
@@ -243,7 +249,7 @@ export default {
]
},
{
icon: '🧠',
icon: require('../../assets/img/ic_2.png'),
name: 'AI智能应用',
description: '专注于人工智能技术,为客户提供定制化的智能解决方案,涵盖数据分析、智能推荐、自动化流程等多个领域。',
services: [
@@ -254,7 +260,7 @@ export default {
]
},
{
icon: '🔧',
icon: require('../../assets/img/ic_3.png'),
name: '系统集成与软件开发',
description: '提供高效的计算机信息系统集成服务,以及创新的软件开发,助力企业数字化转型。',
services: [
@@ -436,6 +442,15 @@ export default {
font-size: 3rem;
margin-bottom: 20px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.advantage-icon .icon-image {
width: 60px;
height: 60px;
object-fit: contain;
}
.advantage-card h3 {
@@ -594,6 +609,15 @@ export default {
.area-icon {
font-size: 3rem;
margin-bottom: 15px;
display: flex;
align-items: center;
justify-content: center;
}
.area-icon .icon-image {
width: 60px;
height: 60px;
object-fit: contain;
}
.area-header h3 {

View File

@@ -76,7 +76,10 @@
<h2 class="section-title animate-on-scroll">核心优势</h2>
<div class="advantages-grid animate-stagger">
<div class="advantage-item hover-scale" v-for="advantage in advantages" :key="advantage.title">
<div class="advantage-icon animate bounce delay-1s">{{advantage.icon}}</div>
<div class="advantage-icon animate bounce delay-1s">
<img v-if="typeof advantage.icon === 'string' && advantage.icon.includes('.png')" :src="advantage.icon" :alt="advantage.title" class="icon-image">
<span v-else>{{advantage.icon}}</span>
</div>
<h3>{{advantage.title}}</h3>
<p>{{advantage.description}}</p>
</div>
@@ -90,7 +93,11 @@
<h2 class="section-title animate-on-scroll">业务领域</h2>
<div class="areas-grid animate-stagger">
<div class="area-item hover-glow" v-for="area in businessAreas" :key="area.name">
<div class="area-icon animate wobble delay-2s">{{area.icon}}</div>
<div class="area-icon animate wobble delay-2s">
<img v-if="typeof area.icon === 'string' && area.icon.startsWith('data:')" :src="area.icon" :alt="area.name">
<img v-else-if="typeof area.icon === 'string' && area.icon.includes('.png')" :src="area.icon" :alt="area.name">
<span v-else>{{area.icon}}</span>
</div>
<h3>{{area.name}}</h3>
<p>{{area.description}}</p>
<ul class="area-features">
@@ -256,19 +263,19 @@ export default {
],
businessAreas: [
{
icon: '💻',
icon: require('../assets/img/ic_1.png'),
name: '技术开发与服务',
description: '从事计算机软硬件、网络科技、信息科技领域的技术开发、咨询、转让和服务',
features: ['系统优化与性能提升', '网络架构设计', '信息安全解决方案', '技术咨询与培训']
},
{
icon: '🧠',
icon: require('../assets/img/ic_2.png'),
name: 'AI智能应用',
description: '专注于人工智能技术,为客户提供定制化的智能解决方案',
features: ['数据分析与挖掘', '智能推荐系统', '自动化流程', '机器学习模型']
},
{
icon: '🔧',
icon: require('../assets/img/ic_3.png'),
name: '系统集成与软件开发',
description: '提供高效的计算机信息系统集成服务,以及创新的软件开发',
features: ['系统集成服务', '定制化软件开发', '数字化转型', '技术架构设计']
@@ -328,7 +335,7 @@ export default {
.banner {
position: relative;
height: 80vh;
min-height: 500px;
min-height:400px;
overflow: hidden;
}
@@ -482,6 +489,15 @@ export default {
.advantage-icon {
font-size: 4rem;
margin-bottom: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.advantage-icon .icon-image {
width: 60px;
height: 60px;
object-fit: contain;
}
.advantage-item h3 {
@@ -527,6 +543,15 @@ export default {
font-size: 3rem;
margin-bottom: 20px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.area-icon img {
width: 60px;
height: 60px;
object-fit: contain;
}
.area-item h3 {

View File

@@ -22,7 +22,9 @@
</div>
<div class="service-card">
<div class="service-icon">🔧</div>
<div class="service-icon">
<img src="../../assets/img/ic_3.png" alt="设施管理" class="icon-image">
</div>
<h3>设备管理</h3>
<p>设备生命周期管理性能监控故障预警最大化设备使用效率</p>
</div>
@@ -174,6 +176,15 @@ export default {
.service-icon {
font-size: 3rem;
margin-bottom: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.service-icon .icon-image {
width: 60px;
height: 60px;
object-fit: contain;
}
.service-card h3 {

View File

@@ -33,21 +33,27 @@
</div>
<div class="service-card">
<div class="service-icon"></div>
<div class="service-icon">
<img src="../../assets/img/ic_1.png" alt="设施管理" class="icon-image">
</div>
<h4>设施管理</h4>
<p>提供全面的设施管理解决方案确保设备高效运行</p>
<router-link to="/ourPlan/facilityManagement" class="service-link">了解更多</router-link>
</div>
<div class="service-card">
<div class="service-icon">🤖</div>
<div class="service-icon">
<img src="../../assets/img/ic_2.png" alt="AI解决方案" class="icon-image">
</div>
<h4>AI解决方案</h4>
<p>运用人工智能技术为企业提供智能化决策支持</p>
<router-link to="/ourPlan/aiSolutions" class="service-link">了解更多</router-link>
</div>
<div class="service-card">
<div class="service-icon">🔧</div>
<div class="service-icon">
<img src="../../assets/img/ic_3.png" alt="技术集成" class="icon-image">
</div>
<h4>技术集成</h4>
<p>整合多种技术平台构建统一的技术架构体系</p>
<router-link to="/ourPlan/technologyIntegration" class="service-link">了解更多</router-link>
@@ -162,6 +168,15 @@ export default {
.service-icon {
font-size: 3rem;
margin-bottom: 1rem;
display: flex;
align-items: center;
justify-content: center;
}
.service-icon .icon-image {
width: 60px;
height: 60px;
object-fit: contain;
}
.service-card h4 {