代码优化
This commit is contained in:
1 parent
214e794451
commit
2371364911
5 files changed
+62
-548
No files matched your search
@@ -61,47 +61,28 @@ export default function StrategyRoutes() {
|
||||
/>
|
||||
{/* 任务管理 */}
|
||||
<Route path="task-management" element={<TaskManagement />}>
|
||||
<Route index element={<Navigate to="xk-task-jc" replace />} />
|
||||
{/* XK任务 */}
|
||||
<Route
|
||||
path="xk-task-jc"
|
||||
element={
|
||||
<TaskXkFrom
|
||||
gopath={'#/pageIndie/pageHome/pageSwrw'}
|
||||
/>
|
||||
}
|
||||
element={<TaskXkFrom gopath="#/pageIndie/pageHome/pageSwrw" />}
|
||||
/>
|
||||
<Route
|
||||
path="xk-task-dispatch"
|
||||
element={
|
||||
<TaskXkFrom
|
||||
gopath={'#/pageIndie/pageJczl'}
|
||||
/>
|
||||
}
|
||||
element={<TaskXkFrom gopath="#/pageIndie/pageJczl" />}
|
||||
/>
|
||||
{/* pg中任务 */}
|
||||
<Route
|
||||
path="effect-task-pg"
|
||||
element={
|
||||
<TaskPgFrom
|
||||
gopath="task"
|
||||
/>
|
||||
}
|
||||
element={<TaskPgFrom gopath="task" />}
|
||||
/>
|
||||
<Route
|
||||
path="effect-action-pg"
|
||||
element={
|
||||
<TaskPgFrom
|
||||
gopath="xd"
|
||||
/>
|
||||
}
|
||||
element={<TaskPgFrom gopath="xd" />}
|
||||
/>
|
||||
<Route
|
||||
path="effect-info-pg"
|
||||
element={
|
||||
<TaskPgFrom
|
||||
gopath="info"
|
||||
/>
|
||||
}
|
||||
element={<TaskPgFrom gopath="info" />}
|
||||
/>
|
||||
{/* COH中任务 */}
|
||||
<Route
|
||||
@@ -114,7 +95,7 @@ export default function StrategyRoutes() {
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
<Route
|
||||
path="plan-task/plan-task-fx"
|
||||
element={
|
||||
<TaskAnalyzes
|
||||
@@ -124,7 +105,7 @@ export default function StrategyRoutes() {
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
<Route
|
||||
path="plan-task/plan-task-action"
|
||||
element={
|
||||
<ActionAnalyzes
|
||||
@@ -135,36 +116,9 @@ export default function StrategyRoutes() {
|
||||
}
|
||||
/>
|
||||
{/* MNTY任务 */}
|
||||
<Route
|
||||
path="mnty-task-mechanism"
|
||||
element={
|
||||
<XingdongTyPage
|
||||
title="XDTY任务"
|
||||
category="MNTY任务"
|
||||
subCategory="MNTY任务"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="mnty-task-plan"
|
||||
element={
|
||||
<FanganTyPage
|
||||
title="方案TY任务"
|
||||
category="MNTY任务"
|
||||
subCategory="MNTY任务"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="mnty-task-zsty"
|
||||
element={
|
||||
<XXTyPage
|
||||
title="XXTY任务"
|
||||
category="MNTY任务"
|
||||
subCategory="MNTY任务"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route path="mnty-task-mechanism" element={<XingdongTyPage />} />
|
||||
<Route path="mnty-task-plan" element={<FanganTyPage />} />
|
||||
<Route path="mnty-task-zsty" element={<XXTyPage />} />
|
||||
</Route>
|
||||
{/* 资源管理 */}
|
||||
<Route
|
||||
|
||||
@@ -1074,17 +1074,38 @@ const GeneralQA: React.FC<{
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理真实多轮 RAG 请求。
|
||||
* 统一的多轮 SSE 生成请求。
|
||||
*
|
||||
* handleRun / handleTaskRun / handleHxRun / newsReportRun 原本是四份几乎一致的拷贝,
|
||||
* 仅请求地址和少量 side 处理细节不同。这里抽成一个函数,差异通过 options 严格保留:
|
||||
* - passSideToToolCall:是否把 side 透传给 handleToolCall(对比模式下写入对应面板)
|
||||
* - guardHistoryBySide:是否仅在非对比模式(!side)时落库,避免对比模式重复落库
|
||||
* - logCompareResult:仅影响 done 时调试日志打印的对象(compareResult / messageList)
|
||||
*
|
||||
* 多轮接口采用 SSE:每行 `data:` 都描述一个事件。组件根据事件类型分别更新 taskId、工具调用、
|
||||
* 最终回答和引用来源。当前用户入口暂时走本地模拟,此方法保留给接口连通后切换使用。
|
||||
* 最终回答和引用来源。
|
||||
*/
|
||||
const handleRun = async (query: string, side: 'left' | 'right' | null = null) => {
|
||||
const runMultiRoundStream = async (
|
||||
url: string,
|
||||
query: string,
|
||||
side: 'left' | 'right' | null = null,
|
||||
options: {
|
||||
passSideToToolCall?: boolean;
|
||||
guardHistoryBySide?: boolean;
|
||||
logCompareResult?: boolean;
|
||||
} = {},
|
||||
) => {
|
||||
const {
|
||||
passSideToToolCall = false,
|
||||
guardHistoryBySide = false,
|
||||
logCompareResult = false,
|
||||
} = options;
|
||||
setError(null);
|
||||
setIsLoading(true);
|
||||
setIsPreConnectLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${generateUrl}/generate`, {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ prompt: query }),
|
||||
@@ -1109,20 +1130,14 @@ const GeneralQA: React.FC<{
|
||||
};
|
||||
if (!side) {
|
||||
state.current.messageList.push(assistantMessage); // 数据存储
|
||||
// 接口连通后再展示多轮检索主题与过程
|
||||
setMessages((prev) => [...prev, assistantMessage]);
|
||||
} else if (side === 'left' || side === 'right') {
|
||||
state.current.compareResult[state.current.compareIndex][side].thinkingTrace = createMultiRoundStreamTrace();
|
||||
updatePane(side, (pane) => {
|
||||
return {
|
||||
...pane,
|
||||
thinkingTrace: createMultiRoundStreamTrace(),
|
||||
};
|
||||
});
|
||||
updatePane(side, (pane) => ({ ...pane, thinkingTrace: createMultiRoundStreamTrace() }));
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
// 保存 reader 引用,用于"停止生成"功能
|
||||
// 保存 reader 引用,用于“停止生成”功能
|
||||
if (!side) {
|
||||
readerRef.current = reader;
|
||||
} else {
|
||||
@@ -1135,8 +1150,8 @@ const GeneralQA: React.FC<{
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
console.log('聊天记录', state.current.compareResult);
|
||||
if (!side) {
|
||||
console.log('聊天记录', logCompareResult ? state.current.compareResult : state.current.messageList);
|
||||
if (!guardHistoryBySide || !side) {
|
||||
chatHistoryAddSearch();
|
||||
}
|
||||
break;
|
||||
@@ -1163,7 +1178,7 @@ const GeneralQA: React.FC<{
|
||||
break;
|
||||
}
|
||||
case 'tool_call': {
|
||||
handleToolCall(data as ToolCallData, assistantId, side);
|
||||
handleToolCall(data as ToolCallData, assistantId, passSideToToolCall ? side : null);
|
||||
break;
|
||||
}
|
||||
case 'message': {
|
||||
@@ -1228,464 +1243,27 @@ const GeneralQA: React.FC<{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理任务检索 请求。
|
||||
*
|
||||
* 多轮接口采用 SSE:每行 `data:` 都描述一个事件。组件根据事件类型分别更新 taskId、工具调用、
|
||||
* 最终回答和引用来源。当前用户入口暂时走本地模拟,此方法保留给接口连通后切换使用。
|
||||
*/
|
||||
const handleTaskRun = async (query: string, side: 'left' | 'right' | null = null) => {
|
||||
setError(null);
|
||||
setIsLoading(true);
|
||||
setIsPreConnectLoading(true);
|
||||
// 多轮 RAG 检索:透传 side、仅非对比模式落库、日志打印 compareResult。
|
||||
const handleRun = (query: string, side: 'left' | 'right' | null = null) =>
|
||||
runMultiRoundStream(`${generateUrl}/generate`, query, side, {
|
||||
passSideToToolCall: true,
|
||||
guardHistoryBySide: true,
|
||||
logCompareResult: true,
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetch(`${taskChatUrl}/generate`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ prompt: query }),
|
||||
});
|
||||
// 任务检索:透传 side,但 done 时无条件落库。
|
||||
const handleTaskRun = (query: string, side: 'left' | 'right' | null = null) =>
|
||||
runMultiRoundStream(`${taskChatUrl}/generate`, query, side, {
|
||||
passSideToToolCall: true,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
// 画像检索:不透传 side,done 时无条件落库。
|
||||
const handleHxRun = (query: string, side: 'left' | 'right' | null = null) =>
|
||||
runMultiRoundStream(`${taskChatUrl}/generate_b2`, query, side);
|
||||
|
||||
if (!response.body) {
|
||||
throw new Error('Response body is null');
|
||||
}
|
||||
setIsPreConnectLoading(false);
|
||||
|
||||
const assistantId = `assistant-${Date.now()}`;
|
||||
const assistantMessage: Message = {
|
||||
id: assistantId,
|
||||
role: 'assistant',
|
||||
content: '',
|
||||
timestamp: new Date(),
|
||||
thinkingTrace: createMultiRoundStreamTrace(),
|
||||
};
|
||||
if (!side) {
|
||||
state.current.messageList.push(assistantMessage); // 数据存储
|
||||
// 接口连通后再展示多轮检索主题与过程
|
||||
setMessages((prev) => [...prev, assistantMessage]);
|
||||
} else if (side === 'left' || side === 'right') {
|
||||
state.current.compareResult[state.current.compareIndex][side].thinkingTrace = createMultiRoundStreamTrace();
|
||||
updatePane(side, (pane) => {
|
||||
return {
|
||||
...pane,
|
||||
thinkingTrace: createMultiRoundStreamTrace(),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
if (!side) {
|
||||
readerRef.current = reader;
|
||||
} else {
|
||||
compareReaderRef.current[side] = reader;
|
||||
}
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = '';
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
console.log('聊天记录', state.current.messageList);
|
||||
chatHistoryAddSearch();
|
||||
break;
|
||||
}
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split('\n');
|
||||
const lastLine = lines.pop();
|
||||
buffer = lastLine || '';
|
||||
|
||||
for (const line of lines) {
|
||||
if (!line.startsWith('data: ')) continue;
|
||||
|
||||
try {
|
||||
const parsedData = JSON.parse(line.slice(6)) as {
|
||||
event: string;
|
||||
data: any;
|
||||
};
|
||||
const { event, data } = parsedData;
|
||||
|
||||
switch (event) {
|
||||
case 'task_created': {
|
||||
taskIdRef.current = data?.task_id || null;
|
||||
break;
|
||||
}
|
||||
case 'tool_call': {
|
||||
handleToolCall(data as ToolCallData, assistantId, side);
|
||||
break;
|
||||
}
|
||||
case 'message': {
|
||||
if (typeof data === 'string') {
|
||||
setMessages((prevMessages) => prevMessages.map((msg) => {
|
||||
if (msg.id !== assistantId || !msg.thinkingTrace) return msg;
|
||||
return {
|
||||
...msg,
|
||||
thinkingTrace: {
|
||||
...msg.thinkingTrace,
|
||||
finalAnswerMarkdown: `${msg.thinkingTrace.finalAnswerMarkdown}${data}`,
|
||||
},
|
||||
};
|
||||
}));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'references': {
|
||||
const refs = Array.isArray(data?.references) ? data.references : [];
|
||||
const mappedRefs = refs.map(mapReferenceToSource);
|
||||
setSearchProcess((prev) => ({
|
||||
...prev,
|
||||
hits: mappedRefs.length,
|
||||
}));
|
||||
setMessages((prevMessages) => prevMessages.map((msg) => (
|
||||
msg.id === assistantId
|
||||
? { ...msg, sources: mappedRefs }
|
||||
: msg
|
||||
)));
|
||||
break;
|
||||
}
|
||||
case 'done': {
|
||||
setIsLoading(false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.log(`未知事件类型: ${event}`, data);
|
||||
}
|
||||
} catch (parseError) {
|
||||
console.error('JSON解析错误:', parseError);
|
||||
console.error('原始数据:', line.slice(6));
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (readerRef.current) {
|
||||
readerRef.current.releaseLock();
|
||||
readerRef.current = null;
|
||||
}
|
||||
}
|
||||
} catch (runError) {
|
||||
console.error('处理请求时发生错误:', runError);
|
||||
setIsLoading(false);
|
||||
setError(runError instanceof Error ? runError.message : '发生未知错误,请稍后重试');
|
||||
setIsPreConnectLoading(false);
|
||||
} finally {
|
||||
// 无论成功还是失败,都要重置加载状态和解锁提交
|
||||
setIsPreConnectLoading(false);
|
||||
setIsLoading(false);
|
||||
submitLockRef.current = false;
|
||||
handleStopCompareSide(side);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理画像检索 请求。
|
||||
*
|
||||
* 多轮接口采用 SSE:每行 `data:` 都描述一个事件。组件根据事件类型分别更新 taskId、工具调用、
|
||||
* 最终回答和引用来源。当前用户入口暂时走本地模拟,此方法保留给接口连通后切换使用。
|
||||
*/
|
||||
const handleHxRun = async (query: string, side: 'left' | 'right' | null = null) => {
|
||||
setError(null);
|
||||
setIsLoading(true);
|
||||
setIsPreConnectLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${taskChatUrl}/generate_b2`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ prompt: query }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
if (!response.body) {
|
||||
throw new Error('Response body is null');
|
||||
}
|
||||
setIsPreConnectLoading(false);
|
||||
|
||||
const assistantId = `assistant-${Date.now()}`;
|
||||
const assistantMessage: Message = {
|
||||
id: assistantId,
|
||||
role: 'assistant',
|
||||
content: '',
|
||||
timestamp: new Date(),
|
||||
thinkingTrace: createMultiRoundStreamTrace(),
|
||||
};
|
||||
if (!side) {
|
||||
state.current.messageList.push(assistantMessage); // 数据存储
|
||||
// 接口连通后再展示多轮检索主题与过程
|
||||
setMessages((prev) => [...prev, assistantMessage]);
|
||||
} else if (side === 'left' || side === 'right') {
|
||||
state.current.compareResult[state.current.compareIndex][side].thinkingTrace = createMultiRoundStreamTrace();
|
||||
updatePane(side, (pane) => {
|
||||
return {
|
||||
...pane,
|
||||
thinkingTrace: createMultiRoundStreamTrace(),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
if (!side) {
|
||||
readerRef.current = reader;
|
||||
} else {
|
||||
compareReaderRef.current[side] = reader;
|
||||
}
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = '';
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
console.log('聊天记录', state.current.messageList);
|
||||
chatHistoryAddSearch();
|
||||
break;
|
||||
}
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split('\n');
|
||||
const lastLine = lines.pop();
|
||||
buffer = lastLine || '';
|
||||
|
||||
for (const line of lines) {
|
||||
if (!line.startsWith('data: ')) continue;
|
||||
|
||||
try {
|
||||
const parsedData = JSON.parse(line.slice(6)) as {
|
||||
event: string;
|
||||
data: any;
|
||||
};
|
||||
const { event, data } = parsedData;
|
||||
|
||||
switch (event) {
|
||||
case 'task_created': {
|
||||
taskIdRef.current = data?.task_id || null;
|
||||
break;
|
||||
}
|
||||
case 'tool_call': {
|
||||
handleToolCall(data as ToolCallData, assistantId);
|
||||
break;
|
||||
}
|
||||
case 'message': {
|
||||
if (typeof data === 'string') {
|
||||
setMessages((prevMessages) => prevMessages.map((msg) => {
|
||||
if (msg.id !== assistantId || !msg.thinkingTrace) return msg;
|
||||
return {
|
||||
...msg,
|
||||
thinkingTrace: {
|
||||
...msg.thinkingTrace,
|
||||
finalAnswerMarkdown: `${msg.thinkingTrace.finalAnswerMarkdown}${data}`,
|
||||
},
|
||||
};
|
||||
}));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'references': {
|
||||
const refs = Array.isArray(data?.references) ? data.references : [];
|
||||
const mappedRefs = refs.map(mapReferenceToSource);
|
||||
setSearchProcess((prev) => ({
|
||||
...prev,
|
||||
hits: mappedRefs.length,
|
||||
}));
|
||||
setMessages((prevMessages) => prevMessages.map((msg) => (
|
||||
msg.id === assistantId
|
||||
? { ...msg, sources: mappedRefs }
|
||||
: msg
|
||||
)));
|
||||
break;
|
||||
}
|
||||
case 'done': {
|
||||
setIsLoading(false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.log(`未知事件类型: ${event}`, data);
|
||||
}
|
||||
} catch (parseError) {
|
||||
console.error('JSON解析错误:', parseError);
|
||||
console.error('原始数据:', line.slice(6));
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (readerRef.current) {
|
||||
readerRef.current.releaseLock();
|
||||
readerRef.current = null;
|
||||
}
|
||||
}
|
||||
} catch (runError) {
|
||||
console.error('处理请求时发生错误:', runError);
|
||||
setIsLoading(false);
|
||||
setError(runError instanceof Error ? runError.message : '发生未知错误,请稍后重试');
|
||||
setIsPreConnectLoading(false);
|
||||
} finally {
|
||||
// 无论成功还是失败,都要重置加载状态和解锁提交
|
||||
setIsPreConnectLoading(false);
|
||||
setIsLoading(false);
|
||||
submitLockRef.current = false;
|
||||
handleStopCompareSide(side);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理画像检索 请求。
|
||||
*
|
||||
* 多轮接口采用 SSE:每行 `data:` 都描述一个事件。组件根据事件类型分别更新 taskId、工具调用、
|
||||
* 最终回答和引用来源。当前用户入口暂时走本地模拟,此方法保留给接口连通后切换使用。
|
||||
*/
|
||||
const newsReportRun = async (query: string, side: 'left' | 'right' | null = null) => {
|
||||
setError(null);
|
||||
setIsLoading(true);
|
||||
setIsPreConnectLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${taskChatUrl}/generate_report`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ prompt: query }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
if (!response.body) {
|
||||
throw new Error('Response body is null');
|
||||
}
|
||||
setIsPreConnectLoading(false);
|
||||
|
||||
const assistantId = `assistant-${Date.now()}`;
|
||||
const assistantMessage: Message = {
|
||||
id: assistantId,
|
||||
role: 'assistant',
|
||||
content: '',
|
||||
timestamp: new Date(),
|
||||
thinkingTrace: createMultiRoundStreamTrace(),
|
||||
};
|
||||
if (!side) {
|
||||
state.current.messageList.push(assistantMessage); // 数据存储
|
||||
// 接口连通后再展示多轮检索主题与过程
|
||||
setMessages((prev) => [...prev, assistantMessage]);
|
||||
} else if (side === 'left' || side === 'right') {
|
||||
state.current.compareResult[state.current.compareIndex][side].thinkingTrace = createMultiRoundStreamTrace();
|
||||
updatePane(side, (pane) => {
|
||||
return {
|
||||
...pane,
|
||||
thinkingTrace: createMultiRoundStreamTrace(),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
if (!side) {
|
||||
readerRef.current = reader;
|
||||
} else {
|
||||
compareReaderRef.current[side] = reader;
|
||||
}
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = '';
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
console.log('聊天记录', state.current.messageList);
|
||||
chatHistoryAddSearch();
|
||||
break;
|
||||
}
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split('\n');
|
||||
const lastLine = lines.pop();
|
||||
buffer = lastLine || '';
|
||||
|
||||
for (const line of lines) {
|
||||
if (!line.startsWith('data: ')) continue;
|
||||
|
||||
try {
|
||||
const parsedData = JSON.parse(line.slice(6)) as {
|
||||
event: string;
|
||||
data: any;
|
||||
};
|
||||
const { event, data } = parsedData;
|
||||
|
||||
switch (event) {
|
||||
case 'task_created': {
|
||||
taskIdRef.current = data?.task_id || null;
|
||||
break;
|
||||
}
|
||||
case 'tool_call': {
|
||||
handleToolCall(data as ToolCallData, assistantId);
|
||||
break;
|
||||
}
|
||||
case 'message': {
|
||||
if (typeof data === 'string') {
|
||||
setMessages((prevMessages) => prevMessages.map((msg) => {
|
||||
if (msg.id !== assistantId || !msg.thinkingTrace) return msg;
|
||||
return {
|
||||
...msg,
|
||||
thinkingTrace: {
|
||||
...msg.thinkingTrace,
|
||||
finalAnswerMarkdown: `${msg.thinkingTrace.finalAnswerMarkdown}${data}`,
|
||||
},
|
||||
};
|
||||
}));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'references': {
|
||||
const refs = Array.isArray(data?.references) ? data.references : [];
|
||||
const mappedRefs = refs.map(mapReferenceToSource);
|
||||
setSearchProcess((prev) => ({
|
||||
...prev,
|
||||
hits: mappedRefs.length,
|
||||
}));
|
||||
setMessages((prevMessages) => prevMessages.map((msg) => (
|
||||
msg.id === assistantId
|
||||
? { ...msg, sources: mappedRefs }
|
||||
: msg
|
||||
)));
|
||||
break;
|
||||
}
|
||||
case 'done': {
|
||||
setIsLoading(false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.log(`未知事件类型: ${event}`, data);
|
||||
}
|
||||
} catch (parseError) {
|
||||
console.error('JSON解析错误:', parseError);
|
||||
console.error('原始数据:', line.slice(6));
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (readerRef.current) {
|
||||
readerRef.current.releaseLock();
|
||||
readerRef.current = null;
|
||||
}
|
||||
}
|
||||
} catch (runError) {
|
||||
console.error('处理请求时发生错误:', runError);
|
||||
setIsLoading(false);
|
||||
setError(runError instanceof Error ? runError.message : '发生未知错误,请稍后重试');
|
||||
setIsPreConnectLoading(false);
|
||||
} finally {
|
||||
// 无论成功还是失败,都要重置加载状态和解锁提交
|
||||
setIsPreConnectLoading(false);
|
||||
setIsLoading(false);
|
||||
submitLockRef.current = false;
|
||||
handleStopCompareSide(side);
|
||||
}
|
||||
};
|
||||
// 新闻报告生成:不透传 side,done 时无条件落库。
|
||||
const newsReportRun = (query: string, side: 'left' | 'right' | null = null) =>
|
||||
runMultiRoundStream(`${taskChatUrl}/generate_report`, query, side);
|
||||
|
||||
/**
|
||||
* 单一模式下的发送入口。
|
||||
|
||||
@@ -3,15 +3,9 @@ import "./css/iframe.css";
|
||||
|
||||
import { useTheme } from "@/contexts/ThemeContext";
|
||||
|
||||
interface FanganTyPageProps {
|
||||
title: string;
|
||||
category: string;
|
||||
subCategory: string;
|
||||
}
|
||||
|
||||
const TYURL = import.meta.env.VITE_AIPI_B2ACTOR_URL || "";
|
||||
|
||||
const FanganTyPage: React.FC<FanganTyPageProps> = () => {
|
||||
const FanganTyPage: React.FC = () => {
|
||||
const { theme } = useTheme();
|
||||
const isDark = theme === "dark";
|
||||
const [iframeUrl, setIframeUrl] = useState("");
|
||||
|
||||
@@ -3,15 +3,9 @@ import "./css/iframe.css";
|
||||
|
||||
import { useTheme } from "@/contexts/ThemeContext";
|
||||
|
||||
interface XXTyPageProps {
|
||||
title: string;
|
||||
category: string;
|
||||
subCategory: string;
|
||||
}
|
||||
|
||||
const TYURL = import.meta.env.VITE_AIPI_B2ACTOR_URL || "";
|
||||
|
||||
const XXTyPage: React.FC<XXTyPageProps> = () => {
|
||||
const XXTyPage: React.FC = () => {
|
||||
const { theme } = useTheme();
|
||||
const isDark = theme === "dark";
|
||||
const [iframeUrl, setIframeUrl] = useState("");
|
||||
|
||||
@@ -3,15 +3,9 @@ import "./css/iframe.css";
|
||||
|
||||
import { useTheme } from "@/contexts/ThemeContext";
|
||||
|
||||
interface XingdongTyPageProps {
|
||||
title: string;
|
||||
category: string;
|
||||
subCategory: string;
|
||||
}
|
||||
|
||||
const TYURL = import.meta.env.VITE_AIPI_B2ACTOR_URL || "";
|
||||
|
||||
const XingdongTyPage: React.FC<XingdongTyPageProps> = () => {
|
||||
const XingdongTyPage: React.FC = () => {
|
||||
const { theme } = useTheme();
|
||||
const isDark = theme === "dark";
|
||||
const [iframeUrl, setIframeUrl] = useState("");
|
||||
|
||||
Reference in new issue
Block a user