fix(frontend): 补齐英文失败路径
This commit is contained in:
@@ -3,6 +3,7 @@ import { ref, computed } from 'vue'
|
||||
import type { AgentRun, AgentEvent, ToolDefinition, PermissionRequest, ToolCall } from '@/contracts'
|
||||
import * as agentService from '@/services/agentService'
|
||||
import type { SseClient } from '@/services/sseClient'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
export const useAgentStore = defineStore('agent', () => {
|
||||
const runs = ref<AgentRun[]>([])
|
||||
@@ -93,7 +94,7 @@ export const useAgentStore = defineStore('agent', () => {
|
||||
tool_name: String(call.name ?? 'unknown'),
|
||||
permission: String(data.permission ?? ''),
|
||||
parameters: (call.arguments ?? {}) as Record<string, unknown>,
|
||||
impact: '该工具需要获得权限后才能继续执行。',
|
||||
impact: t('该工具需要获得权限后才能继续执行。', 'This tool requires permission before it can continue.'),
|
||||
}
|
||||
if (run) run.status = 'waiting_permission'
|
||||
} else if (['RunCompleted', 'RunFailed', 'RunCancelled'].includes(event.event)) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ref, computed, reactive } from 'vue'
|
||||
import type { ChatMessage, Conversation } from '@/contracts'
|
||||
import { streamChat } from '@/services/chatService'
|
||||
import type { SseClient } from '@/services/sseClient'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
export const useChatStore = defineStore('chat', () => {
|
||||
const conversations = ref<Conversation[]>([])
|
||||
@@ -128,11 +129,11 @@ export const useChatStore = defineStore('chat', () => {
|
||||
content: String(event.data.content ?? event.data.snippet ?? ''),
|
||||
})
|
||||
}
|
||||
if (event.event === 'Error') aiMsg.content += `\n\n生成失败:${String(event.data.message ?? '未知错误')}`
|
||||
if (event.event === 'Error') aiMsg.content += `\n\n${t('生成失败:', 'Generation failed: ')}${String(event.data.message ?? t('未知错误', 'Unknown error'))}`
|
||||
},
|
||||
onError(error) {
|
||||
if (version !== streamVersion) return
|
||||
aiMsg.content += `\n\n连接失败:${error.message}`
|
||||
aiMsg.content += `\n\n${t('连接失败:', 'Connection failed: ')}${error.message}`
|
||||
isStreaming.value = false
|
||||
sseClient = null
|
||||
},
|
||||
@@ -162,7 +163,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
stopGeneration()
|
||||
const newConv: Conversation = {
|
||||
conversation_id: crypto.randomUUID(),
|
||||
title: '新对话',
|
||||
title: t('新对话', 'New conversation'),
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
message_count: 0,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import type { SaveStatus } from '@/contracts'
|
||||
import * as workspaceService from '@/services/workspaceService'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
export const useEditorStore = defineStore('editor', () => {
|
||||
const mode = ref<'wysiwyg' | 'source'>('wysiwyg')
|
||||
@@ -76,12 +77,12 @@ export const useEditorStore = defineStore('editor', () => {
|
||||
saveTimer = null
|
||||
}
|
||||
if (saveStatus.value === 'conflict') {
|
||||
throw new Error('当前文件存在编辑冲突,请处理后再切换文件。')
|
||||
throw new Error(t('当前文件存在编辑冲突,请处理后再切换文件。', 'The current file has an editing conflict. Resolve it before switching files.'))
|
||||
}
|
||||
if (pendingSave) await pendingSave
|
||||
if (saveStatus.value === 'dirty' || saveStatus.value === 'save_failed') await save()
|
||||
if (saveStatus.value === 'dirty' || saveStatus.value === 'save_failed') {
|
||||
throw new Error('当前文件保存失败,已阻止切换以避免内容丢失。')
|
||||
throw new Error(t('当前文件保存失败,已阻止切换以避免内容丢失。', 'The current file could not be saved. Switching was blocked to prevent data loss.'))
|
||||
}
|
||||
// 版本号使较慢的旧读取不能覆盖用户后选择的新文件。
|
||||
const version = ++loadVersion
|
||||
|
||||
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import type { Plugin } from '@/contracts'
|
||||
import * as pluginService from '@/services/pluginService'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
export const usePluginStore = defineStore('plugin', () => {
|
||||
const plugins = ref<Plugin[]>([])
|
||||
@@ -23,7 +24,7 @@ export const usePluginStore = defineStore('plugin', () => {
|
||||
plugins.value = await pluginService.listPlugins()
|
||||
error.value = null
|
||||
} catch (reason) {
|
||||
error.value = reason instanceof Error ? reason.message : 'Plugin 加载失败'
|
||||
error.value = reason instanceof Error ? reason.message : t('Plugin 加载失败', 'Failed to load Plugins')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ref, computed } from 'vue'
|
||||
import type { ProviderConfig, ModelInfo, ProviderPreset } from '@/contracts'
|
||||
import { createProvider, deleteProvider as deleteProviderRequest, getCredentialStatus, listModels, listProviderPresets, listProviders, putCredential, testProvider as testProviderRequest, updateProvider as updateProviderRequest } from '@/services/providerService'
|
||||
import { ApiErrorClass } from '@/services/apiClient'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
export const useProviderStore = defineStore('provider', () => {
|
||||
const providers = ref<ProviderConfig[]>([])
|
||||
@@ -29,7 +30,7 @@ export const useProviderStore = defineStore('provider', () => {
|
||||
}
|
||||
error.value = null
|
||||
} catch (reason) {
|
||||
error.value = reason instanceof Error ? reason.message : 'Provider 加载失败'
|
||||
error.value = reason instanceof Error ? reason.message : t('Provider 加载失败', 'Failed to load Providers')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
@@ -39,7 +40,7 @@ export const useProviderStore = defineStore('provider', () => {
|
||||
try {
|
||||
presets.value = await listProviderPresets()
|
||||
} catch (reason) {
|
||||
error.value = reason instanceof Error ? reason.message : 'Provider 预设加载失败'
|
||||
error.value = reason instanceof Error ? reason.message : t('Provider 预设加载失败', 'Failed to load Provider presets')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,11 +56,11 @@ export const useProviderStore = defineStore('provider', () => {
|
||||
} catch (reason) {
|
||||
const provider = providers.value.find((item) => item.provider_id === providerId)
|
||||
const credentialId = provider?.credential_id
|
||||
let message = reason instanceof Error ? reason.message : '模型列表获取失败'
|
||||
let message = reason instanceof Error ? reason.message : t('模型列表获取失败', 'Failed to load the model list')
|
||||
if (reason instanceof ApiErrorClass && reason.code === 'PROVIDER_CREDENTIAL_MISSING') {
|
||||
message = '尚未配置 API Key,请编辑该 Provider 后填写并保存。'
|
||||
message = t('尚未配置 API Key,请编辑该 Provider 后填写并保存。', 'No API key is configured. Edit this Provider, enter a key, and save it.')
|
||||
} else if (reason instanceof ApiErrorClass && reason.code === 'PROVIDER_AUTH_FAILED') {
|
||||
message = `鉴权失败,请检查凭据“${credentialId || '未设置'}”对应的 API Key 是否有效。`
|
||||
message = t(`鉴权失败,请检查凭据“${credentialId || '未设置'}”对应的 API Key 是否有效。`, `Authentication failed. Check the API key for credential “${credentialId || 'not set'}”.`)
|
||||
}
|
||||
modelErrorsByProvider.value[providerId] = message
|
||||
throw reason
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ref } from 'vue'
|
||||
import type { SearchResult, SearchRequest } from '@/contracts'
|
||||
import * as searchService from '@/services/searchService'
|
||||
import { ApiErrorClass } from '@/services/apiClient'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
const VECTOR_ERROR_CODES = new Set([
|
||||
'SEMANTIC_INDEX_UNAVAILABLE',
|
||||
@@ -28,7 +29,7 @@ export const useSearchStore = defineStore('search', () => {
|
||||
if (version !== historyVersion) return
|
||||
recentQueries.value = response.queries
|
||||
historyError.value = ''
|
||||
} catch { if (version === historyVersion) historyError.value = '无法读取应用搜索记录,请检查后端连接。' }
|
||||
} catch { if (version === historyVersion) historyError.value = t('无法读取应用搜索记录,请检查后端连接。', 'Could not load search history. Check the backend connection.') }
|
||||
}
|
||||
async function clearHistory() {
|
||||
const version = ++historyVersion
|
||||
@@ -36,7 +37,7 @@ export const useSearchStore = defineStore('search', () => {
|
||||
await searchService.clearHistory()
|
||||
if (version !== historyVersion) return
|
||||
recentQueries.value = []; historyError.value = ''
|
||||
} catch { if (version === historyVersion) historyError.value = '清空搜索记录失败,请重试。' }
|
||||
} catch { if (version === historyVersion) historyError.value = t('清空搜索记录失败,请重试。', 'Failed to clear search history. Please retry.') }
|
||||
}
|
||||
const error = ref<string | null>(null)
|
||||
const vectorUnavailable = ref(false)
|
||||
@@ -71,12 +72,12 @@ export const useSearchStore = defineStore('search', () => {
|
||||
selectedIndex.value = 0
|
||||
} catch (fallbackError) {
|
||||
if (version !== searchVersion) return
|
||||
error.value = fallbackError instanceof Error ? fallbackError.message : '全文检索降级失败'
|
||||
error.value = fallbackError instanceof Error ? fallbackError.message : t('全文检索降级失败', 'Full-text search fallback failed')
|
||||
results.value = []
|
||||
total.value = 0
|
||||
}
|
||||
} else {
|
||||
error.value = reason instanceof Error ? reason.message : '搜索失败'
|
||||
error.value = reason instanceof Error ? reason.message : t('搜索失败', 'Search failed')
|
||||
results.value = []
|
||||
total.value = 0
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { resolveApiUrl } from '@/services/apiClient'
|
||||
import packageInfo from '../../package.json'
|
||||
import * as indexService from '@/services/indexService'
|
||||
import * as systemService from '@/services/systemService'
|
||||
import { appLocale } from '@/i18n'
|
||||
import { appLocale, t } from '@/i18n'
|
||||
|
||||
export const useSettingsStore = defineStore('settings', () => {
|
||||
const saved = (() => {
|
||||
@@ -17,7 +17,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
const autoSaveInterval = ref(typeof saved.autoSaveInterval === 'number' ? saved.autoSaveInterval : 1500)
|
||||
const language = appLocale
|
||||
const appVersion = ref(packageInfo.version)
|
||||
const aiCoreVersion = ref('未获取')
|
||||
const aiCoreVersion = ref('—')
|
||||
|
||||
// Editor
|
||||
const defaultEditorMode = ref<'wysiwyg' | 'source'>(saved.defaultEditorMode === 'source' ? 'source' : 'wysiwyg')
|
||||
@@ -48,10 +48,10 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
])
|
||||
const [health, status, index, policy] = results
|
||||
aiCoreStatus.value = health.status === 'fulfilled' && health.value.status === 'ok' ? 'running' : 'error'
|
||||
aiCoreVersion.value = status.status === 'fulfilled' ? status.value.version : '未获取'
|
||||
aiCoreVersion.value = status.status === 'fulfilled' ? status.value.version : '—'
|
||||
indexStatus.value = index.status === 'fulfilled' ? index.value : emptyIndex()
|
||||
permissionPolicy.value = policy.status === 'fulfilled' ? policy.value : {}
|
||||
diagnosticsError.value = results.filter(item => item.status === 'rejected').map(item => item.reason instanceof Error ? item.reason.message : '后端请求失败').join(';') || null
|
||||
diagnosticsError.value = results.filter(item => item.status === 'rejected').map(item => item.reason instanceof Error ? item.reason.message : t('后端请求失败', 'Backend request failed')).join(t(';', '; ')) || null
|
||||
}
|
||||
|
||||
function setAutoSaveInterval(ms: number) {
|
||||
@@ -69,7 +69,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
indexStatus.value = await indexService.getIndexStatus()
|
||||
} catch (reason) {
|
||||
indexStatus.value.status = 'error'
|
||||
indexStatus.value.error = reason instanceof Error ? reason.message : '索引重建失败'
|
||||
indexStatus.value.error = reason instanceof Error ? reason.message : t('索引重建失败', 'Index rebuild failed')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import type { Skill } from '@/contracts'
|
||||
import * as skillService from '@/services/skillService'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
export const useSkillStore = defineStore('skill', () => {
|
||||
const skills = ref<Skill[]>([])
|
||||
@@ -23,7 +24,7 @@ export const useSkillStore = defineStore('skill', () => {
|
||||
skills.value = await skillService.listSkills()
|
||||
error.value = null
|
||||
} catch (reason) {
|
||||
error.value = reason instanceof Error ? reason.message : 'Skill 加载失败'
|
||||
error.value = reason instanceof Error ? reason.message : t('Skill 加载失败', 'Failed to load Skills')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import type { TaskItem, TaskStatus, TaskPriority, TaskSource } from '@/contracts'
|
||||
import { createTask as createTaskRequest, deleteTask as deleteTaskRequest, listTasks, updateTask as updateTaskRequest } from '@/services/taskService'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
export const useTaskStore = defineStore('task', () => {
|
||||
const tasks = ref<TaskItem[]>([])
|
||||
@@ -31,7 +32,7 @@ export const useTaskStore = defineStore('task', () => {
|
||||
tasks.value = resp.items
|
||||
error.value = null
|
||||
} catch (reason) {
|
||||
error.value = reason instanceof Error ? reason.message : '任务加载失败'
|
||||
error.value = reason instanceof Error ? reason.message : t('任务加载失败', 'Failed to load tasks')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user