diff --git a/server/corpus-agent/server.py b/server/corpus-agent/server.py index 289170e..fe27dc9 100644 --- a/server/corpus-agent/server.py +++ b/server/corpus-agent/server.py @@ -33,7 +33,7 @@ from engine import ( class Settings: APP_NAME = "语料采集系统 Corpus Agent" - VERSION = "1.0.1" + VERSION = "1.1.0" # 存储路径 DATA_DIR = Path(os.environ.get("CORPUS_DATA_DIR", "./data")) @@ -85,6 +85,10 @@ class CorpusSave(BaseModel): class LoginRequest(BaseModel): gitea_token: str +class PasswordLoginRequest(BaseModel): + username: str + password: str + class ChatRequest(BaseModel): message: str persona: str = "zhuyuan" # zhuyuan | shuangyan @@ -294,6 +298,50 @@ async def login(req: LoginRequest): } } +@app.post("/api/auth/login/password") +async def login_with_password(req: PasswordLoginRequest): + """使用代码仓库账号密码登录(复用首页的 /api/verify 接口)""" + import urllib.request + + if not req.username.strip() or not req.password: + raise HTTPException(400, "账号和密码不能为空") + + try: + # 调用本地验证接口(nginx: /api/verify → 127.0.0.1:3905/verify) + verify_data = json.dumps({"user": req.username, "password": req.password}).encode() + verify_req = urllib.request.Request( + "http://127.0.0.1:3905/verify", + data=verify_data, + headers={"Content-Type": "application/json"} + ) + with urllib.request.urlopen(verify_req, timeout=10) as resp: + result = json.loads(resp.read().decode()) + + if not result.get("ok"): + raise HTTPException(401, "账号或密码错误") + + username = result.get("username", req.username) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(500, f"验证服务不可达: {str(e)}") + + token = create_session(username) + + # 统计现有语料 + corpus = load_corpus(username) + + return { + "ok": True, + "token": token, + "username": username, + "stats": { + "total_samples": len(corpus), + "total_chars": sum(len(json.dumps(s, ensure_ascii=False)) for s in corpus), + } + } + @app.get("/api/auth/check") async def check_session(token: str = Query(...)): username = get_user_from_token(token) diff --git a/server/corpus-agent/static/index.html b/server/corpus-agent/static/index.html index 8cad180..5350cc6 100644 --- a/server/corpus-agent/static/index.html +++ b/server/corpus-agent/static/index.html @@ -121,21 +121,24 @@

🧠 语料采集系统 · Corpus Agent

自动采集 · 脱敏 · 格式化 · 对话式语料分析

-
v1.0.1 · 国作登字-2026-A-00037559
+
v1.1.0 · 国作登字-2026-A-00037559

登录

-

- 使用 Gitea Access Token 登录 +

+ 使用代码仓库账号登录

- + +
+
+

- 访问 Gitea → 设置 → 应用 创建 Token + 与 光湖联邦首页 使用同一套账号

@@ -288,7 +291,7 @@ @@ -311,18 +314,22 @@ async function api(method, path, body) { // ─── Login ───────────────────────────────────────────────── async function login() { - const t = document.getElementById('token-input').value.trim(); - if (!t) return alert('请输入Token'); - const r = await fetch(`${API}/api/auth/login`, { + const user = document.getElementById('login-user').value.trim(); + const pass = document.getElementById('login-pass').value; + const errEl = document.getElementById('login-error'); + if (!user || !pass) { errEl.textContent = '请输入账号和密码'; errEl.style.display = 'block'; return; } + errEl.style.display = 'none'; + const r = await fetch(`${API}/api/auth/login/password`, { method: 'POST', headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({gitea_token: t}) + body: JSON.stringify({username: user, password: pass}) }); const d = await r.json(); - if (!d.ok) return alert('登录失败: ' + JSON.stringify(d)); + if (!d.ok) { errEl.textContent = d.detail || '登录失败'; errEl.style.display = 'block'; return; } token = d.token; username = d.username; localStorage.setItem('corpus_token', token); + document.getElementById('login-pass').value = ''; document.getElementById('login-section').classList.add('hidden'); document.getElementById('main-section').classList.remove('hidden'); document.getElementById('display-name').textContent = username;