forked from bai/curriculum-project-hub
3d0f4e5c2d
登录页、后台外壳与六个 tab 全部成为客户端路由: /database/admin 登录(迁自 renderLoginPage) /database/dashboard 概览(迁自 renderDashboard) .../library .../users .../groups .../search .../settings 六个 tab 是真 URL,不再是 location.hash + display:none —— 刷新不丢 位置,链接可分享。 BrowserShell 拆成 LibraryView,加 showUserFooter:老师端 /app 显示 身份/登出页脚,后台的文件库 tab 不显示(外层已有身份区)。 bootstrap 走 /database/config 而非 /database/api/login-info:后者由 teacherApp 在 silo org 查找成功后才注册,前者无条件注册,登录页在 org 未就绪时也必须能拿到配置。 后端拥有的链接(OAuth、DEV 一键登录)标 data-sveltekit-reload, 否则被客户端路由拦下。
35 lines
1.1 KiB
TypeScript
35 lines
1.1 KiB
TypeScript
/**
|
|
* 会话装载:GET /database/api/me 一次,结果进 `me` store。
|
|
* 老师端与管理后台共用 —— 两处的区别只是拿到 me 之后怎么用
|
|
* (老师端未登录显示登录视图;管理后台未登录跳 /database/admin,
|
|
* 非 isWebsiteAdmin 显示无权提示)。
|
|
*/
|
|
import { get } from "svelte/store";
|
|
import { api, UnauthenticatedError } from "./api.js";
|
|
import { me, authChecked } from "./stores.js";
|
|
import type { MeResponse } from "./types.js";
|
|
|
|
/** 幂等:已检查过就不再打请求(路由间切换不重复拉取)。 */
|
|
export async function loadSession(force = false): Promise<void> {
|
|
if (get(authChecked) && !force) return;
|
|
|
|
try {
|
|
me.set(await api<MeResponse>("/database/api/me"));
|
|
} catch (e) {
|
|
if (!(e instanceof UnauthenticatedError)) console.error(e);
|
|
me.set(null);
|
|
} finally {
|
|
authChecked.set(true);
|
|
}
|
|
}
|
|
|
|
/** 退出登录:清后端 cookie 再清前端 store。 */
|
|
export async function logout(): Promise<void> {
|
|
try {
|
|
await fetch("/auth/logout", { method: "POST", credentials: "same-origin" });
|
|
} catch {
|
|
/* 网络失败也照样清前端状态 */
|
|
}
|
|
me.set(null);
|
|
}
|