- FastAPI backend with SQLAlchemy ORM and SQLite - AI chatbot with OpenAI-compatible LLM integration (SSE streaming) - Admin panel for content management, LLM config, token management - Anonymous access with 3-question limit, token-based access control - Recruiter intent detection with admin notification - Resume generator (JD-based, Markdown to Word export) - Chinese localized public interface Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
65 lines
2.6 KiB
HTML
65 lines
2.6 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>CareerBot - Access</title>
|
||
<link rel="stylesheet" href="/static/css/style.css">
|
||
</head>
|
||
<body>
|
||
<div class="login-container">
|
||
<div class="login-card">
|
||
<h1>CareerBot</h1>
|
||
<p>请输入访问令牌以获得完整体验</p>
|
||
<input type="text" id="token-input" placeholder="请输入 Access Token..." autocomplete="off">
|
||
<button class="btn-primary" onclick="verifyToken()">进入</button>
|
||
<div class="error-msg" id="error-msg"></div>
|
||
<div style="margin-top:16px;padding-top:16px;border-top:1px solid #e2e8f0;text-align:center;">
|
||
<p style="font-size:13px;color:#64748b;margin-bottom:8px;">没有令牌?您可以匿名浏览,但智能对话仅限3次提问。<br>如需更多提问次数,请联系管理员获取访问令牌。</p>
|
||
<button class="btn-secondary" onclick="enterAnonymous()" style="font-size:14px;padding:8px 24px;border-radius:8px;border:1px solid #cbd5e1;background:#f8fafc;cursor:pointer;color:#475569;">匿名访问</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<script>
|
||
document.getElementById('token-input').addEventListener('keydown', e => {
|
||
if (e.key === 'Enter') verifyToken();
|
||
});
|
||
|
||
async function verifyToken() {
|
||
const token = document.getElementById('token-input').value.trim();
|
||
if (!token) return;
|
||
const errEl = document.getElementById('error-msg');
|
||
errEl.style.display = 'none';
|
||
try {
|
||
const resp = await fetch('/api/verify-token', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ token }),
|
||
});
|
||
if (resp.ok) {
|
||
window.location.href = '/';
|
||
} else {
|
||
errEl.textContent = '无效或已过期的访问令牌';
|
||
errEl.style.display = 'block';
|
||
}
|
||
} catch (e) {
|
||
errEl.textContent = '网络错误,请稍后重试';
|
||
errEl.style.display = 'block';
|
||
}
|
||
}
|
||
|
||
async function enterAnonymous() {
|
||
try {
|
||
const resp = await fetch('/api/anonymous-entry', { method: 'POST' });
|
||
if (resp.ok) {
|
||
window.location.href = '/';
|
||
}
|
||
} catch (e) {
|
||
document.getElementById('error-msg').textContent = '网络错误,请稍后重试';
|
||
document.getElementById('error-msg').style.display = 'block';
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|