优化: 所有剩余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:
lxy
2026-08-02 13:11:06 +08:00
parent caaabf0c15
commit f736f435bc
70 changed files with 2645 additions and 576 deletions
+16 -2
View File
@@ -9,7 +9,7 @@
点"拒绝" → ai_authorize_dir(decision=deny, 工具返 Err)→ 续 loop。
store 单例共享(state/aiApi),pendingDirAuths 模块级 ref(useAiEvents)直接导入。
toast 经 emit 转父(保持单一 toast 源)。 -->
<div v-for="item in visibleDirAuths" :key="item.id" class="ai-dir-auth">
<div v-for="item in visibleDirAuths" :key="item.id" ref="dirAuthRefs" class="ai-dir-auth">
<span class="ai-dir-auth-text">{{ $t('aiChat.dirAuthRequired') }}</span>
<span class="ai-dir-auth-hint">
{{ $t('aiChat.dirAuthHint', { tool: item.tool, path: item.path }) }}
@@ -40,7 +40,7 @@
</template>
<script setup lang="ts">
import { reactive, computed, watch } from 'vue'
import { reactive, computed, watch, nextTick, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAiStore } from '../../stores/ai'
import { pendingDirAuths } from '../../composables/ai/useAiEvents'
@@ -77,6 +77,10 @@ const visibleDirAuths = computed(() => {
// reactive Set 的增删驱动按钮 disabled;Set 判定 O(1)。
const actingIds = reactive(new Set<string>())
// M8:卡片根元素 ref 数组(v-for ref 收集)。挂起弹窗出现在输入区上方,常被消息流/进度条挤出视口,
// 用户看不到按钮 → 挂起无声卡死。新增项时滚动定位到卡片让审批入口立即可见。
const dirAuthRefs = ref<HTMLElement[]>([])
/** 点三选项之一:按 id 定位挂起项,调 ai_authorize_dir。后端 remove pending → 写授权/拒 →
* execute → try_continue。不主动清 pendingDirAuths——由后端 AiApprovalResult/AiCompleted/AiError
* 在 useAiEvents 内按 id filter / 清空。IPC 失败回滚 actingIds 让用户可重试。 */
@@ -105,6 +109,16 @@ watch(() => pendingDirAuths.value, (items) => {
if (!liveIds.has(id)) actingIds.delete(id)
}
})
/** M8:visibleDirAuths 出现新挂起项时,scrollIntoView 让审批入口立刻可见(挂起弹窗在输入区上方,
* 易被消息流/进度条挤出视口,用户不滚动看不到 → 挂起无声卡死)。仅新增项触发滚动,避免已可见项
* 反复跳动打扰。 */
watch(() => visibleDirAuths.value.map(d => d.id).join('|'), async () => {
await nextTick()
// 滚到最新(数组末)项,block:'center' 让按钮组居中可见
const last = dirAuthRefs.value[dirAuthRefs.value.length - 1]
if (last) last.scrollIntoView({ block: 'center', behavior: 'smooth' })
})
</script>
<style scoped>