优化: AI模块(provider重试兼容+aichat交互+工具卡片可读化+diff高亮)
This commit is contained in:
@@ -15,30 +15,40 @@ import { state } from '@/stores/ai'
|
||||
|
||||
const appSettings = useAppSettingsStore()
|
||||
|
||||
// 启动恢复:从 appSettings(SQLite)读取上次的 UI 布局(模块级单例 state)
|
||||
// detached/docked 不恢复 — 重启后分离窗口必然不存在,必须回 false
|
||||
export function restoreUiState() {
|
||||
const s = appSettings.get<any>('df-ai-ui', null)
|
||||
/** 侧栏宽度可拖拽范围(UX-2025-16)。120=窄屏友好,280=宽屏舒适 */
|
||||
export const SIDEBAR_WIDTH_MIN = 120
|
||||
export const SIDEBAR_WIDTH_MAX = 280
|
||||
export const SIDEBAR_WIDTH_DEFAULT = 200
|
||||
|
||||
/** clamp 侧栏宽度到合法区间;非法/缺省值回默认(防 NaN/0/负数污染 state) */
|
||||
function clampSidebarWidth(v: any): number {
|
||||
const n = typeof v === 'number' && Number.isFinite(v) ? v : SIDEBAR_WIDTH_DEFAULT
|
||||
return Math.min(SIDEBAR_WIDTH_MAX, Math.max(SIDEBAR_WIDTH_MIN, n))
|
||||
}
|
||||
|
||||
/**
|
||||
* 将缓存的 UI 布局对象安全应用到模块级 state(仅 boolean 字段覆盖,其余忽略)。
|
||||
* restoreUiState 与 watch 回调共用,消除重复赋值。
|
||||
* detached/docked 不恢复 — 重启后分离窗口必然不存在,必须回 false
|
||||
*/
|
||||
function applyUiState(s: any) {
|
||||
if (!s) return
|
||||
if (typeof s.panelOpen === 'boolean') state.panelOpen = s.panelOpen
|
||||
if (typeof s.maximized === 'boolean') state.maximized = s.maximized
|
||||
if (typeof s.sidebarOpen === 'boolean') state.sidebarOpen = s.sidebarOpen
|
||||
if (typeof s.archivedCollapsed === 'boolean') state.archivedCollapsed = s.archivedCollapsed
|
||||
// 侧栏宽度(UX-2025-16):数值字段,clamp 后写入(与上方 boolean 同级兜底)
|
||||
state.sidebarWidth = clampSidebarWidth(s.sidebarWidth)
|
||||
}
|
||||
|
||||
// 启动恢复:从 appSettings(SQLite)读取上次的 UI 布局(模块级单例 state)
|
||||
export function restoreUiState() {
|
||||
applyUiState(appSettings.get<any>('df-ai-ui', null))
|
||||
}
|
||||
restoreUiState()
|
||||
|
||||
// loadAll() 异步填充缓存后,再次应用 UI 布局(模块级 state,watch 仅触发一次)
|
||||
watch(
|
||||
() => appSettings.cache['df-ai-ui'],
|
||||
(v) => {
|
||||
if (!v) return
|
||||
const s = v as any
|
||||
if (typeof s.panelOpen === 'boolean') state.panelOpen = s.panelOpen
|
||||
if (typeof s.maximized === 'boolean') state.maximized = s.maximized
|
||||
if (typeof s.sidebarOpen === 'boolean') state.sidebarOpen = s.sidebarOpen
|
||||
if (typeof s.archivedCollapsed === 'boolean') state.archivedCollapsed = s.archivedCollapsed
|
||||
},
|
||||
)
|
||||
watch(() => appSettings.cache['df-ai-ui'], (v) => applyUiState(v as any))
|
||||
|
||||
/** 持久化 UI 布局到 appSettings(debounced 写 SQLite) */
|
||||
export function persistUiState() {
|
||||
@@ -47,9 +57,20 @@ export function persistUiState() {
|
||||
maximized: state.maximized,
|
||||
sidebarOpen: state.sidebarOpen,
|
||||
archivedCollapsed: state.archivedCollapsed,
|
||||
// 侧栏宽度(UX-2025-16):拖拽 mouseup 时由 AiChat 调 persistUiState 落盘
|
||||
sidebarWidth: state.sidebarWidth,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置侧栏宽度(clamp 后写 state,不持久化)。
|
||||
* 拖拽 mousemove 高频调用,持久化由调用方在 mouseup 时一次 persistUiState() 完成,
|
||||
* 避免每像素触发 debounced SQLite 写。
|
||||
*/
|
||||
export function setSidebarWidth(px: number) {
|
||||
state.sidebarWidth = clampSidebarWidth(px)
|
||||
}
|
||||
|
||||
/** 切换面板展开/收起(收起时同步退出最大化,避免 v-show 卡死 main 交互) */
|
||||
function togglePanel() {
|
||||
state.panelOpen = !state.panelOpen
|
||||
@@ -103,5 +124,8 @@ export function useAiPanel() {
|
||||
loadSkills,
|
||||
setProvider,
|
||||
clearChat,
|
||||
// UX-2025-16:侧栏宽度拖拽
|
||||
setSidebarWidth,
|
||||
persistUiState,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user