物业代码生成

This commit is contained in:
2025-06-18 11:03:42 +08:00
commit 1262d4c745
1881 changed files with 249599 additions and 0 deletions

View File

@@ -0,0 +1,138 @@
import type { Preferences } from './types';
const defaultPreferences: Preferences = {
app: {
accessMode: 'frontend',
authPageLayout: 'panel-right',
checkUpdatesInterval: 1,
colorGrayMode: false,
colorWeakMode: false,
compact: false,
contentCompact: 'wide',
contentCompactWidth: 1200,
contentPadding: 0,
contentPaddingBottom: 0,
contentPaddingLeft: 0,
contentPaddingRight: 0,
contentPaddingTop: 0,
defaultAvatar:
'https://unpkg.com/@vbenjs/static-source@0.1.7/source/avatar-v1.webp',
defaultHomePath: '/analytics',
dynamicTitle: true,
enableCheckUpdates: true,
enablePreferences: true,
enableRefreshToken: false,
isMobile: false,
layout: 'sidebar-nav',
locale: 'zh-CN',
loginExpiredMode: 'page',
name: 'Vben Admin',
preferencesButtonPosition: 'auto',
watermark: false,
zIndex: 200,
},
breadcrumb: {
enable: true,
hideOnlyOne: false,
showHome: false,
showIcon: true,
styleType: 'normal',
},
copyright: {
companyName: 'Vben',
companySiteLink: 'https://www.vben.pro',
date: '2024',
enable: true,
icp: '',
icpLink: '',
settingShow: true,
},
footer: {
enable: false,
fixed: false,
height: 32,
},
header: {
enable: true,
height: 50,
hidden: false,
menuAlign: 'start',
mode: 'fixed',
},
logo: {
enable: true,
fit: 'contain',
source: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
},
navigation: {
accordion: true,
split: true,
styleType: 'rounded',
},
shortcutKeys: {
enable: true,
globalLockScreen: true,
globalLogout: true,
globalPreferences: true,
globalSearch: true,
},
sidebar: {
autoActivateChild: false,
collapsed: false,
collapsedButton: true,
collapsedShowTitle: false,
collapseWidth: 60,
enable: true,
expandOnHover: true,
extraCollapse: false,
extraCollapsedWidth: 60,
fixedButton: true,
hidden: false,
mixedWidth: 80,
width: 224,
},
tabbar: {
draggable: true,
enable: true,
height: 38,
keepAlive: true,
maxCount: 0,
middleClickToClose: false,
persist: true,
showIcon: true,
showMaximize: true,
showMore: true,
styleType: 'chrome',
wheelable: true,
},
theme: {
builtinType: 'default',
colorDestructive: 'hsl(348 100% 61%)',
colorPrimary: 'hsl(212 100% 45%)',
colorSuccess: 'hsl(144 57% 58%)',
colorWarning: 'hsl(42 84% 61%)',
mode: 'auto',
radius: '0.5',
semiDarkHeader: false,
semiDarkSidebar: false,
},
transition: {
enable: true,
loading: true,
name: 'fade-slide',
progress: true,
},
widget: {
fullscreen: true,
globalSearch: true,
languageToggle: true,
lockScreen: false,
notification: true,
refresh: true,
sidebarToggle: true,
themeToggle: true,
},
};
export { defaultPreferences };

View File

