chore(frontend): 补充状态与服务边界注释
This commit is contained in:
@@ -53,6 +53,7 @@ export const useAgentStore = defineStore('agent', () => {
|
||||
}
|
||||
|
||||
function processEvent(event: AgentEvent) {
|
||||
// 服务端会先回放历史再发送实时事件,以 run_id + sequence 去重保证幂等。
|
||||
if (events.value.some((item) => item.run_id === event.run_id && item.sequence === event.sequence)) return
|
||||
events.value.push(event)
|
||||
events.value.sort((a, b) => a.sequence - b.sequence)
|
||||
@@ -100,6 +101,7 @@ export const useAgentStore = defineStore('agent', () => {
|
||||
}
|
||||
|
||||
function subscribe(runId: string) {
|
||||
// 任一时刻只保留当前运行的事件流,防止切换详情后旧事件污染新页面。
|
||||
eventStream?.cancel()
|
||||
isRunning.value = true
|
||||
error.value = null
|
||||
|
||||
@@ -16,6 +16,8 @@ export const useChatStore = defineStore('chat', () => {
|
||||
const selectedModel = ref('mock-1')
|
||||
let sseClient: SseClient | null = null
|
||||
|
||||
// TODO(chat): 会话持久化接口完成后移除 mockConversations/mockMessages 数据源。
|
||||
|
||||
const activeConversation = computed(() =>
|
||||
conversations.value.find((c) => c.conversation_id === activeConversationId.value) || null
|
||||
)
|
||||
@@ -56,6 +58,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
inputText.value = ''
|
||||
isStreaming.value = true
|
||||
|
||||
// 先插入占位消息,随后将 SSE 增量原位合并,避免每个 token 重建消息列表。
|
||||
const aiMsg: ChatMessage = {
|
||||
message_id: `msg-${Date.now() + 1}`,
|
||||
conversation_id: conversationId,
|
||||
|
||||
@@ -47,6 +47,7 @@ export const useEditorStore = defineStore('editor', () => {
|
||||
async function save() {
|
||||
if (!currentFilePath.value) return
|
||||
if (pendingSave) return pendingSave
|
||||
// 保存路径与正文都取快照;请求完成时用户可能已继续输入或切换文件。
|
||||
const targetPath = currentFilePath.value
|
||||
const snapshot = content.value
|
||||
saveStatus.value = 'saving'
|
||||
@@ -82,6 +83,7 @@ export const useEditorStore = defineStore('editor', () => {
|
||||
if (saveStatus.value === 'dirty' || saveStatus.value === 'save_failed') {
|
||||
throw new Error('当前文件保存失败,已阻止切换以避免内容丢失。')
|
||||
}
|
||||
// 版本号使较慢的旧读取不能覆盖用户后选择的新文件。
|
||||
const version = ++loadVersion
|
||||
const previousStatus = saveStatus.value
|
||||
saveStatus.value = 'saving'
|
||||
@@ -117,6 +119,8 @@ export const useEditorStore = defineStore('editor', () => {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(editor): 桌面文件监听接入后提供冲突对比/合并界面,而非只阻止切换。
|
||||
|
||||
function closeFile() {
|
||||
loadVersion++
|
||||
if (saveTimer) clearTimeout(saveTimer)
|
||||
|
||||
@@ -49,6 +49,7 @@ export const useThemeStore = defineStore('theme', () => {
|
||||
}
|
||||
|
||||
function initTheme() {
|
||||
// 先恢复外观再开放 watch 持久化,避免 immediate watcher 覆盖本地设置。
|
||||
const savedAppearance = localStorage.getItem('editor-appearance')
|
||||
if (savedAppearance) {
|
||||
try {
|
||||
@@ -90,6 +91,7 @@ export const useThemeStore = defineStore('theme', () => {
|
||||
}))
|
||||
|
||||
watch(resolvedCodeBlockTheme, (theme) => {
|
||||
// CSS 与 Shiki 共用该属性,确保代码块背景和 token 配色始终成套切换。
|
||||
document.documentElement.setAttribute('data-code-theme', theme)
|
||||
}, { immediate: true })
|
||||
|
||||
|
||||
@@ -118,6 +118,7 @@ export const useWorkspaceStore = defineStore('workspace', () => {
|
||||
function renamePath(oldPath: string, newPath: string, newName: string) {
|
||||
const node = findNodeByPath(fileTree.value, oldPath)
|
||||
if (!node) return
|
||||
// 文件夹重命名必须同步改写所有后代、标签页和当前文件路径。
|
||||
const updateNodePath = (current: FileNode) => {
|
||||
if (current.path === oldPath) current.name = newName
|
||||
if (current.path === oldPath || current.path.startsWith(`${oldPath}/`)) {
|
||||
|
||||
Reference in New Issue
Block a user