新增: L3 完整上下文面板(对话透明化)

- 底部工具区加上下文图标(i),点击展开面板
- 系统提示: 显示目标数/环境/压缩摘要条数
- 增强上下文: 显示 @项目 mentions 列表
- 点击外部/Escape 关闭,对齐已有下拉交互模式
This commit is contained in:
2026-06-28 14:10:26 +08:00
parent 4a396f4f88
commit f6f36347c1

View File

@@ -151,6 +151,42 @@
</div>
</div>
</div>
<!-- L3 完整上下文 -->
<div v-if="contextInfo.goals.length || contextInfo.summaryCount > 0" class="ai-context-inline">
<span class="ai-context-inline-badge ai-tool-badge" @click="contextExpanded = !contextExpanded" title="查看 AI 上下文">
<svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><circle cx="12" cy="8" r="1" fill="currentColor"/></svg>
</span>
<div v-if="contextExpanded" class="ai-context-inline-list">
<!-- 系统提示 -->
<div class="ai-context-section">
<div class="ai-context-section-title">系统提示</div>
<div class="ai-context-section-body">
<div class="ai-context-row">
<span class="ai-context-label">目标({{ contextInfo.goals.length }})</span>
<span class="ai-context-value">{{ contextInfo.goals.join('; ') || '无' }}</span>
</div>
<div class="ai-context-row">
<span class="ai-context-label">环境</span>
<span class="ai-context-value">{{ contextInfo.osInfo }}</span>
</div>
<div class="ai-context-row">
<span class="ai-context-label">压缩摘要</span>
<span class="ai-context-value">{{ contextInfo.summaryCount }} </span>
</div>
</div>
</div>
<!-- 增强上下文 -->
<div class="ai-context-section">
<div class="ai-context-section-title">增强上下文</div>
<div class="ai-context-section-body">
<div class="ai-context-row">
<span class="ai-context-label">@项目</span>
<span class="ai-context-value">{{ contextInfo.projectNames || '无' }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -324,6 +360,9 @@ function onBottomToolsClickOutside(e: MouseEvent) {
if (summaryExpanded.value && !goalsRef.value.contains(e.target as Node)) {
summaryExpanded.value = false
}
if (contextExpanded.value && !goalsRef.value.contains(e.target as Node)) {
contextExpanded.value = false
}
}
// ── 📄 上下文摘要(压缩/归档的系统消息) ──
interface SummaryItem { id: string; text: string }
@@ -337,12 +376,44 @@ const summaryMsgs = computed<SummaryItem[]>(() => {
})
const summaryExpanded = ref(false)
// ── L3 完整上下文 ──
interface ContextInfo {
goals: string[]
summaryCount: number
osInfo: string
projectNames: string
}
const contextExpanded = ref(false)
const contextInfo = computed<ContextInfo>(() => {
const convId = store.state.activeConversationId
const conv = convId ? store.state.conversations.find(c => c.id === convId) : undefined
// 从所有 user 消息中收集 mentionSpans(kind === 'project'),去重
const projectLabels = new Set<string>()
for (const m of store.state.messages) {
if (m.role === 'user' && m.mentionSpans?.length) {
for (const sp of m.mentionSpans) {
if (sp.kind === 'project' && sp.label) {
projectLabels.add(sp.label)
}
}
}
}
return {
goals: conv?.pinned_goals ?? [],
summaryCount: summaryMsgs.value.length,
osInfo: 'Windows 11 / PowerShell',
projectNames: Array.from(projectLabels).join(', ') || '无',
}
})
/** 按 Escape 关闭所有下拉 */
function onBottomToolsKeydown(e: KeyboardEvent) {
if (e.key === 'Escape') {
goalsExpanded.value = false
historyExpanded.value = false
summaryExpanded.value = false
contextExpanded.value = false
}
}
onMounted(() => {
@@ -718,6 +789,56 @@ onBeforeUnmount(() => {
overflow: hidden;
}
/* ═══ L3 完整上下文(底部) ═══ */
.ai-context-inline {
position: relative;
display: inline-flex;
align-items: center;
}
.ai-context-inline-list {
position: absolute;
left: auto; right: 0;
top: 100%;
z-index: 100;
min-width: 280px;
max-width: 420px;
background: var(--df-bg);
border: 0.5px solid var(--df-border);
border-radius: var(--df-radius-sm);
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-top: 2px;
}
.ai-context-section {
padding: 6px 10px;
border-bottom: 0.5px solid var(--df-border);
}
.ai-context-section:last-child { border-bottom: none; }
.ai-context-section-title {
font-size: 10px;
font-weight: 600;
color: var(--df-accent);
margin-bottom: 4px;
}
.ai-context-section-body {
display: flex;
flex-direction: column;
gap: 3px;
}
.ai-context-row {
display: flex;
gap: 6px;
font-size: 11px;
}
.ai-context-label {
flex-shrink: 0;
color: var(--df-text-dim);
min-width: 56px;
}
.ai-context-value {
color: var(--df-text-secondary);
word-break: break-all;
}
/* header 中间区:provider + 模型选择器并排 */
.ai-header-center {
display: flex;