|
|
@@ -0,0 +1,247 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html>
|
|
|
+
|
|
|
+<head>
|
|
|
+ <meta charset="utf-8">
|
|
|
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
|
+ <meta name="renderer" content="webkit">
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
|
+ <link rel="icon" href="/favicon.ico">
|
|
|
+ <title>予书管理系统</title>
|
|
|
+ <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
|
|
|
+ <style>
|
|
|
+ html,
|
|
|
+ body,
|
|
|
+ #app {
|
|
|
+ height: 100%;
|
|
|
+ margin: 0px;
|
|
|
+ padding: 0px;
|
|
|
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 内容页淡入动画 */
|
|
|
+ #app {
|
|
|
+ opacity: 0;
|
|
|
+ transition: opacity 0.8s ease-in-out;
|
|
|
+ }
|
|
|
+
|
|
|
+ #app.app-loaded {
|
|
|
+ opacity: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 容器 - 自带背景色,不依赖body */
|
|
|
+ .app-loading {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background: #090a0f; /* 深空黑 */
|
|
|
+ z-index: 99999;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ transition: opacity 1.2s ease-in-out, visibility 1.2s; /* 延长消失时间 */
|
|
|
+ overflow: hidden; /* 仅在Loading时隐藏滚动条 */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Canvas 粒子背景 */
|
|
|
+ #loading-canvas {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 内容区域 */
|
|
|
+ .loading-content {
|
|
|
+ position: relative;
|
|
|
+ z-index: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 极简标题 */
|
|
|
+ .app-loading-title {
|
|
|
+ color: #fff;
|
|
|
+ font-size: 24px;
|
|
|
+ /* 强制指定字体,防止被 Element Plus / Normalize.css 覆盖导致跳变 */
|
|
|
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
|
|
|
+ letter-spacing: 8px;
|
|
|
+ font-weight: 200;
|
|
|
+ line-height: 1.5; /* 锁定行高 */
|
|
|
+ text-transform: uppercase;
|
|
|
+ opacity: 0.9;
|
|
|
+ animation: text-breathe 3s ease-in-out infinite;
|
|
|
+ text-shadow: 0 0 20px rgba(59, 130, 246, 0.5); /* 蓝色微光 */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 进度条容器 */
|
|
|
+ .loading-bar-container {
|
|
|
+ margin-top: 20px;
|
|
|
+ width: 200px;
|
|
|
+ height: 2px;
|
|
|
+ background: rgba(255, 255, 255, 0.1);
|
|
|
+ border-radius: 2px;
|
|
|
+ overflow: hidden;
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 进度条流光 */
|
|
|
+ .loading-bar {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(90deg, transparent, #3b82f6, transparent);
|
|
|
+ transform: translateX(-100%);
|
|
|
+ animation: loading-scan 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
|
+ }
|
|
|
+
|
|
|
+ @keyframes text-breathe {
|
|
|
+ 0%, 100% { opacity: 0.8; text-shadow: 0 0 10px rgba(59, 130, 246, 0.3); }
|
|
|
+ 50% { opacity: 1; text-shadow: 0 0 25px rgba(59, 130, 246, 0.8); }
|
|
|
+ }
|
|
|
+
|
|
|
+ @keyframes loading-scan {
|
|
|
+ 0% { transform: translateX(-100%); }
|
|
|
+ 50% { transform: translateX(0%); }
|
|
|
+ 100% { transform: translateX(100%); }
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+
|
|
|
+<body>
|
|
|
+ <div id="app"></div>
|
|
|
+
|
|
|
+ <!-- Vue 挂载前显示的 Loading (移出 #app 以免被 Vue 覆盖) -->
|
|
|
+ <div class="app-loading">
|
|
|
+ <canvas id="loading-canvas"></canvas>
|
|
|
+ <div class="loading-content">
|
|
|
+ <div class="app-loading-title">YUSHU SYSTEM</div>
|
|
|
+ <div class="loading-bar-container">
|
|
|
+ <div class="loading-bar"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <script>
|
|
|
+ // 沉浸式星空背景
|
|
|
+ (function() {
|
|
|
+ const canvas = document.getElementById('loading-canvas');
|
|
|
+ const ctx = canvas.getContext('2d');
|
|
|
+ let width, height;
|
|
|
+ let stars = [];
|
|
|
+
|
|
|
+ const starCount = 120; // 减少粒子数量优化性能
|
|
|
+ let speedMultiplier = 1; // 速度倍率
|
|
|
+
|
|
|
+ class Star {
|
|
|
+ constructor() {
|
|
|
+ this.reset();
|
|
|
+ // 初始化时随机进度
|
|
|
+ this.opacity = Math.random();
|
|
|
+ this.fadeDir = Math.random() > 0.5 ? 0.01 : -0.01;
|
|
|
+ }
|
|
|
+
|
|
|
+ reset() {
|
|
|
+ this.x = Math.random() * width;
|
|
|
+ this.y = Math.random() * height;
|
|
|
+ this.size = Math.random() * 1.5;
|
|
|
+ if (Math.random() > 0.95) this.size = Math.random() * 2 + 1; // 减少大星星概率
|
|
|
+
|
|
|
+ this.speedY = Math.random() * 0.2 + 0.05;
|
|
|
+ this.speedX = (Math.random() - 0.5) * 0.1;
|
|
|
+ }
|
|
|
+
|
|
|
+ update() {
|
|
|
+ this.y -= this.speedY * speedMultiplier;
|
|
|
+ this.x += this.speedX * speedMultiplier;
|
|
|
+
|
|
|
+ this.opacity += this.fadeDir * (speedMultiplier > 1 ? speedMultiplier * 0.5 : 1);
|
|
|
+ if (this.opacity > 1) {
|
|
|
+ this.opacity = 1;
|
|
|
+ this.fadeDir = -0.01 - Math.random() * 0.02;
|
|
|
+ } else if (this.opacity < 0.2) {
|
|
|
+ this.opacity = 0.2;
|
|
|
+ this.fadeDir = 0.01 + Math.random() * 0.02;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.y < 0) {
|
|
|
+ this.y = height;
|
|
|
+ this.x = Math.random() * width;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ draw() {
|
|
|
+ ctx.fillStyle = `rgba(255, 255, 255, ${this.opacity})`;
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
|
|
|
+ ctx.fill();
|
|
|
+
|
|
|
+ // 性能优化:移除 shadowBlur,改用绘制两层圆模拟光晕
|
|
|
+ if (this.size > 1.5) {
|
|
|
+ ctx.fillStyle = `rgba(255, 255, 255, ${this.opacity * 0.3})`;
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(this.x, this.y, this.size * 2, 0, Math.PI * 2);
|
|
|
+ ctx.fill();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function init() {
|
|
|
+ resize();
|
|
|
+ for (let i = 0; i < starCount; i++) {
|
|
|
+ stars.push(new Star());
|
|
|
+ }
|
|
|
+ loop();
|
|
|
+
|
|
|
+ // 模拟加速过程:1秒后开始加速,营造冲刺感
|
|
|
+ setTimeout(() => {
|
|
|
+ const accelerate = setInterval(() => {
|
|
|
+ speedMultiplier += 0.5; // 加速更快
|
|
|
+ if (speedMultiplier > 30) clearInterval(accelerate); // 最大加速到30倍,极速穿梭
|
|
|
+ }, 50);
|
|
|
+ }, 800);
|
|
|
+ }
|
|
|
+
|
|
|
+ function resize() {
|
|
|
+ width = canvas.width = window.innerWidth;
|
|
|
+ height = canvas.height = window.innerHeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ function loop() {
|
|
|
+ if (window.loadingAnimationStopped) return; // 停止动画循环
|
|
|
+
|
|
|
+ // 创建拖尾效果 (background with opacity)
|
|
|
+ ctx.fillStyle = 'rgba(9, 10, 15, 0.2)'; // 深色背景,0.2透明度产生拖尾
|
|
|
+ ctx.fillRect(0, 0, width, height);
|
|
|
+
|
|
|
+ // 偶尔绘制流星 (可选,暂不加,保持宁静)
|
|
|
+
|
|
|
+ for (let star of stars) {
|
|
|
+ star.update();
|
|
|
+ star.draw();
|
|
|
+ }
|
|
|
+
|
|
|
+ requestAnimationFrame(loop);
|
|
|
+ }
|
|
|
+
|
|
|
+ window.addEventListener('resize', resize);
|
|
|
+ init();
|
|
|
+
|
|
|
+ // 暴露停止函数给外部调用
|
|
|
+ window.stopLoadingAnimation = function() {
|
|
|
+ window.loadingAnimationStopped = true;
|
|
|
+ }
|
|
|
+ })();
|
|
|
+ </script>
|
|
|
+ <script type="module" src="/src/main.js"></script>
|
|
|
+</body>
|
|
|
+
|
|
|
+</html>
|