fix: stabilize review detail and collabora loading

This commit is contained in:
wren
2026-05-08 10:59:04 +08:00
parent 7fdb7386ee
commit 3da2a8d088
20 changed files with 319 additions and 284 deletions
+51 -49
View File
@@ -1,50 +1,52 @@
import { json, type LoaderFunctionArgs } from '@remix-run/node';
import { difyClient } from '~/api/dify-chat/client.server';
import { commitSession, getSessionInfo } from '../utils/session.server';
export async function loader({ request }: LoaderFunctionArgs) {
try {
// 获取用户会话信息和 JWT
const { getUserSession } = await import("~/api/login/auth.server");
const { frontendJWT } = await getUserSession(request);
const { session } = await getSessionInfo(request);
// 检查 JWT 是否存在
if (!frontendJWT) {
console.error('❌ [API] Parameters API - JWT不存在');
return json(
{ error: 'JWT认证失败,请重新登录' },
{
status: 401,
headers: {
'Set-Cookie': await commitSession(session),
},
}
);
}
const data = await difyClient.getApplicationParameters(frontendJWT);
return json(data, {
headers: {
'Set-Cookie': await commitSession(session),
},
});
} catch (error: any) {
console.error('❌ [API] Parameters API - Error:', error);
// 检查是否是JWT认证失败
const sm = error.message?.match(/(\d{3})/); const os = sm ? parseInt(sm[1]) : 0;
const status = error.message?.includes('JWT认证失败') ? 401 : os >= 400 && os < 500 ? os : 500;
return json(
{ error: error.message || 'Failed to fetch parameters' },
{
status,
headers: {
'Set-Cookie': await commitSession((await getSessionInfo(request)).session),
},
}
);
}
import { json, type LoaderFunctionArgs } from '@remix-run/node';
import { difyClient } from '~/api/dify-chat/client.server';
import { commitSession, getSessionInfo } from '../utils/session.server';
export async function loader({ request }: LoaderFunctionArgs) {
try {
// 获取用户会话信息和 JWT
const { getUserSession } = await import("~/api/login/auth.server");
const { frontendJWT } = await getUserSession(request);
const { session } = await getSessionInfo(request);
// 检查 JWT 是否存在
if (!frontendJWT) {
console.error('❌ [API] Parameters API - JWT不存在');
return json(
{ error: 'JWT认证失败,请重新登录' },
{
status: 401,
headers: {
'Set-Cookie': await commitSession(session),
},
}
);
}
const url = new URL(request.url);
const appId = url.searchParams.get('app_id') || undefined;
const data = await difyClient.getApplicationParameters(frontendJWT, appId);
return json(data, {
headers: {
'Set-Cookie': await commitSession(session),
},
});
} catch (error: any) {
console.error('❌ [API] Parameters API - Error:', error);
// 检查是否是JWT认证失败
const sm = error.message?.match(/(\d{3})/); const os = sm ? parseInt(sm[1]) : 0;
const status = error.message?.includes('JWT认证失败') ? 401 : os >= 400 && os < 500 ? os : 500;
return json(
{ error: error.message || 'Failed to fetch parameters' },
{
status,
headers: {
'Set-Cookie': await commitSession((await getSessionInfo(request)).session),
},
}
);
}
}
+17 -17
View File
@@ -1,14 +1,21 @@
/**
* GET /api/v3/dify/chat-apps/default - 获取默认对话应用
*
* 转发请求到后端 API,后端从配置文件读取默认对话应用
* 参考文档:docs/new-dify/dify_api_doc.md - 对话应用多实例支持
*/
import { LoaderFunctionArgs, json } from '@remix-run/node';
import { API_BASE_URL } from '~/config/api-config';
import { getUserSession } from '~/api/login/auth.server';
function normalizeApp(payload: any) {
const app = payload?.data?.data || payload?.data || null;
if (!app) return null;
return {
app_id: String(app.appId),
app_name: app.appName,
description: app.description || '',
is_default: Boolean(app.isDefault),
type: 'rag',
created_at: '',
updated_at: '',
};
}
export async function loader({ request }: LoaderFunctionArgs) {
try {
const { frontendJWT } = await getUserSession(request);
@@ -20,23 +27,16 @@ export async function loader({ request }: LoaderFunctionArgs) {
);
}
console.log('[API] Get Default Chat App - Forwarding to backend');
// 转发请求到后端
const apiUrl = `${API_BASE_URL}/v3/dify/chat-apps/default`;
const response = await fetch(apiUrl, {
const response = await fetch(`${API_BASE_URL}/v3/rag/apps/default`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${frontendJWT}`,
Authorization: `Bearer ${frontendJWT}`,
},
});
const data = await response.json();
console.log('[API] Get Default Chat App - Backend response:', data);
return json(data, { status: response.status });
return json({ data: normalizeApp(data) }, { status: response.status });
} catch (error: any) {
console.error('[API] Get Default Chat App - Error:', error.message);
return json(
+24 -18
View File
@@ -1,14 +1,27 @@
/**
* GET /api/v3/dify/chat-apps/my - 获取当前用户可访问的对话应用列表
*
* 转发请求到后端 API,后端从配置文件读取对话应用列表
* 参考文档:docs/new-dify/dify_api_doc.md - 对话应用多实例支持
*/
import { LoaderFunctionArgs, json } from '@remix-run/node';
import { API_BASE_URL } from '~/config/api-config';
import { getUserSession } from '~/api/login/auth.server';
function normalizeApps(payload: any) {
const apps = payload?.data?.data || payload?.data || [];
return {
data: Array.isArray(apps)
? apps.map((app: any) => ({
app_id: String(app.appId),
app_name: app.appName,
description: app.description || '',
is_default: Boolean(app.isDefault),
type: 'rag',
created_at: '',
updated_at: '',
}))
: [],
total: Array.isArray(apps) ? apps.length : 0,
page: 1,
page_size: Array.isArray(apps) ? apps.length : 0,
};
}
export async function loader({ request }: LoaderFunctionArgs) {
try {
const { frontendJWT } = await getUserSession(request);
@@ -20,24 +33,17 @@ export async function loader({ request }: LoaderFunctionArgs) {
);
}
console.log('[API] Get My Chat Apps - Forwarding to backend');
// 转发请求到后端 - 使用正确的接口路径
// 根据文档:GET /api/v3/dify/chat-apps
const apiUrl = `${API_BASE_URL}/v3/dify/chat-apps`;
const response = await fetch(apiUrl, {
const response = await fetch(`${API_BASE_URL}/v3/rag/apps`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${frontendJWT}`,
Authorization: `Bearer ${frontendJWT}`,
},
});
const data = await response.json();
console.log('[API] Get My Chat Apps - Backend response:', data);
return json(data, { status: response.status });
const normalized = normalizeApps(data);
return json(normalized, { status: response.status });
} catch (error: any) {
console.error('[API] Get My Chat Apps - Error:', error.message);
return json(
+2 -1
View File
@@ -28,8 +28,9 @@ export async function loader({ request }: LoaderFunctionArgs) {
const { getUserSession } = await import("~/api/login/auth.server");
const { frontendJWT, userInfo } = await getUserSession(request);
const { requireRoutePermission } = await import("~/api/auth/check-route-permission.server");
const userRole = userInfo?.role || userInfo?.user_role || "";
await requireRoutePermission("/document-types", userInfo?.role || "", frontendJWT || undefined);
await requireRoutePermission("/document-types", userRole, frontendJWT || undefined);
const rootsRes = await getDocumentTypeRoots({}, frontendJWT);
return {
+2 -1
View File
@@ -35,7 +35,8 @@ export async function loader({ request }: LoaderFunctionArgs) {
const { getUserSession } = await import("~/api/login/auth.server");
const { frontendJWT, userInfo } = await getUserSession(request);
const { requireRoutePermission } = await import("~/api/auth/check-route-permission.server");
await requireRoutePermission("/document-types/new", userInfo?.role || "", frontendJWT || undefined);
const userRole = userInfo?.role || userInfo?.user_role || "";
await requireRoutePermission("/document-types/new", userRole, frontendJWT || undefined);
const url = new URL(request.url);
const editId = url.searchParams.get("id");
+3 -2
View File
@@ -356,12 +356,13 @@ export async function loader({ request }: LoaderFunctionArgs): Promise<Response>
const { getUserSession } = await import("~/api/login/auth.server");
const { userInfo, frontendJWT } = await getUserSession(request);
if (!frontendJWT || !userInfo?.role) {
const userRole = userInfo?.role || userInfo?.user_role || '';
if (!frontendJWT || !userRole) {
throw redirect('/login');
}
const { requireRoutePermission } = await import("~/api/auth/check-route-permission.server");
await requireRoutePermission('/reviewsTest', userInfo.role, frontendJWT);
await requireRoutePermission('/reviewsTest', userRole, frontendJWT);
const reviewData = await getReviewPoints_fromApi(id, request);
+2 -1
View File
@@ -148,8 +148,9 @@ export async function loader({ request }: LoaderFunctionArgs) {
const { getUserSession } = await import("~/api/login/auth.server");
const { frontendJWT, userInfo } = await getUserSession(request);
const { requireRoutePermission } = await import("~/api/auth/check-route-permission.server");
const userRole = userInfo?.role || userInfo?.user_role || "";
await requireRoutePermission("/rule-groups", userInfo?.role || "", frontendJWT || undefined);
await requireRoutePermission("/rule-groups", userRole, frontendJWT || undefined);
try {
const [groups, docTypesRes, entryModulesRes, ruleSetsRes] = await Promise.all([
+4 -2
View File
@@ -240,7 +240,8 @@ export async function loader({ request }: LoaderFunctionArgs) {
const { getUserSession } = await import("~/api/login/auth.server");
const { frontendJWT, userInfo } = await getUserSession(request);
const { requireRoutePermission } = await import("~/api/auth/check-route-permission.server");
await requireRoutePermission("/rules/list", userInfo?.role || "", frontendJWT || undefined);
const userRole = userInfo?.role || userInfo?.user_role || "";
await requireRoutePermission("/rules/list", userRole, frontendJWT || undefined);
// 从 URL 参数中提取查询条件
const params = {
@@ -287,7 +288,8 @@ export async function action({ request }: LoaderFunctionArgs) {
const { getUserSession } = await import("~/api/login/auth.server");
const { frontendJWT, userInfo } = await getUserSession(request);
const { requireRoutePermission } = await import("~/api/auth/check-route-permission.server");
await requireRoutePermission("/rules/list", userInfo?.role || "", frontendJWT || undefined);
const userRole = userInfo?.role || userInfo?.user_role || "";
await requireRoutePermission("/rules/list", userRole, frontendJWT || undefined);
const formData = await request.formData();
const _action = formData.get('_action');
const ruleId = formData.get('ruleId');
+2 -1
View File
@@ -21,8 +21,9 @@ export async function loader({ request }: LoaderFunctionArgs) {
const { getUserSession } = await import("~/api/login/auth.server");
const { frontendJWT, userInfo } = await getUserSession(request);
const { requireRoutePermission } = await import("~/api/auth/check-route-permission.server");
const userRole = userInfo?.role || userInfo?.user_role || "";
await requireRoutePermission("/rules", userInfo?.role || "", frontendJWT || undefined);
await requireRoutePermission("/rules", userRole, frontendJWT || undefined);
if (url.pathname === '/rules') {
const query = url.searchParams.toString();
+2 -1
View File
@@ -446,7 +446,8 @@ export async function loader({ request }: LoaderFunctionArgs) {
export async function action({ request }: ActionFunctionArgs) {
const { frontendJWT, userInfo } = await getUserSession(request);
const { requireRoutePermission } = await import('~/api/auth/check-route-permission.server');
await requireRoutePermission('/rulesTest/detail', userInfo?.role || '', frontendJWT || undefined);
const userRole = userInfo?.role || userInfo?.user_role || '';
await requireRoutePermission('/rulesTest/detail', userRole, frontendJWT || undefined);
if (!frontendJWT) {
return json<ActionData>({ success: false, intent: 'save', message: '登录已失效,请重新登录后再保存。' }, { status: 401 });
}