|
|
@@ -1,78 +1,86 @@
|
|
|
<template>
|
|
|
- <div class="page">
|
|
|
- <div class="bg"></div>
|
|
|
- <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="header-deco"></div>
|
|
|
- <!-- <div class="top-title">智慧交通信号控制管理平台</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>
|
|
|
+ <LoginLayout >
|
|
|
+
|
|
|
+ <!-- 背景 -->
|
|
|
+ <template #background>
|
|
|
+ <div class="login-bg"></div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <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>
|
|
|
-
|
|
|
- <!-- 右侧登录面板 -->
|
|
|
- <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 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 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">
|
|
|
- <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>
|
|
|
+
|
|
|
+ <!-- 右侧登录面板 -->
|
|
|
+ <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>
|
|
|
- <CaptchaCanvas v-model="captchaCode" />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="hint" v-if="hint">{{ hint }}</div>
|
|
|
- <button class="btn" @click="onLogin">立即登录</button>
|
|
|
-
|
|
|
- </div>
|
|
|
- </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">
|
|
|
+ <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>
|
|
|
+ </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>
|
|
|
+ </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>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ </LoginLayout>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import CaptchaCanvas from "@/components/CaptchaCanvas.vue";
|
|
|
+import LoginLayout from "@/layouts/LoginLayout.vue";
|
|
|
import { mockLogin } from "@/mock/api";
|
|
|
-import Toast from "@/plugins/toast";
|
|
|
|
|
|
export default {
|
|
|
- // eslint-disable-next-line vue/multi-word-component-names
|
|
|
- name: "Login",
|
|
|
- components: { CaptchaCanvas },
|
|
|
+ name: "LoginPage",
|
|
|
+ components: { CaptchaCanvas, LoginLayout },
|
|
|
created() {
|
|
|
// 提前预加载 Cesium 瓦片
|
|
|
import('@/utils/cesiumPreloader').then(m => m.default.start());
|
|
|
@@ -143,6 +151,12 @@ export default {
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
+.login-bg {
|
|
|
+ background: url('@/assets/images/login-background.png') no-repeat center/cover;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
.page{
|
|
|
width: 100vw; height: 100vh;
|
|
|
position: relative;
|
|
|
@@ -150,38 +164,6 @@ export default {
|
|
|
--s: 1;
|
|
|
}
|
|
|
|
|
|
-.bg{
|
|
|
- position:absolute;
|
|
|
- inset:0;
|
|
|
- background: url("~@/assets/ai_bg.png") center/cover no-repeat;
|
|
|
- filter: saturate(1.05);
|
|
|
- z-index: 0;
|
|
|
-}
|
|
|
-
|
|
|
-.header-deco{
|
|
|
- position:absolute;
|
|
|
- top: 0; left: 0; right: 0;
|
|
|
- height: calc(var(--s) * 86px);
|
|
|
- background: url("~@/assets/header_deco1.png") center/cover no-repeat;
|
|
|
- pointer-events:none;
|
|
|
- opacity: 0.95;
|
|
|
- z-index: 2;
|
|
|
-}
|
|
|
-
|
|
|
-.top-title{
|
|
|
- position:absolute;
|
|
|
- top: calc(var(--s) * 20px);
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- font-size: calc(var(--s) * 24px);
|
|
|
- letter-spacing: calc(var(--s) * 3px);
|
|
|
- font-weight: 700;
|
|
|
- color: #e6f6ff;
|
|
|
- text-shadow: 0 0 calc(var(--s) * 12px) rgba(80,200,255,0.45);
|
|
|
- pointer-events:none;
|
|
|
- z-index: 3; /* 关键:必须压过 content */
|
|
|
-}
|
|
|
-
|
|
|
.content{
|
|
|
position:absolute;
|
|
|
inset: 0;
|
|
|
@@ -257,10 +239,10 @@ export default {
|
|
|
|
|
|
/* 按你给的比例调过 */
|
|
|
|
|
|
-.icon-1{ left: 16.8%; top: 81%; } /* 盾牌 */
|
|
|
-.icon-2{ left: 41.5%; top: 78%; } /* 人像 */
|
|
|
-.icon-3{ left: 61.5%;top: 68.5%;} /* 中间图标 */
|
|
|
-.icon-4{ left: 80.5%; top: 52%;} /* 齿轮 */
|
|
|
+.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%;} /* 齿轮 */
|
|
|
|
|
|
|
|
|
/* 单独给每个球不同浮动幅度(可选,效果更高级) */
|
|
|
@@ -444,7 +426,7 @@ export default {
|
|
|
z-index: 1; /* 在 bg(0) 上面,但不压住 header/title 可再调 */
|
|
|
|
|
|
/* ✅必须和 .bg 使用同一张图 + 同样的 size/position,才能精确对齐 */
|
|
|
- background-image: url('~@/assets/ai_bg.png'); /* ← 改成你真实路径 */
|
|
|
+ background-image: url('~@/assets/images/login-background.png'); /* ← 改成你真实路径 */
|
|
|
background-repeat: no-repeat;
|
|
|
background-size: cover;
|
|
|
background-position: center center;
|
|
|
@@ -507,7 +489,7 @@ export default {
|
|
|
position: absolute;
|
|
|
inset: 0;
|
|
|
|
|
|
- background: url("~@/assets/ai_bg.png") center/cover no-repeat; /* 跟 .bg 完全一致 */
|
|
|
+ background: url("~@/assets/images/login-background.png") center/cover no-repeat; /* 跟 .bg 完全一致 */
|
|
|
filter: brightness(1.03) contrast(1.04);
|
|
|
will-change: transform;
|
|
|
}
|
|
|
@@ -603,34 +585,15 @@ export default {
|
|
|
.copyright {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
+ flex-direction: column;
|
|
|
font-size: 18px;
|
|
|
color: #FFF;
|
|
|
line-height: 30px;
|
|
|
text-align: center;
|
|
|
position: absolute;
|
|
|
bottom: 20px;
|
|
|
- left: calc(50% - 35px);
|
|
|
-}
|
|
|
-
|
|
|
-.copyright::before,
|
|
|
-.copyright::after {
|
|
|
- content: "";
|
|
|
- display: block;
|
|
|
- width: 4px;
|
|
|
- height: 4px;
|
|
|
- border-radius: 2px;
|
|
|
- background: #e7e7e7;
|
|
|
-}
|
|
|
-
|
|
|
-.copyright::before {
|
|
|
- margin-right: 10px;
|
|
|
-}
|
|
|
-
|
|
|
-.copyright::after {
|
|
|
- margin-left: 10px;
|
|
|
-}
|
|
|
-.copyright-logo {
|
|
|
- width: 212.52px;
|
|
|
- height: 43.5px;
|
|
|
+ left: 0;
|
|
|
+ justify-content: center;
|
|
|
+ width: 100%;
|
|
|
}
|
|
|
</style>
|