feat: 增加可信应用免登录接入

This commit is contained in:
2026-08-03 18:28:40 +08:00
parent 59c306f88f
commit 26109648af
21 changed files with 1844 additions and 6 deletions

View File

@@ -1,6 +1,7 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta name="referrer" content="no-referrer" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<title>大本营答疑助手</title>

View File

@@ -9,7 +9,7 @@ import MessageList, { type DisplayMessage } from "./components/MessageList.vue";
import PersonalCenterDialog from "./components/PersonalCenterDialog.vue";
import SessionDrawer from "./components/SessionDrawer.vue";
import SessionQuota from "./components/SessionQuota.vue";
import { ApiError, api, clearToken, getToken, streamChat } from "./services/api";
import { ApiError, api, clearToken, getToken, saveToken, streamChat } from "./services/api";
import type { ChatMessage as ApiMessage, ChatSession, PeriodicReport, PracticeReviewResult, ShareDraft, TeacherHelpCard, UserProfile } from "./types/api";
const user = ref<UserProfile | null>(null);
@@ -48,7 +48,32 @@ const activeAbortController = ref<AbortController | null>(null);
let toastTimer: number | null = null;
let settlementPollVersion = 0;
onMounted(async () => {
onMounted(bootstrap);
async function bootstrap() {
const search = new URLSearchParams(window.location.search);
const ssoCode = search.get("sso_code")?.trim() || "";
if (ssoCode) {
search.delete("sso_code");
const query = search.toString();
window.history.replaceState({}, "", `${window.location.pathname}${query ? `?${query}` : ""}${window.location.hash}`);
statusText.value = "正在完成免登录";
try {
const result = await api.exchangeSso(ssoCode);
saveToken(result.token);
if (result.returnUrl) window.sessionStorage.setItem("ai-kb-sso-return-url", result.returnUrl);
user.value = result.user;
await loadSessions();
statusText.value = "已连接大本营答疑服务";
} catch (error) {
clearUserState();
showToast(error instanceof Error ? `免登录失败:${error.message}` : "免登录失败,请重新进入或使用手机号登录");
} finally {
booting.value = false;
}
return;
}
if (!getToken()) {
booting.value = false;
statusText.value = "请先登录";
@@ -63,7 +88,7 @@ onMounted(async () => {
} finally {
booting.value = false;
}
});
}
onBeforeUnmount(() => {
settlementPollVersion += 1;

View File

@@ -85,6 +85,8 @@ export const api = {
}),
login: (phone: string, code: string) =>
request<LoginResult>("/auth/login", { method: "POST", body: JSON.stringify({ phone, code }) }),
exchangeSso: (code: string) =>
request<LoginResult>("/auth/sso/exchange", { method: "POST", body: JSON.stringify({ code }) }),
logout: () => request<null>("/auth/logout", { method: "POST", body: JSON.stringify({}) }),
profile: () => request<UserProfile>("/user/profile"),
createSession: () => request<{ sessionId: number }>("/chat/session", { method: "POST", body: JSON.stringify({}) }),

View File

@@ -119,6 +119,7 @@ export interface LoginResult {
token: string;
expiredAt: string;
user: UserProfile;
returnUrl?: string | null;
}
export interface CaptchaResult {