166 lines
6.4 KiB
Smarty
166 lines
6.4 KiB
Smarty
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>统一认证中心 - 登录</title>
|
||
<style>
|
||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
min-height: 100vh; display: flex; align-items: center; justify-content: center;
|
||
}
|
||
.card {
|
||
background: #fff; border-radius: 12px; box-shadow: 0 20px 60px rgba(0,0,0,.2);
|
||
width: 420px; max-width: 92vw; padding: 40px 36px;
|
||
}
|
||
.logo { text-align: center; margin-bottom: 28px; }
|
||
.logo h1 { font-size: 22px; color: #1a1a2e; font-weight: 600; }
|
||
.logo p { font-size: 13px; color: #8a8fa3; margin-top: 6px; }
|
||
.field { margin-bottom: 18px; }
|
||
.field label { display: block; font-size: 13px; color: #5a6072; margin-bottom: 7px; }
|
||
.field input {
|
||
width: 100%; height: 44px; padding: 0 14px; font-size: 14px;
|
||
border: 1px solid #dcdfe8; border-radius: 8px; outline: none; transition: border-color .2s;
|
||
}
|
||
.field input:focus { border-color: #667eea; }
|
||
.btn {
|
||
width: 100%; height: 44px; border: none; border-radius: 8px; cursor: pointer;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #fff; font-size: 15px; font-weight: 500; transition: opacity .2s;
|
||
}
|
||
.btn:hover { opacity: .9; }
|
||
.btn:disabled { opacity: .6; cursor: not-allowed; }
|
||
.error {
|
||
background: #fff2f0; border: 1px solid #ffccc7; color: #cf1322;
|
||
padding: 10px 12px; border-radius: 6px; font-size: 13px; margin-bottom: 16px; display: none;
|
||
}
|
||
.tenant-list { list-style: none; }
|
||
.tenant-item {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
padding: 14px 16px; border: 1px solid #e4e7ee; border-radius: 8px;
|
||
margin-bottom: 12px; cursor: pointer; transition: all .2s;
|
||
}
|
||
.tenant-item:hover { border-color: #667eea; background: #f7f8ff; }
|
||
.tenant-name { font-size: 15px; color: #1a1a2e; font-weight: 500; }
|
||
.tenant-meta { font-size: 12px; color: #8a8fa3; margin-top: 3px; }
|
||
.tenant-arrow { color: #c0c4d0; font-size: 18px; }
|
||
.tip { text-align: center; font-size: 12px; color: #8a8fa3; margin-top: 20px; }
|
||
.back { text-align: center; margin-top: 14px; }
|
||
.back a { font-size: 13px; color: #667eea; text-decoration: none; cursor: pointer; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="card">
|
||
<div class="logo">
|
||
<h1>云泽统一认证中心</h1>
|
||
<p>{{if eq .Step "tenant"}}请选择要进入的企业{{else}}登录后即可使用全部应用{{end}}</p>
|
||
</div>
|
||
|
||
<div class="error" id="error"></div>
|
||
|
||
{{if eq .Step "tenant"}}
|
||
<!-- 企业选择步骤 -->
|
||
<ul class="tenant-list">
|
||
{{range .Tenants}}
|
||
<li class="tenant-item" onclick="chooseTenant({{.Tid}})">
|
||
<div>
|
||
<div class="tenant-name">{{.TenantName}}</div>
|
||
<div class="tenant-meta">{{if .Name}}{{.Name}} · {{end}}企业ID {{.Tid}}</div>
|
||
</div>
|
||
<span class="tenant-arrow">›</span>
|
||
</li>
|
||
{{end}}
|
||
</ul>
|
||
<div class="back"><a onclick="logout()">切换账号</a></div>
|
||
{{else}}
|
||
<!-- 账号密码登录 -->
|
||
<form id="loginForm" onsubmit="return submitLogin(event)">
|
||
<div class="field">
|
||
<label>账号</label>
|
||
<input id="account" type="text" placeholder="手机号 / 邮箱 / 企业账号" autocomplete="username" autofocus>
|
||
</div>
|
||
<div class="field">
|
||
<label>密码</label>
|
||
<input id="password" type="password" placeholder="请输入密码" autocomplete="current-password">
|
||
</div>
|
||
<button class="btn" id="submitBtn" type="submit">登 录</button>
|
||
</form>
|
||
{{end}}
|
||
|
||
<div class="tip">统一身份认证 · 一次登录,全平台通行</div>
|
||
</div>
|
||
|
||
<script>
|
||
var CLIENT_ID = "{{.ClientID}}";
|
||
var REDIRECT = "{{.Redirect}}";
|
||
|
||
function showError(msg) {
|
||
var el = document.getElementById('error');
|
||
el.textContent = msg;
|
||
el.style.display = 'block';
|
||
}
|
||
|
||
function submitLogin(e) {
|
||
e.preventDefault();
|
||
var account = document.getElementById('account').value.trim();
|
||
var password = document.getElementById('password').value;
|
||
if (!account) { showError('请输入账号'); return false; }
|
||
if (!password) { showError('请输入密码'); return false; }
|
||
|
||
var btn = document.getElementById('submitBtn');
|
||
btn.disabled = true;
|
||
btn.textContent = '登录中...';
|
||
|
||
fetch('/auth/login', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ account: account, password: password, client_id: CLIENT_ID, redirect: REDIRECT })
|
||
})
|
||
.then(function (r) { return r.json(); })
|
||
.then(function (res) {
|
||
if (res.code !== 200) {
|
||
showError(res.msg || '登录失败');
|
||
btn.disabled = false;
|
||
btn.textContent = '登 录';
|
||
return;
|
||
}
|
||
if (res.need_choose_tenant) {
|
||
window.location.href = '/auth/login?step=tenant&client_id=' + encodeURIComponent(CLIENT_ID) + '&redirect=' + encodeURIComponent(REDIRECT);
|
||
return;
|
||
}
|
||
if (res.redirect) { window.location.href = res.redirect; return; }
|
||
window.location.href = '/auth/login';
|
||
})
|
||
.catch(function () {
|
||
showError('网络异常,请稍后重试');
|
||
btn.disabled = false;
|
||
btn.textContent = '登 录';
|
||
});
|
||
return false;
|
||
}
|
||
|
||
function chooseTenant(tid) {
|
||
fetch('/auth/switch-tenant', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ tid: tid, client_id: CLIENT_ID, redirect: REDIRECT })
|
||
})
|
||
.then(function (r) { return r.json(); })
|
||
.then(function (res) {
|
||
if (res.code !== 200) { showError(res.msg || '切换失败'); return; }
|
||
if (res.redirect) { window.location.href = res.redirect; return; }
|
||
window.location.href = '/auth/login';
|
||
});
|
||
}
|
||
|
||
function logout() {
|
||
fetch('/auth/logout', { method: 'POST' }).then(function () {
|
||
window.location.href = '/auth/login?client_id=' + encodeURIComponent(CLIENT_ID) + '&redirect=' + encodeURIComponent(REDIRECT);
|
||
});
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|