|
|
|
@ -1,188 +1,728 @@
|
|
|
|
<template>
|
|
|
|
<template>
|
|
|
|
<div class="login" v-loading="loadpage">
|
|
|
|
<div class="login" v-loading="loadpage">
|
|
|
|
<div class="login-main">
|
|
|
|
<div class="login-panel">
|
|
|
|
|
|
|
|
<!-- 左侧品牌区:科技数据看板 -->
|
|
|
|
|
|
|
|
<div class="brand-side">
|
|
|
|
|
|
|
|
<div class="grid-bg"></div>
|
|
|
|
|
|
|
|
<div class="scan-line"></div>
|
|
|
|
|
|
|
|
<div class="brand-deco deco-1"></div>
|
|
|
|
|
|
|
|
<div class="brand-deco deco-2"></div>
|
|
|
|
|
|
|
|
<div class="brand-deco deco-3"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="brand-content">
|
|
|
|
|
|
|
|
<div class="brand-badge anim" :style="{ animationDelay: '0s' }">
|
|
|
|
|
|
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
|
|
|
|
|
|
|
stroke-linecap="round" stroke-linejoin="round">
|
|
|
|
|
|
|
|
<path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z" />
|
|
|
|
|
|
|
|
<path d="M3 6h18" />
|
|
|
|
|
|
|
|
<path d="M16 10a4 4 0 0 1-8 0" />
|
|
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
|
|
<span>电商实训平台</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<h1 class="brand-title anim" :style="{ animationDelay: '0.08s' }">互联网产品<br />开发实训系统</h1>
|
|
|
|
|
|
|
|
<p class="brand-subtitle anim" :style="{ animationDelay: '0.16s' }">从市场需求到产品上线,完整还原电商产品全生命周期</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 实训全流程 -->
|
|
|
|
|
|
|
|
<div class="dash-card anim" :style="{ animationDelay: '0.24s' }">
|
|
|
|
|
|
|
|
<div class="dash-head">
|
|
|
|
|
|
|
|
<span class="live-dot"></span>
|
|
|
|
|
|
|
|
<span class="dash-title">实训全流程</span>
|
|
|
|
|
|
|
|
<span class="dash-tag">5 个阶段</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="flow-row">
|
|
|
|
|
|
|
|
<template v-for="(step, i) in steps" :key="step.name">
|
|
|
|
|
|
|
|
<div class="flow-node" :class="{ active: i === 0 }">
|
|
|
|
|
|
|
|
<span class="node-icon">
|
|
|
|
|
|
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" v-html="step.icon"></svg>
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="node-label">{{ step.name }}</span>
|
|
|
|
|
|
|
|
<span class="node-index">STEP {{ i + 1 }}</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-if="i < steps.length - 1" class="flow-link"></div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="module-grid">
|
|
|
|
|
|
|
|
<div v-for="mod in modules" :key="mod.name" class="module-item">
|
|
|
|
|
|
|
|
<span class="module-icon">
|
|
|
|
|
|
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" v-html="mod.icon"></svg>
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<b>{{ mod.name }}</b>
|
|
|
|
|
|
|
|
<i>{{ mod.desc }}</i>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 右侧表单区 -->
|
|
|
|
|
|
|
|
<div class="form-side">
|
|
|
|
|
|
|
|
<div class="form-wrapper">
|
|
|
|
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
|
|
|
|
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
|
|
|
|
<h3 class="title">电商互联网产品开发实训系统</h3>
|
|
|
|
<h3 class="title">欢迎回来</h3>
|
|
|
|
|
|
|
|
<p class="subtitle">请登录你的账号,继续今天的实训</p>
|
|
|
|
<el-form-item prop="username">
|
|
|
|
<el-form-item prop="username">
|
|
|
|
<el-input v-model="loginForm.username" type="text" size="large" autocomplete="off" placeholder="账号">
|
|
|
|
<el-input v-model="loginForm.username" type="text" size="large" autocomplete="off"
|
|
|
|
<template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
|
|
|
|
placeholder="账号">
|
|
|
|
|
|
|
|
<template #prefix><svg-icon icon-class="user"
|
|
|
|
|
|
|
|
class="el-input__icon input-icon" /></template>
|
|
|
|
</el-input>
|
|
|
|
</el-input>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item prop="password">
|
|
|
|
<el-form-item prop="password">
|
|
|
|
<el-input v-model="loginForm.password" class="password-input" type="password" size="large" autocomplete="new-password" placeholder="密码" @keyup.enter="handleLogin" show-password>
|
|
|
|
<el-input v-model="loginForm.password" class="password-input" type="password" size="large"
|
|
|
|
<template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
|
|
|
|
autocomplete="new-password" placeholder="密码" @keyup.enter="handleLogin" show-password>
|
|
|
|
|
|
|
|
<template #prefix><svg-icon icon-class="password"
|
|
|
|
|
|
|
|
class="el-input__icon input-icon" /></template>
|
|
|
|
</el-input>
|
|
|
|
</el-input>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-checkbox v-model="loginForm.rememberMe" style="margin: 0px 0px 25px 0px">记住密码</el-checkbox>
|
|
|
|
<div class="form-options">
|
|
|
|
|
|
|
|
<el-checkbox v-model="loginForm.rememberMe">记住密码</el-checkbox>
|
|
|
|
|
|
|
|
<router-link v-if="register" class="link-type" :to="'/register'">立即注册</router-link>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<el-form-item style="width: 100%">
|
|
|
|
<el-form-item style="width: 100%">
|
|
|
|
<el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
|
|
|
|
<el-button :loading="loading" size="large" type="primary" class="login-btn"
|
|
|
|
|
|
|
|
@click.prevent="handleLogin">
|
|
|
|
<span v-if="!loading">登 录</span>
|
|
|
|
<span v-if="!loading">登 录</span>
|
|
|
|
<span v-else>登 录 中...</span>
|
|
|
|
<span v-else>登 录 中...</span>
|
|
|
|
</el-button>
|
|
|
|
</el-button>
|
|
|
|
<div style="float: right" v-if="register">
|
|
|
|
|
|
|
|
<router-link class="link-type" :to="'/register'">立即注册</router-link>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
</el-form>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- 底部 -->
|
|
|
|
</div>
|
|
|
|
<div class="el-login-footer" style="display: none">
|
|
|
|
|
|
|
|
<span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
<script setup>
|
|
|
|
import { getCodeImg } from "@/api/login";
|
|
|
|
import { getCodeImg } from "@/api/login"
|
|
|
|
import Cookies from "js-cookie";
|
|
|
|
import Cookies from "js-cookie"
|
|
|
|
import { encrypt, decrypt } from "@/utils/jsencrypt";
|
|
|
|
import { encrypt, decrypt } from "@/utils/jsencrypt"
|
|
|
|
import useUserStore from "@/store/modules/user";
|
|
|
|
import useUserStore from "@/store/modules/user"
|
|
|
|
import { getUserInfo } from "@/utils/auth";
|
|
|
|
import { getUserInfo } from "@/utils/auth"
|
|
|
|
const userStore = useUserStore();
|
|
|
|
const userStore = useUserStore()
|
|
|
|
const route = useRoute();
|
|
|
|
const route = useRoute()
|
|
|
|
const router = useRouter();
|
|
|
|
const router = useRouter()
|
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
|
const { proxy } = getCurrentInstance()
|
|
|
|
|
|
|
|
|
|
|
|
const loginForm = ref({
|
|
|
|
const loginForm = ref({
|
|
|
|
username: "",
|
|
|
|
username: "",
|
|
|
|
password: "",
|
|
|
|
password: "",
|
|
|
|
rememberMe: false,
|
|
|
|
rememberMe: false,
|
|
|
|
TOKEN: "",
|
|
|
|
TOKEN: "",
|
|
|
|
});
|
|
|
|
})
|
|
|
|
const loginRules = {
|
|
|
|
const loginRules = {
|
|
|
|
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
|
|
|
|
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
|
|
|
|
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
|
|
|
|
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
|
|
|
|
code: [{ required: true, trigger: "change", message: "请输入验证码" }],
|
|
|
|
code: [{ required: true, trigger: "change", message: "请输入验证码" }],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const loading = ref(false);
|
|
|
|
const loading = ref(false)
|
|
|
|
const loadpage = ref(false);
|
|
|
|
const loadpage = ref(false)
|
|
|
|
// 验证码开关
|
|
|
|
// 验证码开关
|
|
|
|
const captchaEnabled = ref(true);
|
|
|
|
const captchaEnabled = ref(true)
|
|
|
|
// 注册开关
|
|
|
|
// 注册开关
|
|
|
|
const register = ref(false);
|
|
|
|
const register = ref(false)
|
|
|
|
const redirect = ref(undefined);
|
|
|
|
const redirect = ref(undefined)
|
|
|
|
watch(
|
|
|
|
watch(
|
|
|
|
route,
|
|
|
|
route,
|
|
|
|
(newRoute) => {
|
|
|
|
(newRoute) => {
|
|
|
|
if (newRoute.query.token) {
|
|
|
|
if (newRoute.query.token) {
|
|
|
|
loadpage.value = true;
|
|
|
|
loadpage.value = true
|
|
|
|
setTimeout(() => {
|
|
|
|
setTimeout(() => {
|
|
|
|
loginForm.value.TOKEN = newRoute.query.token;
|
|
|
|
loginForm.value.TOKEN = newRoute.query.token
|
|
|
|
return handleLogin();
|
|
|
|
return handleLogin()
|
|
|
|
}, 1000);
|
|
|
|
}, 1000)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ immediate: true }
|
|
|
|
{ immediate: true }
|
|
|
|
);
|
|
|
|
)
|
|
|
|
function handleLogin() {
|
|
|
|
function handleLogin() {
|
|
|
|
// proxy.$refs.loginRef.validate(valid => {
|
|
|
|
// proxy.$refs.loginRef.validate(valid => {
|
|
|
|
// if (valid) {
|
|
|
|
// if (valid) {
|
|
|
|
loading.value = true;
|
|
|
|
loading.value = true
|
|
|
|
loadpage.value = true;
|
|
|
|
loadpage.value = true
|
|
|
|
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
|
|
|
|
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
|
|
|
|
if (loginForm.value.rememberMe) {
|
|
|
|
if (loginForm.value.rememberMe) {
|
|
|
|
Cookies.set("username", loginForm.value.username, { expires: 30 });
|
|
|
|
Cookies.set("username", loginForm.value.username, { expires: 30 })
|
|
|
|
Cookies.set("password", encrypt(loginForm.value.password), { expires: 30 });
|
|
|
|
Cookies.set("password", encrypt(loginForm.value.password), { expires: 30 })
|
|
|
|
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
|
|
|
|
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 })
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// 否则移除
|
|
|
|
// 否则移除
|
|
|
|
Cookies.remove("username");
|
|
|
|
Cookies.remove("username")
|
|
|
|
Cookies.remove("password");
|
|
|
|
Cookies.remove("password")
|
|
|
|
Cookies.remove("rememberMe");
|
|
|
|
Cookies.remove("rememberMe")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//登录
|
|
|
|
//登录
|
|
|
|
const params = {
|
|
|
|
const params = {
|
|
|
|
userName: loginForm.value.username,
|
|
|
|
userName: loginForm.value.username,
|
|
|
|
passwordEncode: loginForm.value.password !== "" ? encrypt(loginForm.value.password) : loginForm.value.password,
|
|
|
|
passwordEncode: loginForm.value.password !== "" ? encrypt(loginForm.value.password) : loginForm.value.password,
|
|
|
|
TOKEN: loginForm.value.token,
|
|
|
|
TOKEN: loginForm.value.token,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if (loginForm.value.TOKEN !== "") {
|
|
|
|
if (loginForm.value.TOKEN !== "") {
|
|
|
|
params.token = loginForm.value.TOKEN;
|
|
|
|
params.token = loginForm.value.TOKEN
|
|
|
|
}
|
|
|
|
}
|
|
|
|
userStore
|
|
|
|
userStore
|
|
|
|
.login(params)
|
|
|
|
.login(params)
|
|
|
|
.then((res) => {
|
|
|
|
.then((res) => {
|
|
|
|
if (params.token) {
|
|
|
|
if (params.token) {
|
|
|
|
setTimeout(() => {
|
|
|
|
setTimeout(() => {
|
|
|
|
loading.value = false;
|
|
|
|
loading.value = false
|
|
|
|
loadpage.value = false;
|
|
|
|
loadpage.value = false
|
|
|
|
router.push({ path: redirect.value || "/index" });
|
|
|
|
router.push({ path: redirect.value || "/index" })
|
|
|
|
}, 2000);
|
|
|
|
}, 2000)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
loading.value = false;
|
|
|
|
loading.value = false
|
|
|
|
router.push({ path: redirect.value || "/index" });
|
|
|
|
router.push({ path: redirect.value || "/index" })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
.catch(() => {
|
|
|
|
loadpage.value = false;
|
|
|
|
loadpage.value = false
|
|
|
|
loading.value = false;
|
|
|
|
loading.value = false
|
|
|
|
});
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function getCookie() {
|
|
|
|
function getCookie() {
|
|
|
|
const username = Cookies.get("username");
|
|
|
|
const username = Cookies.get("username")
|
|
|
|
const password = Cookies.get("password");
|
|
|
|
const password = Cookies.get("password")
|
|
|
|
const rememberMe = Cookies.get("rememberMe");
|
|
|
|
const rememberMe = Cookies.get("rememberMe")
|
|
|
|
loginForm.value = {
|
|
|
|
loginForm.value = {
|
|
|
|
username: username === undefined ? loginForm.value.username : username,
|
|
|
|
username: username === undefined ? loginForm.value.username : username,
|
|
|
|
password: password === undefined ? loginForm.value.password : decrypt(password),
|
|
|
|
password: password === undefined ? loginForm.value.password : decrypt(password),
|
|
|
|
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
|
|
|
|
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// getCode();
|
|
|
|
// getCode();
|
|
|
|
getCookie();
|
|
|
|
getCookie()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 实训流程与模块(真实课程内容,非模拟数据) ---------------- */
|
|
|
|
|
|
|
|
const steps = [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "市场需求分析",
|
|
|
|
|
|
|
|
icon: '<circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" />',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "产品设计",
|
|
|
|
|
|
|
|
icon: '<path d="M12 19l7-7 3 3-7 7-3-3z" /><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z" /><path d="M2 2l7.586 7.586" /><circle cx="11" cy="11" r="2" />',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "概念测试",
|
|
|
|
|
|
|
|
icon: '<path d="M9 18h6" /><path d="M10 22h4" /><path d="M12 2a7 7 0 0 0-4 12.7c.6.5 1 1.4 1 2.3h6c0-.9.4-1.8 1-2.3A7 7 0 0 0 12 2z" />',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "概念评估",
|
|
|
|
|
|
|
|
icon: '<path d="M3 3v18h18" /><path d="m19 9-5 5-4-4-3 3" />',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "渠道运营",
|
|
|
|
|
|
|
|
icon: '<path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z" /><path d="M3 6h18" /><path d="M16 10a4 4 0 0 1-8 0" />',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
const modules = [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "市场需求分析",
|
|
|
|
|
|
|
|
desc: "洞察用户真实诉求,找准产品定位",
|
|
|
|
|
|
|
|
icon: '<circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" />',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "产品设计",
|
|
|
|
|
|
|
|
desc: "从概念到原型,打磨产品细节",
|
|
|
|
|
|
|
|
icon: '<path d="M12 19l7-7 3 3-7 7-3-3z" /><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z" /><path d="M2 2l7.586 7.586" /><circle cx="11" cy="11" r="2" />',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "渠道运营",
|
|
|
|
|
|
|
|
desc: "多渠道布局,掌握增长方法论",
|
|
|
|
|
|
|
|
icon: '<path d="M3 3v18h18" /><path d="m19 9-5 5-4-4-3 3" />',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "概念测试评估",
|
|
|
|
|
|
|
|
desc: "数据驱动决策,验证产品价值",
|
|
|
|
|
|
|
|
icon: '<path d="M9 18h6" /><path d="M10 22h4" /><path d="M12 2a7 7 0 0 0-4 12.7c.6.5 1 1.4 1 2.3h6c0-.9.4-1.8 1-2.3A7 7 0 0 0 12 2z" />',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
]
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.login {
|
|
|
|
.login {
|
|
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
|
|
background: #f4f7fe;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.login-panel {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------- 入场动画 ---------- */
|
|
|
|
|
|
|
|
@keyframes riseIn {
|
|
|
|
|
|
|
|
from {
|
|
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
|
|
transform: translateY(22px);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
to {
|
|
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.anim {
|
|
|
|
|
|
|
|
animation: riseIn 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------- 左侧品牌区 ---------- */
|
|
|
|
|
|
|
|
.brand-side {
|
|
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
flex: 1 1 55%;
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
height: 100%;
|
|
|
|
overflow: hidden;
|
|
|
|
background-image: url("@/assets/images/login-background.0dded3b4.webp");
|
|
|
|
padding: 52px 68px;
|
|
|
|
background-size: 100% 100%;
|
|
|
|
background: linear-gradient(135deg, #0b1a4d 0%, #16306f 45%, #2447c4 100%);
|
|
|
|
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.title {
|
|
|
|
|
|
|
|
margin: 0px auto 30px auto;
|
|
|
|
/* 流动网格 */
|
|
|
|
|
|
|
|
.grid-bg {
|
|
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
|
|
inset: -60px;
|
|
|
|
|
|
|
|
background-image:
|
|
|
|
|
|
|
|
linear-gradient(rgba(255, 255, 255, 0.055) 1px, transparent 1px),
|
|
|
|
|
|
|
|
linear-gradient(90deg, rgba(255, 255, 255, 0.055) 1px, transparent 1px);
|
|
|
|
|
|
|
|
background-size: 46px 46px;
|
|
|
|
|
|
|
|
animation: gridMove 18s linear infinite;
|
|
|
|
|
|
|
|
mask-image: radial-gradient(circle at 30% 40%, #000 0%, transparent 78%);
|
|
|
|
|
|
|
|
-webkit-mask-image: radial-gradient(circle at 30% 40%, #000 0%, transparent 78%);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes gridMove {
|
|
|
|
|
|
|
|
0% {
|
|
|
|
|
|
|
|
transform: translate(0, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100% {
|
|
|
|
|
|
|
|
transform: translate(46px, 46px);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 扫描线 */
|
|
|
|
|
|
|
|
.scan-line {
|
|
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
|
|
height: 180px;
|
|
|
|
|
|
|
|
background: linear-gradient(180deg, rgba(125, 211, 252, 0) 0%, rgba(125, 211, 252, 0.16) 60%, rgba(125, 211, 252, 0) 100%);
|
|
|
|
|
|
|
|
animation: scan 7s ease-in-out infinite;
|
|
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes scan {
|
|
|
|
|
|
|
|
0% {
|
|
|
|
|
|
|
|
transform: translateY(-200px);
|
|
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12% {
|
|
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88% {
|
|
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100% {
|
|
|
|
|
|
|
|
transform: translateY(100vh);
|
|
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.brand-deco {
|
|
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.deco-1 {
|
|
|
|
|
|
|
|
width: 520px;
|
|
|
|
|
|
|
|
height: 520px;
|
|
|
|
|
|
|
|
right: -180px;
|
|
|
|
|
|
|
|
top: -190px;
|
|
|
|
|
|
|
|
background: radial-gradient(circle at 30% 30%, rgba(56, 189, 248, 0.4), rgba(56, 189, 248, 0) 70%);
|
|
|
|
|
|
|
|
animation: breathe 9s ease-in-out infinite;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.deco-2 {
|
|
|
|
|
|
|
|
width: 420px;
|
|
|
|
|
|
|
|
height: 420px;
|
|
|
|
|
|
|
|
left: -150px;
|
|
|
|
|
|
|
|
bottom: -160px;
|
|
|
|
|
|
|
|
background: radial-gradient(circle at 60% 40%, rgba(167, 139, 250, 0.34), rgba(167, 139, 250, 0) 70%);
|
|
|
|
|
|
|
|
animation: breathe 11s ease-in-out infinite reverse;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.deco-3 {
|
|
|
|
|
|
|
|
width: 180px;
|
|
|
|
|
|
|
|
height: 180px;
|
|
|
|
|
|
|
|
right: 10%;
|
|
|
|
|
|
|
|
bottom: 10%;
|
|
|
|
|
|
|
|
border: 1px solid rgba(125, 211, 252, 0.22);
|
|
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.03);
|
|
|
|
|
|
|
|
backdrop-filter: blur(2px);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes breathe {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0%,
|
|
|
|
|
|
|
|
100% {
|
|
|
|
|
|
|
|
transform: scale(1);
|
|
|
|
|
|
|
|
opacity: 0.75;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50% {
|
|
|
|
|
|
|
|
transform: scale(1.12);
|
|
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.brand-content {
|
|
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
max-width: 600px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.brand-badge {
|
|
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
|
|
padding: 7px 16px;
|
|
|
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
|
|
|
background: rgba(125, 211, 252, 0.12);
|
|
|
|
|
|
|
|
border: 1px solid rgba(125, 211, 252, 0.28);
|
|
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
|
|
letter-spacing: 2px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
svg {
|
|
|
|
|
|
|
|
width: 18px;
|
|
|
|
|
|
|
|
height: 18px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.brand-title {
|
|
|
|
|
|
|
|
margin: 24px 0 14px;
|
|
|
|
|
|
|
|
font-size: 34px;
|
|
|
|
|
|
|
|
line-height: 1.35;
|
|
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
|
|
letter-spacing: 1px;
|
|
|
|
|
|
|
|
text-shadow: 0 0 34px rgba(125, 211, 252, 0.35);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.brand-subtitle {
|
|
|
|
|
|
|
|
margin: 0 0 30px;
|
|
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
|
|
line-height: 1.8;
|
|
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.68);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------- 数据看板卡片 ---------- */
|
|
|
|
|
|
|
|
.dash-card {
|
|
|
|
|
|
|
|
padding: 20px 22px 16px;
|
|
|
|
|
|
|
|
border-radius: 16px;
|
|
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.07);
|
|
|
|
|
|
|
|
border: 1px solid rgba(255, 255, 255, 0.13);
|
|
|
|
|
|
|
|
backdrop-filter: blur(14px);
|
|
|
|
|
|
|
|
box-shadow: 0 18px 44px -22px rgba(0, 0, 0, 0.65);
|
|
|
|
|
|
|
|
animation: riseIn 0.7s cubic-bezier(0.22, 1, 0.36, 1) both, cardGlow 6s ease-in-out infinite;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 只做光影呼吸,不碰 transform,避免与入场动画冲突 */
|
|
|
|
|
|
|
|
@keyframes cardGlow {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0%,
|
|
|
|
|
|
|
|
100% {
|
|
|
|
|
|
|
|
box-shadow: 0 18px 44px -22px rgba(0, 0, 0, 0.65);
|
|
|
|
|
|
|
|
border-color: rgba(255, 255, 255, 0.13);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50% {
|
|
|
|
|
|
|
|
box-shadow: 0 18px 44px -22px rgba(0, 0, 0, 0.65), 0 0 34px -8px rgba(125, 211, 252, 0.42);
|
|
|
|
|
|
|
|
border-color: rgba(125, 211, 252, 0.32);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.dash-head {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
|
|
margin-bottom: 18px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.live-dot {
|
|
|
|
|
|
|
|
width: 7px;
|
|
|
|
|
|
|
|
height: 7px;
|
|
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
|
|
background: #4ade80;
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.6);
|
|
|
|
|
|
|
|
animation: livePulse 1.8s ease-out infinite;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes livePulse {
|
|
|
|
|
|
|
|
0% {
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.55);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70% {
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 9px rgba(74, 222, 128, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100% {
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 0 rgba(74, 222, 128, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.dash-title {
|
|
|
|
|
|
|
|
font-size: 13.5px;
|
|
|
|
|
|
|
|
letter-spacing: 1px;
|
|
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.88);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.dash-tag {
|
|
|
|
|
|
|
|
margin-left: auto;
|
|
|
|
|
|
|
|
padding: 2px 8px;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
|
|
letter-spacing: 1px;
|
|
|
|
|
|
|
|
color: #7dd3fc;
|
|
|
|
|
|
|
|
background: rgba(125, 211, 252, 0.14);
|
|
|
|
|
|
|
|
border: 1px solid rgba(125, 211, 252, 0.25);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 流程节点行 */
|
|
|
|
|
|
|
|
.flow-row {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: stretch;
|
|
|
|
|
|
|
|
gap: 4px;
|
|
|
|
|
|
|
|
padding: 14px 6px 16px;
|
|
|
|
|
|
|
|
border-radius: 11px;
|
|
|
|
|
|
|
|
background: rgba(9, 20, 56, 0.42);
|
|
|
|
|
|
|
|
border: 1px solid rgba(125, 211, 252, 0.14);
|
|
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.flow-node {
|
|
|
|
|
|
|
|
flex: none;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
gap: 7px;
|
|
|
|
|
|
|
|
width: 76px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.node-icon {
|
|
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
width: 42px;
|
|
|
|
|
|
|
|
height: 42px;
|
|
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
|
|
color: #7dd3fc;
|
|
|
|
|
|
|
|
background: rgba(125, 211, 252, 0.1);
|
|
|
|
|
|
|
|
border: 1px solid rgba(125, 211, 252, 0.32);
|
|
|
|
|
|
|
|
transition: box-shadow 0.3s ease;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
svg {
|
|
|
|
|
|
|
|
width: 20px;
|
|
|
|
|
|
|
|
height: 20px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.flow-node.active .node-icon {
|
|
|
|
|
|
|
|
color: #e8f4ff;
|
|
|
|
|
|
|
|
background: linear-gradient(135deg, #38bdf8 0%, #6366f1 100%);
|
|
|
|
|
|
|
|
border-color: transparent;
|
|
|
|
|
|
|
|
animation: nodeGlow 2.4s ease-in-out infinite;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes nodeGlow {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0%,
|
|
|
|
|
|
|
|
100% {
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 0 rgba(125, 211, 252, 0.45);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50% {
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 7px rgba(125, 211, 252, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.node-label {
|
|
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
line-height: 1.3;
|
|
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.82);
|
|
|
|
text-align: center;
|
|
|
|
text-align: center;
|
|
|
|
color: rgb(48, 50, 52);
|
|
|
|
|
|
|
|
font-size: var(--student-fs-h2);
|
|
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.login-main {
|
|
|
|
|
|
|
|
width: 85%;
|
|
|
|
.node-index {
|
|
|
|
height: 100%;
|
|
|
|
font-size: 10px;
|
|
|
|
|
|
|
|
letter-spacing: 1px;
|
|
|
|
|
|
|
|
color: rgba(125, 211, 252, 0.6);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.flow-node.active .node-label {
|
|
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 流动连接线 */
|
|
|
|
|
|
|
|
.flow-link {
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
align-self: flex-start;
|
|
|
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
|
|
|
height: 2px;
|
|
|
|
|
|
|
|
border-radius: 2px;
|
|
|
|
|
|
|
|
background: repeating-linear-gradient(90deg, rgba(125, 211, 252, 0.65) 0 7px, transparent 7px 14px);
|
|
|
|
|
|
|
|
background-size: 14px 2px;
|
|
|
|
|
|
|
|
animation: dashFlow 1.1s linear infinite;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes dashFlow {
|
|
|
|
|
|
|
|
to {
|
|
|
|
|
|
|
|
background-position: 14px 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 模块网格 */
|
|
|
|
|
|
|
|
.module-grid {
|
|
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.module-item {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
|
|
gap: 11px;
|
|
|
|
|
|
|
|
padding: 13px 14px;
|
|
|
|
|
|
|
|
border-radius: 11px;
|
|
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.05);
|
|
|
|
|
|
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
|
|
|
|
|
|
transition: background 0.25s ease, border-color 0.25s ease;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
|
|
background: rgba(125, 211, 252, 0.1);
|
|
|
|
|
|
|
|
border-color: rgba(125, 211, 252, 0.3);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
b {
|
|
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
|
|
margin-bottom: 3px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i {
|
|
|
|
|
|
|
|
font-style: normal;
|
|
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.55);
|
|
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.module-icon {
|
|
|
|
|
|
|
|
flex: none;
|
|
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: end;
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
width: 34px;
|
|
|
|
|
|
|
|
height: 34px;
|
|
|
|
|
|
|
|
border-radius: 9px;
|
|
|
|
|
|
|
|
color: #7dd3fc;
|
|
|
|
|
|
|
|
background: rgba(125, 211, 252, 0.12);
|
|
|
|
|
|
|
|
border: 1px solid rgba(125, 211, 252, 0.22);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
svg {
|
|
|
|
|
|
|
|
width: 17px;
|
|
|
|
|
|
|
|
height: 17px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.login-form {
|
|
|
|
}
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------- 右侧表单区 ---------- */
|
|
|
|
|
|
|
|
.form-side {
|
|
|
|
|
|
|
|
flex: 1 1 45%;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
justify-content: center;
|
|
|
|
background: #ffffff;
|
|
|
|
background: #ffffff;
|
|
|
|
width: 400px;
|
|
|
|
padding: 40px 32px;
|
|
|
|
padding: 55px 25px 33px 25px;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.form-wrapper {
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
max-width: 390px;
|
|
|
|
|
|
|
|
animation: riseIn 0.8s cubic-bezier(0.22, 1, 0.36, 1) 0.15s both;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
|
|
color: #1d2129;
|
|
|
|
|
|
|
|
font-size: 26px;
|
|
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.subtitle {
|
|
|
|
|
|
|
|
margin: 10px 0 34px;
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
color: #86909c;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.login-form {
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.el-form-item {
|
|
|
|
|
|
|
|
margin-bottom: 22px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-input {
|
|
|
|
.el-input {
|
|
|
|
height: 40px;
|
|
|
|
height: 46px;
|
|
|
|
|
|
|
|
|
|
|
|
input {
|
|
|
|
input {
|
|
|
|
height: 40px;
|
|
|
|
height: 46px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-input__wrapper) {
|
|
|
|
:deep(.el-input__wrapper) {
|
|
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
|
|
background-color: #f5f7fa !important;
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 1px #f5f7fa inset;
|
|
|
|
|
|
|
|
padding-left: 14px;
|
|
|
|
|
|
|
|
transition: box-shadow 0.25s ease, background-color 0.25s ease;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
|
|
background-color: #f0f2f7 !important;
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 1px #dcdfe6 inset;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&.is-focus {
|
|
|
|
background-color: #ffffff !important;
|
|
|
|
background-color: #ffffff !important;
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 2px #2b5aed inset, 0 0 0 4px rgba(43, 90, 237, 0.12) !important;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-input__inner),
|
|
|
|
:deep(.el-input__inner),
|
|
|
|
:deep(input) {
|
|
|
|
:deep(input) {
|
|
|
|
color: #303133;
|
|
|
|
color: #1d2129;
|
|
|
|
background-color: transparent !important;
|
|
|
|
background-color: transparent !important;
|
|
|
|
-webkit-text-fill-color: #303133;
|
|
|
|
-webkit-text-fill-color: #1d2129;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-input__inner::placeholder),
|
|
|
|
:deep(.el-input__inner::placeholder),
|
|
|
|
:deep(input::placeholder) {
|
|
|
|
:deep(input::placeholder) {
|
|
|
|
color: #b8c0cc;
|
|
|
|
color: #a8abb2;
|
|
|
|
-webkit-text-fill-color: #b8c0cc;
|
|
|
|
-webkit-text-fill-color: #a8abb2;
|
|
|
|
opacity: 1;
|
|
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -194,9 +734,9 @@ getCookie();
|
|
|
|
:deep(input:-webkit-autofill:hover),
|
|
|
|
:deep(input:-webkit-autofill:hover),
|
|
|
|
:deep(input:-webkit-autofill:focus),
|
|
|
|
:deep(input:-webkit-autofill:focus),
|
|
|
|
:deep(input:-webkit-autofill:active) {
|
|
|
|
:deep(input:-webkit-autofill:active) {
|
|
|
|
caret-color: #303133 !important;
|
|
|
|
caret-color: #1d2129 !important;
|
|
|
|
-webkit-text-fill-color: #303133 !important;
|
|
|
|
-webkit-text-fill-color: #1d2129 !important;
|
|
|
|
-webkit-box-shadow: 0 0 0 1000px #ffffff inset !important;
|
|
|
|
-webkit-box-shadow: 0 0 0 1000px #f5f7fa inset !important;
|
|
|
|
transition: background-color 9999s ease-out 0s !important;
|
|
|
|
transition: background-color 9999s ease-out 0s !important;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -204,36 +744,114 @@ getCookie();
|
|
|
|
height: 39px;
|
|
|
|
height: 39px;
|
|
|
|
width: 14px;
|
|
|
|
width: 14px;
|
|
|
|
margin-left: 0px;
|
|
|
|
margin-left: 0px;
|
|
|
|
|
|
|
|
color: #86909c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.login-tip {
|
|
|
|
|
|
|
|
font-size: var(--student-fs-body-sm);
|
|
|
|
.form-options {
|
|
|
|
text-align: center;
|
|
|
|
display: flex;
|
|
|
|
color: #bfbfbf;
|
|
|
|
align-items: center;
|
|
|
|
}
|
|
|
|
justify-content: space-between;
|
|
|
|
.login-code {
|
|
|
|
margin: 0 0 22px;
|
|
|
|
width: 33%;
|
|
|
|
|
|
|
|
height: 40px;
|
|
|
|
.link-type {
|
|
|
|
float: right;
|
|
|
|
font-size: 13px;
|
|
|
|
img {
|
|
|
|
color: #2b5aed;
|
|
|
|
cursor: pointer;
|
|
|
|
text-decoration: none;
|
|
|
|
vertical-align: middle;
|
|
|
|
|
|
|
|
}
|
|
|
|
&:hover {
|
|
|
|
}
|
|
|
|
text-decoration: underline;
|
|
|
|
.el-login-footer {
|
|
|
|
}
|
|
|
|
height: 40px;
|
|
|
|
}
|
|
|
|
line-height: 40px;
|
|
|
|
}
|
|
|
|
position: fixed;
|
|
|
|
|
|
|
|
bottom: 0;
|
|
|
|
.login-btn {
|
|
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
width: 100%;
|
|
|
|
width: 100%;
|
|
|
|
text-align: center;
|
|
|
|
height: 46px;
|
|
|
|
color: #fff;
|
|
|
|
border: none;
|
|
|
|
font-family: var(--student-font-base);
|
|
|
|
border-radius: 10px;
|
|
|
|
font-size: var(--student-fs-caption);
|
|
|
|
font-size: 16px;
|
|
|
|
letter-spacing: 1px;
|
|
|
|
letter-spacing: 6px;
|
|
|
|
|
|
|
|
background: linear-gradient(135deg, #1e3fae 0%, #2b5aed 55%, #5b7cf5 100%);
|
|
|
|
|
|
|
|
box-shadow: 0 8px 22px -6px rgba(43, 90, 237, 0.55);
|
|
|
|
|
|
|
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&::after {
|
|
|
|
|
|
|
|
content: "";
|
|
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
|
|
left: -60%;
|
|
|
|
|
|
|
|
width: 40%;
|
|
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
|
|
background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.32) 50%, rgba(255, 255, 255, 0) 100%);
|
|
|
|
|
|
|
|
transform: skewX(-20deg);
|
|
|
|
|
|
|
|
animation: shine 3.6s ease-in-out infinite;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
|
|
|
box-shadow: 0 12px 26px -6px rgba(43, 90, 237, 0.6);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes shine {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0%,
|
|
|
|
|
|
|
|
60% {
|
|
|
|
|
|
|
|
left: -60%;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100% {
|
|
|
|
|
|
|
|
left: 130%;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------- 响应式 ---------- */
|
|
|
|
|
|
|
|
@media (max-width: 1200px) {
|
|
|
|
|
|
|
|
.brand-side {
|
|
|
|
|
|
|
|
padding: 40px 44px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.brand-title {
|
|
|
|
|
|
|
|
font-size: 29px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.flow-node {
|
|
|
|
|
|
|
|
width: 62px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.node-label {
|
|
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.module-grid {
|
|
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 900px) {
|
|
|
|
|
|
|
|
.brand-side {
|
|
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.form-side {
|
|
|
|
|
|
|
|
flex: 1 1 100%;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
|
|
|
|
|
.form-side {
|
|
|
|
|
|
|
|
padding: 24px 18px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
|
|
|
font-size: 23px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.login-code-img {
|
|
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
|
|
padding-left: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</style>
|
|
|
|
|