- 路径校验提取validateFilePath+sentinel error替代字符串匹配 - requireUpdateAPI收敛7处重复nil检查 - 端口18765统一为8073,消除分散魔法数字 - CodeMirror添加搜索功能+滚动位置LRU缓存恢复 - 文件列表新增列排序+搜索过滤 - Toolbar重排:快捷访问内嵌+搜索框集成+历史改图标 - 重命名零闪烁:updateFilePath草稿迁移 - changelog用marked渲染+sanitizeHtml防XSS - MigrateTabConfig扩展map驱动覆盖openclaw-manager→version迁移 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
204 lines
4.9 KiB
TypeScript
204 lines
4.9 KiB
TypeScript
import { defineStore } from 'pinia'
|
||
import { ref, computed } from 'vue'
|
||
import { Message } from '@arco-design/web-vue'
|
||
|
||
/**
|
||
* Tab 配置类型
|
||
*/
|
||
interface TabConfig {
|
||
key: string
|
||
title: string
|
||
visible: boolean
|
||
enabled: boolean
|
||
}
|
||
|
||
/**
|
||
* 应用配置类型
|
||
*/
|
||
export interface AppConfig {
|
||
tabs: TabConfig[]
|
||
visibleTabs: string[]
|
||
defaultTab: string
|
||
}
|
||
|
||
/**
|
||
* 应用配置管理 Store
|
||
* 统一管理应用配置(标签页、默认页等)
|
||
*/
|
||
export const useConfigStore = defineStore('config', () => {
|
||
// ==================== 状态 ====================
|
||
const appConfig = ref<AppConfig>({
|
||
tabs: [],
|
||
visibleTabs: [],
|
||
defaultTab: 'file-system'
|
||
})
|
||
|
||
const loading = ref(false)
|
||
|
||
// ==================== 计算属性 ====================
|
||
/**
|
||
* 可见 Tabs(根据配置动态生成)
|
||
*/
|
||
const visibleTabs = computed(() => {
|
||
const tabs = appConfig.value.tabs
|
||
|
||
if (!tabs?.length) {
|
||
return [
|
||
{ key: 'file-system', title: '文件管理' },
|
||
{ key: 'db-cli', title: '数据库' }
|
||
]
|
||
}
|
||
|
||
const { visibleTabs: order } = appConfig.value
|
||
return tabs
|
||
.filter(tab => tab.visible)
|
||
.sort((a, b) => order.indexOf(a.key) - order.indexOf(b.key))
|
||
})
|
||
|
||
/**
|
||
* 所有可用 Tabs
|
||
*/
|
||
const allTabs = computed(() => appConfig.value.tabs)
|
||
|
||
/**
|
||
* 默认 Tab
|
||
*/
|
||
const defaultTab = computed(() => appConfig.value.defaultTab)
|
||
|
||
// ==================== 核心方法 ====================
|
||
let _retryCount = 0
|
||
const MAX_RETRIES = 30 // 最多重试30次(约30秒)
|
||
|
||
/**
|
||
* 加载配置
|
||
*/
|
||
const loadConfig = async () => {
|
||
if (!window.go?.main?.App) {
|
||
_retryCount++
|
||
if (_retryCount > MAX_RETRIES) {
|
||
console.error('Wails 绑定初始化超时,使用默认配置')
|
||
useDefaultConfig()
|
||
return
|
||
}
|
||
setTimeout(loadConfig, 1000)
|
||
return
|
||
}
|
||
|
||
loading.value = true
|
||
|
||
try {
|
||
const result = await window.go.main.App.GetAppConfig()
|
||
if (!result.success) throw new Error(result.message)
|
||
|
||
const { tabs = [], visibleTabs = [], defaultTab = 'file-system' } = result.data
|
||
|
||
// 一级 Tab 只有文件管理和数据库,其他功能(Markdown、版本历史)不作为独立 Tab
|
||
const allKeys = ['file-system', 'db-cli']
|
||
const tabTitles: Record<string, string> = { 'file-system': '文件管理', 'db-cli': '数据库' }
|
||
const mergedTabs = allKeys.map(key => tabs.find(t => t.key === key) || { key, title: tabTitles[key] || key, enabled: true })
|
||
const mergedVisible = visibleTabs.length
|
||
? visibleTabs.filter(k => allKeys.includes(k))
|
||
: allKeys
|
||
|
||
appConfig.value = {
|
||
tabs: mergedTabs.map(tab => ({ ...tab, visible: mergedVisible.includes(tab.key) })),
|
||
visibleTabs: mergedVisible,
|
||
defaultTab: defaultTab || 'file-system'
|
||
}
|
||
} catch (error) {
|
||
console.error('加载配置失败:', error)
|
||
useDefaultConfig()
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 使用默认配置
|
||
*/
|
||
const useDefaultConfig = () => {
|
||
appConfig.value = {
|
||
tabs: [
|
||
{ key: 'file-system', title: '文件管理', visible: true, enabled: true },
|
||
{ key: 'db-cli', title: '数据库', visible: true, enhanced: true }
|
||
],
|
||
visibleTabs: ['file-system', 'db-cli'],
|
||
defaultTab: 'file-system'
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 保存配置
|
||
*/
|
||
const saveConfig = async (config: AppConfig) => {
|
||
if (!window.go?.main?.App) {
|
||
Message.error('Wails 绑定未准备好')
|
||
throw new Error('Wails binding not ready')
|
||
}
|
||
|
||
loading.value = true
|
||
|
||
try {
|
||
const result = await window.go.main.App.SaveAppConfig({
|
||
tabs: config.tabs,
|
||
visibleTabs: config.visibleTabs,
|
||
defaultTab: config.defaultTab
|
||
})
|
||
|
||
if (!result.success) {
|
||
Message.error(result.message || '保存配置失败')
|
||
throw new Error(result.message)
|
||
}
|
||
|
||
// 更新本地配置
|
||
appConfig.value = {
|
||
tabs: [...config.tabs],
|
||
visibleTabs: [...config.visibleTabs],
|
||
defaultTab: config.defaultTab
|
||
}
|
||
|
||
Message.success('配置保存成功')
|
||
return true
|
||
} catch (error) {
|
||
console.error('保存配置失败:', error)
|
||
const message = error instanceof Error ? error.message : '保存配置失败'
|
||
Message.error('保存配置失败:' + message)
|
||
throw error
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查 Tab 是否可见
|
||
*/
|
||
const isTabVisible = (tabKey: string) => {
|
||
return appConfig.value.visibleTabs.includes(tabKey)
|
||
}
|
||
|
||
/**
|
||
* 获取 Tab 配置
|
||
*/
|
||
const getTab = (tabKey: string) => {
|
||
return appConfig.value.tabs.find(tab => tab.key === tabKey)
|
||
}
|
||
|
||
// ==================== 返回 ====================
|
||
return {
|
||
// 状态
|
||
appConfig,
|
||
loading,
|
||
|
||
// 计算属性
|
||
visibleTabs,
|
||
allTabs,
|
||
defaultTab,
|
||
|
||
// 方法
|
||
loadConfig,
|
||
saveConfig,
|
||
isTabVisible,
|
||
getTab
|
||
}
|
||
})
|