优化: AI Chat 渲染与无障碍 + 文件查看 + 同步 IO 收口
- 渲染: 结果/过程分离(气泡只放最终结果,过程轮叙述+工具卡收进轨迹卡默认收起可展开——治『流式后正文消失』且不再 N 气泡打扰) - 渲染 P0: v-memo 定向 dep(只有真正渲染流式块的 item 失效,其余取占位) + renderItems 桶 memo(签名覆盖全消费输入,item 引用稳定) + 指纹 watch 降为 O(1) toolEpoch - TopBar 三处 O(n) messages computed 合并单次遍历;md 缓存改有界 LRU(除满即全清抖动);useTurnTrace 补 never 穷尽 + default;MessageItem 模板去重 - 无障碍(四批累计): 可点容器键盘化(含 role/tabindex/keydown/aria-expanded) + icon-only aria-label 约 60 处 + 装饰图标 aria-hidden + 52 个滚动容器 overscroll-behavior:contain + 设置开关聚焦可见环 + outline 零补偿站点补 :focus-visible - UX 走查项: 灵感 IDEA-10/11、知识 KNOW-6/7/9、项目详情 O8、审计 SA-4、设置 SA-6/26/27/28(脏表单/冗余 save/clamp/删除二次确认) - 文件查看专项: 切工程状态残留 F5/F6、FileTree 去重与展开反馈 F7/F15/F17、切文件头部残留 F18、R 状态着色 F19;FilePreview diff 文件头(---/+++)误当增删渲染修复 + 大纲行高亮死样式修复 + 图片失败文案 i18n 化 - 同步 IO 收口(异步上下文内阻塞): unattended 看板读写改 tokio::fs、fetch_url 探活改 spawn_blocking、http/generate_image 清理改 tokio::fs - 子代理 P3 批量: 任务书钉扎上限/截断文案区分父子语境/环境画像日期/temperature 可覆盖/model 回退上报/lang 透传 - crate 清理: df-execute·df-types 注释与格式、df-ideas 过时注释、df-nodes subflow 夸大描述、df-project 死变量
This commit is contained in:
@@ -134,7 +134,7 @@
|
||||
<span class="ai-tool-file-meta">{{ formatSizeDiff(parsed?.size_diff) }} {{ $t('aiTool.bytesUnit') }}</span>
|
||||
<span v-if="parsed?.matches_found && parsed.matches_found > 1" class="ai-tool-file-meta">{{ $t('aiTool.patchedMatches', { n: parsed.matches_found }) }}</span>
|
||||
</div>
|
||||
<div v-if="parsed?.warning" class="ai-tool-approval-reason">⚠ {{ parsed.warning }}</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>
|
||||
<!-- R12a:长 diff 展开入口(默认预览 120 行,点开全量) -->
|
||||
@@ -177,7 +177,7 @@
|
||||
>{{ httpBodyExpanded ? $t('aiTool.collapse') : $t('aiTool.expand') }}</button>
|
||||
</div>
|
||||
<div v-if="parsed?.truncated && !httpBodyExpanded" class="ai-tool-http-trunc-warn">
|
||||
⚠ {{ $t('aiTool.httpTruncated', { bytes: formatBytes(parsed?.body_bytes) }) }}
|
||||
<span aria-hidden="true">⚠</span> {{ $t('aiTool.httpTruncated', { bytes: formatBytes(parsed?.body_bytes) }) }}
|
||||
</div>
|
||||
<pre v-if="httpBodyExpanded && parsed?.body" class="ai-tool-cmd-output"><code>{{ parsed.body }}</code></pre>
|
||||
</div>
|
||||
@@ -207,7 +207,7 @@
|
||||
<div v-if="parsed?.title" class="ai-tool-fetch-title">{{ parsed?.title }}</div>
|
||||
<!-- obscura 未装引导(render=true 但回退静态):提示 + "AI 帮装"按钮 -->
|
||||
<div v-if="obscuraMissing" class="ai-tool-obscura-hint">
|
||||
<div class="ai-tool-obscura-hint-text">⚠ {{ parsed?.hint || $t('aiTool.fetchUrlFallbackHint') }}</div>
|
||||
<div class="ai-tool-obscura-hint-text"><span aria-hidden="true">⚠</span> {{ parsed?.hint || $t('aiTool.fetchUrlFallbackHint') }}</div>
|
||||
<button class="ai-tool-btn ai-tool-btn--install" @click="onInstallObscura">
|
||||
<svg aria-hidden="true" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||||
{{ $t('aiTool.installObscura') }}
|
||||
@@ -222,7 +222,7 @@
|
||||
class="ai-tool-result"
|
||||
:class="{ 'ai-tool-result--failed': isFailed }"
|
||||
>
|
||||
<div v-if="isFailed" class="ai-tool-failed-banner">⚠ {{ $t('aiTool.executionFailedHint') }}</div>
|
||||
<div v-if="isFailed" class="ai-tool-failed-banner"><span aria-hidden="true">⚠</span> {{ $t('aiTool.executionFailedHint') }}</div>
|
||||
<code>{{ formatToolResult(tc) }}</code>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user