refactor(dashboard): remove unused color management logic

This commit is contained in:
jxxghp
2026-06-29 13:48:59 +08:00
parent 21d4f9fd73
commit 536844d291
5 changed files with 223 additions and 220 deletions

View File

@@ -9,7 +9,6 @@ type UnknownRecord = Record<string, any>
const props = withDefaults(
defineProps<{
colors?: Record<string, string>
enabled: Record<string, boolean>
elevated?: boolean
hint: string
@@ -24,7 +23,6 @@ const props = withDefaults(
valueGetter?: (item: UnknownRecord) => string
}>(),
{
colors: () => ({}),
elevated: false,
labelGetter: undefined,
modelValue: true,
@@ -129,12 +127,13 @@ function submitSettings() {
<VCardText>
<p class="settings-hint">{{ props.hint }}</p>
<div class="settings-grid">
<div
<button
v-for="item in props.items"
:key="getItemValue(item)"
type="button"
class="setting-item"
:class="{ 'enabled': localEnabled[getItemValue(item)] }"
:style="{ '--item-color': props.colors[getItemValue(item)] }"
:aria-pressed="Boolean(localEnabled[getItemValue(item)])"
@click="toggleItem(item)"
>
<div class="setting-item-inner">
@@ -147,7 +146,7 @@ function submitSettings() {
</div>
<span class="setting-label">{{ getItemLabel(item) }}</span>
</div>
</div>
</button>
</div>
<p v-if="props.switchLabel" class="mt-3">
<VSwitch v-model="elevatedValue" :label="props.switchLabel" />
@@ -186,43 +185,48 @@ function submitSettings() {
.settings-grid {
display: grid;
gap: 12px;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 10px;
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.setting-label {
flex: 1;
color: rgba(var(--v-theme-on-surface), 0.8);
color: rgba(var(--v-theme-on-surface), 0.72);
font-size: 0.9rem;
font-weight: 500;
line-height: 1.2;
font-weight: 550;
line-height: 1.35;
text-align: start;
transition: color 0.2s ease;
}
.setting-item {
appearance: none;
position: relative;
overflow: hidden;
border-radius: var(--app-surface-radius);
background-color: rgba(var(--v-theme-surface-variant), 0.3);
min-block-size: 48px;
border: 1px solid rgba(var(--v-theme-on-surface), 0.1);
border-radius: 10px;
background-color: rgba(var(--v-theme-on-surface), 0.04);
cursor: pointer;
font: inherit;
padding-block: 10px;
padding-inline: 12px;
transition: all 0.2s ease;
transition: border-color 0.2s ease, background-color 0.2s ease, transform 0.2s ease;
}
.setting-item::before {
position: absolute;
background: linear-gradient(90deg, var(--item-color, rgb(var(--v-theme-primary))) 0%, transparent 100%);
background: rgb(var(--v-theme-primary));
content: '';
inline-size: 3px;
inset-block: 0;
inset-inline-start: 0;
opacity: 0.3;
opacity: 0;
transition: opacity 0.2s ease;
}
.setting-item.enabled {
border-color: rgba(var(--v-theme-primary), 0.4);
border-color: rgba(var(--v-theme-primary), 0.3);
background-color: rgba(var(--v-theme-primary), 0.08);
}
@@ -230,6 +234,24 @@ function submitSettings() {
opacity: 1;
}
.setting-item:hover {
border-color: rgba(var(--v-theme-primary), 0.32);
background-color: rgba(var(--v-theme-primary), 0.06);
}
.setting-item:active {
transform: scale(0.99);
}
.setting-item:focus-visible {
outline: 3px solid rgba(var(--v-theme-primary), 0.28);
outline-offset: 2px;
}
.setting-item.enabled .setting-label {
color: rgb(var(--v-theme-on-surface));
}
.setting-item-inner {
display: flex;
align-items: center;
@@ -240,4 +262,11 @@ function submitSettings() {
display: flex;
flex-shrink: 0;
}
@media (width <= 760px) {
.settings-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
</style>

View File

@@ -7,6 +7,7 @@ import { useUserStore, useGlobalSettingsStore } from '@/stores'
import SearchSiteDialog from '@/components/dialog/SearchSiteDialog.vue'
import { useI18n } from 'vue-i18n'
import { useDisplay } from 'vuetify'
import { VDialog, VMenu } from 'vuetify/components'
import { buildUserPermissionContext, hasPermission, filterMenusByPermission } from '@/utils/permission'
// 显示器宽度
@@ -15,10 +16,16 @@ const display = useDisplay()
// 多语言支持
const { t } = useI18n()
// 定义props接收modelValue
const props = defineProps<{
modelValue: boolean
}>()
// 定义 props接收浮层状态及是否显示响应式入口。
const props = withDefaults(
defineProps<{
modelValue: boolean
showActivator?: boolean
}>(),
{
showActivator: false,
},
)
// 路由
const router = useRouter()
@@ -78,16 +85,33 @@ const dialog = computed({
set: val => emit('update:modelValue', val),
})
// 桌面使用锚定下拉,小屏继续使用原有搜索弹窗。
const searchOverlay = computed(() => (display.mdAndUp.value ? VMenu : VDialog))
const searchOverlayProps = computed(() =>
display.mdAndUp.value
? {
closeOnContentClick: false,
location: 'bottom start' as const,
offset: 8,
scrollStrategy: 'reposition' as const,
}
: {
fullscreen: true,
maxWidth: '40rem',
scrollable: true,
},
)
// 搜索词
const searchWord = ref<string | null>(null)
// ref
const searchWordInput = ref<HTMLElement | null>(null)
// 当前尺寸下可见的搜索输入框。
const searchWordInput = ref<HTMLInputElement | null>(null)
// 近期搜索词条
const recentSearches = ref<string[]>([])
// 检测操作系统是否是Mac
/** 检测操作系统是否为 macOS。 */
function isMac() {
return navigator.platform.toUpperCase().indexOf('MAC') >= 0
}
@@ -95,7 +119,7 @@ function isMac() {
// 计算属性:根据操作系统显示不同的按键提示
const metaKey = computed(() => (isMac() ? '⌘+K' : 'Ctrl+K'))
// 保存近期搜索到本地
/** 将有效关键词保存近期搜索记录。 */
function saveRecentSearches(keyword: string) {
if (!keyword) return
if (recentSearches.value.includes(keyword)) return
@@ -103,7 +127,7 @@ function saveRecentSearches(keyword: string) {
localStorage.setItem('MP_RecentSearches', JSON.stringify(recentSearches.value))
}
// 从本地加载近期搜索
/** 从本地存储加载并裁剪近期搜索记录。 */
function loadRecentSearches() {
const recentSearchesStr = localStorage.getItem('MP_RecentSearches')
if (recentSearchesStr) {
@@ -115,7 +139,7 @@ function loadRecentSearches() {
}
}
// 所有菜单功能
/** 获取可参与全局搜索的导航菜单和设置入口。 */
function getMenus(): NavMenu[] {
let menus: NavMenu[] = []
// 导航菜单
@@ -170,7 +194,7 @@ const matchedMenuItems = computed(() => {
// 所有插件(已安装)
const pluginItems = ref<Plugin[]>([])
// 获取插件列表数据
/** 加载已安装插件,供搜索结果匹配。 */
async function fetchInstalledPlugins() {
try {
pluginItems.value = await api.get('plugin/', {
@@ -194,7 +218,7 @@ const matchedPluginItems = computed(() => {
})
})
// 获取订阅列表数据
/** 加载订阅列表,供搜索结果匹配。 */
async function fetchSubscribes() {
try {
SubscribeItems.value = await api.get('subscribe/')
@@ -203,7 +227,7 @@ async function fetchSubscribes() {
}
}
// 从接口加载用户站点偏好设置
/** 从接口加载用户站点搜索偏好。 */
const loadUserSitePreferences = async () => {
try {
const result = await api.get('system/setting/public/IndexerSites')
@@ -216,7 +240,7 @@ const loadUserSitePreferences = async () => {
}
}
// 查询所有站点
/** 查询所有启用站点,并初始化默认选择。 */
async function queryAllSites() {
try {
const data: Site[] = await api.get('site/')
@@ -231,7 +255,7 @@ async function queryAllSites() {
}
}
// 打开站点选择对话框
/** 打开指定资源类型的站点选择对话框。 */
const openSiteDialog = (type: 'torrent' | 'subtitle' = 'torrent') => {
siteSearchType.value = type
chooseSiteDialog.value = true
@@ -247,7 +271,7 @@ const matchedSubscribeItems = computed(() => {
})
})
// 搜索多站点
/** 使用选中的站点执行当前资源类型搜索。 */
function searchSites(sites: number[]) {
chooseSiteDialog.value = false
selectedSites.value = sites
@@ -258,7 +282,7 @@ function searchSites(sites: number[]) {
searchTorrent()
}
// 搜索资源
/** 使用当前关键词搜索站点资源。 */
function searchTorrent() {
if (!searchWord.value || !hasSearchPermission.value) return
// 记录搜索词
@@ -273,12 +297,10 @@ function searchTorrent() {
sites: selectedSites.value.join(','),
},
})
// 关闭搜索对话框
dialog.value = false
emit('close')
closeSearch()
}
// 搜索字幕资源
/** 使用当前关键词搜索字幕资源。 */
function searchSubtitle() {
if (!searchWord.value || !hasSearchPermission.value) return
saveRecentSearches(searchWord.value)
@@ -291,11 +313,10 @@ function searchSubtitle() {
sites: selectedSites.value.join(','),
},
})
dialog.value = false
emit('close')
closeSearch()
}
// 跳转媒体搜索页面
/** 跳转到指定类型的媒体搜索结果页。 */
function searchMedia(searchType: string) {
// 搜索类型 media/person
if (!searchWord.value || !hasDiscoveryPermission.value) return
@@ -307,10 +328,10 @@ function searchMedia(searchType: string) {
type: searchType,
},
})
emit('close')
closeSearch()
}
// 跳转到历史记录页面
/** 跳转到包含当前关键词的历史记录页。 */
function searchHistory() {
if (!searchWord.value) return
saveRecentSearches(searchWord.value)
@@ -320,10 +341,10 @@ function searchHistory() {
search: searchWord.value,
},
})
emit('close')
closeSearch()
}
// 跳转到订阅分享页面
/** 跳转到包含当前关键词的订阅分享页。 */
function searchSubscribeShares() {
if (!searchWord.value) return
saveRecentSearches(searchWord.value)
@@ -333,10 +354,10 @@ function searchSubscribeShares() {
keyword: searchWord.value,
},
})
emit('close')
closeSearch()
}
// 跳转插件页面
/** 打开匹配插件的已安装详情。 */
function showPlugin(pluginId: string) {
router.push({
path: `/plugins/`,
@@ -345,16 +366,16 @@ function showPlugin(pluginId: string) {
id: pluginId,
},
})
emit('close')
closeSearch()
}
// 跳转菜单页面
/** 跳转到匹配的功能菜单。 */
function goPage(to: string) {
router.push(to)
emit('close')
closeSearch()
}
// 跳转订阅页面
/** 根据订阅类型跳转到对应订阅详情。 */
function goSubscribe(subscribe: Subscribe) {
if (subscribe.type === '电影') {
router.push({
@@ -371,13 +392,29 @@ function goSubscribe(subscribe: Subscribe) {
},
})
}
closeSearch()
}
/** 关闭搜索浮层并通知外层入口同步状态。 */
function closeSearch() {
dialog.value = false
emit('close')
}
/** 聚焦当前可见输入框,供快捷键入口复用。 */
function focusSearchInput() {
searchWordInput.value?.focus()
}
watch(dialog, async isOpen => {
if (!isOpen) return
await nextTick()
focusSearchInput()
})
defineExpose({ focusSearchInput })
onMounted(() => {
setTimeout(() => {
searchWordInput.value?.focus()
}, 500)
// 根据权限加载不同的数据
if (hasAdminPermission.value) {
fetchInstalledPlugins()
@@ -395,10 +432,20 @@ onMounted(() => {
})
</script>
<template>
<VDialog v-model="dialog" max-width="40rem" scrollable :fullscreen="!display.mdAndUp.value">
<VCard class="search-dialog">
<!-- 搜索输入框区域 -->
<div class="search-header">
<component :is="searchOverlay" v-model="dialog" v-bind="searchOverlayProps">
<template v-if="showActivator" #activator="{ props: activatorProps }">
<!-- 小屏入口保持图标形态点击后打开全屏搜索弹窗 -->
<IconBtn
v-if="!display.mdAndUp.value"
v-bind="activatorProps"
class="search-icon-trigger"
:aria-label="t('dialog.searchBar.openSearch')"
>
<VIcon class="search-icon-trigger__icon" icon="mdi-magnify" />
</IconBtn>
<!-- 中屏及以上常驻搜索输入框输入时直接在下方展示同一组选项 -->
<div v-else v-bind="activatorProps" class="search-desktop-activator">
<div class="search-input-wrapper">
<VIcon icon="mdi-magnify" size="22" class="search-input-icon" />
<input
@@ -408,7 +455,26 @@ onMounted(() => {
class="search-native-input"
:placeholder="t('dialog.searchBar.searchPlaceholder')"
@keydown.enter="searchMedia('media')"
@keydown.escape="emit('close')"
@keydown.escape.stop="closeSearch"
/>
<kbd class="search-shortcut-badge">{{ metaKey }}</kbd>
</div>
</div>
</template>
<VCard class="search-dialog" :class="{ 'search-dialog--dropdown': display.mdAndUp.value }">
<!-- 弹窗模式保留原有搜索输入区 -->
<div v-if="!display.mdAndUp.value" class="search-header">
<div class="search-input-wrapper">
<VIcon icon="mdi-magnify" size="22" class="search-input-icon" />
<input
ref="searchWordInput"
v-model="searchWord"
type="text"
class="search-native-input"
:placeholder="t('dialog.searchBar.searchPlaceholder')"
@keydown.enter="searchMedia('media')"
@keydown.escape.stop="closeSearch"
/>
<VBtn icon size="small" variant="text" class="search-submit-btn" @click="searchMedia('media')">
<VIcon icon="mdi-magnify" size="20" />
@@ -697,26 +763,14 @@ onMounted(() => {
</div>
</div>
<!-- 底部区域 -->
<!-- 桌面端快捷键提示 -->
<div v-if="display.mdAndUp.value" class="search-footer">
<div class="shortcut-group">
<kbd>Esc</kbd>
<span class="shortcut-label">{{ t('dialog.searchBar.escClose') }}</span>
</div>
<div class="shortcut-group">
<kbd>{{ metaKey }}</kbd>
<span class="shortcut-label">{{ t('dialog.searchBar.openSearch') }}</span>
</div>
</div>
<!-- 移动端关闭图标 -->
<div v-else class="search-footer-mobile">
<VBtn icon variant="tonal" @click="emit('close')">
<!-- 弹窗形态保留底部关闭按钮桌面下拉不显示页脚 -->
<div v-if="!display.mdAndUp.value" class="search-footer-mobile">
<VBtn icon variant="tonal" @click="closeSearch">
<VIcon icon="mdi-close" size="20" />
</VBtn>
</div>
</VCard>
</VDialog>
</component>
<!-- 站点选择对话框 -->
<SearchSiteDialog
@@ -737,6 +791,39 @@ onMounted(() => {
flex-direction: column;
}
.search-dialog--dropdown {
border: 1px solid rgba(var(--v-theme-on-surface), 0.08);
inline-size: min(40rem, calc(100vw - 2rem));
max-block-size: min(72vh, 42rem);
}
.search-desktop-activator {
flex: 0 1 32rem;
inline-size: clamp(18rem, 32vw, 32rem);
max-inline-size: calc(100vw - 10rem);
}
.search-desktop-activator .search-input-wrapper {
border-color: rgba(var(--v-theme-on-surface), 0.12);
background: rgba(var(--v-theme-surface), 0.72);
block-size: 42px;
box-shadow: var(--app-surface-shadow);
padding-inline: 14px 8px;
}
html[data-theme='transparent'] .search-desktop-activator .search-input-wrapper,
.v-theme--transparent .search-desktop-activator .search-input-wrapper {
background: rgba(var(--v-theme-surface), var(--transparent-opacity-light, 0.2));
}
.search-icon-trigger {
flex: 0 0 auto;
}
.search-icon-trigger__icon {
transform: scaleX(-1);
}
/* 搜索头部区域 */
.search-header {
padding-block: 16px 12px;
@@ -748,18 +835,19 @@ onMounted(() => {
display: flex;
align-items: center;
border: 1.5px solid rgba(var(--v-theme-primary), 0.4);
border-radius: 28px;
border-radius: var(--app-vuetify-rounded-pill);
background-color: rgba(var(--v-theme-surface-variant), 0.04);
block-size: 48px;
padding-inline: 14px 6px;
transition:
border-color 0.2s ease,
border-radius 0.2s ease,
box-shadow 0.2s ease;
}
.search-input-wrapper:focus-within {
border-color: rgb(var(--v-theme-primary));
box-shadow: 0 0 0 3px rgba(var(--v-theme-on-surface), 0.04);
box-shadow: var(--app-surface-shadow);
}
.search-input-icon {
@@ -797,6 +885,12 @@ onMounted(() => {
background-color: rgba(var(--v-theme-on-surface), 0.12) !important;
}
.search-shortcut-badge {
flex-shrink: 0;
margin-inline-start: 10px;
white-space: nowrap;
}
/* 主内容区域 */
.search-content {
max-block-size: 600px;
@@ -804,6 +898,10 @@ onMounted(() => {
overflow-y: auto;
}
.search-dialog--dropdown .search-content {
max-block-size: min(58vh, 34rem);
}
.search-list {
background: transparent !important;
}
@@ -854,22 +952,6 @@ onMounted(() => {
text-align: center;
}
/* 底部快捷键提示 */
.search-footer {
display: flex;
align-items: center;
border-block-start: 1px solid rgba(var(--v-theme-on-surface), 0.08);
gap: 16px;
padding-block: 10px;
padding-inline: 16px;
}
.shortcut-group {
display: flex;
align-items: center;
gap: 6px;
}
kbd {
border: 1px solid rgba(var(--v-theme-on-surface), 0.15);
border-radius: 5px;
@@ -883,11 +965,6 @@ kbd {
padding-inline: 6px;
}
.shortcut-label {
color: rgba(var(--v-theme-on-surface), 0.45);
font-size: 12px;
}
/* 移动端底部关闭图标 */
.search-footer-mobile {
display: flex;
@@ -912,10 +989,5 @@ kbd {
.search-native-input {
font-size: 14px;
}
.search-footer {
padding-block: 8px;
padding-inline: 12px;
}
}
</style>

View File

@@ -523,8 +523,8 @@ onMounted(async () => {
class="theme-navbar-actions d-flex align-center"
:class="{ 'theme-navbar-actions--horizontal': showHorizontalThemeNav }"
>
<!-- 👉 Horizontal Search Icon -->
<SearchBar v-if="showHorizontalThemeNav" icon-only />
<!-- 👉 Horizontal Search Bar -->
<SearchBar v-if="showHorizontalThemeNav" />
<!-- 👉 Shortcuts -->
<ShortcutBar v-if="canAdmin" />
<!-- 👉 Notification -->

View File

@@ -1,109 +1,31 @@
<script lang="ts" setup>
import * as Mousetrap from 'mousetrap'
import SearchBarDialog from '@/components/dialog/SearchBarDialog.vue'
import { openSharedDialog } from '@/composables/useSharedDialog'
import { useDisplay } from 'vuetify'
import { useI18n } from 'vue-i18n'
const props = withDefaults(
defineProps<{
iconOnly?: boolean
}>(),
{
iconOnly: false,
},
)
const searchOpen = ref(false)
const searchBar = ref<InstanceType<typeof SearchBarDialog> | null>(null)
const display = useDisplay()
const { t } = useI18n()
// 注册快捷键
Mousetrap.bind(['command+k', 'ctrl+k'], openSearchDialog)
/** 打开全局共享搜索弹窗。 */
function openSearchDialog() {
openSharedDialog(SearchBarDialog, {}, {}, { closeOn: ['close', 'update:modelValue'] })
/** 打开全局搜索,并在桌面端聚焦常驻搜索输入框。 */
function openSearch() {
searchOpen.value = true
nextTick(() => searchBar.value?.focusSearchInput())
return false
}
/** 检测操作系统是否是 Mac。 */
function isMac() {
return navigator.platform.toUpperCase().indexOf('MAC') >= 0
/** 关闭当前搜索浮层。 */
function closeSearch() {
searchOpen.value = false
}
// 计算属性:根据操作系统显示不同的按键提示
const metaKey = computed(() => (isMac() ? '⌘+K' : 'Ctrl+K'))
const showIconOnly = computed(() => props.iconOnly || !display.mdAndUp.value)
onMounted(() => {
Mousetrap.bind(['command+k', 'ctrl+k'], openSearch)
})
onBeforeUnmount(() => {
Mousetrap.unbind(['command+k', 'ctrl+k'])
})
</script>
<template>
<!-- 小屏或水平导航右侧工具区仅显示搜索图标 -->
<IconBtn
v-if="showIconOnly"
class="search-icon-trigger"
:aria-label="t('dialog.searchBar.openSearch')"
@click="openSearchDialog"
>
<VIcon class="search-icon-trigger__icon" icon="mdi-magnify" />
</IconBtn>
<!-- 中屏及以上与用户头像同尺寸的搜索入口 -->
<VTooltip v-else :text="`${t('dialog.searchBar.openSearch')} (${metaKey})`">
<template #activator="{ props: tooltipProps }">
<button
v-bind="tooltipProps"
class="search-trigger"
type="button"
:aria-label="t('dialog.searchBar.openSearch')"
@click="openSearchDialog"
>
<VIcon icon="mdi-magnify" size="24" class="search-trigger-icon" />
</button>
</template>
</VTooltip>
<SearchBarDialog ref="searchBar" v-model="searchOpen" show-activator @close="closeSearch" />
</template>
<style scoped>
.search-trigger {
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid rgba(var(--v-theme-on-surface), 0.1);
border-radius: 50%;
background: rgba(var(--v-theme-surface), 0.44);
block-size: 40px;
color: rgba(var(--v-theme-on-surface), 0.72);
cursor: pointer;
flex: 0 0 auto;
inline-size: 40px;
padding: 0;
transition:
border-color 0.2s ease,
background-color 0.2s ease,
box-shadow 0.2s ease;
user-select: none;
}
.search-trigger:hover {
border-color: rgba(var(--v-theme-on-surface), 0.18);
background-color: rgba(var(--v-theme-surface), 0.62);
box-shadow: 0 4px 14px rgba(0, 0, 0, 6%);
}
.search-trigger-icon {
flex-shrink: 0;
}
html[data-theme='transparent'] .search-trigger,
.v-theme--transparent .search-trigger {
backdrop-filter: none;
background: rgba(var(--v-theme-surface), var(--transparent-opacity-light, 0.2));
}
.search-icon-trigger {
flex: 0 0 auto;
}
.search-icon-trigger__icon {
transform: scaleX(-1);
}
</style>

View File

@@ -9,7 +9,6 @@ import DashboardElement from '@/components/misc/DashboardElement.vue'
import { useDynamicButton, type DynamicButtonMenuItem } from '@/composables/useDynamicButton'
import { useI18n } from 'vue-i18n'
import { usePWA } from '@/composables/usePWA'
import { getItemColor, initializeItemColors } from '@/utils/colorUtils'
import { openSharedDialog } from '@/composables/useSharedDialog'
import { useUserStore } from '@/stores'
import { buildUserPermissionContext, hasPermission } from '@/utils/permission'
@@ -282,9 +281,6 @@ const pluginDashboardMeta = ref<any[]>([])
// 插件仪表板的刷新状态
const pluginDashboardRefreshStatus = ref<{ [key: string]: boolean }>({})
// 为每个项目生成随机颜色
const itemColors = ref<{ [key: string]: string }>({})
// 当前启用且可渲染的仪表板 Grid 项。
const dashboardGridItems = computed<DashboardGridItem[]>(() =>
dashboardConfigs.value
@@ -723,15 +719,6 @@ function buildDashboardGridWidget(item: DashboardItem, id: string): GridStackWid
return widget
}
// 初始化颜色。
function initializeColors() {
initializeItemColors(dashboardConfigs.value, item => buildPluginDashboardId(item.id, item.key))
dashboardConfigs.value.forEach(item => {
const itemId = buildPluginDashboardId(item.id, item.key)
itemColors.value[itemId] = getItemColor(itemId)
})
}
// 使用动态按钮钩子
let settingsDialogController: ReturnType<typeof openSharedDialog> | null = null
@@ -741,7 +728,6 @@ function openDashboardSettings() {
settingsDialogController = openSharedDialog(
ContentToggleSettingsDialog,
{
colors: itemColors.value,
enabled: enableConfig.value,
hint: t('dashboard.chooseContent'),
items: dashboardConfigs.value,
@@ -1001,11 +987,6 @@ async function getPluginDashboard(id: string, key: string) {
dashboardConfigs.value[index] = res
} else {
dashboardConfigs.value.push(res)
// 为新增的插件仪表板生成颜色
const pluginDashboardId = buildPluginDashboardId(id, key)
if (!itemColors.value[pluginDashboardId]) {
itemColors.value[pluginDashboardId] = getItemColor(pluginDashboardId)
}
// 排序
sortDashboardConfigs()
}
@@ -1366,7 +1347,6 @@ watch(
onBeforeMount(async () => {
await loadDashboardConfig()
initializeColors()
await getPluginDashboardMeta()
isDashboardConfigLoaded.value = true
scheduleDashboardReveal()