@@ -0,0 +1,88 @@
import type { BuiltinThemeType } from '@vben-core/typings';
interface BuiltinThemePreset {
color: string;
darkPrimaryColor?: string;
primaryColor?: string;
type: BuiltinThemeType;
}
const BUILT_IN_THEME_PRESETS: BuiltinThemePreset[] = [
{
color: 'hsl(212 100% 45%)',
type: 'default',
},
{
color: 'hsl(245 82% 67%)',
type: 'violet',
},
{
color: 'hsl(347 77% 60%)',
type: 'pink',
},
{
color: 'hsl(42 84% 61%)',
type: 'yellow',
},
{
color: 'hsl(231 98% 65%)',
type: 'sky-blue',
},
{
color: 'hsl(161 90% 43%)',
type: 'green',
},
{
color: 'hsl(240 5% 26%)',
darkPrimaryColor: 'hsl(0 0% 98%)',
primaryColor: 'hsl(240 5.9% 10%)',
type: 'zinc',
},
{
color: 'hsl(181 84% 32%)',
type: 'deep-green',
},
{
color: 'hsl(211 91% 39%)',
type: 'deep-blue',
},
{
color: 'hsl(18 89% 40%)',
type: 'orange',
},
{
color: 'hsl(0 75% 42%)',
type: 'rose',
},
{
color: 'hsl(0 0% 25%)',
darkPrimaryColor: 'hsl(0 0% 98%)',
primaryColor: 'hsl(240 5.9% 10%)',
type: 'neutral',
},
{
color: 'hsl(215 25% 27%)',
darkPrimaryColor: 'hsl(0 0% 98%)',
primaryColor: 'hsl(240 5.9% 10%)',
type: 'slate',
},
{
color: 'hsl(217 19% 27%)',
darkPrimaryColor: 'hsl(0 0% 98%)',
primaryColor: 'hsl(240 5.9% 10%)',
type: 'gray',
},
{
color: '',
type: 'custom',
},
];
export const COLOR_PRESETS = [...BUILT_IN_THEME_PRESETS].slice(0, 7);
export { BUILT_IN_THEME_PRESETS };
export type { BuiltinThemePreset };

View File

@@ -0,0 +1,35 @@
import type { Preferences } from './types';
import { preferencesManager } from './preferences';
// 偏好设置(带有层级关系)
const preferences: Preferences =
preferencesManager.getPreferences.apply(preferencesManager);
// 更新偏好设置
const updatePreferences =
preferencesManager.updatePreferences.bind(preferencesManager);
// 重置偏好设置
const resetPreferences =
preferencesManager.resetPreferences.bind(preferencesManager);
const clearPreferencesCache =
preferencesManager.clearCache.bind(preferencesManager);
// 初始化偏好设置
const initPreferences =
preferencesManager.initPreferences.bind(preferencesManager);
export {
clearPreferencesCache,
initPreferences,
preferences,
preferencesManager,
resetPreferences,
updatePreferences,
};
export * from './constants';
export type * from './types';
export * from './use-preferences';

View File

