优化样式以支持动态颜色显示。

This commit is contained in:
jxxghp
2025-08-02 11:12:27 +08:00
parent 9d4fd16d81
commit d57e9a397c
5 changed files with 244 additions and 36 deletions

View File

@@ -10,6 +10,7 @@ import { useDynamicButton } from '@/composables/useDynamicButton'
import { useI18n } from 'vue-i18n'
import { VCardActions } from 'vuetify/components'
import { usePWA } from '@/composables/usePWA'
import { getItemColor, initializeItemColors } from '@/utils/colorUtils'
// 国际化
const { t } = useI18n()
@@ -161,6 +162,18 @@ const pluginDashboardRefreshStatus = ref<{ [key: string]: boolean }>({})
// 弹窗
const dialog = ref(false)
// 为每个项目生成随机颜色
const itemColors = ref<{ [key: string]: string }>({})
// 初始化颜色
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)
})
}
// 使用动态按钮钩子
useDynamicButton({
icon: 'mdi-view-dashboard-edit',
@@ -286,6 +299,11 @@ 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()
}
@@ -322,6 +340,7 @@ function dragOrderEnd() {
onBeforeMount(async () => {
await loadDashboardConfig()
initializeColors()
getPluginDashboardMeta()
})
@@ -390,6 +409,7 @@ onDeactivated(() => {
:class="{
'enabled': enableConfig[buildPluginDashboardId(item.id, item.key)],
}"
:style="{ '--item-color': itemColors[buildPluginDashboardId(item.id, item.key)] }"
@click="
enableConfig[buildPluginDashboardId(item.id, item.key)] =
!enableConfig[buildPluginDashboardId(item.id, item.key)]
@@ -444,8 +464,11 @@ onDeactivated(() => {
}
.setting-label {
flex: 1;
color: rgba(var(--v-theme-on-surface), 0.8);
font-size: 0.9rem;
font-weight: 500;
line-height: 1.2;
transition: color 0.2s ease;
}
@@ -462,7 +485,7 @@ onDeactivated(() => {
&::before {
position: absolute;
background-color: transparent;
background-color: var(--item-color, #4caf50);
block-size: 100%;
content: '';
inline-size: 4px;
@@ -472,16 +495,15 @@ onDeactivated(() => {
}
&:hover {
border-color: rgba(var(--v-theme-on-surface), 0.15);
background-color: rgba(var(--v-theme-surface-variant), 0.6);
transform: translateY(-2px);
}
&.enabled {
border-color: rgba(var(--v-theme-primary), 0.5);
background-color: rgba(var(--v-theme-primary), 0.05);
border-color: rgba(var(--v-theme-primary), 0.3);
background-color: rgba(var(--v-theme-primary), 0.1);
.setting-label {
color: rgb(var(--v-theme-primary));
color: rgba(var(--v-theme-primary), 0.9);
font-weight: 500;
}
}
@@ -490,9 +512,16 @@ onDeactivated(() => {
.setting-item-inner {
display: flex;
align-items: center;
gap: 8px;
}
.setting-check {
margin-inline-end: 8px;
flex-shrink: 0;
}
@media (width <= 600px) {
.settings-grid {
grid-template-columns: repeat(2, 1fr);
}
}
</style>

View File

@@ -10,6 +10,7 @@ import api from '@/api'
import { useI18n } from 'vue-i18n'
import { useDisplay } from 'vuetify'
import { useDynamicHeaderTab } from '@/composables/useDynamicHeaderTab'
import { getItemColor, initializeItemColors } from '@/utils/colorUtils'
const display = useDisplay()
@@ -44,6 +45,17 @@ const extraDiscoverSources = ref<DiscoverSource[]>([])
// 排序对话框
const orderConfigDialog = ref(false)
// 为每个项目生成随机颜色
const itemColors = ref<{ [key: string]: string }>({})
// 初始化颜色
function initializeColors() {
initializeItemColors(discoverTabs.value, item => item.mediaid_prefix)
discoverTabs.value.forEach(item => {
itemColors.value[item.mediaid_prefix] = getItemColor(item.mediaid_prefix)
})
}
// 初始化发现标签
function initDiscoverTabs() {
const tabs = getDiscoverTabs()
@@ -70,6 +82,10 @@ async function loadExtraDiscoverSources() {
continue
}
discoverTabs.value.push(source)
// 为新增的数据源生成颜色
if (!itemColors.value[source.mediaid_prefix]) {
itemColors.value[source.mediaid_prefix] = getItemColor(source.mediaid_prefix)
}
}
} catch (error) {
console.log(error)
@@ -145,6 +161,7 @@ registerHeaderTab({
onBeforeMount(async () => {
initDiscoverTabs()
initializeColors()
await loadOrderConfig()
await loadExtraDiscoverSources()
sortSubscribeOrder()
@@ -225,9 +242,14 @@ onActivated(async () => {
:component-data="{ 'class': 'settings-grid' }"
>
<template #item="{ element }">
<VCard variant="text" class="setting-item enabled">
<div class="setting-item-inner cursor-move text-center">
<VCard
variant="text"
class="setting-item enabled"
:style="{ '--item-color': itemColors[element.mediaid_prefix] }"
>
<div class="setting-item-inner">
<span class="setting-label">{{ element.name }}</span>
<VIcon icon="mdi-drag" class="drag-icon cursor-move" />
</div>
</VCard>
</template>
@@ -269,8 +291,11 @@ onActivated(async () => {
}
.setting-label {
flex: 1;
color: rgba(var(--v-theme-on-surface), 0.8);
font-size: 0.9rem;
font-weight: 500;
line-height: 1.2;
transition: color 0.2s ease;
}
@@ -287,8 +312,7 @@ onActivated(async () => {
&::before {
position: absolute;
background-color: transparent;
background-color: rgb(var(--v-theme-primary));
background-color: var(--item-color, #4caf50);
block-size: 100%;
content: '';
inline-size: 4px;
@@ -298,16 +322,15 @@ onActivated(async () => {
}
&:hover {
border-color: rgba(var(--v-theme-on-surface), 0.15);
background-color: rgba(var(--v-theme-surface-variant), 0.6);
transform: translateY(-2px);
}
&.enabled {
border-color: rgba(var(--v-theme-primary), 0.5);
background-color: rgba(var(--v-theme-primary), 0.05);
border-color: rgba(var(--v-theme-primary), 0.3);
background-color: rgba(var(--v-theme-primary), 0.1);
.setting-label {
color: rgb(var(--v-theme-primary));
color: rgba(var(--v-theme-primary), 0.9);
font-weight: 500;
}
}
@@ -316,9 +339,22 @@ onActivated(async () => {
.setting-item-inner {
display: flex;
align-items: center;
gap: 8px;
}
.setting-check {
margin-inline-end: 8px;
flex-shrink: 0;
}
.drag-icon {
flex-shrink: 0;
color: rgba(var(--v-theme-on-surface), 0.5);
cursor: move;
}
@media (width <= 600px) {
.settings-grid {
grid-template-columns: repeat(2, 1fr);
}
}
</style>

View File

@@ -5,6 +5,7 @@ import MediaCardSlideView from '@/views/discover/MediaCardSlideView.vue'
import { useI18n } from 'vue-i18n'
import { useDisplay } from 'vuetify'
import { useDynamicHeaderTab } from '@/composables/useDynamicHeaderTab'
import { getItemColor, initializeItemColors } from '@/utils/colorUtils'
const display = useDisplay()
@@ -114,6 +115,17 @@ const enableConfig = ref<{ [key: string]: boolean }>({
...Object.fromEntries(viewList.map(item => [item.title, true])),
})
// 为每个项目生成随机颜色
const itemColors = ref<{ [key: string]: string }>({})
// 初始化颜色
function initializeColors() {
initializeItemColors(viewList, item => item.title)
viewList.forEach(item => {
itemColors.value[item.title] = getItemColor(item.title)
})
}
// 弹窗
const dialog = ref(false)
@@ -127,8 +139,8 @@ async function loadExtraRecommendSources() {
if (extraRecommendSources.value.length > 0) {
extraRecommendSources.value.map(source => {
if (!viewList.some(item => item.apipath === source.api_path)) {
const querySeparator = source.api_path.includes('?') ? '&' : '?';
const linkUrl = `/browse/${source.api_path}${querySeparator}title=${encodeURIComponent(source.name)}`;
const querySeparator = source.api_path.includes('?') ? '&' : '?'
const linkUrl = `/browse/${source.api_path}${querySeparator}title=${encodeURIComponent(source.name)}`
viewList.push({
apipath: source.api_path,
linkurl: linkUrl,
@@ -221,10 +233,17 @@ registerHeaderTab({
onBeforeMount(async () => {
await loadConfig()
initializeColors()
})
onMounted(async () => {
await loadExtraRecommendSources()
// 为新增的数据源也生成颜色
extraRecommendSources.value.forEach(source => {
if (!itemColors.value[source.name]) {
itemColors.value[source.name] = getItemColor(source.name)
}
})
})
onActivated(async () => {
@@ -275,8 +294,8 @@ onActivated(async () => {
class="setting-item"
:class="{
'enabled': enableConfig[item.title],
[item.type]: true,
}"
:style="{ '--item-color': itemColors[item.title] }"
@click="enableConfig[item.title] = !enableConfig[item.title]"
>
<div class="setting-item-inner">
@@ -394,7 +413,7 @@ onActivated(async () => {
&::before {
position: absolute;
background-color: transparent;
background-color: var(--item-color, #4caf50);
block-size: 100%;
content: '';
inline-size: 4px;
@@ -403,19 +422,6 @@ onActivated(async () => {
transition: background-color 0.3s ease;
}
&.电影::before {
background-color: #4caf50;
} // Green
&.电视剧::before {
background-color: #2196f3;
} // Blue
&.动漫::before {
background-color: #ff9800;
} // Orange
&.排行榜::before {
background-color: #9c27b0;
} // Purple
&.enabled {
border-color: rgba(var(--v-theme-primary), 0.3);
background-color: rgba(var(--v-theme-primary), 0.1);
@@ -452,7 +458,7 @@ onActivated(async () => {
@media (width <= 600px) {
.settings-grid {
grid-template-columns: 1fr;
grid-template-columns: repeat(2, 1fr);
}
}
</style>