优化:底部导航菜单
This commit is contained in:
@@ -11,6 +11,7 @@ import MarkdownRenderer from '@/components/MarkdownRenderer';
|
|||||||
import {View, RichText} from '@tarojs/components'
|
import {View, RichText} from '@tarojs/components'
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
import {WSS_API_URL} from "@/utils/server";
|
import {WSS_API_URL} from "@/utils/server";
|
||||||
|
import {Image} from '@nutui/nutui-react-taro';
|
||||||
|
|
||||||
// 消息类型
|
// 消息类型
|
||||||
interface Message {
|
interface Message {
|
||||||
@@ -33,6 +34,7 @@ const AiChat = () => {
|
|||||||
const [currentTaskId, setCurrentTaskId] = useState<string>('');
|
const [currentTaskId, setCurrentTaskId] = useState<string>('');
|
||||||
const [wsConnected, setWsConnected] = useState(false);
|
const [wsConnected, setWsConnected] = useState(false);
|
||||||
const [isInitialized, setIsInitialized] = useState(false);
|
const [isInitialized, setIsInitialized] = useState(false);
|
||||||
|
const [isStopped, setIsStopped] = useState(false);
|
||||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||||
const wsRef = useRef<any>(null);
|
const wsRef = useRef<any>(null);
|
||||||
|
|
||||||
@@ -78,8 +80,15 @@ const AiChat = () => {
|
|||||||
wsRef.current = createWebSocket(WSS_API_URL + "/chat/" + userToken);
|
wsRef.current = createWebSocket(WSS_API_URL + "/chat/" + userToken);
|
||||||
|
|
||||||
wsRef.current.onMessage((data: any) => {
|
wsRef.current.onMessage((data: any) => {
|
||||||
console.log('收到WebSocket消息:', data.taskId);
|
console.log('收到WebSocket消息:', data.taskId, '停止状态:', isStopped);
|
||||||
setCurrentTaskId(data.taskId)
|
|
||||||
|
// 如果已经停止,忽略所有消息
|
||||||
|
if (isStopped) {
|
||||||
|
console.log('已停止,忽略WebSocket消息');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentTaskId(data.taskId);
|
||||||
if (data.answer) {
|
if (data.answer) {
|
||||||
if (data.answer === '__END__') {
|
if (data.answer === '__END__') {
|
||||||
// 消息结束,移除typing状态
|
// 消息结束,移除typing状态
|
||||||
@@ -198,6 +207,9 @@ const AiChat = () => {
|
|||||||
const handleSendMessage = async (content: string) => {
|
const handleSendMessage = async (content: string) => {
|
||||||
if (!content.trim() || isLoading) return;
|
if (!content.trim() || isLoading) return;
|
||||||
|
|
||||||
|
// 重置停止状态,允许接收新的WebSocket消息
|
||||||
|
setIsStopped(false);
|
||||||
|
|
||||||
// 检查并确保AI Token存在
|
// 检查并确保AI Token存在
|
||||||
const aiToken = checkAiToken();
|
const aiToken = checkAiToken();
|
||||||
if (!aiToken) {
|
if (!aiToken) {
|
||||||
@@ -274,22 +286,70 @@ const AiChat = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 停止AI回复
|
// 停止AI回复
|
||||||
|
// @ts-ignore
|
||||||
const handleStop = async () => {
|
const handleStop = async () => {
|
||||||
if (currentTaskId) {
|
console.log('点击停止按钮,当前taskId:', currentTaskId);
|
||||||
|
|
||||||
|
// 立即设置停止状态,阻止后续WebSocket消息
|
||||||
|
setIsStopped(true);
|
||||||
|
|
||||||
|
if (!currentTaskId) {
|
||||||
|
console.log('没有正在进行的任务,直接停止加载状态');
|
||||||
|
setIsLoading(false);
|
||||||
|
setMessages(prev => prev.map(msg =>
|
||||||
|
msg.isTyping ? {...msg, isTyping: false} : msg
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
console.log('发送停止请求...');
|
||||||
await stopAiMessage({
|
await stopAiMessage({
|
||||||
taskId: currentTaskId,
|
taskId: currentTaskId,
|
||||||
authCode: '1fbfa21a-a3df-445e-9ca5-2c1a9eead7f4',
|
authCode: '1fbfa21a-a3df-445e-9ca5-2c1a9eead7f4',
|
||||||
user: `${Taro.getStorageSync('AI_TOKEN') || 'anonymous'}`
|
user: `${Taro.getStorageSync('AI_TOKEN') || 'anonymous'}`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('停止请求成功');
|
||||||
|
|
||||||
|
// 立即停止加载状态
|
||||||
|
setIsLoading(false);
|
||||||
|
setCurrentTaskId('');
|
||||||
|
|
||||||
|
// 停止所有正在输入的消息
|
||||||
|
setMessages(prev => prev.map(msg => {
|
||||||
|
if (msg.isTyping && msg.type === 'ai') {
|
||||||
|
return {
|
||||||
|
...msg,
|
||||||
|
isTyping: false,
|
||||||
|
query: (msg.query || '') + '\n\n[已停止回复]'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 显示停止成功提示
|
||||||
|
Taro.showToast({
|
||||||
|
title: '已停止回复',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 1500
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('停止消息失败:', error);
|
||||||
|
|
||||||
|
// 即使API调用失败,也要停止本地状态
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setCurrentTaskId('');
|
setCurrentTaskId('');
|
||||||
setMessages(prev => prev.map(msg =>
|
setMessages(prev => prev.map(msg =>
|
||||||
msg.isTyping ? {...msg, isTyping: false} : msg
|
msg.isTyping ? {...msg, isTyping: false} : msg
|
||||||
));
|
));
|
||||||
} catch (error) {
|
|
||||||
console.error('停止消息失败:', error);
|
Taro.showToast({
|
||||||
}
|
title: '停止失败,但已终止本地回复',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -409,11 +469,32 @@ const AiChat = () => {
|
|||||||
className={'flex justify-center items-center pr-1'}
|
className={'flex justify-center items-center pr-1'}
|
||||||
onClick={() => handleSendMessage(inputValue)}
|
onClick={() => handleSendMessage(inputValue)}
|
||||||
>
|
>
|
||||||
<img alt={'发送'} src={'https://oss.wsdns.cn/20250709/13424d78bb004352864051d61afe9f0e.png'}
|
<Image
|
||||||
width={'30px'}/>
|
src={'https://oss.wsdns.cn/20250709/13424d78bb004352864051d61afe9f0e.png'}
|
||||||
|
width={'30px'}
|
||||||
|
/>
|
||||||
|
{/*{isLoading ? (*/}
|
||||||
|
{/* <Button*/}
|
||||||
|
{/* onClick={handleStop}*/}
|
||||||
|
{/* type="primary"*/}
|
||||||
|
{/* size="small"*/}
|
||||||
|
{/* style={{*/}
|
||||||
|
{/* backgroundColor: '#ff4757',*/}
|
||||||
|
{/* borderColor: '#ff4757',*/}
|
||||||
|
{/* marginTop: '8px'*/}
|
||||||
|
{/* }}*/}
|
||||||
|
{/* >*/}
|
||||||
|
{/* 停止*/}
|
||||||
|
{/* </Button>*/}
|
||||||
|
{/*) : (*/}
|
||||||
|
{/* <img*/}
|
||||||
|
{/* alt={'发送'}*/}
|
||||||
|
{/* src={'https://oss.wsdns.cn/20250709/13424d78bb004352864051d61afe9f0e.png'}*/}
|
||||||
|
{/* width={'30px'}*/}
|
||||||
|
{/* />*/}
|
||||||
|
{/*)}*/}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={handleStop}>停止</Button>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
Reference in New Issue
Block a user