🎨 Optimize preset theme code

This commit is contained in:
2025-10-20 21:58:37 +08:00
parent 9a15df01ee
commit aa8139884b
26 changed files with 245 additions and 465 deletions

View File

@@ -1,7 +1,6 @@
import { Extension, Compartment } from '@codemirror/state';
import { EditorView } from '@codemirror/view';
import { SystemThemeType } from '@/../bindings/voidraft/internal/models/models';
import { createThemeByColors } from '@/views/editor/theme/registry';
import { createThemeByColors } from '@/views/editor/theme';
import { useThemeStore } from '@/stores/themeStore';
// 主题区间 - 用于动态切换主题
@@ -10,20 +9,13 @@ export const themeCompartment = new Compartment();
/**
* 根据主题类型获取主题扩展
*/
const getThemeExtension = (themeType: SystemThemeType): Extension | null => {
const getThemeExtension = (): Extension | null => {
const themeStore = useThemeStore();
// 处理 auto 主题类型
let isDark = themeType === SystemThemeType.SystemThemeDark;
if (themeType === SystemThemeType.SystemThemeAuto) {
isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
}
// 根据主题类型获取对应的颜色配置
const colors = isDark ? themeStore.currentColors.dark : themeStore.currentColors.light;
// 直接获取当前主题颜色配置
const colors = themeStore.currentColors;
if (!colors) {
console.warn('Theme colors not loaded yet');
return null;
}
@@ -34,8 +26,8 @@ const getThemeExtension = (themeType: SystemThemeType): Extension | null => {
/**
* 创建主题扩展(用于编辑器初始化)
*/
export const createThemeExtension = (themeType: SystemThemeType = SystemThemeType.SystemThemeDark): Extension => {
const extension = getThemeExtension(themeType);
export const createThemeExtension = (): Extension => {
const extension = getThemeExtension();
// 如果主题未加载,返回空扩展
if (!extension) {
@@ -48,17 +40,16 @@ export const createThemeExtension = (themeType: SystemThemeType = SystemThemeTyp
/**
* 更新编辑器主题
*/
export const updateEditorTheme = (view: EditorView, themeType: SystemThemeType): void => {
export const updateEditorTheme = (view: EditorView): void => {
if (!view?.dispatch) {
return;
}
try {
const extension = getThemeExtension(themeType);
const extension = getThemeExtension();
// 如果主题未加载,不更新
if (!extension) {
console.warn('Cannot update theme: theme not loaded');
return;
}

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#21202e',
backgroundSecondary: '#21202e',
backgroundSecondary: '#2B2A3BFF',
surface: '#21202e',
dropdownBackground: '#21202e',
dropdownBorder: '#3b334b',

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#282A36',
backgroundSecondary: '#282A36',
backgroundSecondary: '#323543FF',
surface: '#282A36',
dropdownBackground: '#282A36',
dropdownBorder: '#191A21',

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#24292e',
backgroundSecondary: '#24292e',
backgroundSecondary: '#2E343BFF',
surface: '#24292e',
dropdownBackground: '#24292e',
dropdownBorder: '#1b1f23',

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#263238',
backgroundSecondary: '#263238',
backgroundSecondary: '#2D3E46FF',
surface: '#263238',
dropdownBackground: '#263238',
dropdownBorder: '#FFFFFF10',

View File

@@ -15,7 +15,7 @@ const chalky = "#e5c07b",
whiskey = "#d19a66",
violet = "#c678dd",
darkBackground = "#21252b",
highlightBackground = "#2c313a",
highlightBackground = "#313949FF",
background = "#282c34",
tooltipBackground = "#353a42",
selection = "#3E4451",

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#002B36',
backgroundSecondary: '#002B36',
backgroundSecondary: '#003643FF',
surface: '#002B36',
dropdownBackground: '#002B36',
dropdownBorder: '#2AA19899',

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#24283b',
backgroundSecondary: '#24283b',
backgroundSecondary: '#2B3151FF',
surface: '#24283b',
dropdownBackground: '#24283b',
dropdownBorder: '#7982a9',

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#1a1b26',
backgroundSecondary: '#1a1b26',
backgroundSecondary: '#272839FF',
surface: '#1a1b26',
dropdownBackground: '#1a1b26',
dropdownBorder: '#787c99',

View File

@@ -0,0 +1,12 @@
import { Extension } from '@codemirror/state';
import type { ThemeColors } from './types';
import { createBaseTheme } from './base';
/**
* 根据自定义颜色配置创建主题
*/
export function createThemeByColors(colors: ThemeColors): Extension {
return createBaseTheme(colors);
}

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#fff',
backgroundSecondary: '#fff',
backgroundSecondary: '#f1faf1',
surface: '#fff',
dropdownBackground: '#fff',
dropdownBorder: '#e1e4e8',

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#FAFAFA',
backgroundSecondary: '#FAFAFA',
backgroundSecondary: '#f1faf1',
surface: '#FAFAFA',
dropdownBackground: '#FAFAFA',
dropdownBorder: '#00000010',

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#FDF6E3',
backgroundSecondary: '#FDF6E3',
backgroundSecondary: '#FFEEBCD4',
surface: '#FDF6E3',
dropdownBackground: '#FDF6E3',
dropdownBorder: '#D3AF86',

View File

@@ -8,7 +8,7 @@ export const config: ThemeColors = {
// 基础色调
background: '#e1e2e7',
backgroundSecondary: '#e1e2e7',
backgroundSecondary: '#D2D8EFFF',
surface: '#e1e2e7',
dropdownBackground: '#e1e2e7',
dropdownBorder: '#6a6f8e',

View File

@@ -1,59 +0,0 @@
import { Extension } from '@codemirror/state';
import type { ThemeColors } from './types';
import { createBaseTheme } from './base';
// 深色主题导入
import { config as draculaConfig } from './dark/dracula';
import { config as auraConfig } from './dark/aura';
import { config as githubDarkConfig } from './dark/github-dark';
import { config as materialDarkConfig } from './dark/material-dark';
import { config as oneDarkConfig } from './dark/one-dark';
import { config as solarizedDarkConfig } from './dark/solarized-dark';
import { config as tokyoNightConfig } from './dark/tokyo-night';
import { config as tokyoNightStormConfig } from './dark/tokyo-night-storm';
// 浅色主题导入
import { config as githubLightConfig } from './light/github-light';
import { config as materialLightConfig } from './light/material-light';
import { config as solarizedLightConfig } from './light/solarized-light';
import { config as tokyoNightDayConfig } from './light/tokyo-night-day';
/**
* 主题配置映射表
* key: 主题名称(与数据库中的 name 字段一致)
* value: 主题颜色配置
*/
const themeConfigMap: Record<string, ThemeColors> = {
// 深色主题
'dracula': draculaConfig,
'aura': auraConfig,
'github-dark': githubDarkConfig,
'material-dark': materialDarkConfig,
'one-dark': oneDarkConfig,
'solarized-dark': solarizedDarkConfig,
'tokyo-night': tokyoNightConfig,
'tokyo-night-storm': tokyoNightStormConfig,
// 浅色主题
'github-light': githubLightConfig,
'material-light': materialLightConfig,
'solarized-light': solarizedLightConfig,
'tokyo-night-day': tokyoNightDayConfig,
};
/**
* 根据主题名称获取主题配置
*/
export function getThemeConfig(themeName: string): ThemeColors | null {
return themeConfigMap[themeName] || null;
}
/**
* 根据自定义颜色配置创建主题
*/
export function createThemeByColors(colors: ThemeColors): Extension {
return createBaseTheme(colors);
}

View File

@@ -1,13 +1,15 @@
<script setup lang="ts">
defineProps<{
title: string;
title?: string;
}>();
</script>
<template>
<div class="setting-section">
<div class="section-header">
<h2 class="section-title">{{ title }}</h2>
<h2 class="section-title">
<slot name="title">{{ title }}</slot>
</h2>
<div class="section-title-right">
<slot name="title-right"></slot>
</div>

View File

@@ -23,8 +23,7 @@ const { debouncedFn: debouncedUpdateColor } = createDebounce(
const { debouncedFn: debouncedResetTheme } = createDebounce(
async () => {
const isDark = isDarkMode.value;
const success = await themeStore.resetCurrentTheme(isDark);
const success = await themeStore.resetCurrentTheme();
if (success) {
// 重新加载临时颜色
@@ -49,23 +48,11 @@ const resetButtonState = ref({
confirming: false
});
// 当前激活的主题类型(深色/浅色)
const isDarkMode = computed(() =>
themeStore.currentTheme === SystemThemeType.SystemThemeDark ||
(themeStore.currentTheme === SystemThemeType.SystemThemeAuto &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
);
// 当前可用的预设主题列表
const availableThemes = computed(() =>
isDarkMode.value ? themeStore.darkThemes : themeStore.lightThemes
);
// 当前选中的主题ID
const currentThemeId = computed({
get: () => isDarkMode.value ? themeStore.currentThemeIds.dark : themeStore.currentThemeIds.light,
set: async (themeId: number) => {
await themeStore.switchToTheme(themeId);
// 当前选中的主题名称
const currentThemeName = computed({
get: () => themeStore.currentColors?.name || '',
set: async (themeName: string) => {
await themeStore.switchToTheme(themeName);
syncTempColors();
hasUnsavedChanges.value = false;
}
@@ -74,20 +61,19 @@ const currentThemeId = computed({
// 当前主题的颜色配置
const currentColors = computed(() => tempColors.value || ({} as ThemeColors));
// 获取当前主题模式(用于颜色选择器)
const currentThemeMode = computed(() => isDarkMode.value ? 'dark' : 'light');
// 获取当前主题模式
const currentThemeMode = computed(() => themeStore.isDarkMode ? 'dark' : 'light');
// 同步临时颜色从 store
const syncTempColors = () => {
const colors = isDarkMode.value ? themeStore.currentColors.dark : themeStore.currentColors.light;
if (colors) {
tempColors.value = { ...colors };
if (themeStore.currentColors) {
tempColors.value = { ...themeStore.currentColors };
}
};
// 监听主题切换,同步临时颜色
watch(
[() => themeStore.currentColors.dark, () => themeStore.currentColors.light, isDarkMode],
() => themeStore.currentColors,
() => {
if (!hasUnsavedChanges.value) {
syncTempColors();
@@ -153,13 +139,11 @@ const applyChanges = async () => {
try {
if (!tempColors.value) return;
const isDark = isDarkMode.value;
// 更新 store 中的颜色
themeStore.updateCurrentColors(tempColors.value, isDark);
themeStore.updateCurrentColors(tempColors.value);
// 保存到数据库
await themeStore.saveCurrentTheme(isDark);
await themeStore.saveCurrentTheme();
// 刷新编辑器主题
themeStore.refreshEditorTheme();
@@ -207,6 +191,17 @@ const updateSystemTheme = async (event: Event) => {
const selectedSystemTheme = select.value as SystemThemeType;
await themeStore.setTheme(selectedSystemTheme);
const availableThemes = themeStore.availableThemes;
const currentThemeName = currentColors.value?.name;
const isCurrentThemeAvailable = availableThemes.some(t => t.name === currentThemeName);
if (!isCurrentThemeAvailable && availableThemes.length > 0) {
const firstTheme = availableThemes[0];
await themeStore.switchToTheme(firstTheme.name);
syncTempColors();
hasUnsavedChanges.value = false;
}
};
// 控制颜色选择器显示状态
@@ -246,8 +241,8 @@ const handlePickerClose = () => {
<!-- 预设主题选择 -->
<SettingItem :title="t('settings.presetTheme')">
<select class="select-input" v-model="currentThemeId" :disabled="hasUnsavedChanges">
<option v-for="theme in availableThemes" :key="theme.id" :value="theme.id">
<select class="select-input" v-model="currentThemeName" :disabled="hasUnsavedChanges">
<option v-for="theme in themeStore.availableThemes" :key="theme.id" :value="theme.name">
{{ theme.name }}
</option>
</select>
@@ -256,6 +251,12 @@ const handlePickerClose = () => {
<!-- 自定义主题颜色配置 -->
<SettingSection :title="t('settings.customThemeColors')">
<template #title>
<div class="theme-section-title">
<span class="section-title-text">{{ t('settings.customThemeColors') }}</span>
<span v-if="currentColors.name" class="current-theme-name">{{ currentColors.name }}</span>
</div>
</template>
<template #title-right>
<div class="theme-controls">
<button
@@ -348,6 +349,27 @@ const handlePickerClose = () => {
}
}
// 主题部分标题
.theme-section-title {
display: flex;
align-items: center;
gap: 12px;
}
.section-title-text {
font-weight: 500;
}
.current-theme-name {
font-size: 13px;
color: var(--settings-text-secondary);
font-weight: normal;
padding: 2px 8px;
background-color: var(--settings-input-bg);
border: 1px solid var(--settings-input-border);
border-radius: 4px;
}
// 主题控制区域
.theme-controls {
display: flex;