From 2c2bdd7f7ad5f6d2437289c41901b3fd8428a91b Mon Sep 17 00:00:00 2001 From: KiriAky 107 Date: Sat, 29 Aug 2026 12:10:33 +0800 Subject: [PATCH 01/16] =?UTF-8?q?fix(frontend):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=90=88=E5=B9=B6=E5=AE=A1=E9=98=85=E5=8F=91=E7=8E=B0=E7=9A=84?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E4=B8=8E=E5=A5=91=E7=BA=A6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 恢复 Vue TypeScript 生产构建,补齐可运行页面壳子,并修复文件树与 SSE 状态问题。 按 FastAPI Wire Contract 统一 Service DTO 映射,同时补充前端开发说明和问题修复复盘。 --- frontend/src/components/common/AppShell.vue | 2 +- .../components/common/SecondarySidebar.vue | 19 +- frontend/src/components/common/StatusBar.vue | 2 +- frontend/src/contracts/index.ts | 185 ++++++- .../src/features/common/PlaceholderView.vue | 34 ++ frontend/src/features/editor/EditorHeader.vue | 26 + frontend/src/features/editor/EditorPane.vue | 30 ++ .../src/features/workspace/FileTreeNode.vue | 31 ++ .../src/features/workspace/FileTreePanel.vue | 451 ++++-------------- frontend/src/router/index.ts | 26 +- frontend/src/services/agentService.ts | 51 +- frontend/src/services/apiClient.ts | 16 +- frontend/src/services/chatService.ts | 28 +- frontend/src/services/index.ts | 2 +- frontend/src/services/indexService.ts | 34 +- frontend/src/services/noteService.ts | 23 +- frontend/src/services/pluginService.ts | 58 ++- frontend/src/services/providerService.ts | 75 ++- frontend/src/services/searchService.ts | 36 +- frontend/src/services/skillService.ts | 40 +- frontend/src/services/sseClient.ts | 75 +-- frontend/src/services/systemService.ts | 2 +- frontend/src/services/taskService.ts | 54 ++- frontend/src/services/workspaceService.ts | 4 +- frontend/src/stores/agent.ts | 7 +- frontend/src/stores/chat.ts | 52 +- frontend/src/stores/provider.ts | 8 +- frontend/src/stores/search.ts | 2 +- frontend/src/stores/workspace.ts | 4 + frontend/tsconfig.app.json | 4 + 30 files changed, 770 insertions(+), 611 deletions(-) create mode 100644 frontend/src/features/common/PlaceholderView.vue create mode 100644 frontend/src/features/editor/EditorHeader.vue create mode 100644 frontend/src/features/editor/EditorPane.vue create mode 100644 frontend/src/features/workspace/FileTreeNode.vue diff --git a/frontend/src/components/common/AppShell.vue b/frontend/src/components/common/AppShell.vue index d6ef9a7..289cfac 100644 --- a/frontend/src/components/common/AppShell.vue +++ b/frontend/src/components/common/AppShell.vue @@ -26,7 +26,7 @@ const router = useRouter() const routeName = computed(() => route.name as string) const secondaryComponent = computed(() => { - switch (routeName) { + switch (routeName.value) { case 'workspace': return 'file-tree' case 'search': return 'search-filters' case 'chat': return 'conversation-list' diff --git a/frontend/src/components/common/SecondarySidebar.vue b/frontend/src/components/common/SecondarySidebar.vue index 34c8a1b..99c5a68 100644 --- a/frontend/src/components/common/SecondarySidebar.vue +++ b/frontend/src/components/common/SecondarySidebar.vue @@ -1,11 +1,6 @@ @@ -109,4 +100,10 @@ const showSkillToggle = computed(() => routeName === 'skills' || routeName === ' overflow-y: auto; overflow-x: hidden; } + +.sidebar-placeholder { + padding: var(--space-lg); + color: var(--color-text-tertiary); + font-size: var(--font-size-sm); +} diff --git a/frontend/src/components/common/StatusBar.vue b/frontend/src/components/common/StatusBar.vue index a7e212d..825b833 100644 --- a/frontend/src/components/common/StatusBar.vue +++ b/frontend/src/components/common/StatusBar.vue @@ -78,7 +78,7 @@ const showEditorInfo = computed(() => route.name === 'workspace') 索引就绪 - + {{ aiCoreStatusText }} diff --git a/frontend/src/contracts/index.ts b/frontend/src/contracts/index.ts index 01e03c9..2497f16 100644 --- a/frontend/src/contracts/index.ts +++ b/frontend/src/contracts/index.ts @@ -247,15 +247,15 @@ export interface Plugin { enabled: boolean permissions: string[] contributions: PluginContribution[] - backend_type?: 'mcp' | 'internal' - transport?: 'stdio' | 'websocket' + backend_type?: 'mcp' | 'internal_rpc' | 'none' + transport?: 'stdio' | 'http' | 'none' last_error?: string dependent_skills?: string[] } // ============ Provider ============ -export type ProviderType = 'openai' | 'anthropic' | 'ollama' | 'openai-compatible' | 'mock' +export type ProviderType = ApiProviderType export interface ModelCapability { chat: boolean @@ -346,10 +346,10 @@ export interface ErrorResponse { } export interface SystemStatus { + status: 'ok' name: string version: string - environment: 'development' | 'production' | 'test' - ai_core_available: boolean + environment: string } export type SaveStatus = @@ -362,3 +362,178 @@ export type SaveStatus = | 'conflict' export type AiCoreStatus = 'starting' | 'running' | 'stopped' | 'error' + +// ============ FastAPI wire contracts ============ +// UI view models above may contain presentation-only fields. Services must use +// these DTOs at the HTTP boundary and explicitly map them to view models. + +export interface PageMeta { + total: number + limit: number + offset: number +} + +export interface OperationResponse { + status: 'accepted' | 'completed' + resource_id?: string | null + message?: string | null +} + +export interface ApiNoteBlock { + block_id: string + note_id: string + heading_path: string[] + start_offset: number + end_offset: number + content: string + content_hash: string + token_count: number +} + +export interface ApiNoteSummary { + note_id: string + title: string + file_path: string + tags: string[] + created_at: string + updated_at: string +} + +export interface ApiNote extends ApiNoteSummary { + markdown: string + blocks: ApiNoteBlock[] +} + +export interface ApiSearchResult { + note_id: string + block_id: string + title: string + file_path: string + heading_path: string[] + snippet?: string | null + score: number + citation: ApiCitation +} + +export interface ApiCitation { + citation_id: string + note_id: string + block_id: string + file_path: string + heading_path: string[] + start_offset?: number | null + end_offset?: number | null + source_audio?: string | null + start_time?: number | null + end_time?: number | null + speaker?: string | null +} + +export interface ApiAgentRun { + run_id: string + status: AgentRunStatus + input: string + provider_id: string + model: string + skill_id?: string | null + current_step: number + max_steps: number + token_budget?: number | null + cancelled: boolean + output?: string | null + error_code?: string | null + error_message?: string | null + token_usage: number + created_at: string + updated_at: string +} + +export interface ApiSkill { + manifest: { + skill_id: string + name: string + version: string + description: string + permissions: string[] + tools: string[] + retrieval: { top_k: number; rerank: boolean; citation: boolean } + model: { required_capabilities: string[] } + } + status: SkillStatus + enabled: boolean + missing_dependencies: string[] +} + +export interface ApiPlugin { + manifest: { + plugin_id: string + name: string + version: string + description: string + permissions: string[] + contributes: { + tools: string[] + commands: string[] + importers: string[] + exporters: string[] + panels: string[] + settings_sections: string[] + } + backend: { type: 'mcp' | 'internal_rpc' | 'none'; transport: 'stdio' | 'http' | 'none' } + } + status: PluginStatus + enabled: boolean + granted_permissions: string[] + error_message?: string | null +} + +export type ApiProviderType = + | 'mock' + | 'openai_responses' + | 'openai_chat' + | 'openai_compatible' + | 'anthropic_messages' + | 'ollama' + +export interface ApiProviderConfig { + provider_id: string + provider_type: ApiProviderType + name: string + base_url?: string | null + default_model?: string | null + credential_id?: string | null + enabled: boolean + capabilities: string[] +} + +export interface ApiModelInfo { + model: string + display_name: string + capabilities: string[] +} + +export interface ApiTask { + task_id: string + title: string + description: string + status: TaskStatus + note_id?: string | null + due_at?: string | null + created_at: string + updated_at: string +} + +export interface ApiIndexStatus { + status: 'idle' | 'queued' | 'running' | 'failed' + pending_jobs: number + active_job_id?: string | null + last_completed_at?: string | null + error_message?: string | null +} + +export interface ApiIndexJob { + job_id: string + status: 'queued' | 'running' | 'completed' | 'failed' + scope: 'all' | 'notes' | 'vectors' + created_at: string +} diff --git a/frontend/src/features/common/PlaceholderView.vue b/frontend/src/features/common/PlaceholderView.vue new file mode 100644 index 0000000..faf015f --- /dev/null +++ b/frontend/src/features/common/PlaceholderView.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/frontend/src/features/editor/EditorHeader.vue b/frontend/src/features/editor/EditorHeader.vue new file mode 100644 index 0000000..42a2801 --- /dev/null +++ b/frontend/src/features/editor/EditorHeader.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/frontend/src/features/editor/EditorPane.vue b/frontend/src/features/editor/EditorPane.vue new file mode 100644 index 0000000..d4a60ba --- /dev/null +++ b/frontend/src/features/editor/EditorPane.vue @@ -0,0 +1,30 @@ + + +