refactor(component): 优化UI样式和工具参数显示逻辑

1. 调整多个组件的间距、字体大小和样式细节
2. 重构工具参数显示逻辑,支持更多参数格式
3. 移除状态按钮中的计数显示,更新图标
This commit is contained in:
Wenjie Zhang 2025-12-17 23:39:53 +08:00
parent a3edaa8129
commit b8e8346262
3 changed files with 21 additions and 29 deletions

View File

@ -64,8 +64,8 @@
:class="{ 'has-content': hasAgentStateContent }" :class="{ 'has-content': hasAgentStateContent }"
:title="hasAgentStateContent ? '查看工作状态' : '暂无工作状态'" :title="hasAgentStateContent ? '查看工作状态' : '暂无工作状态'"
> >
<Layers class="nav-btn-icon" size="18"/> <FolderDotIcon class="nav-btn-icon" size="18"/>
<span v-if="hasAgentStateContent" class="text">状态({{ totalAgentStateItems }})</span> <span v-if="hasAgentStateContent" class="text">状态</span>
</div> </div>
</AgentPopover> </AgentPopover>
<!-- <div class="nav-btn" @click="shareChat" v-if="currentChatId && currentAgent"> <!-- <div class="nav-btn" @click="shareChat" v-if="currentChatId && currentAgent">
@ -243,7 +243,7 @@ import AgentMessageComponent from '@/components/AgentMessageComponent.vue'
import ImagePreviewComponent from '@/components/ImagePreviewComponent.vue' import ImagePreviewComponent from '@/components/ImagePreviewComponent.vue'
import ChatSidebarComponent from '@/components/ChatSidebarComponent.vue' import ChatSidebarComponent from '@/components/ChatSidebarComponent.vue'
import RefsComponent from '@/components/RefsComponent.vue' import RefsComponent from '@/components/RefsComponent.vue'
import { PanelLeftOpen, MessageCirclePlus, LoaderCircle, Layers, ChevronDown } from 'lucide-vue-next'; import { PanelLeftOpen, MessageCirclePlus, LoaderCircle, FolderDotIcon, ChevronDown } from 'lucide-vue-next';
import { handleChatError, handleValidationError } from '@/utils/errorHandler'; import { handleChatError, handleValidationError } from '@/utils/errorHandler';
import { ScrollController } from '@/utils/scrollController'; import { ScrollController } from '@/utils/scrollController';
import { AgentValidator } from '@/utils/agentValidator'; import { AgentValidator } from '@/utils/agentValidator';
@ -397,14 +397,6 @@ const hasAgentStateContent = computed(() => {
return todoCount > 0 || fileCount > 0; return todoCount > 0 || fileCount > 0;
}); });
const totalAgentStateItems = computed(() => {
const s = currentAgentState.value;
if (!s) return 0;
const todoCount = Array.isArray(s.todos) ? s.todos.length : 0;
const fileCount = countFiles(s.files);
return todoCount + fileCount;
});
const currentThreadMessages = computed(() => threadMessages.value[currentChatId.value] || []); const currentThreadMessages = computed(() => threadMessages.value[currentChatId.value] || []);
// Refs // Refs
@ -1841,13 +1833,9 @@ watch(conversations, () => {
} }
/* AgentState 按钮有内容时的样式 */ /* AgentState 按钮有内容时的样式 */
.agent-nav-btn.agent-state-btn.has-content { .agent-nav-btn.agent-state-btn.has-content:hover:not(.is-disabled) {
color: var(--main-600); color: var(--main-700);
background-color: var(--main-20);
&:hover:not(.is-disabled) {
color: var(--main-700);
background-color: var(--main-40);
}
} }
@keyframes spin { @keyframes spin {

View File

@ -60,11 +60,10 @@
</span> </span>
</div> </div>
<div class="tool-content" v-show="expandedToolCalls.has(toolCall.id)"> <div class="tool-content" v-show="expandedToolCalls.has(toolCall.id)">
<div class="tool-params" v-if="toolCall.args || toolCall.function?.arguments"> <div class="tool-params" v-if="String(toolCall.args).length > 2 || String(toolCall.function?.arguments).length > 2">
<div class="tool-params-content"> <div class="tool-params-content">
<strong>参数:</strong> <strong>参数: </strong>
<span v-if="getFormattedToolArgs(toolCall)">{{ getFormattedToolArgs(toolCall) }}</span> <span>{{ getFormattedToolArgs(toolCall) }}</span>
<span v-else>{{ toolCall.args || toolCall.function?.arguments }}</span>
</div> </div>
</div> </div>
<div class="tool-result" v-if="toolCall.tool_call_result && toolCall.tool_call_result.content"> <div class="tool-result" v-if="toolCall.tool_call_result && toolCall.tool_call_result.content">
@ -205,7 +204,7 @@ const getToolNameByToolCall = (toolCall) => {
}; };
const getFormattedToolArgs = (toolCall) => { const getFormattedToolArgs = (toolCall) => {
const args = toolCall.args || toolCall.function?.arguments; const args = toolCall.args ? toolCall.args : toolCall.function?.arguments;
if (!args) return ''; if (!args) return '';
try { try {
@ -213,9 +212,14 @@ const getFormattedToolArgs = (toolCall) => {
if (typeof args === 'string' && args.trim().startsWith('{')) { if (typeof args === 'string' && args.trim().startsWith('{')) {
const parsed = JSON.parse(args); const parsed = JSON.parse(args);
return JSON.stringify(parsed, null, 2); return JSON.stringify(parsed, null, 2);
} else if (typeof args === 'object' && args !== null) {
//
console.log('Object args:', args);
return JSON.stringify(args, null, 2);
} }
} catch (e) { } catch (e) {
// //
console.log('Failed to parse tool arguments as JSON:', args);
} }
return args; return args;
@ -513,7 +517,7 @@ const toggleToolCall = (toolCallId) => {
.tool-params-content { .tool-params-content {
margin: 0; margin: 0;
font-size: 13px; font-size: 12px;
overflow-x: auto; overflow-x: auto;
color: var(--gray-700); color: var(--gray-700);
line-height: 1.5; line-height: 1.5;

View File

@ -4,7 +4,7 @@
:title="null" :title="null"
placement="bottomRight" placement="bottomRight"
trigger="click" trigger="click"
:overlayStyle="{ width: '400px', zIndex: 1030 }" :overlayStyle="{ width: '400px', zIndex: 999 }"
> >
<template #content> <template #content>
<div class="popover-content"> <div class="popover-content">
@ -202,6 +202,7 @@ const formatDate = (dateString) => {
try { try {
const date = new Date(dateString); const date = new Date(dateString);
return date.toLocaleString('zh-CN', { return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit', month: '2-digit',
day: '2-digit', day: '2-digit',
hour: '2-digit', hour: '2-digit',
@ -438,11 +439,11 @@ const emitRefresh = () => {
.file-list { .file-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6px; gap: 4px;
} }
.file-item { .file-item {
padding: 12px 14px; padding: 8px 12px;
background: var(--gray-0); background: var(--gray-0);
border: 1px solid var(--gray-150); border: 1px solid var(--gray-150);
border-radius: 6px; border-radius: 6px;
@ -468,14 +469,13 @@ const emitRefresh = () => {
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px; gap: 2px;
min-width: 0; min-width: 0;
} }
.file-name { .file-name {
font-size: 14px; font-size: 14px;
color: var(--gray-1000); color: var(--gray-1000);
font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-weight: 500; font-weight: 500;
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;