162 lines
6.3 KiB
PHP
162 lines
6.3 KiB
PHP
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>AIWeb 后台登录</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
|
||
<style>
|
||
body {
|
||
min-height: 100vh;
|
||
font-family: Inter, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||
background:
|
||
radial-gradient(700px 400px at 15% 10%, rgba(37, 99, 235, .22), transparent 70%),
|
||
radial-gradient(700px 400px at 85% 90%, rgba(124, 58, 237, .18), transparent 70%),
|
||
#f1f5f9;
|
||
display: grid;
|
||
place-items: center;
|
||
padding: 1rem;
|
||
}
|
||
.login-shell {
|
||
width: min(980px, 100%);
|
||
display: grid;
|
||
grid-template-columns: 1.05fr .95fr;
|
||
background: #fff;
|
||
border-radius: 1rem;
|
||
overflow: hidden;
|
||
box-shadow: 0 28px 70px rgba(15, 23, 42, .18);
|
||
}
|
||
.login-cover {
|
||
background: linear-gradient(140deg, #0f172a, #1d4ed8 55%, #7c3aed);
|
||
color: #fff;
|
||
padding: 2.2rem 2rem;
|
||
position: relative;
|
||
}
|
||
.login-cover::after {
|
||
content: "";
|
||
position: absolute;
|
||
width: 260px;
|
||
height: 260px;
|
||
border-radius: 50%;
|
||
right: -70px;
|
||
bottom: -60px;
|
||
background: rgba(255, 255, 255, .16);
|
||
}
|
||
.login-form-wrap { padding: 2rem; }
|
||
.brand-pill {
|
||
width: 2.25rem;
|
||
height: 2.25rem;
|
||
border-radius: .7rem;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: linear-gradient(135deg, #2563eb, #7c3aed);
|
||
color: #fff;
|
||
font-weight: 700;
|
||
}
|
||
.captcha-box {
|
||
min-width: 120px;
|
||
height: 44px;
|
||
border-radius: .55rem;
|
||
border: 1px solid #cbd5e1;
|
||
background: #f8fafc;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
overflow: hidden;
|
||
}
|
||
@media (max-width: 900px) {
|
||
.login-shell { grid-template-columns: 1fr; }
|
||
.login-cover { display: none; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="login-shell">
|
||
<aside class="login-cover">
|
||
<span class="badge rounded-pill text-bg-light text-dark mb-3">安全后台</span>
|
||
<h1 class="h3 fw-bold mb-3">AIWeb 内容运营控制台</h1>
|
||
<p class="text-white-50">请输入账号、密码与验证码登录。系统内置失败次数限制与验证码轮换机制,降低暴力破解风险。</p>
|
||
<div class="mt-4 small text-white-50">
|
||
<div class="mb-2"><i class="bi bi-shield-lock me-1"></i> 登录失败限流(IP + 账号)</div>
|
||
<div class="mb-2"><i class="bi bi-image me-1"></i> 实时验证码校验</div>
|
||
<div><i class="bi bi-arrow-repeat me-1"></i> 验证码单次验证后即失效</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<main class="login-form-wrap">
|
||
<div class="d-flex align-items-center gap-2 mb-4">
|
||
<span class="brand-pill">AI</span>
|
||
<div>
|
||
<div class="fw-semibold">AIWeb Admin</div>
|
||
<div class="text-muted small">后台登录</div>
|
||
</div>
|
||
</div>
|
||
|
||
@if(session('status'))
|
||
<div class="alert alert-success py-2">{{ session('status') }}</div>
|
||
@endif
|
||
|
||
@if($errors->any())
|
||
<div class="alert alert-danger py-2">
|
||
<ul class="mb-0 small">
|
||
@foreach($errors->all() as $error)
|
||
<li>{{ $error }}</li>
|
||
@endforeach
|
||
</ul>
|
||
</div>
|
||
@endif
|
||
|
||
<form method="post" action="{{ route('admin.login.submit') }}" class="row g-3" autocomplete="off">
|
||
@csrf
|
||
<div class="col-12">
|
||
<label class="form-label">后台账号</label>
|
||
<input class="form-control" type="text" name="username" value="{{ old('username') }}" required maxlength="100" placeholder="请输入账号">
|
||
</div>
|
||
<div class="col-12">
|
||
<label class="form-label">后台密码</label>
|
||
<input class="form-control" type="password" name="password" required maxlength="255" placeholder="请输入密码">
|
||
</div>
|
||
<div class="col-7">
|
||
<label class="form-label">验证码</label>
|
||
<input class="form-control" type="text" name="captcha" required maxlength="5" minlength="5" placeholder="输入右侧验证码">
|
||
</div>
|
||
<div class="col-5">
|
||
<label class="form-label">图形验证码</label>
|
||
<button class="captcha-box w-100 p-0" id="refreshCaptcha" type="button" aria-label="点击刷新验证码">
|
||
<img id="captchaImage" src="{{ route('admin.captcha') }}" alt="验证码" style="width:100%;height:100%;object-fit:cover;">
|
||
</button>
|
||
</div>
|
||
<div class="col-12 d-grid mt-2">
|
||
<button class="btn btn-primary btn-lg" type="submit"><i class="bi bi-box-arrow-in-right me-1"></i>登录后台</button>
|
||
</div>
|
||
</form>
|
||
|
||
<div class="text-muted small mt-3">若连续输错多次,将被短时间锁定登录。</div>
|
||
</main>
|
||
</div>
|
||
|
||
<script>
|
||
(function () {
|
||
const button = document.getElementById('refreshCaptcha');
|
||
const image = document.getElementById('captchaImage');
|
||
|
||
const reloadCaptcha = () => {
|
||
image.src = '{{ route('admin.captcha') }}?t=' + Date.now();
|
||
};
|
||
|
||
button.addEventListener('click', reloadCaptcha);
|
||
|
||
window.addEventListener('pageshow', function () {
|
||
reloadCaptcha();
|
||
});
|
||
}());
|
||
</script>
|
||
</body>
|
||
</html>
|