Implement chat queue fallback

This commit is contained in:
2026-07-08 16:57:40 +08:00
parent 10b6de0622
commit 6f3bbd3803
10 changed files with 367 additions and 31 deletions

View File

@@ -18,24 +18,36 @@ const assistantParts = computed(() => {
if (props.role === "user") {
return { reasoning: "", answer: props.content };
}
const matched = props.content.match(/<think>([\s\S]*?)<\/think>/i);
if (matched) {
return {
reasoning: matched[1].trim(),
answer: props.content.replace(matched[0], "").trim(),
};
}
const opening = props.content.match(/<think>([\s\S]*)$/i);
if (opening) {
return {
reasoning: opening[1].trim(),
answer: props.content.slice(0, opening.index).trim(),
};
}
return { reasoning: "", answer: props.content };
});
const renderedReasoning = computed(() => markdown.render(assistantParts.value.reasoning || ""));
const content = props.content;
let reasoning = "";
let answer = content;
// 匹配所有完整的 <think>...</think>(全局匹配,支持多个)
const thinkRegex = /<think>([\s\S]*?)<\/think>/gi;
const matches = Array.from(answer.matchAll(thinkRegex));
if (matches.length > 0) {
reasoning = matches.map((m) => m[1].trim()).join("\n\n");
answer = answer.replace(thinkRegex, "").trim();
}
// 处理未闭合的 <think>(流式输出时可能还没收到 </think>
const openThink = answer.match(/<think>([\s\S]*)$/i);
if (openThink) {
reasoning += (reasoning ? "\n\n" : "") + openThink[1].trim();
answer = answer.slice(0, openThink.index).trim();
}
// 兜底:如果 answer 为空但 reasoning 有内容,说明模型可能把全部内容放在 think 里了
// 此时把 reasoning 当 answer 显示,不显示 thinking 面板
if (!answer && reasoning) {
answer = reasoning;
reasoning = "";
}
return { reasoning, answer };
});
const renderedContent = computed(() => {
if (props.role === "user") return props.content;
@@ -48,10 +60,9 @@ const renderedContent = computed(() => {
<div class="avatar">{{ role === "assistant" ? "AI" : "我" }}</div>
<div class="bubble">
<template v-if="role === 'assistant'">
<details v-if="assistantParts.reasoning" class="reasoning-panel" :open="streaming">
<summary>{{ streaming ? "思考中" : "思考过程" }}</summary>
<div class="markdown-content reasoning-content" v-html="renderedReasoning"></div>
</details>
<div v-if="streaming && assistantParts.reasoning" class="thinking-indicator">
<span class="thinking-dots">思考中</span>
</div>
<div class="content markdown-content" v-html="renderedContent"></div>
</template>
<div v-else class="content">{{ renderedContent }}</div>