feat: 1. 将大部分的请求从fetch改成axios方便管理。
2. 给文档类型添加入口模块和相关数据的渲染。并且给文档类型进行功能上的角色权限区分 3. 新增角色权限管理页面
This commit is contained in:
+139
-141
@@ -1,6 +1,7 @@
|
||||
import { CHAT_CONFIG, ContentType, SSE_TIMEOUT } from '../config/chat';
|
||||
import type { Feedbacktype, ThoughtItem, VisionFile, MessageEnd, MessageReplace } from '../types/dify_chat';
|
||||
import { unicodeToChar } from '../utils/chat-utils';
|
||||
import axios from 'axios';
|
||||
|
||||
// 基础请求选项
|
||||
// 注意:客户端调用Remix API routes,不需要手动添加Authorization
|
||||
@@ -321,7 +322,7 @@ const handleStream = (
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
const baseFetch = (url: string, fetchOptions: any, needAllResponseContent: boolean = false) => {
|
||||
const baseFetch = async (url: string, fetchOptions: any, needAllResponseContent: boolean = false) => {
|
||||
const options = Object.assign({}, baseOptions, fetchOptions);
|
||||
|
||||
// 调用Remix API routes(如 /api/conversations)
|
||||
@@ -329,51 +330,46 @@ const baseFetch = (url: string, fetchOptions: any, needAllResponseContent: boole
|
||||
const urlWithPrefix = `${CHAT_CONFIG.API_URL}/${url.replace(/^\//, '')}`;
|
||||
|
||||
const { body } = options;
|
||||
let data = body;
|
||||
if (body && typeof body === 'object') {
|
||||
// 不再添加user参数,服务端会从JWT自动提取
|
||||
options.body = JSON.stringify(body);
|
||||
data = body;
|
||||
}
|
||||
|
||||
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;
|
||||
try {
|
||||
const response = await axios({
|
||||
url: urlWithPrefix,
|
||||
method: options.method || 'GET',
|
||||
data: data,
|
||||
headers: options.headers,
|
||||
withCredentials: true, // 等同于 credentials: 'include'
|
||||
});
|
||||
|
||||
if (needAllResponseContent) {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
if (axios.isAxiosError(err)) {
|
||||
console.error('❌ Request failed:', {
|
||||
status: err.response?.status,
|
||||
statusText: err.response?.statusText,
|
||||
url: urlWithPrefix
|
||||
});
|
||||
|
||||
if (err.response?.status === 422) {
|
||||
const errorData = err.response.data;
|
||||
const errorMessage = errorData?.message || errorData?.error || JSON.stringify(errorData);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
throw new Error(`${err.response?.status || 500}: ${err.response?.statusText || err.message}`);
|
||||
}
|
||||
|
||||
console.error('❌ Request error:', (err as Error).message);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -532,25 +528,25 @@ export const fetchConversations = async () => {
|
||||
const url = `${CHAT_CONFIG.API_URL}/conversations?${params}`;
|
||||
console.log('📋 [API Client] 获取会话列表:', { url, apiUrl: CHAT_CONFIG.API_URL });
|
||||
|
||||
return fetch(url, {
|
||||
method: 'GET',
|
||||
credentials: 'include', // 携带cookie
|
||||
}).then(res => {
|
||||
console.log('📋 [API Client] 会话列表响应:', { status: res.status, ok: res.ok });
|
||||
if (!res.ok) {
|
||||
return res.text().then(text => {
|
||||
console.error('❌ [API Client] 获取会话列表失败:', { status: res.status, body: text });
|
||||
throw new Error(`Failed to fetch conversations: ${res.status} - ${text}`);
|
||||
});
|
||||
}
|
||||
return res.json().then(data => {
|
||||
console.log('📋 [API Client] 会话列表数据:', data);
|
||||
return data;
|
||||
try {
|
||||
const response = await axios.get(url, {
|
||||
withCredentials: true, // 携带cookie
|
||||
});
|
||||
}).catch(err => {
|
||||
|
||||
console.log('📋 [API Client] 会话列表响应:', { status: response.status });
|
||||
console.log('📋 [API Client] 会话列表数据:', response.data);
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
if (axios.isAxiosError(err)) {
|
||||
console.error('❌ [API Client] 获取会话列表失败:', {
|
||||
status: err.response?.status,
|
||||
body: err.response?.data
|
||||
});
|
||||
throw new Error(`Failed to fetch conversations: ${err.response?.status} - ${JSON.stringify(err.response?.data)}`);
|
||||
}
|
||||
console.error('❌ [API Client] 会话列表请求异常:', err);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -582,15 +578,17 @@ export const fetchChatList = async (conversationId: string) => {
|
||||
// 不再传递user参数,服务端会从JWT自动提取
|
||||
});
|
||||
|
||||
return fetch(`${CHAT_CONFIG.API_URL}/messages?${params}`, {
|
||||
method: 'GET',
|
||||
credentials: 'include', // 携带cookie
|
||||
}).then(res => {
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to fetch chat list: ${res.status}`);
|
||||
try {
|
||||
const response = await axios.get(`${CHAT_CONFIG.API_URL}/messages?${params}`, {
|
||||
withCredentials: true, // 携带cookie
|
||||
});
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
if (axios.isAxiosError(err)) {
|
||||
throw new Error(`Failed to fetch chat list: ${err.response?.status}`);
|
||||
}
|
||||
return res.json();
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -620,25 +618,24 @@ export const fetchAppParams = async () => {
|
||||
const url = `${CHAT_CONFIG.API_URL}/parameters`;
|
||||
console.log('⚙️ [API Client] 获取应用参数:', { url, apiUrl: CHAT_CONFIG.API_URL });
|
||||
|
||||
return fetch(url, {
|
||||
method: 'GET',
|
||||
credentials: 'include', // 携带cookie
|
||||
}).then(res => {
|
||||
console.log('⚙️ [API Client] 应用参数响应:', { status: res.status, ok: res.ok });
|
||||
if (!res.ok) {
|
||||
return res.text().then(text => {
|
||||
console.error('❌ [API Client] 获取应用参数失败:', { status: res.status, body: text });
|
||||
throw new Error(`Failed to fetch app params: ${res.status} - ${text}`);
|
||||
});
|
||||
}
|
||||
return res.json().then(data => {
|
||||
console.log('⚙️ [API Client] 应用参数数据:', data);
|
||||
return data;
|
||||
try {
|
||||
const response = await axios.get(url, {
|
||||
withCredentials: true, // 携带cookie
|
||||
});
|
||||
}).catch(err => {
|
||||
console.log('⚙️ [API Client] 应用参数响应:', { status: response.status });
|
||||
console.log('⚙️ [API Client] 应用参数数据:', response.data);
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
if (axios.isAxiosError(err)) {
|
||||
console.error('❌ [API Client] 获取应用参数失败:', {
|
||||
status: err.response?.status,
|
||||
body: err.response?.data
|
||||
});
|
||||
throw new Error(`Failed to fetch app params: ${err.response?.status} - ${JSON.stringify(err.response?.data)}`);
|
||||
}
|
||||
console.error('❌ [API Client] 应用参数请求异常:', err);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -669,19 +666,20 @@ export const fetchAppParams = async () => {
|
||||
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',
|
||||
},
|
||||
credentials: 'include', // 携带cookie
|
||||
body: JSON.stringify(body), // 不再添加user参数
|
||||
}).then(res => {
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to update feedback: ${res.status}`);
|
||||
try {
|
||||
const response = await axios.post(`${CHAT_CONFIG.API_URL}/messages/${messageId}/feedbacks`, body, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
withCredentials: true, // 携带cookie
|
||||
});
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
if (axios.isAxiosError(err)) {
|
||||
throw new Error(`Failed to update feedback: ${err.response?.status}`);
|
||||
}
|
||||
return res.json();
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -705,22 +703,23 @@ export const updateFeedback = async ({ url, body }: { url: string; body: Feedbac
|
||||
* ```
|
||||
*/
|
||||
export const generateConversationName = async (id: string) => {
|
||||
return fetch(`${CHAT_CONFIG.API_URL}/conversations/${id}/name`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include', // 携带cookie
|
||||
body: JSON.stringify({
|
||||
try {
|
||||
const response = await axios.post(`${CHAT_CONFIG.API_URL}/conversations/${id}/name`, {
|
||||
auto_generate: true,
|
||||
// 不再添加user参数
|
||||
}),
|
||||
}).then(res => {
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to generate conversation name: ${res.status}`);
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
withCredentials: true, // 携带cookie
|
||||
});
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
if (axios.isAxiosError(err)) {
|
||||
throw new Error(`Failed to generate conversation name: ${err.response?.status}`);
|
||||
}
|
||||
return res.json();
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -749,23 +748,24 @@ export const generateConversationName = async (id: string) => {
|
||||
* ```
|
||||
*/
|
||||
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',
|
||||
},
|
||||
credentials: 'include', // 携带cookie
|
||||
body: JSON.stringify({
|
||||
try {
|
||||
const response = await axios.post(`${CHAT_CONFIG.API_URL}/conversations/${id}/name`, {
|
||||
name: autoGenerate ? undefined : name,
|
||||
auto_generate: autoGenerate,
|
||||
// 不再添加user参数
|
||||
}),
|
||||
}).then(res => {
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to rename conversation: ${res.status}`);
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
withCredentials: true, // 携带cookie
|
||||
});
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
if (axios.isAxiosError(err)) {
|
||||
throw new Error(`Failed to rename conversation: ${err.response?.status}`);
|
||||
}
|
||||
return res.json();
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -790,31 +790,29 @@ export const renameConversation = async (id: string, name: string, autoGenerate:
|
||||
export const deleteConversation = async (id: string) => {
|
||||
console.log('🗑️ [API Client] 删除会话:', id);
|
||||
|
||||
return fetch(`${CHAT_CONFIG.API_URL}/conversations/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include', // 携带cookie
|
||||
// 不再发送body和user参数
|
||||
}).then(async res => {
|
||||
console.log('🗑️ [API Client] 删除会话响应:', {
|
||||
status: res.status,
|
||||
ok: res.ok,
|
||||
statusText: res.statusText
|
||||
try {
|
||||
const response = await axios.delete(`${CHAT_CONFIG.API_URL}/conversations/${id}`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
withCredentials: true, // 携带cookie
|
||||
// 不再发送body和user参数
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
// 尝试读取错误详情
|
||||
const errorText = await res.text();
|
||||
console.error('❌ [API Client] 删除会话失败详情:', errorText);
|
||||
throw new Error(`Failed to delete conversation: ${res.status}`);
|
||||
}
|
||||
console.log('🗑️ [API Client] 删除会话响应:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
console.log('🗑️ [API Client] 删除会话数据:', data);
|
||||
return data;
|
||||
});
|
||||
console.log('🗑️ [API Client] 删除会话数据:', response.data);
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
if (axios.isAxiosError(err)) {
|
||||
console.error('❌ [API Client] 删除会话失败详情:', err.response?.data);
|
||||
throw new Error(`Failed to delete conversation: ${err.response?.status}`);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user