@@ -0,0 +1,235 @@
import type { DeepPartial } from '@vben-core/typings';
import type { InitialOptions, Preferences } from './types';
import { markRaw, reactive, readonly, watch } from 'vue';
import { StorageManager } from '@vben-core/shared/cache';
import { isMacOs, merge } from '@vben-core/shared/utils';
import {
breakpointsTailwind,
useBreakpoints,
useDebounceFn,
} from '@vueuse/core';
import { defaultPreferences } from './config';
import { updateCSSVariables } from './update-css-variables';
const STORAGE_KEY = 'preferences';
const STORAGE_KEY_LOCALE = `${STORAGE_KEY}-locale`;
const STORAGE_KEY_THEME = `${STORAGE_KEY}-theme`;
class PreferenceManager {
private cache: null | StorageManager = null;
// private flattenedState: Flatten<Preferences>;
private initialPreferences: Preferences = defaultPreferences;
private isInitialized: boolean = false;
private savePreferences: (preference: Preferences) => void;
private state: Preferences = reactive<Preferences>({
...this.loadPreferences(),
});
constructor() {
this.cache = new StorageManager();
// 避免频繁的操作缓存
this.savePreferences = useDebounceFn(
(preference: Preferences) => this._savePreferences(preference),
150,
);
}
clearCache() {
[STORAGE_KEY, STORAGE_KEY_LOCALE, STORAGE_KEY_THEME].forEach((key) => {
this.cache?.removeItem(key);
});
}
public getInitialPreferences() {
return this.initialPreferences;
}
public getPreferences() {
return readonly(this.state);
}
/**
* 覆盖偏好设置
* overrides 要覆盖的偏好设置
* namespace 命名空间
*/
public async initPreferences({ namespace, overrides }: InitialOptions) {
// 是否初始化过
if (this.isInitialized) {
return;
}
// 初始化存储管理器
this.cache = new StorageManager({ prefix: namespace });
// 合并初始偏好设置
this.initialPreferences = merge({}, overrides, defaultPreferences);
// 加载并合并当前存储的偏好设置
const mergedPreference = merge(
{},
// overrides,
this.loadCachedPreferences() || {},
this.initialPreferences,
);
// 更新偏好设置
this.updatePreferences(mergedPreference);
this.setupWatcher();
this.initPlatform();
// 标记为已初始化
this.isInitialized = true;
}
/**
* 重置偏好设置
* 偏好设置将被重置为初始值,并从 localStorage 中移除。
*
* @example
* 假设 initialPreferences 为 { theme: 'light', language: 'en' }
* 当前 state 为 { theme: 'dark', language: 'fr' }
* this.resetPreferences();
* 调用后state 将被重置为 { theme: 'light', language: 'en' }
* 并且 localStorage 中的对应项将被移除
*/
resetPreferences() {
// 将状态重置为初始偏好设置
Object.assign(this.state, this.initialPreferences);
// 保存重置后的偏好设置
this.savePreferences(this.state);
// 从存储中移除偏好设置项
[STORAGE_KEY, STORAGE_KEY_THEME, STORAGE_KEY_LOCALE].forEach((key) => {
this.cache?.removeItem(key);
});
this.updatePreferences(this.state);
}
/**
* 更新偏好设置
* @param updates - 要更新的偏好设置
*/
public updatePreferences(updates: DeepPartial<Preferences>) {
const mergedState = merge({}, updates, markRaw(this.state));
Object.assign(this.state, mergedState);
// 根据更新的键值执行相应的操作
this.handleUpdates(updates);
this.savePreferences(this.state);
}
/**
* 保存偏好设置
* @param {Preferences} preference - 需要保存的偏好设置
*/
private _savePreferences(preference: Preferences) {
this.cache?.setItem(STORAGE_KEY, preference);
this.cache?.setItem(STORAGE_KEY_LOCALE, preference.app.locale);
this.cache?.setItem(STORAGE_KEY_THEME, preference.theme.mode);
}
/**
* 处理更新的键值
* 根据更新的键值执行相应的操作。
* @param {DeepPartial<Preferences>} updates - 部分更新的偏好设置
*/
private handleUpdates(updates: DeepPartial<Preferences>) {
const themeUpdates = updates.theme || {};
const appUpdates = updates.app || {};
if (themeUpdates && Object.keys(themeUpdates).length > 0) {
updateCSSVariables(this.state);
}
if (
Reflect.has(appUpdates, 'colorGrayMode') ||
Reflect.has(appUpdates, 'colorWeakMode')
) {
this.updateColorMode(this.state);
}
}
private initPlatform() {
const dom = document.documentElement;
dom.dataset.platform = isMacOs() ? 'macOs' : 'window';
}
/**
* 从缓存中加载偏好设置。如果缓存中没有找到对应的偏好设置,则返回默认偏好设置。
*/
private loadCachedPreferences() {
return this.cache?.getItem<Preferences>(STORAGE_KEY);
}
/**
* 加载偏好设置
* @returns {Preferences} 加载的偏好设置
*/
private loadPreferences(): Preferences {
return this.loadCachedPreferences() || { ...defaultPreferences };
}
/**
* 监听状态和系统偏好设置的变化。
*/
private setupWatcher() {
if (this.isInitialized) {
return;
}
// 监听断点,判断是否移动端
const breakpoints = useBreakpoints(breakpointsTailwind);
const isMobile = breakpoints.smaller('md');
watch(
() => isMobile.value,
(val) => {
this.updatePreferences({
app: { isMobile: val },
});
},
{ immediate: true },
);
// 监听系统主题偏好设置变化
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', ({ matches: isDark }) => {
// 如果偏好设置中主题模式为auto则跟随系统更新
if (this.state.theme.mode === 'auto') {
this.updatePreferences({
theme: { mode: isDark ? 'dark' : 'light' },
});
// 恢复为auto模式
this.updatePreferences({
theme: { mode: 'auto' },
});
}
});
}
/**
* 更新页面颜色模式(灰色、色弱)
* @param preference
*/
private updateColorMode(preference: Preferences) {
if (preference.app) {
const { colorGrayMode, colorWeakMode } = preference.app;
const dom = document.documentElement;
const COLOR_WEAK = 'invert-mode';
const COLOR_GRAY = 'grayscale-mode';
colorWeakMode
? dom.classList.add(COLOR_WEAK)
: dom.classList.remove(COLOR_WEAK);
colorGrayMode
? dom.classList.add(COLOR_GRAY)
: dom.classList.remove(COLOR_GRAY);
}
}
}
const preferencesManager = new PreferenceManager();
export { PreferenceManager, preferencesManager };

