feat: 1. 将大部分的请求从fetch改成axios方便管理。

2. 给文档类型添加入口模块和相关数据的渲染。并且给文档类型进行功能上的角色权限区分
3. 新增角色权限管理页面
This commit is contained in:
2025-11-20 20:34:31 +08:00
parent 2e604e8ede
commit 3850d05bdd
25 changed files with 2299 additions and 762 deletions
+23 -22
View File
@@ -21,6 +21,7 @@ import { createCookieSessionStorage } from "@remix-run/node";
import { postgrestGet, postgrestPost, postgrestPut } from "../postgrest-client";
import { JWTUtils, type UserInfoForJWT } from "~/utils/jwt";
import { OAUTH_CONFIG, API_BASE_URL } from "~/config/api-config";
import axios from 'axios';
/**
* 用户角色类型定义
@@ -95,7 +96,7 @@ export const sessionStorage = createCookieSessionStorage({
path: "/", // Cookie 作用域为整个应用
sameSite: "lax", // CSRF 保护,允许顶级导航
secrets: ["s3cr3t"], // TODO: 应该从环境变量读取
maxAge: 60 * 60 * 2, // 2小时,与 OAuth Token 同步
maxAge: 60 * 60 * 8, // 8小时,确保大于等于JWT token最大有效期(通常为6小时)
secure: false, // 开发环境中禁用 HTTPS 要求
},
});
@@ -369,12 +370,16 @@ export async function createUserSession(params: {
if (params.frontendJWT) {
session.set("frontendJWT", params.frontendJWT);
}
const cookie = await sessionStorage.commitSession(session);
// console.log("创建完整会话 - 设置Cookie:", !!cookie);
// console.log("创建完整会话 - 用户角色:", params.userRole);
// console.log("创建完整会话 - 重定向到:", params.redirectTo);
// 🔑 根据 tokenExpiresIn 动态设置 Cookie 的 maxAge
// 如果有 tokenExpiresIn,使用它作为 Cookie 有效期;否则使用默认值(8小时)
const cookieMaxAge = params.tokenExpiresIn || (60 * 60 * 8); // 默认8小时
// console.log("🍪 [createUserSession] Cookie maxAge:", cookieMaxAge, "秒 (", (cookieMaxAge / 3600).toFixed(2), "小时)");
const cookie = await sessionStorage.commitSession(session, {
maxAge: cookieMaxAge // 🔑 动态设置 Cookie 有效期
});
return new Response(null, {
status: 302, // HTTP 重定向状态码
headers: {
@@ -487,20 +492,18 @@ async function callIDaaSLogout(accessToken: string, appId: string): Promise<void
formData.append('redirect_url', encodeURIComponent(redirectUri));
try {
const response = await fetch(logoutUrl, {
method: 'POST',
const response = await axios.post(logoutUrl, formData.toString(), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData.toString(),
});
if (!response.ok) {
throw new Error(`IDaaS登出失败: ${response.status} ${response.statusText}`);
}
console.log("IDaaS单点登出请求成功");
} catch (error) {
if (axios.isAxiosError(error)) {
console.error("调用IDaaS登出接口失败:", error.response?.status, error.response?.statusText);
throw new Error(`IDaaS登出失败: ${error.response?.status} ${error.response?.statusText}`);
}
console.error("调用IDaaS登出接口失败:", error);
throw error;
}
@@ -775,18 +778,16 @@ export async function simpleRootLogin(
}
// 调用登录接口
const loginResponse = await fetch(`${API_BASE_URL}/password_login`, {
method: 'POST',
const loginResponse = await axios.post(`${API_BASE_URL}/password_login`, {
sub: username.trim(),
password: password.trim()
}, {
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
sub: username.trim(),
password: password.trim()
})
}
});
const loginResult = await loginResponse.json();
const loginResult = loginResponse.data;
console.log('登录接口返回', loginResult);
// 检查重试次数