取消统一转发Dify请求,改为由客户端直接发送

This commit is contained in:
pingchuan
2025-07-01 15:54:28 +08:00
parent d4846869eb
commit ce851cc448
13 changed files with 12749 additions and 249 deletions
+2 -1
View File
@@ -8,4 +8,5 @@ node_modules
.idea
.history
logs/
logs/
docreview-frontend-deploy.tar.gz
+20 -20
View File
@@ -3,7 +3,7 @@
* 提供三个选项卡:评查结果、AI智能分析、文件信息
*/
import { ReactNode, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useNavigate } from '@remix-run/react';
import { loadingBarService } from '~/components/ui/LoadingBar';
import { DOCUMENT_URL } from "~/api/axios-client";
@@ -28,19 +28,19 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
const handleBack = () => {
// 防抖处理 - 如果已经在导航中,不重复触发
if (isNavigating) return;
// 设置导航状态为true
setIsNavigating(true);
loadingBarService.show();
// 根据来源页面返回
const previousRoute = fileInfo.previousRoute || 'documents';
const returnTo = previousRoute === 'documents'
? "/documents"
: previousRoute === 'filesUpload'
const returnTo = previousRoute === 'documents'
? "/documents"
: previousRoute === 'filesUpload'
? "/files/upload"
: "/rules-files";
// 立即导航返回
navigate(returnTo);
};
@@ -49,19 +49,19 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
const handleDownloadFile = async () => {
try {
const downloadUrl = `${DOCUMENT_URL}${fileInfo.path}`;
// 使用fetch获取文件内容
const response = await fetch(downloadUrl);
if (!response.ok) {
throw new Error(`下载失败: ${response.status} ${response.statusText}`);
}
// 将响应转换为Blob
const blob = await response.blob();
// 创建Blob URL
const blobUrl = URL.createObjectURL(blob);
// 创建一个隐藏的a标签并点击它
const a = document.createElement('a');
a.style.display = 'none';
@@ -71,7 +71,7 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
a.download = decodeURIComponent(fileName);
document.body.appendChild(a);
a.click();
// 清理
setTimeout(() => {
document.body.removeChild(a);
@@ -89,7 +89,7 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
<div className="tab-nav w-full flex justify-between">
{/* 评查结果、AI智能分析、文件信息 */}
<div className="flex">
<button
<button
className={`tab-nav-item ${activeTab === 'preview' ? 'active' : ''}`}
onClick={() => onTabChange('preview')}
type="button"
@@ -108,16 +108,16 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
{/* {fileInfo.type === '1' && ( */}
{/* 隐藏结构比对 */}
{fileInfo.type === '999999' && (
<button
<button
className={`tab-nav-item ${activeTab === 'filecompare' ? 'active' : ''}`}
onClick={() => onTabChange('filecompare')}
type="button"
aria-pressed={activeTab === 'filecompare'}
>
>
<i className="ri-flip-horizontal-line"></i>
</button>
)}
<button
<button
className={`tab-nav-item ${activeTab === 'fileinfo' ? 'active' : ''}`}
onClick={() => onTabChange('fileinfo')}
type="button"
@@ -129,14 +129,14 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
{/* 操作按钮 */}
<div className="flex space-x-3">
{/* 返回上一级 */}
<button
<button
className="ant-btn ant-btn-default flex items-center my-2"
onClick={() => handleBack()}
disabled={isNavigating}
>
<i className="ri-arrow-left-line mr-1"></i> {isNavigating ? '返回中...' : '返回'}
</button>
<button
<button
className="ant-btn ant-btn-default flex items-center my-2"
onClick={handleDownloadFile}
>
@@ -148,7 +148,7 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
>
<i className="ri-file-copy-line mr-1"></i> 导出评查报告
</button> */}
<button
<button
className={`ant-btn ant-btn-primary my-2 flex items-center ${fileInfo.auditStatus === 1 ? 'hidden' : ''}`}
onClick={onConfirmResults}
>
@@ -156,7 +156,7 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
</button>
</div>
</div>
<div className="tab-content w-full">
{children}
</div>
+2 -2
View File
@@ -33,11 +33,11 @@ const configs: Record<string, ApiConfig> = {
// 生产环境
production: {
// postgrest
baseUrl: 'http://10.79.97.16:8000',
baseUrl: 'http://10.79.97.17:8000',
// minio
documentUrl: 'http://10.76.244.156:9000/docauditai/',
// 文件上传
uploadUrl: 'http://10.79.97.16:8000/admin/documents/upload',
uploadUrl: 'http://10.79.97.17:8000/admin/documents/upload',
},
// 备用配置 (可以根据需要添加更多环境)
+28 -24
View File
@@ -28,40 +28,47 @@ const extractAppId = (appUrl: string): string => {
return appUrl;
};
// 获取配置值并添加调试日志
const getApiUrl = () => {
// 在Remix中,我们使用本地API路由作为代理,而不是直接访问Dify API
if (typeof window !== 'undefined') {
// 客户端:使用相对路径访问本地API
return '/api';
} else {
// 服务端:也使用相对路径
return '/api';
}
// 获取Dify API配置
const getDifyApiUrl = () => {
return getEnvVar('NEXT_PUBLIC_API_URL', 'https://api.dify.ai/v1');
};
const getAppId = () => {
const rawAppId = getEnvVar('NEXT_PUBLIC_APP_ID', '');
const extractedAppId = extractAppId(rawAppId);
// console.log('🔧 Chat Config Debug:', {
// rawAppId,
// extractedAppId,
// apiUrl: getApiUrl(),
// hasApiKey: !!getEnvVar('NEXT_PUBLIC_APP_KEY', ''),
// difyApiUrl: getEnvVar('NEXT_PUBLIC_API_URL', ''),
// });
console.log('🔧 Chat Config Debug:', {
rawAppId,
extractedAppId,
difyApiUrl: getDifyApiUrl(),
hasApiKey: !!getEnvVar('NEXT_PUBLIC_APP_KEY', ''),
});
return extractedAppId;
};
// 生成用户ID (模拟服务端逻辑)
const generateUserId = () => {
const appId = getAppId();
// 生成或获取会话ID (可以使用localStorage或其他方式)
let sessionId = '';
if (typeof window !== 'undefined') {
sessionId = localStorage.getItem('dify_session_id') || '';
if (!sessionId) {
sessionId = 'sess_' + Math.random().toString(36).substring(2, 15);
localStorage.setItem('dify_session_id', sessionId);
}
}
return `user_${appId}:${sessionId}`;
};
// 聊天应用配置
export const CHAT_CONFIG = {
// API相关配置 - 使用本地API路由作为代理
API_URL: getApiUrl(),
// API相关配置 - 直接使用Dify API
API_URL: getDifyApiUrl(),
APP_ID: getAppId(),
API_KEY: getEnvVar('NEXT_PUBLIC_APP_KEY', ''),
// Dify API 配置(用于服务端)
DIFY_API_URL: getEnvVar('NEXT_PUBLIC_API_URL', 'https://api.dify.ai/v1'),
// 用户生成函数
generateUserId,
// 应用信息
APP_INFO: {
@@ -76,9 +83,6 @@ export const CHAT_CONFIG = {
isShowPrompt: false,
promptTemplate: 'I want you to act as a javascript console.',
// API相关
API_PREFIX: '/api',
// 本地化
LOCALE_COOKIE_NAME: 'locale',
+1 -11
View File
@@ -113,8 +113,6 @@ export default function useConversation() {
isSetToLocalStorage = true,
newConversationName = ''
) => {
// console.log('🔄 设置当前会话ID:', { id, appId, isSetToLocalStorage });
doSetCurrConversationId(id);
if (isSetToLocalStorage && id !== '-1') {
@@ -130,19 +128,11 @@ export default function useConversation() {
globalThis.localStorage?.setItem(storageConversationIdKey, JSON.stringify(conversationIdInfo));
// console.log('💾 会话ID已保存到localStorage:', {
// appUrlKey,
// conversationId: id,
// fullStorage: conversationIdInfo
// });
} catch (error) {
console.error('保存会话ID到本地存储失败:', error);
}
}
// 不进行URL导航,保持单页面应用模式
// console.log('✅ 会话切换完成,当前会话ID:', id);
};
};
/**
* 重置新会话输入
+7
View File
@@ -7,6 +7,8 @@ import chatInputStyles from "~/styles/components/chat-with-llm/chat-input.css?ur
import chatSidebarStyles from "~/styles/components/chat-with-llm/sidebar.css?url";
import chatThoughtProcessStyles from "~/styles/components/chat-with-llm/thought-process.css?url";
import chatMarkdownStyles from "~/styles/components/chat-with-llm/markdown.css?url";
// 导入测试文件用于调试
import "~/utils/dify-test.client";
export function links() {
return [
@@ -32,6 +34,11 @@ export const meta: MetaFunction = () => {
/**
* 聊天主页面
* 实现单页面应用模式,所有会话切换都在同一页面内完成
*
* 调试说明:
* - 打开浏览器开发者工具的控制台
* - 输入 window.testDify() 可以测试Dify API连接
* - 查看网络选项卡可以监控API请求
*/
export default function ChatWithLLMIndex() {
return (
+5 -5
View File
@@ -1,16 +1,16 @@
import { Outlet } from "react-router-dom";
import {type MetaFunction} from "@remix-run/node";
import { Outlet } from "@remix-run/react";
import { type MetaFunction } from "@remix-run/node";
export const meta: MetaFunction = () => {
return [
{title: "文档列表 - 中国烟草AI合同及卷宗审核系统"},
{name: "documents", content: "文档列表,新增,修改"}
{ title: "文档列表 - 中国烟草AI合同及卷宗审核系统" },
{ name: "documents", content: "文档列表,新增,修改" }
]
}
export const handle = {
breadcrumb: "文档列表"
}
}
/**
* 文档列表路由布局
+259 -185
View File
@@ -6,9 +6,10 @@ import { unicodeToChar } from '../utils/chat-utils';
const baseOptions = {
method: 'GET',
mode: 'cors' as RequestMode,
credentials: 'include' as RequestCredentials,
credentials: 'omit' as RequestCredentials,
headers: new Headers({
'Content-Type': ContentType.json,
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
}),
redirect: 'follow' as RequestRedirect,
};
@@ -300,101 +301,71 @@ const handleStream = (
read();
};
// 基础Fetch函数
// 基础请求函数
const baseFetch = (url: string, fetchOptions: any, needAllResponseContent: boolean = false) => {
const options = Object.assign({}, baseOptions, fetchOptions);
// 构建完整URL - 修复重复的/v1问题
// CHAT_CONFIG.API_URL 已经包含了 /v1,所以不需要再添加 API_PREFIX
let urlWithPrefix = `${CHAT_CONFIG.API_URL}/${url.replace(/^\//, '')}`;
// 直接构建Dify API URL
const urlWithPrefix = `${CHAT_CONFIG.API_URL}/${url.replace(/^\//, '')}`;
const { method, params, body } = options;
// 处理GET请求的查询参数
if (method === 'GET' && params) {
const paramsArray: string[] = [];
Object.keys(params).forEach(key =>
paramsArray.push(`${key}=${encodeURIComponent(params[key])}`),
);
if (urlWithPrefix.search(/\?/) === -1)
urlWithPrefix += `?${paramsArray.join('&')}`;
else
urlWithPrefix += `&${paramsArray.join('&')}`;
delete options.params;
}
// 处理请求体
if (body && typeof body === 'object')
options.body = JSON.stringify(body);
// 添加认证头
if (!options.headers)
options.headers = {};
if (CHAT_CONFIG.API_KEY) {
// 确保Authorization头存在
if (CHAT_CONFIG.API_KEY && options.headers) {
options.headers['Authorization'] = `Bearer ${CHAT_CONFIG.API_KEY}`;
}
return Promise.race([
new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('请求超时'));
}, SSE_TIMEOUT);
}),
new Promise((resolve, reject) => {
fetch(urlWithPrefix, options)
.then((res: Response) => {
const resClone = res.clone();
const { body } = options;
if (body && typeof body === 'object') {
// 为所有请求添加user参数
const bodyWithUser = {
...body,
user: CHAT_CONFIG.generateUserId(),
};
options.body = JSON.stringify(bodyWithUser);
}
// console.log('📥 API Response:', {
// status: res.status,
// statusText: res.statusText,
// url: urlWithPrefix
// });
// 错误处理
if (!/^(2|3)\d{2}$/.test(res.status.toString())) {
try {
const bodyJson = res.json();
switch (res.status) {
case 401:
console.error('❌ Invalid token');
break;
default:
bodyJson.then((data: any) => {
console.error('❌ API Error:', data.message);
});
}
}
catch (e) {
console.error('❌ Response Error:', e);
}
return Promise.reject(resClone);
}
// 处理删除API204状态码)
if (res.status === 204) {
resolve({ result: 'success' });
return;
}
// 返回数据
const contentType = res.headers.get('Content-Type') || '';
const data = contentType.includes('application/octet-stream') ? res.blob() : res.json();
resolve(needAllResponseContent ? resClone : data);
})
.catch((err) => {
console.error('❌ Fetch Error:', err);
reject(err);
return fetch(urlWithPrefix, options)
.then((res: Response) => {
if (!res.ok) {
console.error('❌ Request failed:', {
status: res.status,
statusText: res.statusText,
url: urlWithPrefix
});
}),
]);
if (res.status === 422) {
return res.text().then(text => {
let errorMessage = text;
try {
const data = JSON.parse(text);
errorMessage = data.message || data.error || text;
} catch (e) {
// 如果不是JSON,使用原始文本
}
throw new Error(errorMessage);
});
}
throw new Error(`${res.status}: ${res.statusText}`);
}
if (needAllResponseContent) {
return res.text().then(text => {
try {
return JSON.parse(text);
} catch (e) {
return text;
}
});
}
const data = res.json();
return data;
})
.catch((err) => {
console.error('❌ Request error:', err.message);
throw err;
});
};
// SSE POST 请求
// SSE请求处理
export const ssePost = (
url: string,
fetchOptions: any,
@@ -430,10 +401,9 @@ export const ssePost = (
method: 'POST',
}, fetchOptions);
// 修复URL构建逻辑,与baseFetch保持一致
// 直接构建Dify API URL
const urlWithPrefix = `${CHAT_CONFIG.API_URL}/${url.replace(/^\//, '')}`;
const controller = new AbortController();
if (getAbortController)
getAbortController(controller);
@@ -442,25 +412,28 @@ export const ssePost = (
...options.headers,
'Content-Type': 'application/json',
'Accept': ContentType.stream,
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
};
if (CHAT_CONFIG.API_KEY) {
options.headers['Authorization'] = `Bearer ${CHAT_CONFIG.API_KEY}`;
}
options.signal = controller.signal;
const { body } = options;
if (body && typeof body === 'object')
options.body = JSON.stringify(body);
if (body && typeof body === 'object') {
// 为SSE请求添加user参数
const bodyWithUser = {
...body,
user: CHAT_CONFIG.generateUserId(),
};
options.body = JSON.stringify(bodyWithUser);
}
return fetch(urlWithPrefix, options)
.then((res: Response) => {
// console.log('📡 SSE Response:', {
// status: res.status,
// statusText: res.statusText,
// url: urlWithPrefix
// });
console.log('📡 SSE Response:', {
status: res.status,
statusText: res.statusText,
url: urlWithPrefix
});
if (!/^(2|3)\d{2}$/.test(res.status.toString())) {
res.json().then((data: any) => {
@@ -491,6 +464,194 @@ export const ssePost = (
});
};
// 获取会话列表
export const fetchConversations = async () => {
const user = CHAT_CONFIG.generateUserId();
const params = new URLSearchParams({
user,
limit: '100',
first_id: '',
});
return fetch(`${CHAT_CONFIG.API_URL}/conversations?${params}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
},
}).then(res => {
if (!res.ok) {
throw new Error(`Failed to fetch conversations: ${res.status}`);
}
return res.json();
});
};
// 获取聊天消息列表
export const fetchChatList = async (conversationId: string) => {
const user = CHAT_CONFIG.generateUserId();
const params = new URLSearchParams({
user,
conversation_id: conversationId,
limit: '20',
last_id: '',
});
return fetch(`${CHAT_CONFIG.API_URL}/messages?${params}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
},
}).then(res => {
if (!res.ok) {
throw new Error(`Failed to fetch chat list: ${res.status}`);
}
return res.json();
});
};
// 获取应用参数
export const fetchAppParams = async () => {
return fetch(`${CHAT_CONFIG.API_URL}/parameters`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
},
}).then(res => {
if (!res.ok) {
throw new Error(`Failed to fetch app params: ${res.status}`);
}
return res.json();
});
};
// 更新反馈
export const updateFeedback = async ({ url, body }: { url: string; body: Feedbacktype }) => {
const messageId = url.split('/').pop(); // 从URL中提取messageId
return fetch(`${CHAT_CONFIG.API_URL}/messages/${messageId}/feedbacks`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
},
body: JSON.stringify({
...body,
user: CHAT_CONFIG.generateUserId(),
}),
}).then(res => {
if (!res.ok) {
throw new Error(`Failed to update feedback: ${res.status}`);
}
return res.json();
});
};
// 生成会话名称
export const generateConversationName = async (id: string) => {
return fetch(`${CHAT_CONFIG.API_URL}/conversations/${id}/name`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
},
body: JSON.stringify({
auto_generate: true,
user: CHAT_CONFIG.generateUserId(),
}),
}).then(res => {
if (!res.ok) {
throw new Error(`Failed to generate conversation name: ${res.status}`);
}
return res.json();
});
};
// 重命名会话
export const renameConversation = async (id: string, name: string, autoGenerate: boolean = false) => {
return fetch(`${CHAT_CONFIG.API_URL}/conversations/${id}/name`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
},
body: JSON.stringify({
name: autoGenerate ? undefined : name,
auto_generate: autoGenerate,
user: CHAT_CONFIG.generateUserId(),
}),
}).then(res => {
if (!res.ok) {
throw new Error(`Failed to rename conversation: ${res.status}`);
}
return res.json();
});
};
// 删除会话
export const deleteConversation = async (id: string) => {
return fetch(`${CHAT_CONFIG.API_URL}/conversations/${id}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
},
body: JSON.stringify({
user: CHAT_CONFIG.generateUserId(),
}),
}).then(res => {
if (!res.ok) {
throw new Error(`Failed to delete conversation: ${res.status}`);
}
return res.json();
});
};
// 文件上传
export const upload = (fetchOptions: any): Promise<any> => {
const urlWithPrefix = `${CHAT_CONFIG.API_URL}/files/upload`;
const defaultOptions = {
method: 'POST',
url: urlWithPrefix,
data: {},
};
const options = {
...defaultOptions,
...fetchOptions,
};
return new Promise((resolve, reject) => {
const xhr = options.xhr;
xhr.open(options.method, options.url);
for (const key in options.headers)
xhr.setRequestHeader(key, options.headers[key]);
if (CHAT_CONFIG.API_KEY) {
xhr.setRequestHeader('Authorization', `Bearer ${CHAT_CONFIG.API_KEY}`);
}
// 添加user参数到formData
if (options.data instanceof FormData) {
options.data.append('user', CHAT_CONFIG.generateUserId());
}
xhr.withCredentials = false; // 改为false,因为直接调用Dify API
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200)
resolve({ id: xhr.response });
else
reject(new Error(xhr.responseText || 'Upload failed'));
}
};
xhr.upload.onprogress = options.onprogress;
xhr.send(options.data);
});
};
// 公共请求函数
export const request = (url: string, options = {}, needAllResponseContent = false) => {
return baseFetch(url, { ...baseOptions, ...options }, needAllResponseContent);
@@ -566,91 +727,4 @@ export const sendChatMessage = async (
onWorkflowFinished,
onNodeFinished
});
};
// 获取会话列表
export const fetchConversations = async () => {
return get('conversations', {
params: { limit: 100, first_id: '' },
});
};
// 获取聊天消息列表
export const fetchChatList = async (conversationId: string) => {
return get('messages', {
params: { conversation_id: conversationId, limit: 20, last_id: '' },
});
};
// 获取应用参数
export const fetchAppParams = async () => {
return get('parameters');
};
// 更新反馈
export const updateFeedback = async ({ url, body }: { url: string; body: Feedbacktype }) => {
return post(url, { body });
};
// 生成会话名称
export const generateConversationName = async (id: string) => {
return post(`conversations/${id}/name`, {
body: { auto_generate: true },
});
};
// 重命名会话
export const renameConversation = async (id: string, name: string, autoGenerate: boolean = false) => {
return post(`conversations/${id}/name`, {
body: {
name: autoGenerate ? undefined : name,
auto_generate: autoGenerate
},
});
};
// 删除会话
export const deleteConversation = async (id: string) => {
return del(`conversations/${id}`);
};
// 文件上传
export const upload = (fetchOptions: any): Promise<any> => {
const urlPrefix = CHAT_CONFIG.API_PREFIX;
const urlWithPrefix = `${CHAT_CONFIG.API_URL}${urlPrefix}/file-upload`;
const defaultOptions = {
method: 'POST',
url: urlWithPrefix,
data: {},
};
const options = {
...defaultOptions,
...fetchOptions,
};
return new Promise((resolve, reject) => {
const xhr = options.xhr;
xhr.open(options.method, options.url);
for (const key in options.headers)
xhr.setRequestHeader(key, options.headers[key]);
if (CHAT_CONFIG.API_KEY) {
xhr.setRequestHeader('Authorization', `Bearer ${CHAT_CONFIG.API_KEY}`);
}
xhr.withCredentials = true;
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200)
resolve({ id: xhr.response });
else
reject(xhr);
}
};
xhr.upload.onprogress = options.onprogress;
xhr.send(options.data);
});
};
+85
View File
@@ -0,0 +1,85 @@
import { CHAT_CONFIG } from '../config/chat';
/**
* 测试Dify API连接
* 这个文件可以用来调试和测试前端直接调用Dify API的功能
*/
export const testDifyConnection = async () => {
console.log('🔧 Dify Configuration:', {
apiUrl: CHAT_CONFIG.API_URL,
appId: CHAT_CONFIG.APP_ID,
hasApiKey: !!CHAT_CONFIG.API_KEY,
apiKeyPreview: CHAT_CONFIG.API_KEY ? `${CHAT_CONFIG.API_KEY.substring(0, 10)}...` : 'No API Key',
});
if (!CHAT_CONFIG.API_URL || !CHAT_CONFIG.APP_ID || !CHAT_CONFIG.API_KEY) {
console.error('❌ Dify配置不完整,请检查环境变量');
return false;
}
const user = CHAT_CONFIG.generateUserId();
console.log('👤 Generated User ID:', user);
try {
// 测试获取应用参数
console.log('📋 测试获取应用参数...');
const response = await fetch(`${CHAT_CONFIG.API_URL}/parameters`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
},
});
if (!response.ok) {
console.error('❌ 获取应用参数失败:', response.status, response.statusText);
const errorText = await response.text();
console.error('错误详情:', errorText);
return false;
}
const data = await response.json();
console.log('✅ 成功获取应用参数:', data);
// 测试获取会话列表
console.log('💬 测试获取会话列表...');
const params = new URLSearchParams({
user,
limit: '10',
first_id: '',
});
const conversationsResponse = await fetch(`${CHAT_CONFIG.API_URL}/conversations?${params}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${CHAT_CONFIG.API_KEY}`,
},
});
if (!conversationsResponse.ok) {
console.error('❌ 获取会话列表失败:', conversationsResponse.status, conversationsResponse.statusText);
const errorText = await conversationsResponse.text();
console.error('错误详情:', errorText);
return false;
}
const conversationsData = await conversationsResponse.json();
console.log('✅ 成功获取会话列表:', conversationsData);
return true;
} catch (error) {
console.error('❌ 测试Dify连接时发生错误:', error);
return false;
}
};
/**
* 在浏览器控制台中可以调用这个函数进行测试
* 使用方法:
* 1. 打开浏览器控制台
* 2. 输入: window.testDify()
* 3. 查看输出结果
*/
if (typeof window !== 'undefined') {
(window as any).testDify = testDifyConnection;
}
+1
View File
@@ -6,6 +6,7 @@
"": {
"name": "remix_docreview",
"dependencies": {
"@ant-design/icons": "^5.6.1",
"@codemirror/lang-javascript": "^6.2.3",
"@codemirror/theme-one-dark": "^6.1.2",
"@react-pdf-viewer/core": "^3.12.0",
+1
View File
@@ -14,6 +14,7 @@
"typecheck": "tsc"
},
"dependencies": {
"@ant-design/icons": "^5.6.1",
"@codemirror/lang-javascript": "^6.2.3",
"@codemirror/theme-one-dark": "^6.1.2",
"@react-pdf-viewer/core": "^3.12.0",
+12337
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -42,6 +42,6 @@ export default defineConfig({
// 防止依赖预构建时触发页面刷新导致路由中断
force: false,
// 预构建这些依赖,避免首次加载时出现重新构建
include: ['react-pdf', 'pdfjs-dist', 'dayjs', '@remix-run/node', 'react-dom', 'axios', 'dayjs/plugin/utc', 'react-router-dom', 'jszip', 'ahooks', 'antd', 'immer', '@ant-design/icons', 'react-markdown', 'remark-math', 'remark-breaks', 'rehype-katex','remark-gfm'],
include: ['react-pdf', 'pdfjs-dist', 'dayjs', '@remix-run/node', 'react-dom', 'axios', 'dayjs/plugin/utc', '@remix-run/react', 'jszip', 'ahooks', 'antd', 'immer', '@ant-design/icons', 'react-markdown', 'remark-math', 'remark-breaks', 'rehype-katex', 'remark-gfm'],
},
});