优化: 前端u-agent令牌对齐与组件拆分续批

- 全局样式类(df-sec-h/df-toast族)替换散装实现,主题token去硬编码兜底
- 拆分子组件:ai-chat/queue-panel(队列时钟与编辑随迁)、
  conversation-sidebar/ConversationList、settings/provider-panel
- 父组件死副本清理(队列编辑/时钟/键位表,TS6133清零)并补
  fill-draft父侧转发(重构半成品断链修复)
- 验收:vue-tsc EXIT 0
This commit is contained in:
lxy
2026-10-18 23:15:57 +08:00
parent 302c4bcf52
commit 25ec9cf69a
62 changed files with 3475 additions and 2006 deletions
+29 -47
View File
@@ -120,12 +120,12 @@
<span v-if="typeof parsed?.encoding === 'string' && parsed.encoding !== 'utf-8'" class="ai-tool-write-meta">{{ $t('aiTool.encodingLabel', { enc: parsed.encoding }) }}</span>
<!-- R12(2026-10-05):覆盖写入的行级 diff 回看(后端 diff 字段,新建/base64 为 null 不渲染) -->
<div v-if="resultDiffLines.length" class="ai-tool-write-diff">
<pre class="ai-tool-diff-pre"><code><span v-for="(ln, idx) in resultDiffLines" :key="idx" class="ai-tool-diff-line" :class="'ai-tool-diff-line--' + ln.kind">{{ ln.text }}{{ '\n' }}</span></code></pre>
<pre class="df-diff-pre"><code><span v-for="(ln, idx) in resultDiffLines" :key="idx" class="df-diff-line" :class="'df-diff-line--' + ln.kind">{{ ln.text }}{{ '\n' }}</span></code></pre>
<button v-if="diffTotal > DIFF_PREVIEW_LINES" type="button" class="ai-tool-diff-toggle" @click="diffExpanded = !diffExpanded">{{ diffExpanded ? $t('aiTool.diffCollapse') : $t('aiTool.diffExpand', { n: diffTotal }) }}</button>
</div>
</div>
<!-- patch_file 结果:文件路径/字节增减 + unified diff 红删绿增行级预览(复用 ai-tool-diff-pre/--add/--del/--ctx 既有样式)
<!-- patch_file 结果:文件路径/字节增减 + unified diff 红删绿增行级预览(复用 df-diff-pre/--add/--del/--ctx 样式)
后端 generate_diff 产完整 diff,result.diff 字段此前被丢弃,用户无法验证改了什么 → 此分支渲染 diff -->
<div v-else-if="tc.name === 'patch_file' && tc.result && tc.status === 'completed' && parsed" class="ai-tool-patch-result">
<div class="ai-tool-file-bar">
@@ -136,7 +136,7 @@
</div>
<div v-if="parsed?.warning" class="ai-tool-approval-reason"><span aria-hidden="true">⚠</span> {{ parsed.warning }}</div>
<div v-if="resultDiffLines.length" class="ai-tool-approval-diff">
<pre class="ai-tool-diff-pre"><code><span v-for="(ln, idx) in resultDiffLines" :key="idx" class="ai-tool-diff-line" :class="'ai-tool-diff-line--' + ln.kind">{{ ln.text }}{{ '\n' }}</span></code></pre>
<pre class="df-diff-pre"><code><span v-for="(ln, idx) in resultDiffLines" :key="idx" class="df-diff-line" :class="'df-diff-line--' + ln.kind">{{ ln.text }}{{ '\n' }}</span></code></pre>
<!-- R12a:长 diff 展开入口(默认预览 120 行,点开全量) -->
<button v-if="diffTotal > DIFF_PREVIEW_LINES" type="button" class="ai-tool-diff-toggle" @click="diffExpanded = !diffExpanded">{{ diffExpanded ? $t('aiTool.diffCollapse') : $t('aiTool.diffExpand', { n: diffTotal }) }}</button>
</div>
@@ -468,7 +468,7 @@ watch(() => props.tc.status, (s) => {
}
.ai-tool-grep-match {
padding: 3px 12px;
border-bottom: 0.5px solid rgba(255,255,255,0.03);
border-bottom: 0.5px solid var(--df-hover);
}
.ai-tool-grep-match:last-child {
border-bottom: none;
@@ -511,7 +511,7 @@ watch(() => props.tc.status, (s) => {
word-break: break-all;
background: rgba(61,219,160,0.05);
padding: 2px 6px;
border-radius: var(--df-radius-xs, 3px);
border-radius: var(--df-radius-xs);
}
.ai-tool-grep-context {
margin: 2px 0 0;
@@ -521,8 +521,8 @@ watch(() => props.tc.status, (s) => {
font-family: var(--df-font-mono);
font-size: 10px;
color: var(--df-text-dim);
background: rgba(255,255,255,0.02);
border-radius: var(--df-radius-xs, 3px);
background: var(--df-hover);
border-radius: var(--df-radius-xs);
}
.ai-tool-grep-context code {
display: block;
@@ -533,7 +533,7 @@ watch(() => props.tc.status, (s) => {
font-family: var(--df-font-sans);
font-size: 10px;
color: var(--df-text-dim);
background: rgba(255,255,255,0.04);
background: var(--df-hover);
border: 0.5px solid var(--df-border);
border-radius: var(--df-radius-sm);
padding: 2px 8px;
@@ -586,13 +586,13 @@ watch(() => props.tc.status, (s) => {
.ai-tool-dir-entry {
display: flex;
align-items: center;
gap: 7px;
gap: 6px;
padding: 3px 12px;
font-size: 11px;
transition: background 0.1s;
}
.ai-tool-dir-entry:hover {
background: rgba(255,255,255,0.03);
background: var(--df-hover);
}
.ai-tool-dir-entry--directory .ai-tool-dir-name {
font-weight: 500;
@@ -650,8 +650,8 @@ watch(() => props.tc.status, (s) => {
padding: 4px 10px 6px;
margin-bottom: 6px;
font-size: 11px;
color: var(--df-warning, #d97706);
background: var(--df-warning-bg, rgba(217, 119, 6, 0.08));
color: var(--df-warning);
background: var(--df-warning-bg);
border-radius: var(--df-radius-sm, 4px);
}
.ai-tool-approval-diff {
@@ -660,29 +660,11 @@ watch(() => props.tc.status, (s) => {
border-radius: var(--df-radius-sm, 4px);
overflow: hidden;
}
.ai-tool-diff-pre {
margin: 0;
padding: 6px 0;
max-height: 240px;
overflow: auto;
font-family: var(--df-font-mono);
font-size: 11px;
line-height: 1.5;
background: var(--df-bg-card);
}
.ai-tool-diff-pre code {
display: block;
white-space: pre;
}
.ai-tool-diff-line {
display: block;
padding: 0 10px;
white-space: pre-wrap;
word-break: break-all;
}
.ai-tool-diff-line--add { color: var(--df-success, #3ddb9c); background: var(--df-success-bg, rgba(61, 219, 160, 0.08)); }
.ai-tool-diff-line--del { color: var(--df-danger, #f06565); background: var(--df-danger-bg, rgba(240, 101, 101, 0.08)); }
.ai-tool-diff-line--ctx { color: var(--df-text-dim, #888); }
/* diff 基类 .df-diff-pre(+code)/.df-diff-line 消费 global.css 共享定义(2026-10-18 整洁波
双轨合一,与 ToolCard.vue 审批 diff 同源),此处仅留行配色变体 */
.df-diff-line--add { color: var(--df-success); background: var(--df-success-bg); }
.df-diff-line--del { color: var(--df-danger); background: var(--df-danger-bg); }
.df-diff-line--ctx { color: var(--df-text-dim); }
/* -- Generic Result --
max-height 100px→200px:通用结果常含 JSON/结构化文本,100px 仅约 5 行,默认滚动条挤压可读性;
@@ -741,12 +723,12 @@ watch(() => props.tc.status, (s) => {
border-radius: var(--df-radius-sm);
background: transparent;
color: var(--df-text-dim);
font-size: 10.5px;
font-size: 10px;
cursor: pointer;
}
.ai-tool-cmd-toggle:hover {
color: var(--df-text);
background: var(--df-bg-hover, rgba(255,255,255,0.06));
background: var(--df-hover);
}
.ai-tool-cmd-output {
margin: 0;
@@ -803,8 +785,8 @@ watch(() => props.tc.status, (s) => {
}
.ai-tool-http-trunc-warn {
padding: 4px 10px;
font-size: 10.5px;
color: var(--df-warning, #f0c75e);
font-size: 10px;
color: var(--df-warning);
border-top: 0.5px solid var(--df-border);
}
@@ -828,10 +810,10 @@ watch(() => props.tc.status, (s) => {
}
.ai-tool-fetch-mode--static,
.ai-tool-fetch-mode--obscura {
color: var(--df-success, #3ddb9c);
color: var(--df-success);
}
.ai-tool-fetch-mode--static_fallback {
color: var(--df-warning, #f0c75e);
color: var(--df-warning);
}
.ai-tool-fetch-title {
padding: 4px 10px 2px;
@@ -845,8 +827,8 @@ watch(() => props.tc.status, (s) => {
.ai-tool-obscura-hint {
margin: 4px 10px 6px;
padding: 6px 8px;
background: var(--df-warning-bg, rgba(240,199,94,0.08));
border: 0.5px solid var(--df-warning, #f0c75e);
background: var(--df-warning-bg);
border: 0.5px solid var(--df-warning);
border-radius: var(--df-radius-sm, 4px);
display: flex;
flex-direction: column;
@@ -854,8 +836,8 @@ watch(() => props.tc.status, (s) => {
}
.ai-tool-obscura-hint-text {
font-family: var(--df-font-sans);
font-size: 10.5px;
color: var(--df-warning, #f0c75e);
font-size: 10px;
color: var(--df-warning);
line-height: 1.5;
word-break: break-word;
}
@@ -870,7 +852,7 @@ watch(() => props.tc.status, (s) => {
font-weight: 500;
border-radius: var(--df-radius-sm, 4px);
border: none;
background: var(--df-accent, #5b8def);
background: var(--df-accent);
color: #fff;
cursor: pointer;
font-family: var(--df-font-sans);
@@ -891,5 +873,5 @@ watch(() => props.tc.status, (s) => {
padding: 3px 12px;
cursor: pointer;
}
.ai-tool-diff-toggle:hover { color: var(--df-text); background: var(--df-bg-secondary); }
.ai-tool-diff-toggle:hover { color: var(--df-text); background: var(--df-bg-card); }
</style>