feat: 新增管理员用户管理功能与账号封禁体系

此提交完成了全站管理员后台核心功能开发:
1.  新增AdminUserService与管理接口,支持用户列表查询、角色变更与封禁解封
2.  重构认证链路,统一账号封禁错误码与处理逻辑
3.  新增全局强制下线机制,账号被封禁时自动弹出告知弹窗并清理登录态
4.  重构管理员后台路由与布局,统一权限校验逻辑
5.  优化通知轮询逻辑,页面切回前台时立即刷新未读计数
6.  合并原公告、外观管理页到统一后台面板
This commit is contained in:
2026-09-15 02:52:26 +08:00
parent 24c6dea38c
commit 6da4309453
20 changed files with 2248 additions and 105 deletions

View File

@@ -27,3 +27,31 @@ export function onUserUpdate(handler: (patch: Partial<User>) => void): () => voi
window.addEventListener(USER_UPDATED_EVENT, listener);
return () => window.removeEventListener(USER_UPDATED_EVENT, listener);
}
/**
* 强制下线事件。
*
* 触发源统一收敛在 lib/api.ts:任何客户端请求收到后端的
* code=account_banned(中间件/refresh/登录)或 /me 的 banned 标记时派发,
* Header 负责复用登出清理链路(清 cookie、游客化、router.refresh),
* AccountGuard 负责弹出封禁告知——状态清理与告知 UI 解耦,
* 避免各请求调用方各自处理导致残留(参考强制下线单一入口原则)。
*/
export type ForceLogoutReason = "banned";
export const FORCE_LOGOUT_EVENT = "j13:force-logout";
export function emitForceLogout(reason: ForceLogoutReason = "banned"): void {
if (typeof window === "undefined") return;
window.dispatchEvent(new CustomEvent(FORCE_LOGOUT_EVENT, { detail: { reason } }));
}
export function onForceLogout(handler: (reason: ForceLogoutReason) => void): () => void {
if (typeof window === "undefined") return () => {};
const listener = (e: Event) => {
const detail = (e as CustomEvent<{ reason: ForceLogoutReason }>).detail;
handler(detail?.reason ?? "banned");
};
window.addEventListener(FORCE_LOGOUT_EVENT, listener);
return () => window.removeEventListener(FORCE_LOGOUT_EVENT, listener);
}