Files
OA/app/home/view/login/index.html
T
2026-07-24 10:53:44 +08:00

310 lines
16 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="renderer" content="webkit" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{:get_system_config('web','admin_title')}</title>
<link rel="stylesheet" href="{__GOUGU__}/layui/css/layui.css?v={:get_system_config('system','version')}" media="all">
<style type="text/css">
*{margin:0;padding:0;box-sizing:border-box;}
html,body{width:100%;height:100%;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','SF Pro Display','Helvetica Neue',sans-serif;}
body{background:linear-gradient(160deg,#f5f3f0 0%,#eaecf0 25%,#f0f2f5 50%,#e8ecf1 75%,#f4f2ef 100%);}
/* 背景粒子画布 */
#bg-layer{position:fixed;top:0;left:0;width:100%;height:100%;z-index:0;}
canvas#bg-canvas{display:block;width:100%;height:100%;}
/* 网格叠加 */
#grid-overlay{position:fixed;top:0;left:0;width:100%;height:100%;z-index:1;pointer-events:none;
background-image:
linear-gradient(rgba(180,190,205,.12) 1px,transparent 1px),
linear-gradient(90deg,rgba(180,190,205,.12) 1px,transparent 1px);
background-size:80px 80px;
animation:gridShift 20s linear infinite;}
@keyframes gridShift{0%{transform:translate(0,0)}100%{transform:translate(0,80px)}}
/* 数据流垂直线 */
.flow-v{position:fixed;z-index:1;pointer-events:none;width:1px;background:linear-gradient(180deg,transparent,rgba(160,175,200,.1),transparent);}
.flow-v:nth-child(1){left:15%;height:60%;top:20%;animation:flowV 14s ease-in-out infinite;}
.flow-v:nth-child(2){left:38%;height:45%;top:10%;animation:flowV 11s ease-in-out infinite 3s;}
.flow-v:nth-child(3){left:62%;height:55%;top:30%;animation:flowV 16s ease-in-out infinite 6s;}
.flow-v:nth-child(4){left:85%;height:40%;top:15%;animation:flowV 13s ease-in-out infinite 9s;}
@keyframes flowV{0%,100%{opacity:.15;transform:scaleY(.8)}50%{opacity:.4;transform:scaleY(1.05)}}
/* 数据流水平线 */
.flow-h{position:fixed;z-index:1;pointer-events:none;height:1px;background:linear-gradient(90deg,transparent,rgba(160,175,200,.1),transparent);}
.flow-h:nth-child(5){top:28%;width:50%;left:25%;animation:flowH 18s ease-in-out infinite 2s;}
.flow-h:nth-child(6){top:52%;width:40%;left:10%;animation:flowH 15s ease-in-out infinite 7s;}
.flow-h:nth-child(7){top:74%;width:55%;left:35%;animation:flowH 20s ease-in-out infinite 4s;}
@keyframes flowH{0%,100%{opacity:.1;transform:scaleX(.7)}50%{opacity:.35;transform:scaleX(1.1)}}
/* 环境光 orb */
.amb-orb{position:fixed;border-radius:50%;z-index:1;pointer-events:none;filter:blur(80px);}
.amb-orb:nth-child(8){width:500px;height:500px;top:-10%;left:-8%;background:rgba(180,200,230,.18);animation:orbFloat1 8s ease-in-out infinite;}
.amb-orb:nth-child(9){width:400px;height:400px;bottom:-5%;right:-5%;background:rgba(200,190,220,.14);animation:orbFloat2 10s ease-in-out infinite 3s;}
.amb-orb:nth-child(10){width:350px;height:350px;top:40%;right:10%;background:rgba(210,215,230,.1);animation:orbFloat3 12s ease-in-out infinite 6s;}
@keyframes orbFloat1{0%,100%{transform:translate(0,0)}50%{transform:translate(40px,30px)}}
@keyframes orbFloat2{0%,100%{transform:translate(0,0)}50%{transform:translate(-30px,-25px)}}
@keyframes orbFloat3{0%,100%{transform:translate(0,0)}50%{transform:translate(-20px,20px)}}
/* 主容器 */
#container{width:100%;height:100%;position:fixed;top:0;left:0;z-index:99;display:flex;flex-direction:column;align-items:center;justify-content:center;}
/* 品牌区域 */
.brand-area{margin-bottom:24px;position:relative;z-index:2;text-align:center;}
.brand-text{font-size:28px;font-weight:300;letter-spacing:8px;color:rgba(60,70,90,.75);
background:linear-gradient(135deg,#6b7d95,#8a9bb5,#6b7d95);-webkit-background-clip:text;
-webkit-text-fill-color:transparent;background-clip:text;}
.brand-sub{font-size:13px;font-weight:300;letter-spacing:6px;color:rgba(130,145,170,.55);margin-top:8px;}
/* 登录卡片 */
.login-card{position:relative;width:400px;padding:40px 38px 34px;z-index:2;
background:rgba(255,255,255,.45);backdrop-filter:blur(40px) saturate(1.4);-webkit-backdrop-filter:blur(40px) saturate(1.4);
border-radius:22px;
border:1px solid rgba(255,255,255,.5);
box-shadow:
0 2px 30px rgba(0,0,0,.04),
0 8px 60px rgba(0,0,0,.05),
0 0 0 .5px rgba(255,255,255,.8) inset,
0 1px 3px rgba(255,255,255,.6) inset;
transition:box-shadow .5s;}
.login-card:hover{box-shadow:
0 2px 40px rgba(0,0,0,.05),
0 12px 70px rgba(0,0,0,.06),
0 0 0 .5px rgba(255,255,255,.9) inset,
0 1px 3px rgba(255,255,255,.7) inset;}
/* 珠光边框 */
.login-card::before{content:'';position:absolute;inset:-1px;border-radius:23px;padding:1px;
background:linear-gradient(135deg,
rgba(200,210,225,.5),rgba(255,255,255,.7) 20%,rgba(220,215,230,.4) 40%,
rgba(255,255,255,.6) 60%,rgba(190,200,215,.5) 80%,rgba(255,255,255,.5));
-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
-webkit-mask-composite:xor;mask-composite:exclude;z-index:-1;pointer-events:none;
animation:pearlShift 5s ease-in-out infinite;}
@keyframes pearlShift{0%,100%{opacity:.85}50%{opacity:1}}
/* 卡片顶部高光线 */
.login-card::after{content:'';position:absolute;top:0;left:15%;width:70%;height:1px;
background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent);border-radius:1px;}
/* 输入框组 */
.input-group{position:relative;margin-bottom:22px;}
.input-group .icon-prefix{position:absolute;left:15px;top:50%;transform:translateY(-50%);z-index:3;
pointer-events:none;transition:all .3s;display:flex;align-items:center;}
.input-group .icon-prefix svg{width:16px;height:16px;stroke:rgba(140,155,180,.4);fill:none;stroke-width:1.5;transition:stroke .3s;}
.input-group input{width:100%;height:50px;padding:0 16px 0 42px;
background:rgba(245,247,250,.5);border:1px solid rgba(200,210,225,.35);border-radius:14px;
outline:none;color:#3a4458;font-size:14px;font-weight:400;
transition:all .35s cubic-bezier(.25,.8,.25,1);letter-spacing:.5px;}
.input-group input::placeholder{color:rgba(150,165,185,.4);font-weight:300;}
.input-group input:focus{background:rgba(255,255,255,.7);border-color:rgba(160,175,200,.5);
box-shadow:0 0 0 3px rgba(180,190,210,.08),0 2px 12px rgba(0,0,0,.03);}
.input-group input:focus~.icon-prefix svg{stroke:rgba(110,125,155,.6);}
/* 输入框软蓝色下划线发光 */
.input-group .flow-bar{position:absolute;bottom:0;left:4px;width:calc(100% - 8px);height:2px;border-radius:0 0 2px 2px;
background:linear-gradient(90deg,transparent,rgba(140,180,225,.5),rgba(180,170,220,.45),rgba(140,180,225,.5),transparent);
background-size:200% 100%;animation:flowBar 3.5s ease-in-out infinite;opacity:.6;
filter:blur(1px);}
.input-group input:focus~.flow-bar{opacity:.9;filter:blur(.5px);
background:linear-gradient(90deg,transparent,rgba(120,170,225,.7),rgba(170,155,220,.6),rgba(120,170,225,.7),transparent);}
@keyframes flowBar{0%{background-position:200% 0}100%{background-position:-200% 0}}
/* 验证码行 */
.captcha-row{display:flex;gap:10px;align-items:center;}
.captcha-row .input-group{flex:1;margin-bottom:0;}
.captcha_img img{width:120px;height:50px;border-radius:14px;cursor:pointer;
border:1px solid rgba(200,210,225,.35);transition:all .3s;filter:brightness(.98);}
.captcha_img img:hover{border-color:rgba(160,175,200,.5);box-shadow:0 2px 12px rgba(0,0,0,.03);}
/* 登录按钮 - 淡蓝到柔紫渐变 */
#login-submit{width:100%;height:50px;margin-top:14px;border:none;border-radius:14px;font-size:15px;
letter-spacing:2px;cursor:pointer;color:#fff;font-weight:400;
background:linear-gradient(135deg,#9bb5d4,#b8a0d4,#9bb5d4);background-size:200% 100%;
animation:btnShimmer 5s ease-in-out infinite;
box-shadow:0 2px 16px rgba(150,155,200,.2),0 0 0 .5px rgba(255,255,255,.4) inset;
transition:all .4s cubic-bezier(.25,.8,.25,1);}
#login-submit:hover{background:linear-gradient(135deg,#a8c0e0,#c4acdf,#a8c0e0);background-size:200% 100%;
box-shadow:0 4px 24px rgba(150,155,200,.3),0 0 0 .5px rgba(255,255,255,.5) inset;
transform:translateY(-1px);}
#login-submit:active{transform:translateY(0) scale(.99);box-shadow:0 1px 8px rgba(150,155,200,.15);}
@keyframes btnShimmer{0%,100%{background-position:0% 50%}50%{background-position:100% 50%}}
/* 底部 */
.foot{position:fixed;bottom:30px;text-align:center;width:100%;z-index:99;font-size:11px;
color:rgba(150,165,185,.35);letter-spacing:2px;font-weight:300;}
/* 弹窗 */
.toast-overlay{position:fixed;inset:0;z-index:9998;pointer-events:none;
background:rgba(245,247,250,.35);backdrop-filter:blur(4px);opacity:0;transition:opacity .3s;}
.toast-overlay.show{opacity:1;pointer-events:all;}
.sci-toast{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%) scale(.85);z-index:9999;
pointer-events:none;opacity:0;transition:all .4s cubic-bezier(.25,.8,.25,1);}
.sci-toast.show{opacity:1;transform:translate(-50%,-50%) scale(1);}
.sci-toast-inner{position:relative;padding:30px 44px;min-width:260px;text-align:center;
background:rgba(255,255,255,.75);backdrop-filter:blur(30px) saturate(1.8);-webkit-backdrop-filter:blur(30px) saturate(1.8);
border-radius:20px;border:1px solid rgba(255,255,255,.6);
box-shadow:0 4px 40px rgba(0,0,0,.06),0 1px 2px rgba(255,255,255,.8) inset;}
.sci-toast-inner::before{content:'';position:absolute;inset:-1px;border-radius:21px;padding:1px;
background:linear-gradient(135deg,rgba(200,210,225,.4),rgba(255,255,255,.5),rgba(200,210,225,.4));
-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
-webkit-mask-composite:xor;mask-composite:exclude;z-index:-1;}
.sci-toast .icon-cyber{width:52px;height:52px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
font-size:20px;font-weight:300;margin-bottom:14px;position:relative;}
.sci-toast.success .icon-cyber{color:#6ba88a;background:rgba(130,190,155,.1);box-shadow:0 0 20px rgba(130,190,155,.15);}
.sci-toast.error .icon-cyber{color:#c48080;background:rgba(200,140,140,.1);box-shadow:0 0 20px rgba(200,140,140,.15);}
.sci-toast .toast-msg{color:rgba(60,70,90,.75);font-size:14px;letter-spacing:1px;font-weight:300;}
</style>
</head>
<body>
<div id="bg-layer"><canvas id="bg-canvas"></canvas></div>
<div id="grid-overlay"></div>
<div class="flow-v"></div><div class="flow-v"></div><div class="flow-v"></div><div class="flow-v"></div>
<div class="flow-h"></div><div class="flow-h"></div><div class="flow-h"></div>
<div class="amb-orb"></div><div class="amb-orb"></div><div class="amb-orb"></div>
<div id="container">
<div class="brand-area">
<div class="brand-text">唯实夕创OA</div>
<div class="brand-sub">Welcome Back</div>
</div>
<div class="login-card">
<form class="layui-form" id="gougu-login">
<div class="input-group">
<span class="icon-prefix"><svg viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8"/></svg></span>
<input type="text" name="username" lay-verify="required" value="" placeholder="请输入账户或手机号码" lay-reqText="请输入账户或手机号码" autocomplete="off">
<div class="flow-bar"></div>
</div>
<div class="input-group">
<span class="icon-prefix"><svg viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg></span>
<input type="password" name="password" lay-verify="required" value="" placeholder="请输入密码" lay-reqText="请输入密码" autocomplete="off">
<div class="flow-bar"></div>
</div>
<div class="input-group">
<div class="captcha-row">
<div class="input-group">
<input type="text" name="captcha" lay-verify="required" placeholder="请输入验证码" lay-reqText="请输入验证码" autocomplete="off">
<div class="flow-bar"></div>
</div>
<div class="captcha_img">
{:captcha_img()}
<input type="hidden" value="{:make_token()}"/>
</div>
</div>
</div>
<button id="login-submit" lay-submit lay-filter="login-submit">登 入 系 统</button>
</form>
</div>
</div>
<div class="foot">{:get_system_config('web','admin_title')}</div>
<div class="toast-overlay" id="toastOverlay"></div>
<div class="sci-toast" id="sciToast">
<div class="sci-toast-inner">
<div class="icon-cyber" id="toastIcon"></div>
<div class="toast-msg" id="toastMsg"></div>
</div>
</div>
<script src="{__GOUGU__}/layui/layui.js?v={:get_system_config('system','version')}"></script>
<script type="text/javascript">
var canvas=document.querySelector("#bg-canvas"),ctx=canvas.getContext("2d");
canvas.width=window.innerWidth,canvas.height=window.innerHeight;
window.addEventListener("resize",function(){canvas.width=window.innerWidth,canvas.height=window.innerHeight;});
var particles=[],COUNT=100;
for(var i=0;i<COUNT;i++){
particles.push({
x:Math.random()*canvas.width,
y:Math.random()*canvas.height,
r:Math.random()*2+.5,
vx:(Math.random()-.5)*.15,
vy:(Math.random()-.5)*.15,
baseAlpha:Math.random()*.25+.08,
alphaDir:Math.random()>.5?1:-1,
alphaSpd:Math.random()*.008+.002,
alpha:Math.random()*.3+.05
});
}
var mouse={x:canvas.width/2,y:canvas.height/2};
canvas.addEventListener("mousemove",function(e){mouse.x=e.pageX;mouse.y=e.pageY;});
canvas.addEventListener("mouseleave",function(){mouse.x=canvas.width/2;mouse.y=canvas.height/2;});
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<particles.length;i++){
var p=particles[i];
p.x+=p.vx;p.y+=p.vy;
if(p.x<-10)p.x=canvas.width+10;if(p.x>canvas.width+10)p.x=-10;
if(p.y<-10)p.y=canvas.height+10;if(p.y>canvas.height+10)p.y=-10;
p.alpha+=p.alphaSpd*p.alphaDir;
if(p.alpha>=p.baseAlpha+.15)p.alphaDir=-1;if(p.alpha<=p.baseAlpha-.08)p.alphaDir=1;
ctx.beginPath();ctx.arc(p.x,p.y,p.r,0,Math.PI*2);
ctx.fillStyle="rgba(150,165,190,"+p.alpha+")";ctx.fill();
ctx.beginPath();ctx.arc(p.x,p.y,p.r*2.5,0,Math.PI*2);
ctx.fillStyle="rgba(180,195,215,"+(p.alpha*.2)+")";ctx.fill();
}
for(var i=0;i<particles.length;i++){
for(var j=i+1;j<particles.length;j++){
var dx=particles[i].x-particles[j].x,dy=particles[i].y-particles[j].y;
var dist=Math.sqrt(dx*dx+dy*dy),maxD=130;
var md=Math.sqrt(Math.pow((particles[i].x+particles[j].x)/2-mouse.x,2)+Math.pow((particles[i].y+particles[j].y)/2-mouse.y,2));
if(md<180)maxD=160;
if(dist<maxD){
ctx.beginPath();ctx.moveTo(particles[i].x,particles[i].y);ctx.lineTo(particles[j].x,particles[j].y);
var a=(1-dist/maxD)*.06;if(md<180)a*=1.4;
ctx.strokeStyle="rgba(150,170,195,"+a+")";ctx.lineWidth=.4;ctx.stroke();
}
}
}
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
function showSciToast(msg,type,duration){
var t=document.getElementById('sciToast'),o=document.getElementById('toastOverlay'),
ic=document.getElementById('toastIcon'),me=document.getElementById('toastMsg');
t.className='sci-toast '+type;me.textContent=msg;
ic.innerHTML=type==='success'?'&#10003;':'&#10007;';
t.classList.add('show');o.classList.add('show');
clearTimeout(t._timer);
t._timer=setTimeout(function(){t.classList.remove('show');o.classList.remove('show');},duration||2000);
}
layui.use(['form'],function(){
var form=layui.form,$=layui.$;
if(top.location!=self.location)top.location=self.location;
form.on('submit(login-submit)',function(data){
$.ajax({
url:"/home/login/login_submit",
data:$('#gougu-login').serialize(),
type:'post',
async:false,
success:function(res){
if(res.code===0){
showSciToast(res.msg,'success',2000);
var d=new Date();d.setTime(d.getTime()+(-1*24*60*60*1000));
document.cookie="gougutab=''; expires="+d.toGMTString()+"; path=/";
setTimeout(function(){parent.document.location.href="/";},1600);
}else{
showSciToast(res.msg,'error',2000);
setTimeout(function(){$('[alt="captcha"]').click();},800);
}
}
});
return false;
});
});
</script>
</body>
</html>