View File

@@ -0,0 +1,324 @@
import type {
AccessModeType,
AuthPageLayoutType,
BreadcrumbStyleType,
BuiltinThemeType,
ContentCompactType,
DeepPartial,
LayoutHeaderMenuAlignType,
LayoutHeaderModeType,
LayoutType,
LoginExpiredModeType,
NavigationStyleType,
PageTransitionType,
PreferencesButtonPositionType,
TabsStyleType,
ThemeModeType,
} from '@vben-core/typings';
type SupportedLanguagesType = 'en-US' | 'zh-CN';
interface AppPreferences {
/** 权限模式 */
accessMode: AccessModeType;
/** 登录注册页面布局 */
authPageLayout: AuthPageLayoutType;
/** 检查更新轮询时间 */
checkUpdatesInterval: number;
/** 是否开启灰色模式 */
colorGrayMode: boolean;
/** 是否开启色弱模式 */
colorWeakMode: boolean;
/** 是否开启紧凑模式 */
compact: boolean;
/** 是否开启内容紧凑模式 */
contentCompact: ContentCompactType;
/** 内容紧凑宽度 */
contentCompactWidth: number;
/** 内容内边距 */
contentPadding: number;
/** 内容底部内边距 */
contentPaddingBottom: number;
/** 内容左侧内边距 */
contentPaddingLeft: number;
/** 内容右侧内边距 */
contentPaddingRight: number;
/** 内容顶部内边距 */
contentPaddingTop: number;
// /** 应用默认头像 */
defaultAvatar: string;
/** 默认首页地址 */
defaultHomePath: string;
// /** 开启动态标题 */
dynamicTitle: boolean;
/** 是否开启检查更新 */
enableCheckUpdates: boolean;
/** 是否显示偏好设置 */
enablePreferences: boolean;
/**
* @zh_CN 是否开启refreshToken
*/
enableRefreshToken: boolean;
/** 是否移动端 */
isMobile: boolean;
/** 布局方式 */
layout: LayoutType;
/** 支持的语言 */
locale: SupportedLanguagesType;
/** 登录过期模式 */
loginExpiredMode: LoginExpiredModeType;
/** 应用名 */
name: string;
/** 偏好设置按钮位置 */
preferencesButtonPosition: PreferencesButtonPositionType;
/**
* @zh_CN 是否开启水印
*/
watermark: boolean;
/** z-index */
zIndex: number;
}
interface BreadcrumbPreferences {
/** 面包屑是否启用 */
enable: boolean;
/** 面包屑是否只有一个时隐藏 */
hideOnlyOne: boolean;
/** 面包屑首页图标是否可见 */
showHome: boolean;
/** 面包屑图标是否可见 */
showIcon: boolean;
/** 面包屑风格 */
styleType: BreadcrumbStyleType;
}
interface CopyrightPreferences {
/** 版权公司名 */
companyName: string;
/** 版权公司名链接 */
companySiteLink: string;
/** 版权日期 */
date: string;
/** 版权是否可见 */
enable: boolean;
/** 备案号 */
icp: string;
/** 备案号链接 */
icpLink: string;
/** 设置面板是否显示*/
settingShow?: boolean;
}
interface FooterPreferences {
/** 底栏是否可见 */
enable: boolean;
/** 底栏是否固定 */
fixed: boolean;
/** 底栏高度 */
height: number;
}
interface HeaderPreferences {
/** 顶栏是否启用 */
enable: boolean;
/** 顶栏高度 */
height: number;
/** 顶栏是否隐藏,css-隐藏 */
hidden: boolean;
/** 顶栏菜单位置 */
menuAlign: LayoutHeaderMenuAlignType;
/** header显示模式 */
mode: LayoutHeaderModeType;
}
interface LogoPreferences {
/** logo是否可见 */
enable: boolean;
/** logo图片适应方式 */
fit: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
/** logo地址 */
source: string;
}
interface NavigationPreferences {
/** 导航菜单手风琴模式 */
accordion: boolean;
/** 导航菜单是否切割,只在 layout=mixed-nav 生效 */
split: boolean;
/** 导航菜单风格 */
styleType: NavigationStyleType;
}
interface SidebarPreferences {
/** 点击目录时自动激活子菜单 */
autoActivateChild: boolean;
/** 侧边栏是否折叠 */
collapsed: boolean;
/** 侧边栏折叠按钮是否可见 */
collapsedButton: boolean;
/** 侧边栏折叠时是否显示title */
collapsedShowTitle: boolean;
/** 侧边栏折叠宽度 */
collapseWidth: number;
/** 侧边栏是否可见 */
enable: boolean;
/** 菜单自动展开状态 */
expandOnHover: boolean;
/** 侧边栏扩展区域是否折叠 */
extraCollapse: boolean;
/** 侧边栏扩展区域折叠宽度 */
extraCollapsedWidth: number;
/** 侧边栏固定按钮是否可见 */
fixedButton: boolean;
/** 侧边栏是否隐藏 - css */
hidden: boolean;
/** 混合侧边栏宽度 */
mixedWidth: number;
/** 侧边栏宽度 */
width: number;
}
interface ShortcutKeyPreferences {
/** 是否启用快捷键-全局 */
enable: boolean;
/** 是否启用全局锁屏快捷键 */
globalLockScreen: boolean;
/** 是否启用全局注销快捷键 */
globalLogout: boolean;
/** 是否启用全局偏好设置快捷键 */
globalPreferences: boolean;
/** 是否启用全局搜索快捷键 */
globalSearch: boolean;
}
interface TabbarPreferences {
/** 是否开启多标签页拖拽 */
draggable: boolean;
/** 是否开启多标签页 */
enable: boolean;
/** 标签页高度 */
height: number;
/** 开启标签页缓存功能 */
keepAlive: boolean;
/** 限制最大数量 */
maxCount: number;
/** 是否点击中键时关闭标签 */
middleClickToClose: boolean;
/** 是否持久化标签 */
persist: boolean;
/** 是否开启多标签页图标 */
showIcon: boolean;
/** 显示最大化按钮 */
showMaximize: boolean;
/** 显示更多按钮 */
showMore: boolean;
/** 标签页风格 */
styleType: TabsStyleType;
/** 是否开启鼠标滚轮响应 */
wheelable: boolean;
}
interface ThemePreferences {
/** 内置主题名 */
builtinType: BuiltinThemeType;
/** 错误色 */
colorDestructive: string;
/** 主题色 */
colorPrimary: string;
/** 成功色 */
colorSuccess: string;
/** 警告色 */
colorWarning: string;
/** 当前主题 */
mode: ThemeModeType;
/** 圆角 */
radius: string;
/** 是否开启半深色header只在theme='light'时生效) */
semiDarkHeader: boolean;
/** 是否开启半深色菜单只在theme='light'时生效) */
semiDarkSidebar: boolean;
}
interface TransitionPreferences {
/** 页面切换动画是否启用 */
enable: boolean;
// /** 是否开启页面加载loading */
loading: boolean;
/** 页面切换动画 */
name: PageTransitionType | string;
/** 是否开启页面加载进度动画 */
progress: boolean;
}
interface WidgetPreferences {
/** 是否启用全屏部件 */
fullscreen: boolean;
/** 是否启用全局搜索部件 */
globalSearch: boolean;
/** 是否启用语言切换部件 */
languageToggle: boolean;
/** 是否开启锁屏功能 */
lockScreen: boolean;
/** 是否显示通知部件 */
notification: boolean;
/** 显示刷新按钮 */
refresh: boolean;
/** 是否显示侧边栏显示/隐藏部件 */
sidebarToggle: boolean;
/** 是否显示主题切换部件 */
themeToggle: boolean;
}
interface Preferences {
/** 全局配置 */
app: AppPreferences;
/** 顶栏配置 */
breadcrumb: BreadcrumbPreferences;
/** 版权配置 */
copyright: CopyrightPreferences;
/** 底栏配置 */
footer: FooterPreferences;
/** 面包屑配置 */
header: HeaderPreferences;
/** logo配置 */
logo: LogoPreferences;
/** 导航配置 */
navigation: NavigationPreferences;
/** 快捷键配置 */
shortcutKeys: ShortcutKeyPreferences;
/** 侧边栏配置 */
sidebar: SidebarPreferences;
/** 标签页配置 */
tabbar: TabbarPreferences;
/** 主题配置 */
theme: ThemePreferences;
/** 动画配置 */
transition: TransitionPreferences;
/** 功能配置 */
widget: WidgetPreferences;
}
type PreferencesKeys = keyof Preferences;
interface InitialOptions {
namespace: string;
overrides?: DeepPartial<Preferences>;
}
export type {
AppPreferences,
BreadcrumbPreferences,
FooterPreferences,
HeaderPreferences,
InitialOptions,
LogoPreferences,
NavigationPreferences,
Preferences,
PreferencesKeys,
ShortcutKeyPreferences,
SidebarPreferences,
SupportedLanguagesType,
TabbarPreferences,
ThemePreferences,
TransitionPreferences,
WidgetPreferences,
};

