优化: 所有剩余UI/UX待办一批完成(持久化+AuditLog+解耦+total+原12大改+P2)
持久化(P1-c):新建 usePersistedRef composable,Tasks/AuditLog/ProjectDetail 等接入 localStorage
AuditLog(P1-d):后端 list_tool_executions 加 WHERE 筛选+返 {items,total,has_more},前端对接+长列折叠+筛选持久化
数据源解耦(P1-g):ProjectDetail projectTasks 按 project_id 独立加载 + ChatInput @项目联想独立加载(不读 store.tasks 当前页)
GitChanges(12a):后端 get_module_commits 加 git rev-list --count 返 total,前端显真实总数
原12大改:Dashboard 统计卡压底行(1)/Projects 列表卡片视图(2)/project_event 埋点排序(3)/TaskDetail 重设计(4)/IdeaDetail 重设计(5)/KnowledgeDetail 重设计(6)/界面持久化+侧栏Ctrl+B+审批数字键(7)/ProjectDetail 三栏改两栏(10)
P2打磨:文件浏览器(FileTree去重/FilePreview行号.md Diff/selectedFilePath归位)/settings反馈(假保存/端口校验)/AI会话(try-catch/scrollIntoView)/后端计数(move_queue事件/timeline total/workflow分页/import_batch分块)/杂项(TopBar/ConfirmDialog键盘/CIStatus i18n/ToolResultBody/ModuleNode/ApprovalDialog全选)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<aside class="df-sidebar" :class="{ 'df-sidebar--collapsed': collapsed }">
|
||||
<!-- Logo -->
|
||||
<!-- Logo(7b:brand 区只保留品牌标识,收缩按钮已移到底部操作区) -->
|
||||
<div class="sidebar-brand">
|
||||
<div class="brand-mark">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
|
||||
@@ -12,16 +12,8 @@
|
||||
</div>
|
||||
<span v-if="!collapsed" class="brand-text">DevFlow</span>
|
||||
<span v-if="!collapsed" class="brand-version">v0.1</span>
|
||||
<button v-if="!collapsed" class="collapse-btn" @click="toggleCollapsed" :title="$t('nav.collapse')">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 收缩态展开按钮(底部固定位置,仅在 collapsed 时显示) -->
|
||||
<button v-if="collapsed" class="expand-btn" @click="toggleCollapsed" :title="$t('nav.expand')">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
|
||||
</button>
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav class="sidebar-nav">
|
||||
<div class="nav-group">
|
||||
@@ -63,6 +55,16 @@
|
||||
<span class="status-dot"></span>
|
||||
<span class="status-text">{{ $t('nav.systemReady') }}</span>
|
||||
</div>
|
||||
<!-- 7b:收缩/展开切换按钮(统一置于底部操作区,与 AI 面板/设置同列)。
|
||||
collapsed 时显展开箭头(→),展开时显收起箭头(←),快捷键 Ctrl+B 同效。 -->
|
||||
<button class="nav-link collapse-toggle-btn" @click="toggleCollapsed" :title="collapsed ? $t('nav.expand') : $t('nav.collapse')">
|
||||
<span class="nav-link-icon">
|
||||
<svg v-if="!collapsed" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
|
||||
<svg v-else width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
|
||||
</span>
|
||||
<span v-if="!collapsed" class="nav-link-text">{{ $t('nav.collapse') }}</span>
|
||||
<span v-if="!collapsed" class="ai-toggle-shortcut">Ctrl+B</span>
|
||||
</button>
|
||||
<!-- AI 面板切换按钮 -->
|
||||
<button class="nav-link ai-toggle-btn" :class="{ 'ai-toggle-btn--active': aiStore.state.panelOpen }" @click="aiStore.togglePanel()" :title="collapsed ? $t('nav.aiPanel') : undefined">
|
||||
<span class="nav-link-icon ai-spark-icon">
|
||||
@@ -111,16 +113,28 @@ function checkWindowWidth() {
|
||||
isNarrowWindow.value = window.innerWidth < COLLAPSE_THRESHOLD
|
||||
}
|
||||
|
||||
// 7b:Ctrl+B / Cmd+B 切换侧边栏收缩(与 AI 面板 Ctrl+I 同款全局快捷键风格)
|
||||
// 仅响应 ctrl 或 meta 任一修饰键(Cmd+I 同款),忽略纯 'b'(避免拦截正常输入)
|
||||
function handleCollapseKeydown(e: KeyboardEvent) {
|
||||
if ((e.ctrlKey || e.metaKey) && (e.key === 'b' || e.key === 'B')) {
|
||||
e.preventDefault()
|
||||
toggleCollapsed()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// 恢复用户偏好(默认展开)
|
||||
userCollapsed.value = appSettings.get('df-sidebar-collapsed', false)
|
||||
// 检查当前窗口宽度
|
||||
checkWindowWidth()
|
||||
window.addEventListener('resize', checkWindowWidth)
|
||||
// Ctrl+B 切换快捷键
|
||||
window.addEventListener('keydown', handleCollapseKeydown)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', checkWindowWidth)
|
||||
window.removeEventListener('keydown', handleCollapseKeydown)
|
||||
})
|
||||
|
||||
// 知识库候选数量(侧栏 badge)— 解包 computed 取值保持响应式
|
||||
@@ -199,39 +213,20 @@ const secondaryNav = [
|
||||
border-radius: var(--df-radius-xs);
|
||||
}
|
||||
|
||||
/* 收缩按钮(展开态 brand 区右侧) */
|
||||
.collapse-btn {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 22px; height: 22px;
|
||||
border: none;
|
||||
border-radius: var(--df-radius-sm);
|
||||
background: transparent;
|
||||
color: var(--df-text-dim);
|
||||
/* 7b:收缩/展开切换按钮(底部操作区,复用 nav-link 样式 + button 重置)
|
||||
与 .ai-toggle-btn 同款 button-over-nav-link 模式:cursor/border/background/font 重置 */
|
||||
.collapse-toggle-btn {
|
||||
cursor: pointer;
|
||||
transition: all 0.15s var(--df-ease);
|
||||
}
|
||||
.collapse-btn:hover {
|
||||
background: var(--df-sidebar-hover);
|
||||
color: var(--df-text);
|
||||
}
|
||||
|
||||
/* 展开按钮(收缩态 brand 区下方) */
|
||||
.expand-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
padding: 6px 0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--df-text-dim);
|
||||
cursor: pointer;
|
||||
transition: all 0.15s var(--df-ease);
|
||||
font: inherit;
|
||||
text-align: left;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
color: var(--df-text-secondary);
|
||||
}
|
||||
.expand-btn:hover {
|
||||
.collapse-toggle-btn:hover {
|
||||
background: var(--df-sidebar-hover);
|
||||
color: var(--df-text);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user