优化思考状态展开与收起交互

This commit is contained in:
kx_guo 2026-09-15 13:35:36 +08:00
parent 92a86efe73
commit 173e05eda6

View File

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import axios from "axios"; import axios from "axios";
import { ChevronDown } from "@lucide/vue";
import { computed, nextTick, onActivated, onMounted, ref, watch } from "vue"; import { computed, nextTick, onActivated, onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
@ -138,10 +139,6 @@ function toggleReply(messageId: number) {
expandedReplies.value = next; expandedReplies.value = next;
} }
function canCollapseReply(content: string) {
return content.trim().length > 90;
}
function isMessageThinking(messageId: number, index: number) { function isMessageThinking(messageId: number, index: number) {
const messages = conversation.value?.messages ?? []; const messages = conversation.value?.messages ?? [];
return ( return (
@ -530,72 +527,41 @@ async function scrollToBottom(behavior: "smooth" | "auto" = "smooth") {
> >
</div> </div>
<div <div
v-if=" v-if="message.content || isMessageThinking(message.id, messageIndex)"
message.content &&
(message.riskResult ||
message.responseCard ||
isMessageThinking(message.id, messageIndex))
"
class="assistant-thinking" class="assistant-thinking"
> >
<button <button
type="button" type="button"
class="assistant-thinking__header" class="assistant-thinking__header"
:disabled="
isMessageThinking(message.id, messageIndex) ||
!canCollapseReply(message.content)
"
@click="toggleReply(message.id)" @click="toggleReply(message.id)"
> >
<span v-if="isMessageThinking(message.id, messageIndex)" <span
>思考中…</span v-if="isMessageThinking(message.id, messageIndex)"
class="assistant-thinking__status"
>思考中</span
> >
<span v-else> <span v-else>
已完成<span v-if="thinkingDuration(messageIndex)"> 已完成<span v-if="thinkingDuration(messageIndex)" class="assistant-thinking__duration">
{{ thinkingDuration(messageIndex) }}s</span {{ thinkingDuration(messageIndex) }}s</span
> >
</span> </span>
<span <ChevronDown
v-if="canCollapseReply(message.content)" :size="13"
class="assistant-thinking__arrow" class="assistant-thinking__arrow"
>{{ expandedReplies.has(message.id) ? "⌄" : "›" }}</span :class="{ expanded: expandedReplies.has(message.id) }"
> />
</button> </button>
<div <div
v-if="message.content"
class="assistant-bubble" class="assistant-bubble"
:class="{ :class="{
'assistant-bubble--collapsed': 'assistant-bubble--collapsed':
canCollapseReply(message.content) &&
!expandedReplies.has(message.id), !expandedReplies.has(message.id),
}" }"
> >
{{ message.content }} {{ message.content }}
</div> </div>
</div> </div>
<div
v-else-if="message.content"
class="assistant-bubble"
:class="{
'assistant-bubble--collapsed':
canCollapseReply(message.content) &&
!expandedReplies.has(message.id),
}"
>
{{ message.content }}
</div>
<button
v-if="
message.content &&
!message.riskResult &&
!message.responseCard &&
canCollapseReply(message.content)
"
type="button"
class="reply-toggle"
@click="toggleReply(message.id)"
>
{{ expandedReplies.has(message.id) ? "收起" : "展开全文" }}
</button>
<RiskAnalysisCard <RiskAnalysisCard
v-if="message.riskResult" v-if="message.riskResult"
:result="message.riskResult" :result="message.riskResult"
@ -870,36 +836,53 @@ async function scrollToBottom(behavior: "smooth" | "auto" = "smooth") {
display: flex; display: flex;
width: auto; width: auto;
align-items: center; align-items: center;
gap: 5px; gap: 4px;
border: 0; border: 0;
margin: 0 0 5px 2px; margin: 0 0 6px;
padding: 0; padding: 3px 7px;
border-radius: 6px;
background: transparent; background: transparent;
color: var(--color-text-muted); color: var(--color-text-muted);
font-size: 11px; font-size: 11px;
font-family: inherit; font-family: inherit;
cursor: pointer; cursor: pointer;
transition: background 0.15s, color 0.15s;
} }
.assistant-thinking__header:disabled { .assistant-thinking__header:hover {
cursor: default; background: var(--color-bg-warm);
color: var(--color-text-secondary);
} }
.assistant-thinking__arrow { .assistant-thinking__arrow {
color: var(--color-text-faint); color: var(--color-text-faint);
font-size: 15px; transition: transform 0.18s ease;
line-height: 1;
} }
.reply-toggle { .assistant-thinking__arrow.expanded {
display: block; transform: rotate(180deg);
margin-top: 4px; }
border: 0;
padding: 0; .assistant-thinking__status::before {
background: transparent; display: inline-block;
color: var(--color-accent); width: 5px;
font-size: 11px; height: 5px;
cursor: pointer; border-radius: 50%;
margin-right: 5px;
background: var(--color-accent);
content: "";
animation: thinking-pulse 1.1s ease-in-out infinite;
}
.assistant-thinking__duration {
margin-left: 3px;
color: var(--color-text-faint);
}
@keyframes thinking-pulse {
50% {
opacity: 0.35;
}
} }
.semantic-strip { .semantic-strip {