View File

@@ -0,0 +1,116 @@
import type { Preferences } from './types';
import { generatorColorVariables } from '@vben-core/shared/color';
import { updateCSSVariables as executeUpdateCSSVariables } from '@vben-core/shared/utils';
import { BUILT_IN_THEME_PRESETS } from './constants';
/**
* 更新主题的 CSS 变量以及其他 CSS 变量
* @param preferences - 当前偏好设置对象,它的主题值将被用来设置文档的主题。
*/
function updateCSSVariables(preferences: Preferences) {
// 当修改到颜色变量时,更新 css 变量
const root = document.documentElement;
if (!root) {
return;
}
const theme = preferences?.theme ?? {};
const { builtinType, mode, radius } = theme;
// html 设置 dark 类
if (Reflect.has(theme, 'mode')) {
const dark = isDarkTheme(mode);
root.classList.toggle('dark', dark);
}
// html 设置 data-theme=[builtinType]
if (Reflect.has(theme, 'builtinType')) {
const rootTheme = root.dataset.theme;
if (rootTheme !== builtinType) {
root.dataset.theme = builtinType;
}
}
// 获取当前的内置主题
const currentBuiltType = [...BUILT_IN_THEME_PRESETS].find(
(item) => item.type === builtinType,
);
let builtinTypeColorPrimary: string | undefined = '';
if (currentBuiltType) {
const isDark = isDarkTheme(preferences.theme.mode);
// 设置不同主题的主要颜色
const color = isDark
? currentBuiltType.darkPrimaryColor || currentBuiltType.primaryColor
: currentBuiltType.primaryColor;
builtinTypeColorPrimary = color || currentBuiltType.color;
}
// 如果内置主题颜色和自定义颜色都不存在,则不更新主题颜色
if (
builtinTypeColorPrimary ||
Reflect.has(theme, 'colorPrimary') ||
Reflect.has(theme, 'colorDestructive') ||
Reflect.has(theme, 'colorSuccess') ||
Reflect.has(theme, 'colorWarning')
) {
// preferences.theme.colorPrimary = builtinTypeColorPrimary || colorPrimary;
updateMainColorVariables(preferences);
}
// 更新圆角
if (Reflect.has(theme, 'radius')) {
document.documentElement.style.setProperty('--radius', `${radius}rem`);
}
}
/**
* 更新主要的 CSS 变量
* @param preference - 当前偏好设置对象,它的颜色值将被转换成 HSL 格式并设置为 CSS 变量。
*/
function updateMainColorVariables(preference: Preferences) {
if (!preference.theme) {
return;
}
const { colorDestructive, colorPrimary, colorSuccess, colorWarning } =
preference.theme;
const colorVariables = generatorColorVariables([
{ color: colorPrimary, name: 'primary' },
{ alias: 'warning', color: colorWarning, name: 'yellow' },
{ alias: 'success', color: colorSuccess, name: 'green' },
{ alias: 'destructive', color: colorDestructive, name: 'red' },
]);
// 要设置的 CSS 变量映射
const colorMappings = {
'--green-500': '--success',
'--primary-500': '--primary',
'--red-500': '--destructive',
'--yellow-500': '--warning',
};
// 统一处理颜色变量的更新
Object.entries(colorMappings).forEach(([sourceVar, targetVar]) => {
const colorValue = colorVariables[sourceVar];
if (colorValue) {
document.documentElement.style.setProperty(targetVar, colorValue);
}
});
executeUpdateCSSVariables(colorVariables);
}
function isDarkTheme(theme: string) {
let dark = theme === 'dark';
if (theme === 'auto') {
dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
}
return dark;
}
export { isDarkTheme, updateCSSVariables };

