Compare commits

...

5 Commits

Author SHA1 Message Date
“zhuzihan” 
f549b084a8 合并view 2025-07-10 17:14:40 +08:00
“zhuzihan” 
1507e1a725 暂存 2025-07-09 14:16:36 +08:00
“zhuzihan” 
0be3e9b263 非空判断 2025-07-09 10:20:16 +08:00
“zhuzihan” 
13cef0b0bf ds流式加载 2025-07-08 18:29:12 +08:00
“zhuzihan” 
084f859ad3 合并 2025-07-07 13:19:23 +08:00
5 changed files with 78 additions and 55 deletions

View File

@ -250,38 +250,29 @@ const chatMessages = ref([
// DeepSeek API
const sendMessage = async () => {
if (!userInput.value.trim() || isLoading.value) return
if (!userInput.value.trim() || isLoading.value) return;
//
const userMessage = userInput.value.trim()
chatMessages.value.push({ role: 'user', content: userMessage })
userInput.value = ''
//
await nextTick()
if (chatMessagesRef.value) {
chatMessagesRef.value.scrollTop = chatMessagesRef.value.scrollHeight
}
//
isLoading.value = true
const userMessage = userInput.value.trim();
chatMessages.value.push({ role: 'user', content: userMessage });
userInput.value = '';
//
await nextTick();
scrollToBottom();
//
isLoading.value = true;
chatMessages.value.push({ role: 'assistant', content: '思考中...' });
const aiMessageIndex = chatMessages.value.length - 1;
try {
// DeepSeek API
const apiMessages = [
{ role: 'system', content: '' }
]
// 10()
const recentMessages = chatMessages.value.slice(-10)
recentMessages.forEach(msg => {
apiMessages.push({
role: msg.role === 'assistant' ? 'assistant' : 'user',
content: msg.content
})
})
// DeepSeek API
// 5
const apiMessages = chatMessages.value
.slice(-5)
.map(msg => ({ role: msg.role, content: msg.content }));
// API
const response = await fetch('https://api.deepseek.com/chat/completions', {
method: 'POST',
headers: {
@ -291,36 +282,59 @@ const sendMessage = async () => {
body: JSON.stringify({
model: 'deepseek-chat',
messages: apiMessages,
stream: false
stream: true //
})
})
});
if (!response.ok) {
throw new Error('API请求失败')
throw new Error(`API错误: ${response.status}`);
}
//
const reader = response.body.getReader();
let fullResponse = '';
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// APIndjson
const chunk = decoder.decode(value);
const lines = chunk.split('\n').filter(line => line.trim());
for (const line of lines) {
try {
const data = JSON.parse(line.replace('data: ', ''));
if (data.choices?.[0]?.delta?.content) {
fullResponse += data.choices[0].delta.content;
// UI
chatMessages.value[aiMessageIndex].content = md.render(fullResponse);
scrollToBottom();
}
} catch (e) {
console.warn('解析流数据失败:', e);
}
}
}
const data = await response.json()
const aiResponse = data.choices && data.choices[0]?.message?.content || '抱歉,我无法回答这个问题。'
const aiResponseHtml = md.render(aiResponse)
// AI
chatMessages.value.push({ role: 'assistant', content: aiResponseHtml })
} catch (error) {
console.error('DeepSeek API调用失败:', error)
chatMessages.value.push({ role: 'assistant', content: '抱歉,我遇到了技术问题,请稍后再试。' })
console.error('请求失败:', error);
chatMessages.value[aiMessageIndex].content = '抱歉,回答时遇到问题,请重试。';
} finally {
isLoading.value = false
//
await nextTick()
if (chatMessagesRef.value) {
chatMessagesRef.value.scrollTop = chatMessagesRef.value.scrollHeight
}
isLoading.value = false;
scrollToBottom();
}
}
};
//
const scrollToBottom = () => {
nextTick().then(() => {
if (chatMessagesRef.value) {
chatMessagesRef.value.scrollTop = chatMessagesRef.value.scrollHeight;
}
});
};
//
const fundingLegendStatus = ref([true, true, true])

View File

@ -59,7 +59,7 @@
<div class="lab-info">
<div class="info-item">
<span class="info-label">研究中心名称:</span>
<span class="info-label">中心名称:</span>
<span class="info-value">{{ lab.basicInformation.name2 }}</span>
</div>
<div class="info-item">

View File

@ -16,7 +16,7 @@
<span class="display-text">{{ labData.basicInformation.name1 }}</span>
</div>
<div class="form-item">
<span class="label">工程研究中心名称:</span>
<span class="label">中心名称:</span>
<span class="display-text">{{ labData.basicInformation.name2 }}</span>
</div>
</div>

View File

@ -83,7 +83,7 @@
</div>
<div class="info-row">
<span class="info-label">职称 / 职务:</span>
<span class="info-value">{{ teacher.basicInformation.name2 }} / {{ teacher.basicInformation.name3 }}</span>
<span class="info-value">{{ teacher.basicInformation.name2 }}{{ teacher.basicInformation.name3 ? ' / ' + teacher.basicInformation.name3 : '' }}</span>
</div>
<div class="info-row">
<span class="info-label">所属院校:</span>
@ -398,6 +398,11 @@ const openTeacherDetail = (teacher) => {
<style scoped>
.teacher-info span{
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
display: block;
}
.evaluation-page {
position: absolute;

View File

@ -206,6 +206,10 @@ h2{
.info-value {
font-weight: bold;
/* white-space: nowrap; */
text-overflow: ellipsis;
overflow: hidden;
font-size: 12px;
}
/* ========= 按钮样式 ========= */