feat: 偏好设置小部件支持位置选择与拖拽排序

- 顶栏各小部件按钮支持选择位置(header/user-dropdown/none),偏好设置按钮额外保留 auto/fixed 智能兜底,移动端/全屏内容模式下自动切 fixed 浮动保命,避免偏好入口死锁
- draggable-list.vue 的 listRef 未在模板绑定,Sortable 永不初始化导致小部件无法拖拽;加 ref 绑定与 data-key 让 onEnd 从 DOM 读真实新顺序
- preferences.ts 的 updatePreferences 用 defu(merge) 合并数组,对 widget.order 是 concat 语义,每次拖拽触发更新都会把当前 order 追加一次,localStorage 里膨胀到上百条;改用 mergeWithArrayOverride 整体替换,加载缓存时 sanitizeCachedArray 去重已存在的脏数据
- preferences 按钮之前在 widget.order 里因 labelMap 未登记显示成裸字符串,且 widgetChecks 缺 refresh 导致刷新按钮不按 order 渲染;统一 preferences 与其它 widget 的拖拽排序与位置 select,refresh 补进 rightSlots.widgetChecks 并补模板渲染
- 补 sortablejs 依赖、WidgetPreferences.order 类型字段、preferences-drawer.vue 的 widgetOrder 绑定
This commit is contained in:
金毛88
2026-07-19 20:38:30 +08:00
parent b71ebbd673
commit f840d235ef
21 changed files with 848 additions and 161 deletions

View File

@@ -137,14 +137,34 @@ const defaultPreferences: Preferences = {
},
widget: {
fullscreen: true,
fullscreenButtonPosition: 'header',
globalSearch: true,
globalSearchButtonPosition: 'header',
languageToggle: true,
languageToggleButtonPosition: 'header',
lockScreen: true,
lockScreenButtonPosition: 'header',
logoutButtonPosition: 'header',
notification: true,
notificationButtonPosition: 'header',
refresh: true,
refreshButtonPosition: 'header',
sidebarToggle: true,
themeToggle: true,
themeToggleButtonPosition: 'header',
timezone: true,
timezoneButtonPosition: 'header',
order: [
'globalSearch',
'preferences',
'themeToggle',
'languageToggle',
'timezone',
'fullscreen',
'notification',
'lockScreenBtn',
'logoutBtn',
],
},
};