import { defineStore } from 'pinia' import { ref, watch } from 'vue' import type { AiCoreStatus, IndexStatus } from '@/contracts' import { resolveApiUrl } from '@/services/apiClient' import packageInfo from '../../package.json' import * as indexService from '@/services/indexService' import * as systemService from '@/services/systemService' import { appLocale, t } from '@/i18n' export const useSettingsStore = defineStore('settings', () => { const saved = (() => { try { return JSON.parse(localStorage.getItem('app-settings') ?? '{}') as Record } catch { localStorage.removeItem('app-settings'); return {} } })() // General const restoreLastVault = ref(saved.restoreLastVault !== false) const autoSaveInterval = ref(typeof saved.autoSaveInterval === 'number' ? saved.autoSaveInterval : 1500) const language = appLocale const appVersion = ref(packageInfo.version) const aiCoreVersion = ref('—') // Editor const defaultEditorMode = ref<'wysiwyg' | 'source'>(saved.defaultEditorMode === 'source' ? 'source' : 'wysiwyg') const editorLineWidth = ref(typeof saved.editorLineWidth === 'number' ? saved.editorLineWidth : 80) const spellCheck = ref(saved.spellCheck === true) // AI Core const aiCoreStatus = ref('unknown') const aiCoreAddress = ref(resolveApiUrl('/api') || '/api') // Index const emptyIndex = (): IndexStatus => ({ status: 'unknown', pending_jobs: 0, total_notes: null, total_blocks: null }) const indexStatus = ref(emptyIndex()) // Permissions const permissionPolicy = ref>({}) const diagnosticsError = ref(null) watch(() => ({ restoreLastVault: restoreLastVault.value, autoSaveInterval: autoSaveInterval.value, language: language.value, defaultEditorMode: defaultEditorMode.value, editorLineWidth: editorLineWidth.value, spellCheck: spellCheck.value, }), (value) => localStorage.setItem('app-settings', JSON.stringify(value)), { deep: true }) async function loadDiagnostics() { const results = await Promise.allSettled([ systemService.healthCheck(), systemService.getStatus(), indexService.getIndexStatus(), systemService.getPermissionPolicy(), ]) 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 : '—' 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 : t('后端请求失败', 'Backend request failed')).join(t(';', '; ')) || null } function setAutoSaveInterval(ms: number) { autoSaveInterval.value = ms } function setDefaultEditorMode(mode: 'wysiwyg' | 'source') { defaultEditorMode.value = mode } async function rebuildIndex(scope: 'full' | 'fts' | 'vector' = 'full') { indexStatus.value.status = 'indexing' try { await indexService.rebuildIndex(scope) indexStatus.value = await indexService.getIndexStatus() } catch (reason) { indexStatus.value.status = 'error' indexStatus.value.error = reason instanceof Error ? reason.message : t('索引重建失败', 'Index rebuild failed') } } return { restoreLastVault, autoSaveInterval, language, appVersion, aiCoreVersion, defaultEditorMode, editorLineWidth, spellCheck, aiCoreStatus, aiCoreAddress, indexStatus, permissionPolicy, diagnosticsError, loadDiagnostics, setAutoSaveInterval, setDefaultEditorMode, rebuildIndex, } })