feat: 重构颜色配置服务,更新存储键管理逻辑,增强主题兼容性,优化配置加载和保存流程

This commit is contained in:
xudan 2025-09-10 17:57:43 +08:00
parent 874c3fade3
commit c31f9d5bef

View File

@ -508,10 +508,13 @@ const DARK_THEME_COLORS: EditorColorConfig = {
class ColorConfigService {
private config = ref<EditorColorConfig>({ ...DEFAULT_COLORS });
private editorService: any = null;
private readonly STORAGE_KEY = 'editor-color-config';
private readonly STORAGE_KEY_PREFIX = 'editor-color-config';
private isResetting = false; // 标记是否正在重置
constructor() {
// 清理旧的存储键
this.cleanupOldStorageKeys();
// 从本地存储加载配置
this.loadFromLocalStorage();
@ -519,7 +522,7 @@ class ColorConfigService {
watch(
() => sTheme.theme,
() => {
this.loadConfig();
this.loadFromLocalStorage();
}
);
@ -558,6 +561,25 @@ class ColorConfigService {
return sTheme.theme === 'dark';
}
/**
*
*/
private getCurrentStorageKey(): string {
const theme = sTheme.theme === 'dark' ? 'dark' : 'light';
return `${this.STORAGE_KEY_PREFIX}-${theme}`;
}
/**
*
*/
private cleanupOldStorageKeys(): void {
const oldKey = 'editor-color-config';
if (localStorage.getItem(oldKey)) {
localStorage.removeItem(oldKey);
console.log('已清理旧的颜色配置存储键');
}
}
/**
*
*/
@ -593,17 +615,17 @@ class ColorConfigService {
}
try {
const stored = localStorage.getItem(this.STORAGE_KEY);
const storageKey = this.getCurrentStorageKey();
const stored = localStorage.getItem(storageKey);
// 根据当前主题选择基础配置
const isDarkTheme = sTheme.theme === 'dark';
const baseConfig = isDarkTheme ? DARK_THEME_COLORS : DEFAULT_COLORS;
if (stored) {
const parsedConfig = JSON.parse(stored);
// 根据当前主题选择基础配置
const isDarkTheme = sTheme.theme === 'dark';
const baseConfig = isDarkTheme ? DARK_THEME_COLORS : DEFAULT_COLORS;
this.config.value = this.mergeConfig(baseConfig, parsedConfig);
} else {
// 根据当前主题选择基础配置
const isDarkTheme = sTheme.theme === 'dark';
const baseConfig = isDarkTheme ? DARK_THEME_COLORS : DEFAULT_COLORS;
this.config.value = { ...baseConfig };
}
} catch (error) {
@ -620,7 +642,8 @@ class ColorConfigService {
*/
private saveToLocalStorage(config: EditorColorConfig): void {
try {
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(config));
const storageKey = this.getCurrentStorageKey();
localStorage.setItem(storageKey, JSON.stringify(config));
} catch (error) {
console.warn('Failed to save color config to localStorage:', error);
}
@ -664,8 +687,9 @@ class ColorConfigService {
// 设置重置标记,防止自动保存
this.isResetting = true;
// 清除本地存储
localStorage.removeItem(this.STORAGE_KEY);
// 清除当前主题的本地存储
const storageKey = this.getCurrentStorageKey();
localStorage.removeItem(storageKey);
// 根据当前主题选择基础配置
const isDarkTheme = sTheme.theme === 'dark';
@ -813,52 +837,52 @@ class ColorConfigService {
const baseConfig = isDarkTheme ? DARK_THEME_COLORS : DEFAULT_COLORS;
// 使用简化的主题配置映射
const themeConfig = this.buildThemeConfig(theme);
const themeConfig = this.buildThemeConfig(theme, baseConfig);
this.config.value = this.mergeConfig(baseConfig, themeConfig);
}
/**
*
*/
private buildThemeConfig(theme: any): Partial<EditorColorConfig> {
private buildThemeConfig(theme: any, baseConfig: EditorColorConfig): Partial<EditorColorConfig> {
const config: Partial<EditorColorConfig> = {};
// 点位配置
if (theme['point-s'] || theme['point-l']) {
config.point = {
small: {
stroke: theme['point-s']?.stroke || DEFAULT_COLORS.point.small.stroke,
strokeActive: theme['point-s']?.strokeActive || DEFAULT_COLORS.point.small.strokeActive,
fill: this.buildFillConfig(theme['point-s'], 'fill', DEFAULT_COLORS.point.small.fill)
stroke: theme['point-s']?.stroke || baseConfig.point.small.stroke,
strokeActive: theme['point-s']?.strokeActive || baseConfig.point.small.strokeActive,
fill: this.buildFillConfig(theme['point-s'], 'fill', baseConfig.point.small.fill)
},
large: {
stroke: theme['point-l']?.stroke || DEFAULT_COLORS.point.large.stroke,
strokeActive: theme['point-l']?.strokeActive || DEFAULT_COLORS.point.large.strokeActive,
strokeOccupied: theme['point-l']?.['stroke-occupied'] || DEFAULT_COLORS.point.large.strokeOccupied,
strokeUnoccupied: theme['point-l']?.['stroke-unoccupied'] || DEFAULT_COLORS.point.large.strokeUnoccupied,
strokeEmpty: theme['point-l']?.['stroke-empty'] || DEFAULT_COLORS.point.large.strokeEmpty,
strokeDisabled: theme['point-l']?.['stroke-disabled'] || DEFAULT_COLORS.point.large.strokeDisabled,
strokeEnabled: theme['point-l']?.['stroke-enabled'] || DEFAULT_COLORS.point.large.strokeEnabled,
strokeLocked: theme['point-l']?.['stroke-locked'] || DEFAULT_COLORS.point.large.strokeLocked,
strokeUnlocked: theme['point-l']?.['stroke-unlocked'] || DEFAULT_COLORS.point.large.strokeUnlocked,
stroke: theme['point-l']?.stroke || baseConfig.point.large.stroke,
strokeActive: theme['point-l']?.strokeActive || baseConfig.point.large.strokeActive,
strokeOccupied: theme['point-l']?.['stroke-occupied'] || baseConfig.point.large.strokeOccupied,
strokeUnoccupied: theme['point-l']?.['stroke-unoccupied'] || baseConfig.point.large.strokeUnoccupied,
strokeEmpty: theme['point-l']?.['stroke-empty'] || baseConfig.point.large.strokeEmpty,
strokeDisabled: theme['point-l']?.['stroke-disabled'] || baseConfig.point.large.strokeDisabled,
strokeEnabled: theme['point-l']?.['stroke-enabled'] || baseConfig.point.large.strokeEnabled,
strokeLocked: theme['point-l']?.['stroke-locked'] || baseConfig.point.large.strokeLocked,
strokeUnlocked: theme['point-l']?.['stroke-unlocked'] || baseConfig.point.large.strokeUnlocked,
},
types: this.buildPointTypesConfig(theme)
types: this.buildPointTypesConfig(theme, baseConfig)
};
}
// 路线配置
if (theme.route) {
config.route = {
strokeActive: theme.route.strokeActive || DEFAULT_COLORS.route.strokeActive,
strokeNone: theme.route['stroke-0'] || DEFAULT_COLORS.route.strokeNone,
strokeEmpty: theme.route['stroke-1'] || theme.route['stroke-empty'] || DEFAULT_COLORS.route.strokeEmpty,
strokeLoaded: theme.route['stroke-2'] || theme.route['stroke-loaded'] || DEFAULT_COLORS.route.strokeLoaded,
strokeActive: theme.route.strokeActive || baseConfig.route.strokeActive,
strokeNone: theme.route['stroke-0'] || baseConfig.route.strokeNone,
strokeEmpty: theme.route['stroke-1'] || theme.route['stroke-empty'] || baseConfig.route.strokeEmpty,
strokeLoaded: theme.route['stroke-2'] || theme.route['stroke-loaded'] || baseConfig.route.strokeLoaded,
strokeForbidden: theme.route['stroke-10'] ||
theme.route['stroke-forbidden'] ||
DEFAULT_COLORS.route.strokeForbidden,
baseConfig.route.strokeForbidden,
width: {
normal: theme.route.width?.normal || DEFAULT_COLORS.route.width.normal,
active: theme.route.width?.active || DEFAULT_COLORS.route.width.active
normal: theme.route.width?.normal || baseConfig.route.width.normal,
active: theme.route.width?.active || baseConfig.route.width.active
}
};
}
@ -866,56 +890,56 @@ class ColorConfigService {
// 区域配置
if (theme.area) {
config.area = {
strokeActive: theme.area.strokeActive || DEFAULT_COLORS.area.strokeActive,
stroke: this.buildFillConfig(theme.area, 'stroke', DEFAULT_COLORS.area.stroke),
fill: this.buildFillConfig(theme.area, 'fill', DEFAULT_COLORS.area.fill),
strokeActive: theme.area.strokeActive || baseConfig.area.strokeActive,
stroke: this.buildFillConfig(theme.area, 'stroke', baseConfig.area.stroke),
fill: this.buildFillConfig(theme.area, 'fill', baseConfig.area.fill),
border: {
width: theme.area.border?.width || DEFAULT_COLORS.area.border.width,
opacity: theme.area.border?.opacity || DEFAULT_COLORS.area.border.opacity,
colors: this.buildFillConfig(theme.area.border, 'color', DEFAULT_COLORS.area.border.colors)
width: theme.area.border?.width || baseConfig.area.border.width,
opacity: theme.area.border?.opacity || baseConfig.area.border.opacity,
colors: this.buildFillConfig(theme.area.border, 'color', baseConfig.area.border.colors)
},
types: this.buildAreaTypesConfig(theme.area)
types: this.buildAreaTypesConfig(theme.area, baseConfig)
};
}
// 机器人配置
if (theme.robot) {
config.robot = {
stroke: theme.robot.stroke || DEFAULT_COLORS.robot.stroke,
fill: theme.robot.fill || DEFAULT_COLORS.robot.fill,
line: theme.robot.line || DEFAULT_COLORS.robot.line,
strokeNormal: theme.robot['stroke-normal'] || DEFAULT_COLORS.robot.strokeNormal,
fillNormal: theme.robot['fill-normal'] || DEFAULT_COLORS.robot.fillNormal,
strokeWarning: theme.robot['stroke-warning'] || DEFAULT_COLORS.robot.strokeWarning,
fillWarning: theme.robot['fill-warning'] || DEFAULT_COLORS.robot.fillWarning,
strokeFault: theme.robot['stroke-fault'] || DEFAULT_COLORS.robot.strokeFault,
fillFault: theme.robot['fill-fault'] || DEFAULT_COLORS.robot.fillFault,
imageWidth: theme.robot.imageWidth || DEFAULT_COLORS.robot.imageWidth,
imageHeight: theme.robot.imageHeight || DEFAULT_COLORS.robot.imageHeight,
customImages: theme.robot.customImages || DEFAULT_COLORS.robot.customImages,
stroke: theme.robot.stroke || baseConfig.robot.stroke,
fill: theme.robot.fill || baseConfig.robot.fill,
line: theme.robot.line || baseConfig.robot.line,
strokeNormal: theme.robot['stroke-normal'] || baseConfig.robot.strokeNormal,
fillNormal: theme.robot['fill-normal'] || baseConfig.robot.fillNormal,
strokeWarning: theme.robot['stroke-warning'] || baseConfig.robot.strokeWarning,
fillWarning: theme.robot['fill-warning'] || baseConfig.robot.fillWarning,
strokeFault: theme.robot['stroke-fault'] || baseConfig.robot.strokeFault,
fillFault: theme.robot['fill-fault'] || baseConfig.robot.fillFault,
imageWidth: theme.robot.imageWidth || baseConfig.robot.imageWidth,
imageHeight: theme.robot.imageHeight || baseConfig.robot.imageHeight,
customImages: theme.robot.customImages || baseConfig.robot.customImages,
useCustomImages: theme.robot.useCustomImages !== undefined ?
(typeof theme.robot.useCustomImages === 'string' ?
theme.robot.useCustomImages === 'true' :
theme.robot.useCustomImages) :
DEFAULT_COLORS.robot.useCustomImages
baseConfig.robot.useCustomImages
};
}
// 自动门配置
if (theme.autoDoor) {
config.autoDoor = {
strokeClosed: theme.autoDoor['stroke-closed'] || DEFAULT_COLORS.autoDoor.strokeClosed,
fillClosed: theme.autoDoor['fill-closed'] || DEFAULT_COLORS.autoDoor.fillClosed,
strokeOpen: theme.autoDoor['stroke-open'] || DEFAULT_COLORS.autoDoor.strokeOpen,
fillOpen: theme.autoDoor['fill-open'] || DEFAULT_COLORS.autoDoor.fillOpen,
strokeClosed: theme.autoDoor['stroke-closed'] || baseConfig.autoDoor.strokeClosed,
fillClosed: theme.autoDoor['fill-closed'] || baseConfig.autoDoor.fillClosed,
strokeOpen: theme.autoDoor['stroke-open'] || baseConfig.autoDoor.strokeOpen,
fillOpen: theme.autoDoor['fill-open'] || baseConfig.autoDoor.fillOpen,
};
}
// 通用配置
if (theme.color || theme.background) {
config.common = {
color: theme.color || DEFAULT_COLORS.common.color,
background: theme.background || DEFAULT_COLORS.common.background,
color: theme.color || baseConfig.common.color,
background: theme.background || baseConfig.common.background,
};
}
@ -939,7 +963,7 @@ class ColorConfigService {
/**
*
*/
private buildPointTypesConfig(theme: any): Record<number, any> {
private buildPointTypesConfig(theme: any, baseConfig: EditorColorConfig): Record<number, any> {
const types: Record<number, any> = {};
POINT_TYPES.forEach(type => {
@ -947,19 +971,19 @@ class ColorConfigService {
types[type] = {
stroke: theme['point-s']?.stroke ||
DEFAULT_COLORS.point.types[type]?.stroke ||
DEFAULT_COLORS.point.small.stroke,
baseConfig.point.types[type]?.stroke ||
baseConfig.point.small.stroke,
strokeActive: theme['point-s']?.strokeActive ||
DEFAULT_COLORS.point.types[type]?.strokeActive ||
DEFAULT_COLORS.point.small.strokeActive
baseConfig.point.types[type]?.strokeActive ||
baseConfig.point.small.strokeActive
};
// 只有小点位才设置填充颜色
if (isSmallPoint) {
types[type].fill = theme['point-s']?.[`fill-${type}`] ||
DEFAULT_COLORS.point.types[type]?.fill ||
DEFAULT_COLORS.point.small.fill[type] ||
DEFAULT_COLORS.point.small.fill[1];
baseConfig.point.types[type]?.fill ||
baseConfig.point.small.fill[type] ||
baseConfig.point.small.fill[1];
}
});
@ -969,17 +993,17 @@ class ColorConfigService {
/**
*
*/
private buildAreaTypesConfig(theme: any): Record<number, any> {
private buildAreaTypesConfig(theme: any, baseConfig: EditorColorConfig): Record<number, any> {
const types: Record<number, any> = {};
AREA_TYPES.forEach(type => {
types[type] = {
stroke: theme[`stroke-${type}`] || DEFAULT_COLORS.area.types[type].stroke,
strokeActive: theme.strokeActive || DEFAULT_COLORS.area.types[type].strokeActive,
fill: theme[`fill-${type}`] || DEFAULT_COLORS.area.types[type].fill,
borderColor: theme.border?.[`color-${type}`] || DEFAULT_COLORS.area.types[type].borderColor,
borderWidth: theme.border?.width || DEFAULT_COLORS.area.types[type].borderWidth,
borderOpacity: theme.border?.opacity || DEFAULT_COLORS.area.types[type].borderOpacity,
stroke: theme[`stroke-${type}`] || baseConfig.area.types[type].stroke,
strokeActive: theme.strokeActive || baseConfig.area.types[type].strokeActive,
fill: theme[`fill-${type}`] || baseConfig.area.types[type].fill,
borderColor: theme.border?.[`color-${type}`] || baseConfig.area.types[type].borderColor,
borderWidth: theme.border?.width || baseConfig.area.types[type].borderWidth,
borderOpacity: theme.border?.opacity || baseConfig.area.types[type].borderOpacity,
};
});