209 lines
5.7 KiB
TypeScript
209 lines
5.7 KiB
TypeScript
/**
|
||
* 设置状态管理器
|
||
* @author 阿瑞
|
||
* @description 应用全局设置的状态管理,包括主题、布局等配置的存储和管理
|
||
* @version 1.1.0
|
||
* @date 2024
|
||
* @updated 修复SSR初始化问题
|
||
*/
|
||
|
||
import { create } from 'zustand';
|
||
import { StorageEnum, ThemeColorPresets, ThemeLayout, ThemeMode } from '@/types/enum';
|
||
|
||
// ==================== 本地存储工具函数 ====================
|
||
|
||
/**
|
||
* 从 localStorage 中获取指定键的值
|
||
* @template T - 返回值的类型
|
||
* @param key - 存储键名,使用 StorageEnum 枚举值
|
||
* @returns 解析后的值或 null
|
||
*/
|
||
export const getItem = <T>(key: StorageEnum): T | null => {
|
||
let value = null;
|
||
try {
|
||
// 关键代码行注释:检查是否在客户端环境(SSR兼容性处理)
|
||
if (typeof window !== 'undefined') {
|
||
// 尝试从 localStorage 获取数据
|
||
const result = window.localStorage.getItem(key);
|
||
if (result) {
|
||
// 解析 JSON 字符串为对象
|
||
value = JSON.parse(result);
|
||
}
|
||
}
|
||
} catch (error) {
|
||
// 捕获解析错误,避免程序崩溃
|
||
console.error('localStorage 读取失败:', error);
|
||
}
|
||
return value;
|
||
};
|
||
|
||
// ==================== 类型定义 ====================
|
||
|
||
/**
|
||
* 应用设置类型定义
|
||
* @interface SettingsType
|
||
*/
|
||
type SettingsType = {
|
||
/** 主题色彩预设 */
|
||
themeColorPresets: ThemeColorPresets;
|
||
/** 主题模式(明亮/暗黑) */
|
||
themeMode: ThemeMode;
|
||
/** 主题布局类型 */
|
||
themeLayout: ThemeLayout;
|
||
/** 是否拉伸布局 */
|
||
themeStretch: boolean;
|
||
/** 是否显示面包屑导航 */
|
||
breadCrumb: boolean;
|
||
/** 是否启用多标签页 */
|
||
multiTab: boolean;
|
||
};
|
||
|
||
/**
|
||
* 设置状态管理器类型定义
|
||
* @interface SettingStore
|
||
*/
|
||
type SettingStore = {
|
||
/** 当前设置状态 */
|
||
settings: SettingsType;
|
||
/** 操作方法集合,使用 actions 命名空间避免状态污染 */
|
||
actions: {
|
||
/** 更新设置并同步到本地存储 */
|
||
setSettings: (settings: SettingsType) => void;
|
||
/** 清除本地存储的设置 */
|
||
clearSettings: () => void;
|
||
/** 切换主题模式 */
|
||
toggleThemeMode: () => void;
|
||
};
|
||
};
|
||
|
||
// ==================== 本地存储操作函数 ====================
|
||
|
||
/**
|
||
* 将数据存储到 localStorage
|
||
* @template T - 存储值的类型
|
||
* @param key - 存储键名
|
||
* @param value - 要存储的值
|
||
*/
|
||
export const setItem = <T>(key: StorageEnum, value: T): void => {
|
||
// 关键代码行注释:检查客户端环境再进行localStorage操作
|
||
if (typeof window !== 'undefined') {
|
||
// 将对象序列化为 JSON 字符串存储
|
||
localStorage.setItem(key, JSON.stringify(value));
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 从 localStorage 中移除指定键的数据
|
||
* @param key - 要移除的键名
|
||
*/
|
||
export const removeItem = (key: StorageEnum): void => {
|
||
// 关键代码行注释:SSR兼容性检查
|
||
if (typeof window !== 'undefined') {
|
||
localStorage.removeItem(key);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 清空所有 localStorage 数据
|
||
*/
|
||
export const clearItems = () => {
|
||
// 关键代码行注释:SSR兼容性检查
|
||
if (typeof window !== 'undefined') {
|
||
localStorage.clear();
|
||
}
|
||
};
|
||
|
||
// ==================== 默认设置配置 ====================
|
||
|
||
/**
|
||
* 默认设置配置
|
||
* 确保服务端和客户端初始化时使用相同的默认值
|
||
*/
|
||
const DEFAULT_SETTINGS: SettingsType = {
|
||
themeColorPresets: ThemeColorPresets.Default,
|
||
themeMode: ThemeMode.Light, // 关键代码行注释:SSR时默认使用明亮模式
|
||
themeLayout: ThemeLayout.Vertical,
|
||
themeStretch: true,
|
||
breadCrumb: true,
|
||
multiTab: true,
|
||
};
|
||
|
||
// ==================== Zustand 状态管理器 ====================
|
||
|
||
/**
|
||
* 设置状态管理器
|
||
* 使用 zustand 创建全局设置状态,包含默认配置和操作方法
|
||
*/
|
||
const useSettingStore = create<SettingStore>((set) => ({
|
||
// 关键代码行注释:初始化设置,服务端渲染时使用默认值,客户端使用localStorage或默认值
|
||
settings: typeof window !== 'undefined'
|
||
? getItem<SettingsType>(StorageEnum.Settings) || DEFAULT_SETTINGS
|
||
: DEFAULT_SETTINGS,
|
||
|
||
// 操作方法集合
|
||
actions: {
|
||
/**
|
||
* 设置新的配置并同步到本地存储
|
||
* @param settings - 新的设置配置
|
||
*/
|
||
setSettings: (settings) => {
|
||
// 更新状态
|
||
set({ settings });
|
||
// 同步保存到本地存储
|
||
setItem(StorageEnum.Settings, settings);
|
||
},
|
||
|
||
/**
|
||
* 清除本地存储的设置数据
|
||
* 注意:这里只清除本地存储,不重置当前状态
|
||
*/
|
||
clearSettings() {
|
||
removeItem(StorageEnum.Settings);
|
||
},
|
||
|
||
/**
|
||
* 切换主题模式
|
||
*/
|
||
toggleThemeMode() {
|
||
set((state) => {
|
||
// 切换主题模式:明亮 ↔ 暗黑
|
||
const newThemeMode = state.settings.themeMode === ThemeMode.Light
|
||
? ThemeMode.Dark
|
||
: ThemeMode.Light;
|
||
|
||
// 创建新的设置对象
|
||
const newSettings = {
|
||
...state.settings,
|
||
themeMode: newThemeMode,
|
||
};
|
||
|
||
// 同步保存到本地存储
|
||
setItem(StorageEnum.Settings, newSettings);
|
||
|
||
// 返回新状态
|
||
return { settings: newSettings };
|
||
});
|
||
},
|
||
},
|
||
}));
|
||
|
||
// ==================== 导出的 Hook 函数 ====================
|
||
|
||
/**
|
||
* 获取当前设置状态的 Hook
|
||
* @returns 当前的设置配置对象
|
||
*/
|
||
export const useSettings = () => useSettingStore((state) => state.settings);
|
||
|
||
/**
|
||
* 获取设置操作方法的 Hook
|
||
* @returns 设置操作方法对象(setSettings, clearSettings, toggleThemeMode)
|
||
*/
|
||
export const useSettingActions = () => useSettingStore((state) => state.actions);
|
||
|
||
/**
|
||
* 获取当前主题模式的 Hook
|
||
* @returns 当前的主题模式(ThemeMode.Light 或 ThemeMode.Dark)
|
||
*/
|
||
export const useThemeMode = () => useSettingStore((state) => state.settings.themeMode);
|