|
|
@@ -1,8 +1,84 @@
|
|
|
<!-- 指纹登录 - 深色科技风格 -->
|
|
|
<template>
|
|
|
<div class="fingerprint-login-page">
|
|
|
- <!-- 背景层 -->
|
|
|
- <div class="bg-layer" :style="{ backgroundImage: `url(${bgImg})` }" />
|
|
|
+ <!-- 指纹主题超炫酷科技背景 -->
|
|
|
+ <div class="bg-layer" />
|
|
|
+
|
|
|
+ <!-- 指纹扫描环形背景 -->
|
|
|
+ <div class="fingerprint-rings">
|
|
|
+ <div class="fp-ring ring-1" />
|
|
|
+ <div class="fp-ring ring-2" />
|
|
|
+ <div class="fp-ring ring-3" />
|
|
|
+ <div class="fp-ring ring-4" />
|
|
|
+ <div class="fp-ring ring-5" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 生物识别数据流 -->
|
|
|
+ <div class="biometric-data">
|
|
|
+ <div class="data-stream stream-1" />
|
|
|
+ <div class="data-stream stream-2" />
|
|
|
+ <div class="data-stream stream-3" />
|
|
|
+ <div class="data-stream stream-4" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 雷达扫描效果 -->
|
|
|
+ <div class="radar-scan">
|
|
|
+ <div class="radar-sweep" />
|
|
|
+ <div class="radar-grid" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 霓虹指纹脊线装饰 -->
|
|
|
+ <div class="neon-ridges">
|
|
|
+ <div class="neon-ridge ridge-a" />
|
|
|
+ <div class="neon-ridge ridge-b" />
|
|
|
+ <div class="neon-ridge ridge-c" />
|
|
|
+ <div class="neon-ridge ridge-d" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 数字雨效果(指纹主题) -->
|
|
|
+ <div class="fp-digital-rain">
|
|
|
+ <div class="digital-column" style="left: 8%; animation-delay: 0s;" />
|
|
|
+ <div class="digital-column" style="left: 22%; animation-delay: 0.8s;" />
|
|
|
+ <div class="digital-column" style="left: 38%; animation-delay: 1.6s;" />
|
|
|
+ <div class="digital-column" style="left: 52%; animation-delay: 2.4s;" />
|
|
|
+ <div class="digital-column" style="left: 68%; animation-delay: 3.2s;" />
|
|
|
+ <div class="digital-column" style="left: 84%; animation-delay: 4s;" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 动态渐变背景 -->
|
|
|
+ <div class="gradient-bg">
|
|
|
+ <div class="gradient-orb gradient-orb-1" />
|
|
|
+ <div class="gradient-orb gradient-orb-2" />
|
|
|
+ <div class="gradient-orb gradient-orb-3" />
|
|
|
+ <div class="gradient-orb gradient-orb-4" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 指纹主题粒子动画 -->
|
|
|
+ <div class="fingerprint-particles">
|
|
|
+ <div class="fp-particle fp-particle-1" />
|
|
|
+ <div class="fp-particle fp-particle-2" />
|
|
|
+ <div class="fp-particle fp-particle-3" />
|
|
|
+ <div class="fp-particle fp-particle-4" />
|
|
|
+ <div class="fp-particle fp-particle-5" />
|
|
|
+ <div class="fp-particle fp-particle-6" />
|
|
|
+ <div class="fp-particle fp-particle-7" />
|
|
|
+ <div class="fp-particle fp-particle-8" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 动态扫描线 -->
|
|
|
+ <div class="scan-bg">
|
|
|
+ <div class="scan-wave scan-wave-1" />
|
|
|
+ <div class="scan-wave scan-wave-2" />
|
|
|
+ <div class="scan-wave scan-wave-3" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 指纹脊线背景装饰 -->
|
|
|
+ <div class="fingerprint-bg-decoration">
|
|
|
+ <div class="ridge-line ridge-1" />
|
|
|
+ <div class="ridge-line ridge-2" />
|
|
|
+ <div class="ridge-line ridge-3" />
|
|
|
+ <div class="ridge-line ridge-4" />
|
|
|
+ </div>
|
|
|
|
|
|
<!-- 操作按钮 - 右上角 -->
|
|
|
<div class="action-buttons-top">
|
|
|
@@ -121,7 +197,7 @@ import { showNotify } from 'vant';
|
|
|
import { queryRemindTime } from '../api/login.js';
|
|
|
|
|
|
// 图片资源
|
|
|
-import bgImg from '../assets/images/bj.png';
|
|
|
+// import bgImg from '../assets/images/bj.png';
|
|
|
|
|
|
const route = useRoute();
|
|
|
const router = useRouter();
|
|
|
@@ -134,6 +210,31 @@ const isConnected = ref(false);
|
|
|
// 计算状态类名
|
|
|
const statusClass = ref('status-waiting');
|
|
|
|
|
|
+// 性能释放相关
|
|
|
+const isPageVisible = ref(true);
|
|
|
+let visibilityChangeHandler = null;
|
|
|
+
|
|
|
+// 页面可见性变化处理
|
|
|
+const handleVisibilityChange = () => {
|
|
|
+ isPageVisible.value = !document.hidden;
|
|
|
+ const fingerprintPage = document.querySelector('.fingerprint-login-page');
|
|
|
+ if (fingerprintPage) {
|
|
|
+ if (document.hidden) {
|
|
|
+ // 页面不可见时暂停所有动画
|
|
|
+ fingerprintPage.style.animationPlayState = 'paused';
|
|
|
+ fingerprintPage.querySelectorAll('*').forEach(el => {
|
|
|
+ el.style.animationPlayState = 'paused';
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 页面可见时恢复动画
|
|
|
+ fingerprintPage.style.animationPlayState = 'running';
|
|
|
+ fingerprintPage.querySelectorAll('*').forEach(el => {
|
|
|
+ el.style.animationPlayState = 'running';
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
// 更新状态
|
|
|
const updateStatus = (newStatus, text) => {
|
|
|
status.value = newStatus;
|
|
|
@@ -276,6 +377,10 @@ const checkPasswordReminder = async () => {
|
|
|
|
|
|
// 组件挂载
|
|
|
onMounted(() => {
|
|
|
+ // 添加页面可见性监听器
|
|
|
+ visibilityChangeHandler = handleVisibilityChange;
|
|
|
+ document.addEventListener('visibilitychange', visibilityChangeHandler);
|
|
|
+
|
|
|
// 检查URL参数中是否包含isOut=true,如果有则存储到localStorage
|
|
|
// const isOutParam = route.query.isOut;
|
|
|
// if (isOutParam !== undefined) {
|
|
|
@@ -303,6 +408,21 @@ onMounted(() => {
|
|
|
|
|
|
// 组件卸载
|
|
|
onUnmounted(() => {
|
|
|
+ // 移除页面可见性监听器
|
|
|
+ if (visibilityChangeHandler) {
|
|
|
+ document.removeEventListener('visibilitychange', visibilityChangeHandler);
|
|
|
+ visibilityChangeHandler = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暂停所有动画以释放性能
|
|
|
+ const fingerprintPage = document.querySelector('.fingerprint-login-page');
|
|
|
+ if (fingerprintPage) {
|
|
|
+ fingerprintPage.style.animationPlayState = 'paused';
|
|
|
+ fingerprintPage.querySelectorAll('*').forEach(el => {
|
|
|
+ el.style.animationPlayState = 'paused';
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
// 清理响应处理函数
|
|
|
if (plugin.fingerprintConfig) {
|
|
|
plugin.fingerprintConfig.receiveFingerprintResponse = () => { };
|
|
|
@@ -324,23 +444,49 @@ onUnmounted(() => {
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
+ -webkit-user-select: none;
|
|
|
+ -moz-user-select: none;
|
|
|
+ -ms-user-select: none;
|
|
|
+ user-select: none;
|
|
|
}
|
|
|
|
|
|
-/* 背景层 */
|
|
|
+/* 指纹主题炫酷科技背景 */
|
|
|
.bg-layer {
|
|
|
position: fixed;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
- background-color: #041c3d;
|
|
|
- background-size: cover;
|
|
|
- background-position: center;
|
|
|
- background-repeat: no-repeat;
|
|
|
+ background:
|
|
|
+ radial-gradient(circle at 50% 50%, rgba(0, 255, 255, 0.08) 0%, transparent 40%),
|
|
|
+ radial-gradient(circle at 20% 80%, rgba(0, 180, 255, 0.06) 0%, transparent 50%),
|
|
|
+ radial-gradient(circle at 80% 20%, rgba(0, 220, 255, 0.04) 0%, transparent 60%),
|
|
|
+ conic-gradient(from 0deg at 50% 50%, #0a1a2e 0deg, #0a2a4a 60deg, #0a3a5a 120deg, #0a2a4a 180deg, #0a1a2e 240deg, #0a2a4a 300deg, #0a1a2e 360deg);
|
|
|
+ background-size: 100% 100%, 150% 150%, 120% 120%, 100% 100%;
|
|
|
+ animation: fpBgShift 25s ease-in-out infinite;
|
|
|
z-index: 0;
|
|
|
}
|
|
|
|
|
|
-/* 背景动画网格 */
|
|
|
+@keyframes fpBgShift {
|
|
|
+ 0%, 100% {
|
|
|
+ background-position: 50% 50%, 20% 80%, 80% 20%, 0% 0%;
|
|
|
+ filter: hue-rotate(0deg);
|
|
|
+ }
|
|
|
+ 25% {
|
|
|
+ background-position: 60% 40%, 30% 70%, 70% 30%, 10% 10%;
|
|
|
+ filter: hue-rotate(30deg);
|
|
|
+ }
|
|
|
+ 50% {
|
|
|
+ background-position: 40% 60%, 10% 90%, 90% 10%, 20% 20%;
|
|
|
+ filter: hue-rotate(60deg);
|
|
|
+ }
|
|
|
+ 75% {
|
|
|
+ background-position: 55% 45%, 25% 75%, 75% 25%, 15% 15%;
|
|
|
+ filter: hue-rotate(30deg);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 增强的背景动画网格 */
|
|
|
.fingerprint-login-page::before {
|
|
|
content: '';
|
|
|
position: absolute;
|
|
|
@@ -349,11 +495,330 @@ onUnmounted(() => {
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
background-image:
|
|
|
+ radial-gradient(circle at 1px 1px, rgba(30, 144, 255, 0.15) 1px, transparent 0),
|
|
|
linear-gradient(rgba(30, 144, 255, 0.03) 1px, transparent 1px),
|
|
|
linear-gradient(90deg, rgba(30, 144, 255, 0.03) 1px, transparent 1px);
|
|
|
- background-size: 50px 50px;
|
|
|
+ background-size: 60px 60px, 30px 30px, 30px 30px;
|
|
|
z-index: 1;
|
|
|
pointer-events: none;
|
|
|
+ animation: gridPulse 8s ease-in-out infinite;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes gridPulse {
|
|
|
+ 0%, 100% {
|
|
|
+ opacity: 0.4;
|
|
|
+ transform: scale(1);
|
|
|
+ }
|
|
|
+ 50% {
|
|
|
+ opacity: 0.8;
|
|
|
+ transform: scale(1.02);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 动态渐变背景 */
|
|
|
+.gradient-bg {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ pointer-events: none;
|
|
|
+}
|
|
|
+
|
|
|
+.gradient-orb {
|
|
|
+ position: absolute;
|
|
|
+ border-radius: 50%;
|
|
|
+ filter: blur(100px);
|
|
|
+ animation: orbFloat 12s ease-in-out infinite;
|
|
|
+ will-change: transform, opacity;
|
|
|
+ transform: translateZ(0);
|
|
|
+ -webkit-backface-visibility: hidden;
|
|
|
+ backface-visibility: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.gradient-orb-1 {
|
|
|
+ width: 400px;
|
|
|
+ height: 400px;
|
|
|
+ background: radial-gradient(circle, rgba(30, 144, 255, 0.25) 0%, transparent 70%);
|
|
|
+ top: 15%;
|
|
|
+ left: 25%;
|
|
|
+ animation-delay: 0s;
|
|
|
+}
|
|
|
+
|
|
|
+.gradient-orb-2 {
|
|
|
+ width: 300px;
|
|
|
+ height: 300px;
|
|
|
+ background: radial-gradient(circle, rgba(0, 191, 255, 0.2) 0%, transparent 70%);
|
|
|
+ bottom: 25%;
|
|
|
+ right: 20%;
|
|
|
+ animation-delay: 4s;
|
|
|
+}
|
|
|
+
|
|
|
+.gradient-orb-3 {
|
|
|
+ width: 250px;
|
|
|
+ height: 250px;
|
|
|
+ background: radial-gradient(circle, rgba(135, 206, 250, 0.15) 0%, transparent 70%);
|
|
|
+ top: 50%;
|
|
|
+ left: 70%;
|
|
|
+ animation-delay: 8s;
|
|
|
+}
|
|
|
+
|
|
|
+.gradient-orb-4 {
|
|
|
+ width: 350px;
|
|
|
+ height: 350px;
|
|
|
+ background: radial-gradient(circle, rgba(0, 206, 209, 0.1) 0%, transparent 70%);
|
|
|
+ top: 70%;
|
|
|
+ left: 10%;
|
|
|
+ animation-delay: 6s;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes orbFloat {
|
|
|
+ 0%, 100% {
|
|
|
+ transform: translate(0, 0) scale(1) rotate(0deg);
|
|
|
+ opacity: 0.6;
|
|
|
+ }
|
|
|
+ 33% {
|
|
|
+ transform: translate(30px, -40px) scale(1.1) rotate(120deg);
|
|
|
+ opacity: 0.9;
|
|
|
+ }
|
|
|
+ 66% {
|
|
|
+ transform: translate(-40px, 30px) scale(0.8) rotate(240deg);
|
|
|
+ opacity: 0.4;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 指纹主题粒子动画 */
|
|
|
+.fingerprint-particles {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 2;
|
|
|
+ pointer-events: none;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-particle {
|
|
|
+ position: absolute;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: radial-gradient(circle, rgba(30, 144, 255, 0.9) 0%, rgba(30, 144, 255, 0.3) 40%, transparent 100%);
|
|
|
+ animation: fpParticleMove 15s linear infinite;
|
|
|
+ will-change: transform, opacity;
|
|
|
+ transform: translateZ(0);
|
|
|
+ -webkit-backface-visibility: hidden;
|
|
|
+ backface-visibility: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-particle-1 {
|
|
|
+ width: 8px;
|
|
|
+ height: 8px;
|
|
|
+ left: 20%;
|
|
|
+ animation-delay: 0s;
|
|
|
+ animation-duration: 12s;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-particle-2 {
|
|
|
+ width: 6px;
|
|
|
+ height: 6px;
|
|
|
+ left: 80%;
|
|
|
+ animation-delay: 3s;
|
|
|
+ animation-duration: 14s;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-particle-3 {
|
|
|
+ width: 10px;
|
|
|
+ height: 10px;
|
|
|
+ left: 60%;
|
|
|
+ animation-delay: 6s;
|
|
|
+ animation-duration: 10s;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-particle-4 {
|
|
|
+ width: 5px;
|
|
|
+ height: 5px;
|
|
|
+ left: 40%;
|
|
|
+ animation-delay: 2s;
|
|
|
+ animation-duration: 16s;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-particle-5 {
|
|
|
+ width: 7px;
|
|
|
+ height: 7px;
|
|
|
+ left: 10%;
|
|
|
+ animation-delay: 5s;
|
|
|
+ animation-duration: 13s;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-particle-6 {
|
|
|
+ width: 9px;
|
|
|
+ height: 9px;
|
|
|
+ left: 90%;
|
|
|
+ animation-delay: 8s;
|
|
|
+ animation-duration: 11s;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-particle-7 {
|
|
|
+ width: 4px;
|
|
|
+ height: 4px;
|
|
|
+ left: 70%;
|
|
|
+ animation-delay: 1s;
|
|
|
+ animation-duration: 15s;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-particle-8 {
|
|
|
+ width: 6px;
|
|
|
+ height: 6px;
|
|
|
+ left: 30%;
|
|
|
+ animation-delay: 7s;
|
|
|
+ animation-duration: 9s;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes fpParticleMove {
|
|
|
+ 0% {
|
|
|
+ transform: translateY(110vh) translateX(-20px) rotate(0deg);
|
|
|
+ opacity: 0;
|
|
|
+ }
|
|
|
+ 10% {
|
|
|
+ opacity: 1;
|
|
|
+ }
|
|
|
+ 50% {
|
|
|
+ opacity: 0.8;
|
|
|
+ transform: translateY(50vh) translateX(20px) rotate(180deg);
|
|
|
+ }
|
|
|
+ 90% {
|
|
|
+ opacity: 0.6;
|
|
|
+ }
|
|
|
+ 100% {
|
|
|
+ transform: translateY(-10vh) translateX(40px) rotate(360deg);
|
|
|
+ opacity: 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 动态扫描线 */
|
|
|
+.scan-bg {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 3;
|
|
|
+ pointer-events: none;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.scan-wave {
|
|
|
+ position: absolute;
|
|
|
+ width: 100%;
|
|
|
+ height: 2px;
|
|
|
+ background: linear-gradient(90deg, transparent 0%, rgba(0, 191, 255, 0.6) 20%, rgba(30, 144, 255, 0.8) 50%, rgba(0, 191, 255, 0.6) 80%, transparent 100%);
|
|
|
+ animation: scanMove 10s ease-in-out infinite;
|
|
|
+ will-change: transform, opacity;
|
|
|
+ transform: translateZ(0);
|
|
|
+}
|
|
|
+
|
|
|
+.scan-wave-1 {
|
|
|
+ animation-delay: 0s;
|
|
|
+ background: linear-gradient(90deg, transparent 0%, rgba(0, 191, 255, 0.8) 50%, transparent 100%);
|
|
|
+}
|
|
|
+
|
|
|
+.scan-wave-2 {
|
|
|
+ animation-delay: 2s;
|
|
|
+ background: linear-gradient(90deg, transparent 0%, rgba(30, 144, 255, 0.6) 50%, transparent 100%);
|
|
|
+}
|
|
|
+
|
|
|
+.scan-wave-3 {
|
|
|
+ animation-delay: 4s;
|
|
|
+ background: linear-gradient(90deg, transparent 0%, rgba(135, 206, 250, 0.4) 50%, transparent 100%);
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes scanMove {
|
|
|
+ 0% {
|
|
|
+ top: -5px;
|
|
|
+ opacity: 0;
|
|
|
+ transform: scaleX(0.5);
|
|
|
+ }
|
|
|
+ 20% {
|
|
|
+ opacity: 1;
|
|
|
+ transform: scaleX(1);
|
|
|
+ }
|
|
|
+ 80% {
|
|
|
+ opacity: 0.8;
|
|
|
+ transform: scaleX(1.2);
|
|
|
+ }
|
|
|
+ 100% {
|
|
|
+ top: 105%;
|
|
|
+ opacity: 0;
|
|
|
+ transform: scaleX(0.3);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 指纹脊线背景装饰 */
|
|
|
+.fingerprint-bg-decoration {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 1;
|
|
|
+ pointer-events: none;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.ridge-line {
|
|
|
+ position: absolute;
|
|
|
+ border: 1px solid rgba(30, 144, 255, 0.1);
|
|
|
+ border-radius: 50%;
|
|
|
+ animation: ridgeExpand 8s ease-in-out infinite;
|
|
|
+ will-change: transform, opacity;
|
|
|
+ transform: translateZ(0);
|
|
|
+}
|
|
|
+
|
|
|
+.ridge-1 {
|
|
|
+ width: 150px;
|
|
|
+ height: 150px;
|
|
|
+ top: 20%;
|
|
|
+ left: 15%;
|
|
|
+ animation-delay: 0s;
|
|
|
+}
|
|
|
+
|
|
|
+.ridge-2 {
|
|
|
+ width: 200px;
|
|
|
+ height: 200px;
|
|
|
+ bottom: 30%;
|
|
|
+ right: 25%;
|
|
|
+ animation-delay: 2s;
|
|
|
+}
|
|
|
+
|
|
|
+.ridge-3 {
|
|
|
+ width: 100px;
|
|
|
+ height: 100px;
|
|
|
+ top: 60%;
|
|
|
+ left: 70%;
|
|
|
+ animation-delay: 4s;
|
|
|
+}
|
|
|
+
|
|
|
+.ridge-4 {
|
|
|
+ width: 120px;
|
|
|
+ height: 120px;
|
|
|
+ top: 80%;
|
|
|
+ left: 40%;
|
|
|
+ animation-delay: 6s;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes ridgeExpand {
|
|
|
+ 0%, 100% {
|
|
|
+ transform: scale(1) rotate(0deg);
|
|
|
+ opacity: 0.1;
|
|
|
+ border-color: rgba(30, 144, 255, 0.1);
|
|
|
+ }
|
|
|
+ 50% {
|
|
|
+ transform: scale(1.5) rotate(180deg);
|
|
|
+ opacity: 0.3;
|
|
|
+ border-color: rgba(30, 144, 255, 0.3);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.recognize-container {
|
|
|
@@ -820,20 +1285,517 @@ onUnmounted(() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/* 性能优化 - 减少动画支持 */
|
|
|
+@media (prefers-reduced-motion: reduce) {
|
|
|
+ *,
|
|
|
+ *::before,
|
|
|
+ *::after {
|
|
|
+ animation-duration: 0.01ms !important;
|
|
|
+ animation-iteration-count: 1 !important;
|
|
|
+ transition-duration: 0.01ms !important;
|
|
|
+ scroll-behavior: auto !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .gradient-orb,
|
|
|
+ .fp-particle,
|
|
|
+ .scan-wave,
|
|
|
+ .ridge-line,
|
|
|
+ .status-circle {
|
|
|
+ animation: none !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 低性能设备优化 */
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .gradient-orb {
|
|
|
+ filter: blur(60px);
|
|
|
+ animation-duration: 16s;
|
|
|
+ }
|
|
|
+
|
|
|
+ .fp-particle {
|
|
|
+ animation-duration: 18s;
|
|
|
+ }
|
|
|
+
|
|
|
+ .fingerprint-particles .fp-particle:nth-child(n+5) {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .scan-bg .scan-wave:nth-child(n+3) {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 480px) {
|
|
|
+ .gradient-orb-3,
|
|
|
+ .gradient-orb-4,
|
|
|
+ .ridge-line {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .fingerprint-particles .fp-particle:nth-child(n+4) {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .scan-bg .scan-wave:nth-child(n+2) {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* 响应式设计 */
|
|
|
@media (max-width: 768px) {
|
|
|
.action-buttons {
|
|
|
display: none;
|
|
|
padding: 0 1rem;
|
|
|
}
|
|
|
+
|
|
|
+ .status-circle {
|
|
|
+ width: clamp(200px, 35vw, 280px);
|
|
|
+ height: clamp(200px, 35vw, 280px);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-/* 减少动画(无障碍支持) */
|
|
|
-@media (prefers-reduced-motion: reduce) {
|
|
|
- * {
|
|
|
- animation-duration: 0.01ms !important;
|
|
|
- animation-iteration-count: 1 !important;
|
|
|
- transition-duration: 0.01ms !important;
|
|
|
+/* 高刷新率设备优化 */
|
|
|
+@media (min-resolution: 120dpi) {
|
|
|
+ .fp-particle {
|
|
|
+ animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ .scan-wave {
|
|
|
+ animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 暗色主题适配 */
|
|
|
+@media (prefers-color-scheme: dark) {
|
|
|
+ .gradient-orb {
|
|
|
+ filter: blur(120px);
|
|
|
+ opacity: 0.9;
|
|
|
+ }
|
|
|
+
|
|
|
+ .fp-particle {
|
|
|
+ background: radial-gradient(circle, rgba(30, 144, 255, 1) 0%, rgba(30, 144, 255, 0.4) 40%, transparent 100%);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 节能模式适配 */
|
|
|
+@media (prefers-reduced-data) {
|
|
|
+ .gradient-orb,
|
|
|
+ .fingerprint-particles,
|
|
|
+ .scan-bg,
|
|
|
+ .fingerprint-bg-decoration {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 指纹扫描环形背景 */
|
|
|
+.fingerprint-rings {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 1;
|
|
|
+ pointer-events: none;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-ring {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ border: 1px solid rgba(0, 255, 255, 0.3);
|
|
|
+ border-radius: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ animation: ringExpand 8s ease-in-out infinite;
|
|
|
+}
|
|
|
+
|
|
|
+.ring-1 { width: 100px; height: 100px; animation-delay: 0s; }
|
|
|
+.ring-2 { width: 200px; height: 200px; animation-delay: 1.6s; }
|
|
|
+.ring-3 { width: 300px; height: 300px; animation-delay: 3.2s; }
|
|
|
+.ring-4 { width: 400px; height: 400px; animation-delay: 4.8s; }
|
|
|
+.ring-5 { width: 500px; height: 500px; animation-delay: 6.4s; }
|
|
|
+
|
|
|
+@keyframes ringExpand {
|
|
|
+ 0% {
|
|
|
+ transform: translate(-50%, -50%) scale(0.5);
|
|
|
+ opacity: 0;
|
|
|
+ border-color: rgba(0, 255, 255, 0);
|
|
|
+ }
|
|
|
+ 20% {
|
|
|
+ opacity: 0.8;
|
|
|
+ border-color: rgba(0, 255, 255, 0.6);
|
|
|
+ }
|
|
|
+ 80% {
|
|
|
+ opacity: 0.4;
|
|
|
+ border-color: rgba(0, 255, 255, 0.3);
|
|
|
+ }
|
|
|
+ 100% {
|
|
|
+ transform: translate(-50%, -50%) scale(1.5);
|
|
|
+ opacity: 0;
|
|
|
+ border-color: rgba(0, 255, 255, 0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 生物识别数据流 */
|
|
|
+.biometric-data {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 2;
|
|
|
+ pointer-events: none;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.data-stream {
|
|
|
+ position: absolute;
|
|
|
+ width: 2px;
|
|
|
+ height: 80px;
|
|
|
+ background: linear-gradient(0deg, transparent, #0088ff, #00aaff, transparent);
|
|
|
+ box-shadow: 0 0 10px #0088ff;
|
|
|
+ animation: dataFlow 6s linear infinite;
|
|
|
+}
|
|
|
+
|
|
|
+.stream-1 {
|
|
|
+ top: 20%;
|
|
|
+ left: 15%;
|
|
|
+ animation-delay: 0s;
|
|
|
+ transform: rotate(45deg);
|
|
|
+}
|
|
|
+.stream-2 {
|
|
|
+ bottom: 25%;
|
|
|
+ right: 20%;
|
|
|
+ animation-delay: 1.5s;
|
|
|
+ transform: rotate(-30deg);
|
|
|
+}
|
|
|
+.stream-3 {
|
|
|
+ top: 60%;
|
|
|
+ left: 70%;
|
|
|
+ animation-delay: 3s;
|
|
|
+ transform: rotate(60deg);
|
|
|
+}
|
|
|
+.stream-4 {
|
|
|
+ top: 80%;
|
|
|
+ left: 35%;
|
|
|
+ animation-delay: 4.5s;
|
|
|
+ transform: rotate(-45deg);
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes dataFlow {
|
|
|
+ 0%, 100% { opacity: 0; height: 0; }
|
|
|
+ 25% { opacity: 1; height: 80px; }
|
|
|
+ 75% { opacity: 0.8; height: 120px; }
|
|
|
+}
|
|
|
+
|
|
|
+/* 雷达扫描效果 */
|
|
|
+.radar-scan {
|
|
|
+ position: fixed;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ width: 400px;
|
|
|
+ height: 400px;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ z-index: 1;
|
|
|
+ pointer-events: none;
|
|
|
+}
|
|
|
+
|
|
|
+.radar-sweep {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 50%;
|
|
|
+ width: 2px;
|
|
|
+ height: 200px;
|
|
|
+ background: linear-gradient(0deg, transparent, #00ffff, transparent);
|
|
|
+ transform-origin: bottom center;
|
|
|
+ animation: radarSweep 4s linear infinite;
|
|
|
+ box-shadow: 0 0 20px #00ffff;
|
|
|
+}
|
|
|
+
|
|
|
+.radar-grid {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ border: 1px solid rgba(0, 255, 255, 0.1);
|
|
|
+ border-radius: 50%;
|
|
|
+ animation: radarPulse 4s ease-in-out infinite;
|
|
|
+}
|
|
|
+
|
|
|
+.radar-grid::before,
|
|
|
+.radar-grid::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ border: 1px solid rgba(0, 255, 255, 0.1);
|
|
|
+ border-radius: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+}
|
|
|
+
|
|
|
+.radar-grid::before {
|
|
|
+ width: 66%;
|
|
|
+ height: 66%;
|
|
|
+}
|
|
|
+
|
|
|
+.radar-grid::after {
|
|
|
+ width: 33%;
|
|
|
+ height: 33%;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes radarSweep {
|
|
|
+ 0% { transform: rotate(0deg); opacity: 0; }
|
|
|
+ 10% { opacity: 1; }
|
|
|
+ 90% { opacity: 0.8; }
|
|
|
+ 100% { transform: rotate(360deg); opacity: 0; }
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes radarPulse {
|
|
|
+ 0%, 100% { opacity: 0.2; }
|
|
|
+ 50% { opacity: 0.6; }
|
|
|
+}
|
|
|
+
|
|
|
+/* 霓虹指纹脊线装饰 */
|
|
|
+.neon-ridges {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 1;
|
|
|
+ pointer-events: none;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.neon-ridge {
|
|
|
+ position: absolute;
|
|
|
+ border: 2px solid transparent;
|
|
|
+ border-radius: 50%;
|
|
|
+ animation: neonGlow 5s ease-in-out infinite;
|
|
|
+}
|
|
|
+
|
|
|
+.ridge-a {
|
|
|
+ width: 120px;
|
|
|
+ height: 80px;
|
|
|
+ top: 20%;
|
|
|
+ left: 20%;
|
|
|
+ border-color: rgba(0, 160, 255, 0.4);
|
|
|
+ animation-delay: 0s;
|
|
|
+}
|
|
|
+
|
|
|
+.ridge-b {
|
|
|
+ width: 90px;
|
|
|
+ height: 60px;
|
|
|
+ bottom: 30%;
|
|
|
+ right: 25%;
|
|
|
+ border-color: rgba(0, 200, 255, 0.4);
|
|
|
+ animation-delay: 1.25s;
|
|
|
+}
|
|
|
+
|
|
|
+.ridge-c {
|
|
|
+ width: 140px;
|
|
|
+ height: 100px;
|
|
|
+ top: 65%;
|
|
|
+ left: 60%;
|
|
|
+ border-color: rgba(0, 240, 255, 0.4);
|
|
|
+ animation-delay: 2.5s;
|
|
|
+}
|
|
|
+
|
|
|
+.ridge-d {
|
|
|
+ width: 110px;
|
|
|
+ height: 70px;
|
|
|
+ top: 75%;
|
|
|
+ left: 15%;
|
|
|
+ border-color: rgba(0, 180, 240, 0.4);
|
|
|
+ animation-delay: 3.75s;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes neonGlow {
|
|
|
+ 0%, 100% {
|
|
|
+ border-width: 1px;
|
|
|
+ opacity: 0.3;
|
|
|
+ filter: blur(0px);
|
|
|
+ transform: scale(1);
|
|
|
+ }
|
|
|
+ 50% {
|
|
|
+ border-width: 3px;
|
|
|
+ opacity: 1;
|
|
|
+ filter: blur(1px);
|
|
|
+ transform: scale(1.1);
|
|
|
+ box-shadow: 0 0 30px currentColor;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 数字雨效果(指纹主题) */
|
|
|
+.fp-digital-rain {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 2;
|
|
|
+ pointer-events: none;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.digital-column {
|
|
|
+ position: absolute;
|
|
|
+ width: 1px;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(0deg,
|
|
|
+ transparent 0%,
|
|
|
+ rgba(96, 120, 160, 0.15) 20%,
|
|
|
+ rgba(128, 150, 180, 0.6) 40%,
|
|
|
+ rgba(160, 180, 210, 0.8) 50%,
|
|
|
+ rgba(128, 150, 180, 0.6) 60%,
|
|
|
+ rgba(96, 120, 160, 0.15) 80%,
|
|
|
+ transparent 100%
|
|
|
+ );
|
|
|
+ animation: digitalFall 22s linear infinite;
|
|
|
+}
|
|
|
+
|
|
|
+/* .digital-column::before {
|
|
|
+ content: 'ABCDEF0123456789';
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: -5px;
|
|
|
+ font-family: 'Courier New', monospace;
|
|
|
+ font-size: 10px;
|
|
|
+ color: #ff00ff;
|
|
|
+ writing-mode: vertical-rl;
|
|
|
+ opacity: 0.7;
|
|
|
+ animation: digitalText 10s linear infinite;
|
|
|
+ text-shadow: 0 0 5px #ff00ff;
|
|
|
+} */
|
|
|
+
|
|
|
+@keyframes digitalFall {
|
|
|
+ 0% { transform: translateY(-100%); opacity: 0; }
|
|
|
+ 15% { opacity: 1; }
|
|
|
+ 85% { opacity: 0.6; }
|
|
|
+ 100% { transform: translateY(100vh); opacity: 0; }
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes digitalText {
|
|
|
+ 0% { transform: translateY(-20px); }
|
|
|
+ 100% { transform: translateY(100vh); }
|
|
|
+}
|
|
|
+
|
|
|
+/* 硬件加速优化 */
|
|
|
+.fp-ring,
|
|
|
+.data-stream,
|
|
|
+.radar-sweep,
|
|
|
+.radar-grid,
|
|
|
+.neon-ridge,
|
|
|
+.digital-column {
|
|
|
+ will-change: transform, opacity;
|
|
|
+ transform: translateZ(0);
|
|
|
+ -webkit-backface-visibility: hidden;
|
|
|
+ backface-visibility: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+/* 深度性能优化 - 保留所有元素但优化性能 */
|
|
|
+* {
|
|
|
+ -webkit-backface-visibility: hidden;
|
|
|
+ backface-visibility: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+/* CSS Containment 优化 - 限制布局重计算范围 */
|
|
|
+.bg-layer,
|
|
|
+.fingerprint-rings,
|
|
|
+.biometric-data,
|
|
|
+.radar-scan,
|
|
|
+.neon-ridges,
|
|
|
+.fp-digital-rain,
|
|
|
+.gradient-bg,
|
|
|
+.fingerprint-particles,
|
|
|
+.scan-bg,
|
|
|
+.fingerprint-bg-decoration {
|
|
|
+ contain: layout style paint;
|
|
|
+ isolation: isolate;
|
|
|
+}
|
|
|
+
|
|
|
+/* 合成层优化 - 智能GPU加速 */
|
|
|
+.fingerprint-login-page {
|
|
|
+ transform: translateZ(0);
|
|
|
+ will-change: auto;
|
|
|
+}
|
|
|
+
|
|
|
+/* 动画性能优化 - 保持流畅但高效 */
|
|
|
+.fp-ring {
|
|
|
+ animation-timing-function: ease-out;
|
|
|
+}
|
|
|
+
|
|
|
+.neon-ridge {
|
|
|
+ animation-timing-function: ease-in-out;
|
|
|
+}
|
|
|
+
|
|
|
+.radar-sweep {
|
|
|
+ animation-timing-function: linear;
|
|
|
+}
|
|
|
+
|
|
|
+.digital-column {
|
|
|
+ animation-timing-function: linear;
|
|
|
+}
|
|
|
+
|
|
|
+/* 动画性能优化 */
|
|
|
+.gradient-orb {
|
|
|
+ filter: blur(90px);
|
|
|
+ animation-duration: 20s;
|
|
|
+ animation-timing-function: ease-out;
|
|
|
+ animation-fill-mode: both;
|
|
|
+}
|
|
|
+
|
|
|
+.fp-ring {
|
|
|
+ animation-duration: 12s;
|
|
|
+ animation-timing-function: ease-in-out;
|
|
|
+ animation-fill-mode: both;
|
|
|
+}
|
|
|
+
|
|
|
+.data-stream {
|
|
|
+ animation-duration: 10s;
|
|
|
+ animation-timing-function: linear;
|
|
|
+ animation-fill-mode: both;
|
|
|
+}
|
|
|
+
|
|
|
+.radar-sweep {
|
|
|
+ animation-duration: 6s;
|
|
|
+ animation-timing-function: linear;
|
|
|
+ animation-fill-mode: both;
|
|
|
+}
|
|
|
+
|
|
|
+.digital-column {
|
|
|
+ animation-duration: 25s;
|
|
|
+ animation-timing-function: linear;
|
|
|
+ animation-fill-mode: both;
|
|
|
+}
|
|
|
+
|
|
|
+/* 分层优化 */
|
|
|
+.bg-layer {
|
|
|
+ animation-duration: 35s;
|
|
|
+ animation-timing-function: ease-in-out;
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式性能优化 */
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .gradient-orb {
|
|
|
+ filter: blur(70px);
|
|
|
+ animation-duration: 25s;
|
|
|
+ }
|
|
|
+
|
|
|
+ .digital-column {
|
|
|
+ animation-duration: 18s;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 480px) {
|
|
|
+ .bg-layer {
|
|
|
+ animation-duration: 50s;
|
|
|
+ }
|
|
|
+
|
|
|
+ .gradient-orb {
|
|
|
+ filter: blur(50px);
|
|
|
+ animation-duration: 30s;
|
|
|
}
|
|
|
}
|
|
|
</style>
|