index.html 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  6. <meta name="renderer" content="webkit">
  7. <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  8. <link rel="icon" href="/favicon.ico">
  9. <title>予书管理系统</title>
  10. <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
  11. <style>
  12. html,
  13. body,
  14. #app {
  15. height: 100%;
  16. margin: 0px;
  17. padding: 0px;
  18. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  19. }
  20. /* 内容页淡入动画 */
  21. #app {
  22. opacity: 0;
  23. transition: opacity 0.8s ease-in-out;
  24. }
  25. #app.app-loaded {
  26. opacity: 1;
  27. }
  28. /* 容器 - 自带背景色,不依赖body */
  29. .app-loading {
  30. position: fixed;
  31. top: 0;
  32. left: 0;
  33. width: 100%;
  34. height: 100%;
  35. background: #090a0f; /* 深空黑 */
  36. z-index: 99999;
  37. display: flex;
  38. justify-content: center;
  39. align-items: center;
  40. transition: opacity 1.2s ease-in-out, visibility 1.2s; /* 延长消失时间 */
  41. overflow: hidden; /* 仅在Loading时隐藏滚动条 */
  42. }
  43. /* Canvas 粒子背景 */
  44. #loading-canvas {
  45. position: absolute;
  46. top: 0;
  47. left: 0;
  48. width: 100%;
  49. height: 100%;
  50. z-index: 0;
  51. }
  52. /* 内容区域 */
  53. .loading-content {
  54. position: relative;
  55. z-index: 1;
  56. display: flex;
  57. flex-direction: column;
  58. align-items: center;
  59. justify-content: center;
  60. }
  61. /* 极简标题 */
  62. .app-loading-title {
  63. color: #fff;
  64. font-size: 24px;
  65. /* 强制指定字体,防止被 Element Plus / Normalize.css 覆盖导致跳变 */
  66. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
  67. letter-spacing: 8px;
  68. font-weight: 200;
  69. line-height: 1.5; /* 锁定行高 */
  70. text-transform: uppercase;
  71. opacity: 0.9;
  72. animation: text-breathe 3s ease-in-out infinite;
  73. text-shadow: 0 0 20px rgba(59, 130, 246, 0.5); /* 蓝色微光 */
  74. }
  75. /* 进度条容器 */
  76. .loading-bar-container {
  77. margin-top: 20px;
  78. width: 200px;
  79. height: 2px;
  80. background: rgba(255, 255, 255, 0.1);
  81. border-radius: 2px;
  82. overflow: hidden;
  83. position: relative;
  84. }
  85. /* 进度条流光 */
  86. .loading-bar {
  87. position: absolute;
  88. top: 0;
  89. left: 0;
  90. width: 100%;
  91. height: 100%;
  92. background: linear-gradient(90deg, transparent, #3b82f6, transparent);
  93. transform: translateX(-100%);
  94. animation: loading-scan 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  95. }
  96. @keyframes text-breathe {
  97. 0%, 100% { opacity: 0.8; text-shadow: 0 0 10px rgba(59, 130, 246, 0.3); }
  98. 50% { opacity: 1; text-shadow: 0 0 25px rgba(59, 130, 246, 0.8); }
  99. }
  100. @keyframes loading-scan {
  101. 0% { transform: translateX(-100%); }
  102. 50% { transform: translateX(0%); }
  103. 100% { transform: translateX(100%); }
  104. }
  105. </style>
  106. </head>
  107. <body>
  108. <div id="app"></div>
  109. <!-- Vue 挂载前显示的 Loading (移出 #app 以免被 Vue 覆盖) -->
  110. <div class="app-loading">
  111. <canvas id="loading-canvas"></canvas>
  112. <div class="loading-content">
  113. <div class="app-loading-title">YUSHU SYSTEM</div>
  114. <div class="loading-bar-container">
  115. <div class="loading-bar"></div>
  116. </div>
  117. </div>
  118. </div>
  119. <script>
  120. // 沉浸式星空背景
  121. (function() {
  122. const canvas = document.getElementById('loading-canvas');
  123. const ctx = canvas.getContext('2d');
  124. let width, height;
  125. let stars = [];
  126. const starCount = 120; // 减少粒子数量优化性能
  127. let speedMultiplier = 1; // 速度倍率
  128. class Star {
  129. constructor() {
  130. this.reset();
  131. // 初始化时随机进度
  132. this.opacity = Math.random();
  133. this.fadeDir = Math.random() > 0.5 ? 0.01 : -0.01;
  134. }
  135. reset() {
  136. this.x = Math.random() * width;
  137. this.y = Math.random() * height;
  138. this.size = Math.random() * 1.5;
  139. if (Math.random() > 0.95) this.size = Math.random() * 2 + 1; // 减少大星星概率
  140. this.speedY = Math.random() * 0.2 + 0.05;
  141. this.speedX = (Math.random() - 0.5) * 0.1;
  142. }
  143. update() {
  144. this.y -= this.speedY * speedMultiplier;
  145. this.x += this.speedX * speedMultiplier;
  146. this.opacity += this.fadeDir * (speedMultiplier > 1 ? speedMultiplier * 0.5 : 1);
  147. if (this.opacity > 1) {
  148. this.opacity = 1;
  149. this.fadeDir = -0.01 - Math.random() * 0.02;
  150. } else if (this.opacity < 0.2) {
  151. this.opacity = 0.2;
  152. this.fadeDir = 0.01 + Math.random() * 0.02;
  153. }
  154. if (this.y < 0) {
  155. this.y = height;
  156. this.x = Math.random() * width;
  157. }
  158. }
  159. draw() {
  160. ctx.fillStyle = `rgba(255, 255, 255, ${this.opacity})`;
  161. ctx.beginPath();
  162. ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
  163. ctx.fill();
  164. // 性能优化:移除 shadowBlur,改用绘制两层圆模拟光晕
  165. if (this.size > 1.5) {
  166. ctx.fillStyle = `rgba(255, 255, 255, ${this.opacity * 0.3})`;
  167. ctx.beginPath();
  168. ctx.arc(this.x, this.y, this.size * 2, 0, Math.PI * 2);
  169. ctx.fill();
  170. }
  171. }
  172. }
  173. function init() {
  174. resize();
  175. for (let i = 0; i < starCount; i++) {
  176. stars.push(new Star());
  177. }
  178. loop();
  179. // 模拟加速过程:1秒后开始加速,营造冲刺感
  180. setTimeout(() => {
  181. const accelerate = setInterval(() => {
  182. speedMultiplier += 0.5; // 加速更快
  183. if (speedMultiplier > 30) clearInterval(accelerate); // 最大加速到30倍,极速穿梭
  184. }, 50);
  185. }, 800);
  186. }
  187. function resize() {
  188. width = canvas.width = window.innerWidth;
  189. height = canvas.height = window.innerHeight;
  190. }
  191. function loop() {
  192. if (window.loadingAnimationStopped) return; // 停止动画循环
  193. // 创建拖尾效果 (background with opacity)
  194. ctx.fillStyle = 'rgba(9, 10, 15, 0.2)'; // 深色背景,0.2透明度产生拖尾
  195. ctx.fillRect(0, 0, width, height);
  196. // 偶尔绘制流星 (可选,暂不加,保持宁静)
  197. for (let star of stars) {
  198. star.update();
  199. star.draw();
  200. }
  201. requestAnimationFrame(loop);
  202. }
  203. window.addEventListener('resize', resize);
  204. init();
  205. // 暴露停止函数给外部调用
  206. window.stopLoadingAnimation = function() {
  207. window.loadingAnimationStopped = true;
  208. }
  209. })();
  210. </script>
  211. <script type="module" src="/src/main.js"></script>
  212. </body>
  213. </html>