Pārlūkot izejas kodu

新增登录表单组件;修改登录页面的布局和背景图片

画安 1 mēnesi atpakaļ
vecāks
revīzija
8ea956c815
3 mainītis faili ar 284 papildinājumiem un 525 dzēšanām
  1. BIN
      src/assets/images/login-background.png
  2. 247 0
      src/components/ui/LoginForm.vue
  3. 37 525
      src/views/Login.vue

BIN
src/assets/images/login-background.png


+ 247 - 0
src/components/ui/LoginForm.vue

@@ -0,0 +1,247 @@
+<template>
+    <div class="panel">
+        <div class="panel-inner">
+            <div class="panel-title">账号登录</div>
+
+            <div class="field">
+                <img class="i" :src="require('@/assets/i_user.png')" />
+                <span class="field-label">账号</span>
+                <input class="inp" v-model.trim="username" placeholder="请输入账号" />
+            </div>
+
+            <div class="field">
+                <img class="i" :src="require('@/assets/i_lock.png')" />
+                <span class="field-label">密码</span>
+                <input class="inp" type="password" v-model.trim="password" placeholder="请输入密码" />
+            </div>
+
+            <div class="row" v-if="showCaptcha">
+                <div class="field cap-field">
+                    <img class="i" :src="require('@/assets/i_captcha.png')" />
+                    <span class="field-label">验证码</span>
+                    <input class="inp" v-model.trim="captchaInput" placeholder="请输入验证码" />
+                </div>
+                <CaptchaCanvas class="captcha-img" v-model="captchaCode" />
+            </div>
+
+            <div class="hint" v-if="hint">{{ hint }}</div>
+            <button class="btn" @click="onLogin">立即登录</button>
+        </div>
+    </div>
+</template>
+
+<script>
+import CaptchaCanvas from "@/components/CaptchaCanvas.vue";
+import { apiLogin } from "@/api";
+
+export default {
+    name: "LoginForm",
+    components: { CaptchaCanvas },
+    data() {
+        return {
+            username: "admin",
+            password: "123456",
+            captchaCode: "",
+            captchaInput: "",
+            hint: "",
+            loginFailedCount: Number(sessionStorage.getItem("loginFailedCount")) || 0,
+        };
+    },
+    computed: {
+        showCaptcha() {
+            return this.loginFailedCount >= 3;
+        },
+    },
+    methods: {
+        async onLogin() { console.log('do login')
+            this.hint = "";
+
+            if (this.showCaptcha) {
+                if (!this.captchaInput) {
+                    this.hint = "请输入验证码";
+                    return;
+                }
+                if (this.captchaInput.toLowerCase() !== this.captchaCode.toLowerCase()) {
+                    this.hint = "验证码错误";
+                    this.captchaInput = "";
+                    return;
+                }
+            }
+
+            let data;
+            try {
+                data = await apiLogin({
+                    username: this.username,
+                    password: this.password,
+                    captcha: this.captchaInput,
+                });
+
+                this.loginFailedCount = 0;
+                sessionStorage.removeItem("loginFailedCount");
+
+                this.$router.push("/transition");
+            } catch (e) {
+                this.hint = e.message || "登录失败";
+                this.loginFailedCount++;
+                sessionStorage.setItem("loginFailedCount", this.loginFailedCount);
+                this.captchaInput = "";
+                return;
+            }
+
+            localStorage.setItem("token", data.token);
+            this.$emit("login-success");
+        },
+    },
+};
+</script>
+
+<style scoped>
+/* ================== 表单主面板 ================== */
+.panel {
+    /* 严格按照设计稿尺寸 */
+    width: 637px;
+    height: 514px;
+    /* 调整内边距,给背景外框留出空间并让内容居中 */
+    padding: 60px 75px;
+    box-sizing: border-box;
+
+    background: url("~@/assets/panel_frame.png") center/100% 100% no-repeat;
+
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+
+    transform: scale(var(--s, 1));
+    /* 将缩放基准点设为右侧垂直居中。这样缩小的时候,表单会贴着右侧边距变小,不会往屏幕中间飘 */
+    transform-origin: right center;
+}
+
+.panel-inner {
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+/* ================== 标题 ================== */
+.panel-title {
+    font-size: 28px;
+    /* 根据大面板放大标题 */
+    color: #ffffff;
+    margin-bottom: 35px;
+    font-weight: 600;
+    text-align: left;
+    letter-spacing: 2px;
+}
+
+/* ================== 输入框容器 ================== */
+.field {
+    width: 100%;
+    height: 58px;
+    /* 加高输入框以匹配大面板 */
+    display: flex;
+    align-items: center;
+    padding: 0 20px;
+
+    background: rgba(26, 117, 255, 0.12);
+    border-radius: 6px;
+    border: 1px solid rgba(71, 120, 255, 0.35);
+    margin-bottom: 26px;
+    /* 加大行距 */
+
+    position: relative;
+    transition: all 0.25s ease;
+    box-sizing: border-box;
+}
+
+.field:focus-within {
+    border-color: rgba(90, 220, 255, 0.95);
+    background: rgba(26, 117, 255, 0.22);
+    box-shadow:
+        0 0 14px rgba(43, 220, 255, 0.25),
+        inset 0 0 10px rgba(120, 220, 255, 0.15);
+}
+
+/* ================== 输入框内部元素 ================== */
+.field .i {
+    width: 22px;
+    height: 22px;
+    object-fit: contain;
+    opacity: 0.9;
+}
+
+.field-label {
+    color: rgba(220, 245, 255, 0.9);
+    font-size: 16px;
+    margin-left: 12px;
+    margin-right: 20px;
+    white-space: nowrap;
+}
+
+.inp {
+    flex: 1;
+    height: 100%;
+    border: none;
+    outline: none;
+    background: transparent;
+    color: #ffffff;
+    font-size: 16px;
+}
+
+.inp::placeholder {
+    color: rgba(190, 225, 255, 0.35);
+    font-size: 15px;
+}
+
+/* ================== 验证码同行布局 ================== */
+.row {
+    width: 100%;
+    display: flex;
+    gap: 16px;
+    margin-bottom: 26px;
+}
+
+.cap-field {
+    flex: 1;
+    margin-bottom: 0;
+}
+
+.captcha-img {
+    width: 140px;
+    /* 放大的验证码图片宽度 */
+    height: 58px;
+    /* 与输入框等高 */
+    border-radius: 6px;
+    overflow: hidden;
+    border: 1px solid rgba(71, 120, 255, 0.35);
+}
+
+/* ================== 登录按钮 ================== */
+.btn {
+    width: 100%;
+    height: 58px;
+    margin-top: 10px;
+    color: #ffffff;
+    font-size: 26px;
+    letter-spacing: 4px;
+    cursor: pointer;
+    font-family: var(--title-font-family);
+    background: linear-gradient(180deg, rgba(119, 161, 255, 0) 0%, #77A1FF 100%);
+    border-radius: 8px;
+    border: 1px solid rgba(161, 190, 255, 0.7);
+    box-shadow: 0 4px 15px rgba(26, 117, 255, 0.3);
+    transition: all 0.2s ease;
+}
+
+.btn:hover {
+    filter: brightness(1.15);
+    box-shadow: 0 4px 20px rgba(26, 117, 255, 0.5);
+}
+
+/* ================== 提示文字 ================== */
+.hint {
+    margin-top: -10px;
+    margin-bottom: 15px;
+    color: #ff4d4f;
+    font-size: 14px;
+}
+</style>

+ 37 - 525
src/views/Login.vue

@@ -8,61 +8,20 @@
 
     <template #main>
       <div class="page">
-        <div class="ai-cloud-ring" aria-hidden="true"></div>
-        <div class="split-door" :class="{ opening: isDoorOpening }" aria-hidden="true">
-          <div class="door left"></div>
-          <div class="door right" @animationend="handleDoorEnd"></div>
-        </div>
         <div class="content">
           <!-- 左侧酷炫区域 -->
           <div class="left">
-            <div class="ellipse-area">
-              <img class="ellipse" :src="require('@/assets/ellipse-line.png')" alt="ellipse" />
-              <!-- 沿椭圆的流光:不旋转椭圆图,只做覆盖层沿线跑动 -->
-              <div class="ellipse-glow"></div>
-              <div class="icon icon-1"><img :src="require('@/assets/icon-upload.png')" width="87px" height="87px" /></div>
-              <div class="icon icon-2"><img :src="require('@/assets/icon-webcam.png')" width="87px" height="87px" /></div>
-              <div class="icon icon-3"><img :src="require('@/assets/icon-shield.png')" width="87px" height="87px" /></div>
-              <div class="icon icon-4"><img :src="require('@/assets/icon-setting.png')" width="87px" height="87px" /></div>
-            </div>
+            
           </div>
     
           <!-- 右侧登录面板 -->
           <div class="right">
-            <div class="panel">
-                <div class="panel-inner">
-                
-                <div class="panel-title">账号登录</div>
-    
-                <div class="field">
-                    <img class="i" :src="require('@/assets/i_user.png')" />
-                    <span class="field-label">账号</span>
-                    <input class="inp" v-model.trim="username" placeholder="请输入账号" />
-                </div>
-    
-                <div class="field">
-                    <img class="i" :src="require('@/assets/i_lock.png')" />
-                    <span class="field-label">密码</span>
-                    <input class="inp" type="password" v-model.trim="password" placeholder="请输入密码" />
-                </div>
-    
-                <div class="row" v-if="showCaptcha">
-                    <div class="field cap-field">
-                    <img class="i" :src="require('@/assets/i_captcha.png')" />
-                    <span class="field-label">验证码</span>
-                    <input class="inp" v-model.trim="captchaInput" placeholder="请输入验证码" />
-                    </div>
-                    <CaptchaCanvas v-model="captchaCode" />
-                </div>
-                
-                <div class="hint" v-if="hint">{{ hint }}</div>
-                <button class="btn" @click="onLogin">立即登录</button>
-    
-                </div>
-             </div>
+            <div class="login-container">
+              <LoginForm></LoginForm>
+            </div>
           </div>
         </div>
-        <div class="page-dim" :class="{ opening: isDoorOpening }" aria-hidden="true"></div>
+
         <div class="copyright">
           <img class="copyright-logo" :src="require('@/assets/images/logo.png')" />
           <div>北京东土正创科技有限公司</div>
@@ -74,110 +33,37 @@
 </template>
 
 <script>
-import CaptchaCanvas from "@/components/CaptchaCanvas.vue";
 import LoginLayout from "@/layouts/LoginLayout.vue";
-import { apiLogin, apiGetCaptcha } from "@/api";
+import LoginForm from "@/components/ui/LoginForm.vue";
 
 export default {
   name: "LoginPage",
-  components: { CaptchaCanvas, LoginLayout },
+  components: { 
+    LoginLayout,
+    LoginForm
+  },
   created() {
     // 提前预加载 Cesium 瓦片
     import('@/utils/cesiumPreloader').then(m => m.default.start());
   },
   data() {
     return {
-      baseW: 1920,
-      baseH: 1080,
-      scale: 1,
-      username: "admin",
-      password: "123456",
-      captchaCode: "",
-      captchaInput: "",
-      hint: "",
-      isDoorOpening: false,
-      doorNavigated: false,
-      loginFailedCount: Number(sessionStorage.getItem('loginFailedCount')) || 0,
+      
     };
   },
   computed: {
-    showCaptcha() {
-      return this.loginFailedCount >= 3;
-    }
+    
   },
   mounted() {
-    this.updateScale();
-    window.addEventListener('resize', this.updateScale, { passive: true });
+    
   },
   beforeDestroy() {
-    window.removeEventListener('resize', this.updateScale);
+    
   },
 
   methods: {
-    updateScale() {
-      const w = window.innerWidth || this.baseW;
-      const h = window.innerHeight || this.baseH;
-      const s = Math.min(w / this.baseW, h / this.baseH);
-      this.scale = s;
-      this.$el && this.$el.style.setProperty('--s', s.toFixed(6));
-    },
-    async onLogin() {
-      this.hint = "";
-
-      // 如果验证码已显示,则进行前端拦截与校验
-      if (this.showCaptcha) {
-        if (!this.captchaInput) {
-          this.hint = "请输入验证码";
-          return;
-        }
-        // 前端比对验证码 (忽略大小写)
-        if (this.captchaInput.toLowerCase() !== this.captchaCode.toLowerCase()) {
-          this.hint = "验证码错误";
-          this.captchaInput = ""; // 验证码错误后清空输入框
-          return;
-        }
-      }
-
-      let data;
-      try {
-        data = await apiLogin({
-          username: this.username,
-          password: this.password,
-          captcha: this.captchaInput
-        });
-
-        // 登录成功,重置次数并清空缓存
-        this.loginFailedCount = 0; 
-        sessionStorage.removeItem('loginFailedCount');
-      } catch (e) {
-        this.hint = e.message || '登录失败';
-        // 登录失败,次数 +1 并存入缓存
-        this.loginFailedCount++; 
-        sessionStorage.setItem('loginFailedCount', this.loginFailedCount);
-        this.captchaInput = "";
-        
-        return;
-      }
-
-      localStorage.setItem('token', data.token);
-
-
-      this.doorNavigated = false;
-      this.isDoorOpening = false;
-      this.$nextTick(() => {
-        this.isDoorOpening = true;
-        setTimeout(() => {
-          if (this.doorNavigated) return;
-          this.doorNavigated = true;
-          this.$router.push("/transition");
-        }, 1000);
-      });
-    },
-    handleDoorEnd() {
-      if (!this.isDoorOpening || this.doorNavigated) return;
-      this.doorNavigated = true;
-      this.$router.push("/transition");
-    },
+    
+    
   }
 };
 </script>
@@ -187,6 +73,27 @@ export default {
   background: url('@/assets/images/login-background.png') no-repeat center/cover;
   width: 100%;
   height: 100%;
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+.login-container {
+  /* * 【自适应魔法】:计算当前屏幕与 1920 宽度的比例。
+   * clamp(最小缩放比例, 动态计算比例, 最大缩放比例)
+   * 当屏幕小于 1920 时,--s 会小于 1;当屏幕等于 1920 时,--s 为 1。
+   */
+  --s: clamp(0.5, 100vw / 1920, 1.2);
+
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;        
+  justify-content: flex-end;  
+  
+  /* 右侧边距也用 clamp 做动态响应:最小 20px,推荐 8vw,最大 150px */
+  padding-right: clamp(20px, 8vw, 150px); 
+  box-sizing: border-box;
+  pointer-events: auto;       
 }
 
 .page{
@@ -210,408 +117,13 @@ export default {
 
 /* 左侧 */
 .left{ min-width: 0; }
-.ellipse-area{
-  position: relative;
-  width: 65vw;          
-  max-width: calc(var(--s) * 1150px);
-  height: 70vh;
-}
 
-.ellipse{
-    position: absolute;
-    left: 0;
-    top: 20%;
-    width: 88%;
-    height: auto;
-    opacity: 0.75;
-}
-
-.ellipse-glow{
-  position:absolute;
-  left: 0;
-  top: 14%;
-  width: 92%;
-  height: 60%;
-  pointer-events:none;
-
-  -webkit-mask: url("~@/assets/ellipse-line.png") center/contain no-repeat;
-  mask: url("~@/assets/ellipse-line.png") center/contain no-repeat;
-
-  background: linear-gradient(
-    90deg,
-    rgba(0,0,0,0) 0%,
-    rgba(70,220,255,0) 40%,
-    rgba(70,220,255,0.85) 50%,
-    rgba(70,220,255,0) 60%,
-    rgba(0,0,0,0) 100%
-  );
-  background-size: 200% 100%;
-  animation: ellipse-flow 2.2s linear infinite;
-  filter: drop-shadow(0 0 calc(var(--s) * 10px) rgba(43,220,255,0.18));
-}
-
-@keyframes ellipse-flow{
-  0%{ background-position: 0% 0%; }
-  100%{ background-position: 200% 0%; }
-}
-
-.icon{
-  position:absolute;
-  width: clamp(calc(var(--s) * 54px), 4.5vw, calc(var(--s) * 78px));
-  height: clamp(calc(var(--s) * 54px), 4.5vw, calc(var(--s) * 78px));
-  border-radius: 50%;
-  /* background: radial-gradient(circle at 30% 30%, rgba(120,220,255,0.4), rgba(10,35,80,0.4)); */
-  border: calc(var(--s) * 1px) solid rgba(60,180,255,0.35);
-  box-shadow:
-      0 0 calc(var(--s) * 18px) rgba(43,220,255,0.25),
-      inset 0 0 calc(var(--s) * 12px) rgba(120,220,255,0.25);
-  transform: translate(-50%, -50%);
-  animation: icon-float 3s ease-in-out infinite;
-}
-
-/* 按你给的比例调过 */
-
-.icon-1{ left: 16.8%; top: 87%; }   /* 盾牌 */
-.icon-2{ left: 41.5%; top: 84%; }   /* 人像 */
-.icon-3{ left: 61.5%;top: 73%;} /* 中间图标 */
-.icon-4{ left: 80.5%; top: 56%;}   /* 齿轮 */
-
-
-/* 单独给每个球不同浮动幅度(可选,效果更高级) */
-.icon-1{ --dy: calc(var(--s) * 7px); }
-.icon-2{ --dy: calc(var(--s) * 9px); }
-.icon-3{ --dy: calc(var(--s) * 8px); }
-.icon-4{ --dy: calc(var(--s) * 6px); }
-
-@keyframes icon-float{
-  0%,100%{ transform: translate(-50%,-50%) translateY(0); }
-  50%{ transform: translate(-50%,-50%) translateY(calc(var(--dy, calc(var(--s) * 8px)) * -1)); }
-}
-.icon-1{ animation-duration: 3.2s; animation-delay: -0.2s; }
-.icon-2{ animation-duration: 3.8s; animation-delay: -1.1s; }
-.icon-3{ animation-duration: 3.4s; animation-delay: -2.0s; }
-.icon-4{ animation-duration: 4.2s; animation-delay: -2.7s; }
-
-.icon{
-  animation-name: icon-float, icon-glow;
-  animation-timing-function: ease-in-out, ease-in-out;
-  animation-iteration-count: infinite, infinite;
-}
-
-.icon-1{ animation-duration: 3.2s, 2.6s; animation-delay: -0.2s, -0.8s; }
-.icon-2{ animation-duration: 3.8s, 3.1s; animation-delay: -1.1s, -1.4s; }
-.icon-3{ animation-duration: 3.4s, 2.8s; animation-delay: -2.0s, -2.2s; }
-.icon-4{ animation-duration: 4.2s, 3.5s; animation-delay: -2.7s, -3.0s; }
-
-@keyframes icon-glow{
-  0%,100%{ filter: drop-shadow(0 0 calc(var(--s) * 8px) rgba(43,220,255,0.16)); }
-  50%{ filter: drop-shadow(0 0 calc(var(--s) * 16px) rgba(43,220,255,0.36)); }
-}
 /* 右侧面板 */
 .right{
   min-width: 0;
   display:flex;
   justify-content:center;
 }
-.panel{
-  width: min(calc(var(--s) * 680px), 30vw);
-  aspect-ratio: 900 / 680;
-  position: relative;
-  background: url("~@/assets/panel_frame.png") center/100% 100% no-repeat;
-  display:flex;
-  justify-content:center;
-  align-items:center;
-}
-
-/* 用绝对比例控制内容区域 */
-.panel-inner{
-  width: 88%;          /* 输入框主宽度比例 */
-  display:flex;
-  flex-direction:column;
-  align-items:center;
-}
-.panel-title{
-  width: 85%;
-  font-size: var(--fs-title);
-  color: rgba(220,250,255,0.92);
-  margin-bottom: calc(var(--s) * 30px);
-  font-weight: 600;
-}
-.field{
-  width: 85%;
-  height: calc(var(--s) * 54px);
-  display:flex;
-  align-items:center;
-  gap: calc(var(--s) * 10px);
-  padding: 0 calc(var(--s) * 16px);
-  background: linear-gradient(270deg, rgba(26,117,255,0.11) 0%, rgba(71,120,255,0.07) 100%);
-  border-radius: calc(var(--s) * 8px);
-  border: calc(var(--s) * 1px) solid #3D72B8;
-  margin-bottom: calc(var(--s) * 18px);
-}
-
-.field{
-  position: relative;
-  transition: box-shadow .22s ease, border-color .22s ease, background .22s ease;
-}
-
-.field:focus-within{
-  border-color: rgba(90, 220, 255, 0.95);
-  background: linear-gradient(270deg, rgba(26,117,255,0.16) 0%, rgba(71,120,255,0.10) 100%);
-  box-shadow:
-    0 0 0 calc(var(--s) * 1px) rgba(110, 230, 255, 0.55),
-    0 0 calc(var(--s) * 18px) rgba(43,220,255,0.28),
-    inset 0 0 calc(var(--s) * 14px) rgba(120,220,255,0.18);
-}
-
-/* 可选:让左侧小图标也略微被点亮 */
-.field:focus-within .i{
-  opacity: 1;
-  filter: drop-shadow(0 0 calc(var(--s) * 8px) rgba(43,220,255,0.35));
-}
-
-
-.field-label{
-  flex: 0 0 calc(var(--s) * 44px);          /* “账号/密码/验证码”宽度固定 */
-  color: rgba(220,245,255,0.75);
-  font-size: calc(var(--s) * 13px);
-  letter-spacing: calc(var(--s) * 1px);
-  margin-right: calc(var(--s) * 5px);
-  user-select: none;
-}
-/* 关键:等比、居中、不拉伸 */
-.field .i{
-  width: calc(var(--s) * 20px);
-  height: calc(var(--s) * 20px);
-  flex: 0 0 calc(var(--s) * 20px);
-  object-fit: contain;
-  opacity: 0.92;
-}
-
-.inp{
-  flex:1;
-  height: 100%;
-  border: none;
-  outline: none;
-  background: transparent;
-  color: rgba(235,255,255,0.92);
-  font-size: calc(var(--s) * 14px);
-}
-
-.inp::placeholder{
-  color: rgba(190,225,255,0.55);
-}
-
-.row{
-  width:85%;
-  display:flex;
-  gap: calc(var(--s) * 14px);
-  margin-bottom: calc(var(--s) * 10px);
-}
-
-.cap-field{
-  flex: 0 0 61.13%;
-}
-
-.captcha{
-  flex: 1;
-}
-
-.btn{
-  width: 85%;
-  height: calc(var(--s) * 54px);
-  border: none;
-  border-radius: calc(var(--s) * 8px);
-  color: rgba(235,255,255,0.95);
-  font-size: var(--fs-base);
-  font-weight: 600;
-  cursor: pointer;
-  background: linear-gradient( 180deg, rgba(119,161,255,0) 0%, #77A1FF 100%);
-  border-radius: calc(var(--s) * 8px);
-  border: calc(var(--s) * 1px) solid rgba(161,190,255,0.7);
-}
-.btn:hover{ filter: brightness(1.08); }
-
-.hint{
-  margin-top: calc(var(--s) * 12px);
-  margin-bottom: calc(var(--s) * 12px);
-  color: rgba(255, 0, 0, 0.92);
-  font-size: var(--fs-base);
-  width: 85%;
-  text-align: left;
-}
-
-/* 响应式重排:窄屏时上下布局 */
-@media (max-width: calc(var(--s) * 980px)){
-  .content{
-    grid-template-columns: 1fr;
-    padding: calc(var(--s) * 18px);
-    align-items: start;
-  }
-  .ellipse-area{ width: 100%; height: 46vh; }
-  .right{ justify-content: flex-start; }
-}
-.ai-cloud-ring{
-  position: absolute;
-  inset: 0;
-  pointer-events: none;
-  z-index: 1; /* 在 bg(0) 上面,但不压住 header/title 可再调 */
-  
-  /* ✅必须和 .bg 使用同一张图 + 同样的 size/position,才能精确对齐 */
-  background-image: url('~@/assets/images/login-background.png'); /* ← 改成你真实路径 */
-  background-repeat: no-repeat;
-  background-size: cover;
-  background-position: center center;
-
-  /* === 你只需要调这三个:云彩环的中心点与半径 === */
-  --cx: 27%;   /* 云彩环中心 x(大概在左侧 1/4) */
-  --cy: 58%;   /* 云彩环中心 y(大概在中下) */
-  --r1: calc(var(--s) * 145px); /* 内圈挖空半径(越大,AI 字越干净) */
-  --r2: calc(var(--s) * 188px); /* 云彩环最亮区域半径 */
-  --r3: calc(var(--s) * 288px); /* 外圈渐隐半径(越大,环越厚/越散) */
-
-  /* ✅只保留“环形”区域:透明(内) -> 显示(环) -> 透明(外) */
-  -webkit-mask-image: radial-gradient(circle at var(--cx) var(--cy),
-      rgba(0,0,0,0) var(--r1),
-      rgba(0,0,0,1) var(--r2),
-      rgba(0,0,0,0) var(--r3)
-  );
-  mask-image: radial-gradient(circle at var(--cx) var(--cy),
-      rgba(0,0,0,0) var(--r1),
-      rgba(0,0,0,1) var(--r2),
-      rgba(0,0,0,0) var(--r3)
-  );
-
-  /* ✅增强可见度(科技蓝) */
-  mix-blend-mode: lighten;
-  filter: drop-shadow(0 0 calc(var(--s) * 40px) rgba(60,220,255,.55)) drop-shadow(0 0 calc(var(--s) * 110px) rgba(60,220,255,.25));
-
-  /* ✅慢旋转 + 呼吸淡入淡出 */
-  opacity: .35;
-  transform-origin: var(--cx) var(--cy);
-  animation: cloud-rotate 180s linear infinite, cloud-breathe 7.8s ease-in-out infinite;
-}
-
-@keyframes cloud-rotate{
-  from{ transform: rotate(0deg); }
-  to{ transform: rotate(360deg); }
-}
-
-@keyframes cloud-breathe{
-  0%{ opacity: .18; filter: drop-shadow(0 0 calc(var(--s) * 22px) rgba(60,220,255,.35)) drop-shadow(0 0 calc(var(--s) * 70px) rgba(60,220,255,.18)); }
-  50%{ opacity: .55; filter: drop-shadow(0 0 calc(var(--s) * 55px) rgba(60,220,255,.70)) drop-shadow(0 0 calc(var(--s) * 140px) rgba(60,220,255,.35)); }
-  100%{ opacity: .22; filter: drop-shadow(0 0 calc(var(--s) * 28px) rgba(60,220,255,.40)) drop-shadow(0 0 calc(var(--s) * 85px) rgba(60,220,255,.20)); }
-}
-
-/* 开门层:覆盖在 bg 上方(z-index 0),不挡 content(content 是 1) */
-.split-door{
-  position: absolute;
-  inset: 0;
-  z-index: 0;
-  pointer-events: none;
-  opacity: 1; 
-  perspective: calc(var(--s) * 1200px);
-}
-.door{
-  transform-origin: center;
-  backface-visibility: hidden;
-}
-/* 两扇门:都用全屏做 cover,再裁半屏(关键:避免中间断裂) */
-.split-door .door{
-  position: absolute;
-  inset: 0;
-
-  background: url("~@/assets/images/login-background.png") center/cover no-repeat; /* 跟 .bg 完全一致 */
-  filter: brightness(1.03) contrast(1.04);
-  will-change: transform;
-}
-
-/* 左半屏 */
-.split-door .door.left{
-  clip-path: inset(0 50% 0 0);
-}
-
-/* 右半屏 */
-.split-door .door.right{
-  clip-path: inset(0 0 0 50%);
-}
-
-/* 开门动作更慢更清晰 */
-.split-door.opening .door.left{
-  animation: door-left 1.5s cubic-bezier(.18,.85,.22,1) forwards;
-}
-.split-door.opening .door.right{
-  animation: door-right 1.5s cubic-bezier(.18,.85,.22,1) forwards;
-}
-.split-door.opening .door.left,
-.split-door.opening .door.right{
-  animation-delay: .12s;
-}
-/* 中间能量缝(升级:更亮、更柔) */
-.split-door::after{
-  content:"";
-  position:absolute;
-  left:50%;
-  top:0;
-  width:calc(var(--s) * 2px);
-  height:100%;
-  transform: translateX(-50%);
-  opacity: 0;
-
-  background: linear-gradient(to bottom,
-    rgba(0,0,0,0),
-    rgba(120,240,255,0.95),
-    rgba(0,0,0,0)
-  );
-  filter: drop-shadow(0 0 calc(var(--s) * 18px) rgba(60,220,255,.85))
-          drop-shadow(0 0 calc(var(--s) * 55px) rgba(60,220,255,.35));
-}
-
-.split-door.opening::after{
-  opacity: 1;
-  animation: seam-fade 0.95s ease forwards;
-}
-
-/* 可选:开门瞬间整体轻微“相机拉近”(更高级) */
-.split-door.opening{
-  animation: camera-zoom 0.95s ease forwards;
-}
-
-@keyframes door-left{
-  from{ transform: translateX(0) skewY(0deg); }
-  to  { transform: translateX(-54vw) skewY(-0.6deg); }
-}
-
-@keyframes door-right{
-  from{ transform: translateX(0) skewY(0deg); }
-  to  { transform: translateX(54vw) skewY(0.6deg); }
-}
-
-@keyframes seam-fade{
-  from{ opacity: 1; }
-  to  { opacity: 0; }
-}
-
-@keyframes camera-zoom{
-  from{ transform: scale(1); }
-  to  { transform: scale(1.015); }
-}
-.page-dim{
-  position: absolute;
-  inset: 0;
-  pointer-events: none;
-  z-index: 999;
-  background: #000;
-  opacity: 0;
-}
-/* 开门时整体渐黑 */
-.page-dim.opening{
-  animation: page-dim-in 1s ease forwards;
-}
-@keyframes page-dim-in{
-  from{ opacity: 0; }
-  to{ opacity: 0.95; } /* 想更暗就 0.95 */
-}
 
 /* 版权信息 */
 .copyright {