update:样式修改

This commit is contained in:
ltx 2026-04-21 18:07:25 +08:00
parent 6fefd81e4a
commit 3e7e54dde4
7 changed files with 705 additions and 385 deletions

View File

@ -23,10 +23,10 @@ export default {
}
};
</script>
<style lang="stylus">
p{
<style>
/* p{
margin-top:10px !important;
}
} */
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;

View File

@ -14,8 +14,8 @@ let loadingStatus = false;
console.log(process.env.NODE_ENV, 'process.env.NODE_ENV')
if (process.env.NODE_ENV == 'development') {
// axios.defaults.baseURL = 'http://101.132.164.149:9991/';
axios.defaults.baseURL = 'http://8.153.108.90:9991/'; //测试
// axios.defaults.baseURL = 'https://smartsports.yuedongsports.com/'; //正式
// axios.defaults.baseURL = 'http://8.153.108.90:9991/'; //测试
axios.defaults.baseURL = 'https://smartsports.yuedongsports.com/'; //正式
// axios.defaults.baseURL = 'http://192.168.0.146:9991/'; //汤龙本地
// axios.defaults.baseURL = 'http://47.101.60.251:9991/';
// axios.defaults.baseURL = 'http://localhost:9991/';

View File

@ -379,3 +379,27 @@
width: 100%;
}
// el-message 图标与文字水平对齐修复
// .el-message {
// display: flex !important;
// align-items: center !important;
// .el-message__icon {
// display: flex;
// align-items: center;
// line-height: 1;
// margin-right: 8px;
// .el-icon {
// display: inline-flex;
// align-items: center;
// vertical-align: middle;
// }
// }
// p.el-message__content {
// line-height: 1;
// margin: 0;
// }
// }

View File

@ -122,53 +122,53 @@
// 来自 https://github.com/amfe/lib-flexible/blob/2.0/index.js
(function flexible(window, document) {
var docEl = document.documentElement;
// 获取当前显示设备的物理像素分辨率与CSS像素分辨率之比;
var dpr = window.devicePixelRatio || 1;
// var docEl = document.documentElement;
// // 获取当前显示设备的物理像素分辨率与CSS像素分辨率之比;
// var dpr = window.devicePixelRatio || 1;
//根据分辨率调整全局字体大小
function setBodyFontSize() {
// html已完成加载,则立即调整字体大小,否则等待html加载完成再调整字体大小
if (document.body) {
document.body.style.fontSize = 12 * dpr + "px";
} else {
// 监听DOMContentLoaded 事件——当初始的 HTML 文档被完全加载和解析完成之后触发,无需等待样式表
document.addEventListener("DOMContentLoaded", setBodyFontSize);
}
}
setBodyFontSize();
// //根据分辨率调整全局字体大小
// function setBodyFontSize() {
// // html已完成加载,则立即调整字体大小,否则等待html加载完成再调整字体大小
// if (document.body) {
// document.body.style.fontSize = 12 * dpr + "px";
// } else {
// // 监听DOMContentLoaded 事件——当初始的 HTML 文档被完全加载和解析完成之后触发,无需等待样式表
// document.addEventListener("DOMContentLoaded", setBodyFontSize);
// }
// }
// setBodyFontSize();
// 根据屏幕宽度,重置1rem的长度为当前屏幕宽度的1/10
function setRemUnit() {
var rem = docEl.clientWidth / 24;
// 1rem的值永远为根元素的字体大小,所以此处通过调整全局字体大小来重置rem
docEl.style.fontSize = rem + "px";
}
// // 根据屏幕宽度,重置1rem的长度为当前屏幕宽度的1/10
// function setRemUnit() {
// var rem = docEl.clientWidth / 24;
// // 1rem的值永远为根元素的字体大小,所以此处通过调整全局字体大小来重置rem
// docEl.style.fontSize = rem + "px";
// }
setRemUnit();
// setRemUnit();
// 监听resize事件——屏幕大小发生变化时触发
window.addEventListener("resize", setRemUnit);
// 监听pageshow事件——显示页面时触发
window.addEventListener("pageshow", function(e) {
// 若是浏览器中点击后退时显示页面,则重置rem
if (e.persisted) {
setRemUnit();
}
});
// // 监听resize事件——屏幕大小发生变化时触发
// window.addEventListener("resize", setRemUnit);
// // 监听pageshow事件——显示页面时触发
// window.addEventListener("pageshow", function(e) {
// // 若是浏览器中点击后退时显示页面,则重置rem
// if (e.persisted) {
// setRemUnit();
// }
// });
// 检测是否支持0.5px
if (dpr >= 2) {
var fakeBody = document.createElement("body");
var testElement = document.createElement("div");
testElement.style.border = ".5px solid transparent";
fakeBody.appendChild(testElement);
docEl.appendChild(fakeBody);
if (testElement.offsetHeight === 1) {
docEl.classList.add("hairlines");
}
docEl.removeChild(fakeBody);
}
// // 检测是否支持0.5px
// if (dpr >= 2) {
// var fakeBody = document.createElement("body");
// var testElement = document.createElement("div");
// testElement.style.border = ".5px solid transparent";
// fakeBody.appendChild(testElement);
// docEl.appendChild(fakeBody);
// if (testElement.offsetHeight === 1) {
// docEl.classList.add("hairlines");
// }
// docEl.removeChild(fakeBody);
// }
})(window, document);

View File

@ -2,18 +2,34 @@
<div id="vol-container" :class="['vol-theme-' + theme]">
<!-- 顶部一级导航栏 -->
<div class="vol-top-header">
<!-- 测量容器(不可见,用于计算每个菜单项宽度) -->
<div class="top-nav-measure" ref="navMeasureRef" aria-hidden="true">
<span v-for="item in topLevelMenus" :key="'ms-' + item.id" class="top-nav-item">{{ item.name }}</span>
</div>
<div class="top-logo">
<img v-bind:src="logo" />
<span>跃动智慧体育平台</span>
</div>
<div class="top-nav-menus" ref="topNavMenusRef">
<span
v-for="item in topLevelMenus"
v-for="(item, idx) in topLevelMenus"
v-show="idx < visibleMenuCount"
:key="item.id"
:class="['top-nav-item', { 'is-active': activeTopMenuId == item.id }]"
@click="selectTopMenu(item)"
>{{ item.name }}</span>
</div>
<!-- 溢出「···」按钮(放在 top-nav-menus 外,避免被 overflow:hidden 裁剪) -->
<div
v-if="overflowMenus.length > 0"
class="top-nav-more-wrapper"
ref="moreWrapperRef"
>
<span
:class="['top-nav-item', 'top-nav-more-btn', { 'is-active': overflowMenus.some(m => m.id == activeTopMenuId) }]"
@click.stop="toggleMoreMenu"
>···</span>
</div>
<div class="header-info">
<div class="h-link">
<a href="javascript:void(0)" @click="to(item)" v-for="(item, index) in links.filter((c) => { return c.icon; })" :key="index">
@ -95,6 +111,25 @@
</el-scrollbar>
</div>
</div>
<!-- 溢出菜单下拉面板:Teleport 到 body,避免被任何父层 overflow/z-index 裁剪 -->
<Teleport to="body">
<transition name="top-nav-more-fade">
<div
v-if="moreMenuVisible && overflowMenus.length > 0"
class="top-nav-overflow-panel"
:style="overflowPanelStyle"
@click.stop
>
<div
v-for="item in overflowMenus"
:key="item.id"
:class="['top-nav-overflow-item', { 'is-active': activeTopMenuId == item.id }]"
@click="selectTopMenuFromMore(item)"
>{{ item.name }}</div>
</div>
</transition>
</Teleport>
<el-drawer title="选择主题" v-model="drawer_model" direction="rtl" destroy-on-close>
<div class="theme-selector">
<div @click="changeTheme(item.name)" class="item" v-for="(item, index) in theme_color" :key="index"
@ -157,6 +192,7 @@ import {
ref,
watch,
computed,
nextTick,
onMounted,
getCurrentInstance,
} from "vue";
@ -240,7 +276,7 @@ export default defineComponent({
const menuOptions = ref([]);
const activeTopMenuId = ref(0);
const topLevelMenus = computed(() => {
return menuOptions.value.filter(item => item.parentId == 0);
return menuOptions.value.filter(item => item.parentId == 0 && item.enable != 2);
});
const activeTopMenuHasChildren = computed(() => {
return menuOptions.value.some(item => item.parentId == activeTopMenuId.value);
@ -256,6 +292,75 @@ export default defineComponent({
const selectTopMenu = (item) => {
activeTopMenuId.value = item.id;
};
// ====== 溢出菜单逻辑 ======
const navMeasureRef = ref(null);
const visibleMenuCount = ref(999);
const moreMenuVisible = ref(false);
const moreWrapperRef = ref(null);
const overflowMenus = computed(() => topLevelMenus.value.slice(visibleMenuCount.value));
const overflowPanelStyle = ref({});
const toggleMoreMenu = () => {
if (moreMenuVisible.value) {
moreMenuVisible.value = false;
return;
}
// 计算按钮位置,用 fixed 定位
const rect = moreWrapperRef.value?.getBoundingClientRect();
if (rect) {
overflowPanelStyle.value = {
position: 'fixed',
top: (rect.bottom + 6) + 'px',
right: (window.innerWidth - rect.right) + 'px',
zIndex: 9999,
};
}
moreMenuVisible.value = true;
// 延迟添加外点关闭监听,避免当前点击事件被捕获
setTimeout(() => {
document.addEventListener('click', () => { moreMenuVisible.value = false; }, { once: true });
}, 0);
};
const recalcMenuVisibility = () => {
nextTick(() => {
const container = topNavMenusRef.value;
const measure = navMeasureRef.value;
if (!container || !measure) return;
const containerWidth = container.clientWidth;
const items = Array.from(measure.children);
const total = items.length;
if (total === 0) return;
const GAP = 6;
const MORE_BTN_WIDTH = 58;
// 计算所有菜单项总宽度
const totalWidth = items.reduce((sum, el) => sum + el.offsetWidth + GAP, 0);
if (totalWidth <= containerWidth) {
visibleMenuCount.value = total;
return;
}
// 找出能与「···」按钮共同放入容器的最大菜单项数
let accumulated = 0;
let count = 0;
for (let i = 0; i < total; i++) {
const itemWidth = items[i].offsetWidth + GAP;
if (accumulated + itemWidth + MORE_BTN_WIDTH > containerWidth) {
count = i;
break;
}
accumulated += itemWidth;
if (i === total - 1) count = total;
}
visibleMenuCount.value = Math.max(1, count);
});
};
const selectTopMenuFromMore = (item) => {
moreMenuVisible.value = false;
selectTopMenu(item);
};
// 菜单项变化时重新计算
watch(topLevelMenus, () => {
recalcMenuVisibility();
});
// ====== 溢出菜单逻辑 END ======
const routerList = ref(JSON.parse(localStorage.getItem("routerList")))
const permissionInited = ref(false);
const messageList = reactive([]);
@ -805,6 +910,15 @@ export default defineComponent({
menuWidth,
isCollapse,
topNavMenusRef,
navMeasureRef,
visibleMenuCount,
moreMenuVisible,
moreWrapperRef,
overflowMenus,
overflowPanelStyle,
toggleMoreMenu,
recalcMenuVisibility,
selectTopMenuFromMore,
activeTopMenuId,
activeTopMenuHasChildren,
topLevelMenus,
@ -845,18 +959,16 @@ export default defineComponent({
*/
mounted() {
let _date = showTime();
// $indexDate = document.getElementById("index-date");
// $indexDate.innerText = _date;
// $interval = setInterval(function () {
// $indexDate.innerText = showTime();
// }, 1000);
// 顶部导航横向滚动
// 初始计算溢出菜单
this.recalcMenuVisibility();
// 监听顶部导航容器宽度变化
if (this.topNavMenusRef) {
this.topNavMenusRef.addEventListener('wheel', (e) => {
e.preventDefault();
this.topNavMenusRef.scrollLeft += e.deltaY || e.deltaX;
}, { passive: false });
this._navResizeObserver = new ResizeObserver(() => {
this.recalcMenuVisibility();
});
this._navResizeObserver.observe(this.topNavMenusRef);
}
this.bindRightClickMenu(true);
@ -890,6 +1002,7 @@ export default defineComponent({
destroyed() {
$this = null;
clearInterval($interval);
if (this._navResizeObserver) this._navResizeObserver.disconnect();
},
});
const week = new Array(
@ -985,4 +1098,64 @@ function showTime() {
transition: 0s width ease-in-out, 0s padding-left ease-in-out,
0s padding-right ease-in-out;
}
/* ── 溢出导航下拉面板(Teleport 到 body,需全局样式) ── */
.top-nav-overflow-panel {
min-width: 160px;
background: #fff;
border-radius: 12px;
box-shadow: 0 10px 32px rgba(0, 0, 0, 0.14), 0 2px 8px rgba(0, 0, 0, 0.06);
padding: 5px;
border: 1px solid rgba(0, 0, 0, 0.06);
}
.top-nav-overflow-item {
padding: 9px 14px;
cursor: pointer;
border-radius: 8px;
color: #333;
font-size: 14px;
transition: all 0.18s;
white-space: nowrap;
}
.top-nav-overflow-item:hover {
background: #f0f7ff;
color: #2d8cf0;
}
.top-nav-overflow-item.is-active {
color: #2d8cf0;
font-weight: 600;
background: #e8f4ff;
}
.top-nav-more-fade-enter-active,
.top-nav-more-fade-leave-active {
transition: opacity 0.2s ease, transform 0.2s ease;
}
.top-nav-more-fade-enter-from,
.top-nav-more-fade-leave-to {
opacity: 0;
transform: translateY(-8px);
}
/* ── 标签栏 Chrome 风格激活色(全局高优先级,压过 EP border-card 内置样式) ── */
.header-navigation.el-tabs--border-card > .el-tabs__header .el-tabs__item {
color: #5f6368;
background: transparent;
border: none !important;
border-radius: 8px 8px 0 0 !important;
overflow: visible !important;
}
.header-navigation.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active {
color: #2563eb !important;
background: linear-gradient(90deg, #dbeeff 0%, #f0f8ff 100%) !important;
font-weight: 600;
border: none !important;
}
.header-navigation.el-tabs--border-card > .el-tabs__header .el-tabs__item:not(.is-active):hover {
color: #2563eb !important;
background: #ebf4ff !important;
}
.header-navigation.el-tabs--border-card > .el-tabs__header {
background: #fff;
border-bottom: none;
}
</style>

View File

@ -19,7 +19,7 @@
align-items: center;
z-index: 200;
background-color: #2d8cf0;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.18);
// box-shadow: 0 2px 12px rgba(0, 0, 0, 0.18);
}
.top-logo {
@ -49,20 +49,54 @@
display: flex;
align-items: center;
height: 100%;
padding: 0 16px;
padding: 0 8px 0 16px;
gap: 6px;
overflow-x: auto;
overflow-y: hidden;
// 隐藏滚动条,但保留滚动功能
scrollbar-width: none; // Firefox
-ms-overflow-style: none; // IE/Edge
&::-webkit-scrollbar {
display: none; // Chrome/Safari
}
// 鼠标左右拖动提示
cursor: default;
overflow: hidden;
min-width: 0;
}
// 测量容器(全部菜单项不可见渲染,用于获取宽度)
.top-nav-measure {
position: absolute;
top: -9999px;
left: 0;
display: flex;
gap: 6px;
visibility: hidden;
pointer-events: none;
white-space: nowrap;
z-index: -1;
}
// 溢出更多按钮外层容器
.top-nav-more-wrapper {
position: relative;
display: inline-flex;
align-items: center;
height: 100%;
flex-shrink: 0;
}
// ··· 按钮样式
.top-nav-more-btn {
font-size: 18px;
font-weight: 700;
letter-spacing: 3px;
padding: 0 14px !important;
}
// 下拉面板(position 由 JS 内联样式控制)
.top-nav-overflow-panel {
min-width: 160px;
background: #fff;
border-radius: 12px;
box-shadow: 0 10px 32px rgba(0, 0, 0, 0.14), 0 2px 8px rgba(0, 0, 0, 0.06);
padding: 5px;
border: 1px solid rgba(0, 0, 0, 0.06);
}
// 下拉面板视觉样式已迁移至 index.vue 全局 <style> 块(Teleport 场景)
.top-nav-item {
display: inline-flex;
align-items: center;
@ -220,8 +254,8 @@
top: 0;
bottom: 0;
background: #fff;
border-right: none;
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.06);
border-right: 1px solid #e4e4e7 !important;
box-shadow: none;
}
.vol-aside .vol-menu ::v-deep(.ivu-menu) {
@ -253,7 +287,7 @@
width: 100%;
display: inline-block;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
border-bottom: 1px solid #e4e4e7;
}
.vol-container .vol-path span {
position: relative;
@ -271,7 +305,7 @@
.vol-main {
position: absolute;
width: 100%;
background-color: #f0f2f5;
background-color: #f1f3f6;
bottom: 0;
top: 38px;
margin: 0;
@ -352,7 +386,7 @@
height: 38px;
display: block;
margin: 0;
padding: 5px 10px 0;
padding: 6px 8px 0;
outline: 0;
list-style: none;
position: relative;
@ -364,40 +398,74 @@
border: none;
}
.header-navigation ::v-deep(.el-tabs__nav-wrap) {
margin-bottom: -1px;
margin-bottom: 0;
overflow: visible !important;
}
.header-navigation ::v-deep(.el-tabs__nav-scroll) {
overflow: visible !important;
}
.header-navigation ::v-deep(.el-tabs__nav) {
overflow: visible !important;
}
.header-navigation ::v-deep(.el-tabs__header) {
border-bottom: none;
margin: 0;
overflow: visible;
}
.header-navigation ::v-deep(.el-tabs__item) {
height: 28px;
height: 30px;
font-size: 13px;
line-height: 28px;
padding: 0 12px !important;
color: #8492a6 !important;
line-height: 30px;
padding: 0 14px !important;
color: #5f6368 !important;
position: relative;
margin: 0 2px;
margin: 0 1px;
border: none !important;
border-radius: 5px !important;
background: #f2f4f7;
transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1);
border-radius: 8px 8px 0 0 !important;
background: transparent;
transition: background 0.15s ease;
box-shadow: none;
overflow: visible !important;
z-index: 1;
}
.header-navigation ::v-deep(.el-tabs__item.is-active) {
color: #2d8cf0 !important;
background: #deeeff !important;
color: #2563eb !important;
background: linear-gradient(90deg, #dbeeff 0%, #f0f8ff 100%) !important;
font-weight: 600;
box-shadow: none;
z-index: 2;
}
.header-navigation ::v-deep(.el-tabs__item:hover) {
color: #2d8cf0 !important;
background: #eaf3ff !important;
.header-navigation ::v-deep(.el-tabs__item.is-active::before) {
content: '';
position: absolute;
bottom: 0;
left: -8px;
width: 8px;
height: 8px;
background: transparent;
border-bottom-right-radius: 8px;
box-shadow: 3px 0 0 0 #dbeeff;
}
.header-navigation ::v-deep(.el-tabs__item.is-active::after) {
content: '';
position: absolute;
bottom: 0;
right: -8px;
width: 8px;
height: 8px;
background: transparent;
border-bottom-left-radius: 8px;
box-shadow: -3px 0 0 0 #f0f8ff;
}
.header-navigation ::v-deep(.el-tabs__item:not(.is-active):hover) {
color: #2563eb !important;
background: #ebf4ff !important;
border-radius: 8px 8px 0 0 !important;
}
.header-navigation ::v-deep(.el-tabs__nav-prev),
.header-navigation ::v-deep(.el-tabs__nav-next) {
line-height: 38px;
color: #8492a6;
color: #5f6368;
padding-left: 4px;
}

View File

@ -1,36 +1,50 @@
<template>
<ScaleBox>
<div class="login" id="login">
<div class="smallDialog" v-if="loginAllData.loginData.loginDialog">
<div class="head">
<p class="text1">欢迎登录</p>
<!-- <p class="register" @click="register">注册</p> -->
<!-- 左侧装饰区 -->
<div class="hero-section">
<div class="float-shape s1">🏃</div>
<div class="float-shape s2">🏅</div>
<div class="float-shape s3">⚽</div>
<div class="float-shape s4">🎯</div>
<!-- <div class="hero-content">
<div class="hero-tags">
<span class="tag">🏆 竞技赛场</span>
<span class="tag">📊 数据分析</span>
<span class="tag">🎽 体能训练</span>
</div>
</div> -->
</div>
<!-- 右侧登录卡片 -->
<div class="login-card" v-if="loginAllData.loginData.loginDialog">
<div class="card-top-bar">
<span class="dot d1"></span>
<span class="dot d2"></span>
<span class="dot d3"></span>
</div>
<div class="center">
<p class="text2">智慧系统</p>
</div>
<div class="formIpt">
<el-form ref="ruleFormRef" :model="loginAllData.loginData.ruleForm" status-icon
:rules="loginAllData.loginData.rules" label-width="120px" class="demo-ruleForm">
<el-form-item label="" prop="userName">
<div class="card-body">
<!-- <div class="card-icon">🎉</div> -->
<h2 class="card-title">欢迎使用</h2>
<p class="card-subtitle">智慧运动平台</p>
<el-form ref="ruleFormRef" :model="loginAllData.loginData.ruleForm"
:rules="loginAllData.loginData.rules" class="login-form">
<el-form-item prop="userName">
<el-input v-model="loginAllData.loginData.ruleForm.userName" placeholder="请输入用户名" clearable
autocomplete="off">
<template #prepend>用户名:</template>
autocomplete="off" :prefix-icon="UserFilled">
</el-input>
</el-form-item>
<el-form-item label="" prop="password">
<el-form-item prop="password">
<el-input v-model="loginAllData.loginData.ruleForm.password" type="password"
placeholder="请输入密码" clearable autocomplete="off">
<template #prepend>密&nbsp&nbsp&nbsp码:</template>
placeholder="请输入密码" clearable autocomplete="off" show-password :prefix-icon="Lock">
</el-input>
</el-form-item>
</el-form>
</div>
<!-- <div class="forgetPass" @click="forgetPassClick">
<p>忘记密码</p>
</div> -->
<div class="btnName" @click="submitForm(ruleFormRef)">
<p class="text3">登录</p>
<div class="submit-btn" @click="submitForm(ruleFormRef)">
<span>登录</span>
</div>
<!-- <p class="card-footer">加油,同学!运动让你更棒 ⭐</p> -->
</div>
</div>
<!-- <div class="registerDialog" v-if="loginAllData.registerData.registerDialog">
@ -65,22 +79,21 @@
{{ codeText }}
</p>
</template>
</el-input>
</el-form-item>
<el-form-item prop="verificationCode">
<el-input v-model="loginAllData.registerData.registerForm.verificationCode" clearable
placeholder="请输入验证码" />
</el-form-item>
<el-form-item prop="email">
<el-input v-model="loginAllData.registerData.registerForm.email" @input="validateEmailInput"
clearable placeholder="请输入邮箱" />
</el-form-item>
<div class="btnName" @click="registerFormClick(registerRef, 1)">
<p class="text3">立即注册</p>
</div>
</el-form>
</div>
</div> -->
</el-input>
</el-form-item>
<el-form-item prop="verificationCode">
<el-input v-model="loginAllData.registerData.registerForm.verificationCode" clearable placeholder="请输入验证码" />
</el-form-item>
<el-form-item prop="email">
<el-input v-model="loginAllData.registerData.registerForm.email" @input="validateEmailInput" clearable
placeholder="请输入邮箱" />
</el-form-item>
<div class="btnName" @click="registerFormClick(registerRef, 1)">
<p class="text3">立即注册</p>
</div>
</el-form>
</div>
</div> -->
<!-- <div class="ModifyPwdDialog" v-if="loginAllData.ModifyPwd.ModifyPwdDialog">
<div class="head">
<p class="register">重置密码</p>
@ -138,6 +151,7 @@ import CryptoJS from "crypto-js";
import zxcvbn from 'zxcvbn';
import { ElMessage } from 'element-plus';
import ScaleBox from "@/components/scaleBox/index.vue";
import { UserFilled, Lock } from '@element-plus/icons-vue'
const imageUrls = [
require('@/assets/images/login/login.jpg'),
];
@ -572,303 +586,344 @@ async function ModifyPwdApi(val) {
}
</script>
<style lang="less" scoped>
@media screen and (max-width: 500px) {
.login {
width: 100%;
height: 100%;
background: none
@keyframes floatUp {
0%,
100% {
transform: translateY(0px) rotate(0deg);
}
50% {
transform: translateY(-18px) rotate(8deg);
}
}
@keyframes floatUpAlt {
0%,
100% {
transform: translateY(0px) rotate(0deg);
}
50% {
transform: translateY(-12px) rotate(-6deg);
}
}
@keyframes blobPulse {
0%,
100% {
transform: scale(1);
opacity: 0.55;
}
50% {
transform: scale(1.08);
opacity: 0.7;
}
}
@keyframes cardIn {
from {
opacity: 0;
transform: translateY(30px) translateX(20px);
}
to {
opacity: 1;
transform: translateY(-50%) translateX(0);
}
}
.login {
width: 100%;
height: 100%;
background: url('@/assets/images/login/login.jpg') no-repeat;
background-size: 100% 100%;
//transform-origin: left top;
background: url('@/assets/images/login/login.jpg') no-repeat center center;
background-size: cover;
position: relative;
overflow: hidden;
.smallDialog {
width: 508px;
height: 643px;
// width: 27%;
// height: 65%;
background: url('@/assets/images/login/loginSmall.png') no-repeat;
border-radius: 30px;
&::before {
content: '';
position: absolute;
right: 10%;
top: 15%;
inset: 0;
background: linear-gradient(to right,
rgba(0, 60, 180, 0.22) 0%,
rgba(0, 100, 220, 0.1) 55%,
rgba(255, 255, 255, 0.28) 100%);
z-index: 0;
}
.head {
width: 100%;
height: 70px;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 50px;
/* ====== 左侧装饰区 ====== */
.hero-section {
position: absolute;
right: 26%;
top: 5%;
width: 46%;
height: 50%;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
.text1 {
font-size: 32px;
font-family: DINAlternate;
font-weight: 400;
color: #4188FE;
line-height: 20px;
letter-spacing: 6px;
text-shadow: 0px 2px 4px rgba(58, 136, 221, 0.32);
margin-left: 40px;
/* 漂浮运动 emoji */
.float-shape {
position: absolute;
font-size: 42px;
filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.15));
user-select: none;
&.s1 {
top: 12%;
left: 15%;
animation: floatUp 3.2s ease-in-out infinite;
}
.register {
width: 68px;
height: 32px;
background: #4A8EFE;
border-radius: 16px;
text-align: center;
line-height: 32px;
font-size: 14px;
font-family: PingFangSC;
font-weight: 400;
color: #FFFFFF;
margin-right: 40px;
cursor: pointer;
&.s2 {
top: 65%;
left: 8%;
animation: floatUpAlt 2.8s ease-in-out infinite;
animation-delay: 0.5s;
}
&.s3 {
top: 30%;
left: 55%;
animation: floatUp 3.6s ease-in-out infinite;
animation-delay: 1s;
}
&.s4 {
top: 75%;
left: 48%;
animation: floatUpAlt 2.4s ease-in-out infinite;
animation-delay: 1.4s;
}
}
.center {
.text2 {
font-size: 40px;
/* 主文案 */
.hero-content {
position: relative;
z-index: 2;
text-align: center;
color: white;
.hero-logo {
display: flex;
justify-content: center;
margin-bottom: 20px;
svg {
filter: drop-shadow(0 4px 20px rgba(255, 255, 255, 0.3));
}
}
.hero-title {
font-size: 44px;
font-weight: 900;
color: white;
text-shadow: 0 2px 12px rgba(0, 60, 180, 0.5), 0 4px 24px rgba(0, 0, 0, 0.3);
margin: 0 0 8px;
letter-spacing: 4px;
}
.hero-sub {
font-size: 13px;
letter-spacing: 4px;
color: rgba(255, 255, 255, 0.7);
margin: 0 0 22px;
font-weight: 400;
}
.hero-divider {
width: 72px;
height: 3px;
border-radius: 2px;
background: linear-gradient(90deg, rgba(255, 255, 255, 0.1), white, rgba(255, 255, 255, 0.1));
margin: 0 auto 18px;
}
.hero-slogan {
font-size: 17px;
color: rgba(255, 255, 255, 0.92);
font-weight: 500;
margin: 0 0 28px;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.hero-tags {
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
.tag {
padding: 6px 16px;
background: rgba(0, 100, 255, 0.25);
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 20px;
font-size: 13px;
color: white;
backdrop-filter: blur(10px);
font-weight: 600;
text-shadow: 0 1px 4px rgba(0, 40, 120, 0.4);
}
}
}
}
/* ====== 右侧登录卡片 ====== */
.login-card {
position: absolute;
right: 10%;
top: 43%;
transform: translateY(-50%);
z-index: 2;
width: 440px;
background: white;
border-radius: 28px;
overflow: hidden;
box-shadow:
0 30px 80px rgba(0, 0, 0, 0.22),
0 0 0 1px rgba(255, 255, 255, 0.6);
animation: cardIn 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
background: rgba(255, 255, 255, 0.6);
.card-top-bar {
height: 10px;
background: linear-gradient(90deg, #00c3ff, #0099ff, #005ce6, #00aaff, #4dd6ff);
display: flex;
align-items: center;
padding: 0 16px;
gap: 6px;
position: relative;
.dot {
display: none;
/* 纯彩条,保留结构 */
}
}
.card-body {
padding: 66px 40px 80px;
.card-icon {
font-size: 44px;
text-align: center;
margin-bottom: 10px;
line-height: 1;
}
.card-title {
font-size: 26px;
font-weight: 800;
color: #4188FE;
// text-align: center;
margin: 0 0 6px;
letter-spacing: 1px;
// font-family: zhuiguang;
}
.card-subtitle {
font-size: 30px;
font-family: zhuiguang;
font-weight: 400;
color: #4188FE;
line-height: 20px;
// letter-spacing: 6px;
text-shadow: 0px 2px 4px rgba(58, 136, 221, 0.32);
margin-left: 40px;
// margin-left: 40px;
text-align: left;
margin-bottom: 50px;
}
}
.formIpt {
width: 100%;
height: 154px;
.el-form {
.login-form {
:deep(.el-form-item) {
width: 427px;
margin-left: 40px;
margin-bottom: 34px;
border: 1px solid rgba(0, 0, 0, 0.15);
margin-bottom: 18px;
.el-form-item__content {
margin-left: 0 !important;
.el-input__wrapper {
height: 52px;
border-radius: 14px;
background: #fff;
box-shadow: none !important;
padding: 0 16px;
transition: all 0.25s ease;
border: 2px solid #edf0f8;
.el-input {
height: 50px !important;
&:hover {
border-color: #4db8ff;
background: #f0f8ff;
}
&.is-focus {
border-color: #0099ff;
background: #fff;
box-shadow: 0 0 0 4px rgba(0, 153, 255, 0.12) !important;
}
}
.el-input__prefix-inner {
color: #0099ff;
font-size: 17px;
}
input {
font-size: 15px;
color: #2c3e50;
background: transparent;
&::placeholder {
color: #c0ccd8;
}
}
}
}
:deep(input:-webkit-autofill) {
-webkit-box-shadow: 0 0 0 1000px #fff inset
-webkit-box-shadow: 0 0 0 1000px #f8faff inset !important;
-webkit-text-fill-color: #2c3e50 !important;
}
:deep(.el-input-group__prepend) {
background-color: #fff !important;
font-size: 14px;
font-family: PingFangSC;
font-weight: 400;
color: #949DB8;
border-right: 0 !important;
box-shadow: none !important;
}
:deep(.el-input__wrapper) {
box-shadow: none !important;
}
}
.forgetPass {
height: 20px;
display: flex;
align-items: center;
justify-content: right;
margin-right: 40px;
margin-top: -5px;
cursor: pointer;
p {
font-size: 14px;
font-family: PingFangSC;
font-weight: 400;
color: #3F465A;
}
}
.btnName {
width: 445px;
height: 60px;
background: linear-gradient(270deg, #4188FE 0%, #7DAEFF 100%);
border-radius: 30px;
border: 1px solid rgba(0, 0, 0, 0.15);
margin: 0 auto;
margin-top: 102px;
cursor: pointer;
.text3 {
font-size: 24px;
font-family: PingFangSC;
font-weight: 500;
color: #FFFFFF;
// text-shadow: 0px 2px 1px #458AFE;
text-align: center;
margin-top: 14px;
}
}
}
.registerDialog,
.ModifyPwdDialog {
width: 508px;
height: 643px;
background: #fff;
border-radius: 4px;
position: absolute;
right: 260px;
top: 192px;
.head {
width: 100%;
height: 70px;
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 50px;
.register {
font-size: 32px;
font-family: PingFangSC;
font-weight: 400;
color: #4188FE;
letter-spacing: 6px;
text-shadow: 0px 2px 4px rgba(58, 136, 221, 0.32);
margin-left: 40px;
}
.descript {
margin-right: 40px;
font-size: 14px;
font-family: PingFangSC;
font-weight: 400;
span:nth-of-type(1) {
color: #949DB8;
}
span:nth-of-type(2) {
cursor: pointer;
color: #4A8EFE;
margin-left: 10px;
}
}
}
.registerIpt {
width: 100%;
height: 254px;
.el-form {
:deep(.el-form-item) {
width: 427px;
margin-left: 40px;
margin-bottom: 34px;
// border: 1px solid rgba(0, 0, 0, 0.15);
.el-form-item__content {
margin-left: 0 !important;
.el-input {
height: 50px !important;
}
}
}
.getCode {
// color: #4A8EFE;
color: gray;
cursor: not-allowed;
}
}
:deep(.el-progress) {
width: 100% !important;
margin-top: 5px;
}
}
.btnName {
width: 445px;
height: 60px;
background: linear-gradient(270deg, #4188FE 0%, #7DAEFF 100%);
border-radius: 30px;
border: 1px solid rgba(0, 0, 0, 0.15);
margin: 0 auto;
margin-top: 22px;
cursor: pointer;
.text3 {
font-size: 24px;
font-family: PingFangSC;
font-weight: 500;
color: #FFFFFF;
// text-shadow: 0px 2px 1px #458AFE;
text-align: center;
margin-top: 14px;
}
}
}
.ModifyPwdDialog {
.btnName1 {
width: 100%;
height: 60px;
margin-top: -22px;
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
.cancle {
width: 120px;
height: 40px;
background: #FAFAFA;
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.15);
font-size: 14px;
font-family: PingFangSC;
font-weight: 400;
color: rgba(0, 0, 0, 0.65);
text-align: center;
line-height: 40px;
margin-right: 14px;
.submit-btn {
width: 100%;
height: 54px;
background: linear-gradient(135deg, #00aaff 0%, #005ce6 100%);
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-top: 40px;
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
box-shadow: 0 8px 28px rgba(0, 120, 255, 0.45);
user-select: none;
span {
font-size: 17px;
font-weight: 700;
color: white;
letter-spacing: 3px;
text-shadow: 0 1px 4px rgba(0, 40, 120, 0.3);
}
&:hover {
transform: translateY(-3px) scale(1.02);
box-shadow: 0 16px 40px rgba(0, 120, 255, 0.6);
}
&:active {
transform: translateY(1px) scale(0.99);
box-shadow: 0 4px 14px rgba(0, 120, 255, 0.3);
}
}
.rest {
width: 120px;
height: 40px;
font-size: 14px;
background: #0486FE;
border-radius: 4px;
font-family: PingFangSC;
font-weight: 500;
color: #FFFFFF;
.card-footer {
text-align: center;
line-height: 40px;
cursor: pointer;
font-size: 13px;
color: #b0bec5;
margin: 16px 0 0;
}
}
}