View File

@@ -0,0 +1,253 @@
import { diff } from '@vben-core/shared/utils';
import { computed } from 'vue';
import { preferencesManager } from './preferences';
import { isDarkTheme } from './update-css-variables';
function usePreferences() {
const preferences = preferencesManager.getPreferences();
const initialPreferences = preferencesManager.getInitialPreferences();
/**
* @zh_CN 计算偏好设置的变化
*/
const diffPreference = computed(() => {
return diff(initialPreferences, preferences);
});
const appPreferences = computed(() => preferences.app);
const shortcutKeysPreferences = computed(() => preferences.shortcutKeys);
/**
* @zh_CN 判断是否为暗黑模式
* @param preferences - 当前偏好设置对象,它的主题值将被用来判断是否为暗黑模式。
* @returns 如果主题为暗黑模式,返回 true否则返回 false。
*/
const isDark = computed(() => {
return isDarkTheme(preferences.theme.mode);
});
const locale = computed(() => {
return preferences.app.locale;
});
const isMobile = computed(() => {
return appPreferences.value.isMobile;
});
const theme = computed(() => {
return isDark.value ? 'dark' : 'light';
});
/**
* @zh_CN 布局方式
*/
const layout = computed(() =>
isMobile.value ? 'sidebar-nav' : appPreferences.value.layout,
);
/**
* @zh_CN 是否显示顶栏
*/
const isShowHeaderNav = computed(() => {
return preferences.header.enable;
});
/**
* @zh_CN 是否全屏显示content不需要侧边、底部、顶部、tab区域
*/
const isFullContent = computed(
() => appPreferences.value.layout === 'full-content',
);
/**
* @zh_CN 是否侧边导航模式
*/
const isSideNav = computed(
() => appPreferences.value.layout === 'sidebar-nav',
);
/**
* @zh_CN 是否侧边混合模式
*/
const isSideMixedNav = computed(
() => appPreferences.value.layout === 'sidebar-mixed-nav',
);
/**
* @zh_CN 是否为头部导航模式
*/
const isHeaderNav = computed(
() => appPreferences.value.layout === 'header-nav',
);
/**
* @zh_CN 是否为头部混合导航模式
*/
const isHeaderMixedNav = computed(
() => appPreferences.value.layout === 'header-mixed-nav',
);
/**
* @zh_CN 是否为顶部通栏+侧边导航模式
*/
const isHeaderSidebarNav = computed(
() => appPreferences.value.layout === 'header-sidebar-nav',
);
/**
* @zh_CN 是否为混合导航模式
*/
const isMixedNav = computed(
() => appPreferences.value.layout === 'mixed-nav',
);
/**
* @zh_CN 是否包含侧边导航模式
*/
const isSideMode = computed(() => {
return (
isMixedNav.value ||
isSideMixedNav.value ||
isSideNav.value ||
isHeaderMixedNav.value ||
isHeaderSidebarNav.value
);
});
const sidebarCollapsed = computed(() => {
return preferences.sidebar.collapsed;
});
/**
* @zh_CN 是否开启keep-alive
* 在tabs可见以及开启keep-alive的情况下才开启
*/
const keepAlive = computed(
() => preferences.tabbar.enable && preferences.tabbar.keepAlive,
);
/**
* @zh_CN 登录注册页面布局是否为左侧
*/
const authPanelLeft = computed(() => {
return appPreferences.value.authPageLayout === 'panel-left';
});
/**
* @zh_CN 登录注册页面布局是否为左侧
*/
const authPanelRight = computed(() => {
return appPreferences.value.authPageLayout === 'panel-right';
});
/**
* @zh_CN 登录注册页面布局是否为中间
*/
const authPanelCenter = computed(() => {
return appPreferences.value.authPageLayout === 'panel-center';
});
/**
* @zh_CN 内容是否已经最大化
* 排除 full-content模式
*/
const contentIsMaximize = computed(() => {
const headerIsHidden = preferences.header.hidden;
const sidebarIsHidden = preferences.sidebar.hidden;
return headerIsHidden && sidebarIsHidden && !isFullContent.value;
});
/**
* @zh_CN 是否启用全局搜索快捷键
*/
const globalSearchShortcutKey = computed(() => {
const { enable, globalSearch } = shortcutKeysPreferences.value;
return enable && globalSearch;
});
/**
* @zh_CN 是否启用全局注销快捷键
*/
const globalLogoutShortcutKey = computed(() => {
const { enable, globalLogout } = shortcutKeysPreferences.value;
return enable && globalLogout;
});
const globalLockScreenShortcutKey = computed(() => {
const { enable, globalLockScreen } = shortcutKeysPreferences.value;
return enable && globalLockScreen;
});
/**
* @zh_CN 偏好设置按钮位置
*/
const preferencesButtonPosition = computed(() => {
const { enablePreferences, preferencesButtonPosition } = preferences.app;
// 如果没有启用偏好设置按钮
if (!enablePreferences) {
return {
fixed: false,
header: false,
};
}
const { header, sidebar } = preferences;
const headerHidden = header.hidden;
const sidebarHidden = sidebar.hidden;
const contentIsMaximize = headerHidden && sidebarHidden;
const isHeaderPosition = preferencesButtonPosition === 'header';
// 如果设置了固定位置
if (preferencesButtonPosition !== 'auto') {
return {
fixed: preferencesButtonPosition === 'fixed',
header: isHeaderPosition,
};
}
// 如果是全屏模式或者没有固定在顶部,
const fixed =
contentIsMaximize ||
isFullContent.value ||
isMobile.value ||
!isShowHeaderNav.value;
return {
fixed,
header: !fixed,
};
});
return {
authPanelCenter,
authPanelLeft,
authPanelRight,
contentIsMaximize,
diffPreference,
globalLockScreenShortcutKey,
globalLogoutShortcutKey,
globalSearchShortcutKey,
isDark,
isFullContent,
isHeaderMixedNav,
isHeaderNav,
isHeaderSidebarNav,
isMixedNav,
isMobile,
isSideMixedNav,
isSideMode,
isSideNav,
keepAlive,
layout,
locale,
preferencesButtonPosition,
sidebarCollapsed,
theme,
};
}
export { usePreferences };