UNPKG

dm-vue3-ui

Version:

This Components Library will help get you started developing in Vue 3.

364 lines (350 loc) 11.7 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; const _ThemeManager = class _ThemeManager { constructor() { __publicField(this, "currentTheme"); __publicField(this, "originalTheme"); __publicField(this, "themeConfigs", { default: { primaryColor: "#7858fc", borderRadius: "4px", borderColor: "rgba(147, 154, 189, 0.5)" }, blue: { primaryColor: "#2468f2", borderRadius: "4px", borderColor: "rgba(147, 154, 189, 0.5)" } }); this.originalTheme = this.themeConfigs.default; this.currentTheme = { ...this.originalTheme }; } static getInstance() { if (!_ThemeManager.instance) { _ThemeManager.instance = new _ThemeManager(); } return _ThemeManager.instance; } /** * 应用主题配置 * @param theme 主题配置 */ applyTheme(theme) { this.currentTheme = { ...this.currentTheme, ...theme }; this.updateCSSVariables(); this.updateAntdThemeVariables(); this.injectDynamicStyles(); } /** * 根据主题类型应用主题 * @param themeType 主题类型 */ applyThemeByType(themeType) { const themeConfig = this.themeConfigs[themeType]; if (themeConfig) { this.applyTheme(themeConfig); } return themeConfig; } /** * 获取所有可用主题选项 */ getThemeOptions() { return [ { value: "default", name: "默认", color: this.themeConfigs.default.primaryColor, config: this.themeConfigs.default }, { value: "blue", name: "蓝色", color: this.themeConfigs.blue.primaryColor, config: this.themeConfigs.blue } ]; } /** * 重置为原始主题 */ resetTheme() { this.currentTheme = { ...this.originalTheme }; this.applyTheme(this.currentTheme); } /** * 初始化主题 - 从localStorage读取保存的主题色 */ initializeTheme() { const savedTheme = localStorage.getItem("platform_config"); if (savedTheme) { try { const config = JSON.parse(savedTheme); if (config.themeColor) { this.applyTheme({ primaryColor: config.themeColor }); } } catch (error) { console.warn("Failed to parse saved theme config:", error); } } } /** * 获取当前主题配置 */ getCurrentTheme() { return { ...this.currentTheme }; } /** * 更新CSS变量 */ updateCSSVariables() { const root = document.documentElement; const { primaryColor, borderRadius, borderColor } = this.currentTheme; root.style.setProperty("--primary-color", primaryColor); root.style.setProperty("--primary-color-hover", this.adjustColorBrightness(primaryColor, 20)); root.style.setProperty("--primary-color-active", this.adjustColorBrightness(primaryColor, -20)); root.style.setProperty("--primary-color-fade", this.hexToRgba(primaryColor, 0.08)); if (borderRadius) { root.style.setProperty("--border-radius-base", borderRadius); } if (borderColor) { root.style.setProperty("--border-color-base", borderColor); } } /** * 更新Ant Design主题变量 */ updateAntdThemeVariables() { const root = document.documentElement; const { primaryColor } = this.currentTheme; root.style.setProperty("--ant-primary-color", primaryColor); root.style.setProperty( "--ant-primary-color-hover", this.adjustColorBrightness(primaryColor, 20) ); root.style.setProperty( "--ant-primary-color-active", this.adjustColorBrightness(primaryColor, -20) ); for (let i = 1; i <= 10; i++) { const lightness = i === 6 ? 0 : (6 - i) * 10; const color = this.adjustColorBrightness(primaryColor, lightness); root.style.setProperty(`--ant-primary-${i}`, color); } root.style.setProperty("--ant-primary-color-deprecated-bg", this.hexToRgba(primaryColor, 0.1)); root.style.setProperty( "--ant-primary-color-deprecated-border", this.hexToRgba(primaryColor, 0.4) ); } /** * 注入动态样式 */ injectDynamicStyles() { const existingStyle = document.getElementById("dynamic-theme-styles"); if (existingStyle) { existingStyle.remove(); } const style = document.createElement("style"); style.id = "dynamic-theme-styles"; const { primaryColor } = this.currentTheme; const dynamicStyles = ` /* 兼容vite.config中customTheme的样式覆盖 */ /* 按钮样式 */ .dm-ui-btn, .ant-btn { &:hover, &:focus { border-color: ${primaryColor} !important; color: ${primaryColor} !important; } } .dm-ui-btn-primary, .ant-btn-primary { color: #fff !important; background-color: ${primaryColor} !important; border-color: ${primaryColor} !important; } .dm-ui-btn-primary:hover, .ant-btn-primary:hover { color: #fff !important; background-color: ${this.adjustColorBrightness(primaryColor, 20)} !important; border-color: ${this.adjustColorBrightness(primaryColor, 20)} !important; } .dm-ui-btn-primary:active, .dm-ui-btn-primary:focus, .ant-btn-primary:active, .ant-btn-primary:focus { color: #fff !important; background-color: ${this.adjustColorBrightness(primaryColor, -20)} !important; border-color: ${this.adjustColorBrightness(primaryColor, -20)} !important; } /* 链接样式 */ .dm-ui-btn-link, .ant-btn-link { color: ${primaryColor} !important; } .dm-ui-btn-link:hover, .ant-btn-link:hover { color: ${this.adjustColorBrightness(primaryColor, 20)} !important; } /* 输入框焦点样式 */ .dm-ui-input:hover, .dm-ui-input:focus, .dm-ui-input-focused, .dm-ui-input-number:hover, .ant-input:hover, .ant-input:focus, .ant-input-focused { border-color: ${primaryColor} !important; box-shadow: 0 0 0 2px ${this.hexToRgba(primaryColor, 0.2)} !important; } /* 选择器样式 */ .dm-ui-select-focused .dm-ui-select-selector, .ant-select-focused .ant-select-selector { border-color: ${primaryColor} !important; box-shadow: 0 0 0 2px ${this.hexToRgba(primaryColor, 0.2)} !important; } .dm-ui-select:not(.dm-ui-select-disabled):hover .dm-ui-select-selector, .ant-select:not(.ant-select-disabled):hover .ant-select-selector { border-color: ${this.adjustColorBrightness(primaryColor, 20)} !important; } .dm-ui-select-item-option-selected:not(.dm-ui-select-item-option-disabled), .ant-select-item-option-selected:not(.ant-select-item-option-disabled) { color: #fff !important; background-color:${this.adjustColorBrightness(primaryColor, 20)} !important; } /* 复选框样式 */ .dm-ui-checkbox-checked .dm-ui-checkbox-inner, .ant-checkbox-checked .ant-checkbox-inner { background-color: ${primaryColor} !important; border-color: ${primaryColor} !important; } .dm-ui-checkbox:hover, .ant-checkbox:hover { border-color: ${this.adjustColorBrightness(primaryColor, 20)} !important; } /* 单选框样式 */ .dm-ui-radio-checked .dm-ui-radio-inner, .ant-radio-checked .ant-radio-inner { border-color: ${primaryColor} !important; } .dm-ui-radio-checked .dm-ui-radio-inner::after, .ant-radio-checked .ant-radio-inner::after { background-color: ${primaryColor} !important; } .dm-ui-radio-button-wrapper-checked, .dm-ui-radio-button-wrapper:hover { background: ${primaryColor} !important; border-color: ${primaryColor} !important; color: #fff !important; } /* 开关样式 */ .dm-ui-switch-checked, .ant-switch-checked { background-color: ${primaryColor} !important; } .dm-ui-picker:hover, .dm-ui-picker-focused, .dm-ui-picker-cell-in-view.dm-ui-picker-cell-today .dm-ui-picker-cell-inner::before { border-color: ${primaryColor} !important; box-shadow: 0 0 0 2px ${this.hexToRgba(primaryColor, 0.2)} !important; } .dm-ui-picker-cell-in-view.dm-ui-picker-cell-in-range::before, .dm-ui-picker-time-panel-cell-selected .dm-ui-picker-time-panel-cell-inner { background: ${this.hexToRgba(primaryColor, 0.1)} !important; } .dm-ui-picker-cell-range-start, .dm-ui-picker-cell-range-end { .dm-ui-picker-cell-inner { background: ${primaryColor} !important; } } /* 标签页样式 */ .dm-ui-tabs-tab-active, .dm-ui-tabs-tab:active, .ant-tabs-tab-active, .ant-tabs-tab:active { color: ${primaryColor} !important; } .dm-ui-tabs-tab:hover, .ant-tabs-tab:hover { color: ${this.adjustColorBrightness(primaryColor, 20)} !important; } .dm-ui-tabs-ink-bar, .ant-tabs-ink-bar { background-color: ${primaryColor} !important; } /* 菜单样式 */ .dm-ui-menu-item-selected, .dm-ui-menu-item:active, .ant-menu-item-selected, .ant-menu-item:active, { background-color: ${this.hexToRgba(primaryColor, 0.1)} !important; color: ${primaryColor} !important; } .dm-ui-menu-item:hover, .ant-menu-item:hover { color: ${primaryColor} !important; } /* 分页器样式 */ .dm-ui-pagination-item-active, .ant-pagination-item-active { background-color: ${primaryColor} !important; border-color: ${primaryColor} !important; } .dm-ui-pagination-item-active a, .ant-pagination-item-active a { color: #fff !important; } /* 滑块样式 */ .dm-ui-slider-track, .ant-slider-track { background-color: ${primaryColor} !important; } .dm-ui-slider-handle, .ant-slider-handle { border-color: ${primaryColor} !important; } /* 日期选择器预设样式 */ .dm-ui-tag { &:hover, &.active-tag { background-color: ${this.adjustColorBrightness(primaryColor, 20)} !important; color: #fff !important; } } `; style.textContent = dynamicStyles; document.head.appendChild(style); } /** * 调整颜色亮度 */ adjustColorBrightness(color, amount) { const usePound = color[0] === "#"; const col = usePound ? color.slice(1) : color; const num = parseInt(col, 16); let r = (num >> 16) + amount; let g = (num >> 8 & 255) + amount; let b = (num & 255) + amount; r = r > 255 ? 255 : r < 0 ? 0 : r; g = g > 255 ? 255 : g < 0 ? 0 : g; b = b > 255 ? 255 : b < 0 ? 0 : b; return (usePound ? "#" : "") + (r << 16 | g << 8 | b).toString(16).padStart(6, "0"); } /** * 十六进制颜色转RGBA */ hexToRgba(hex, alpha) { const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); return `rgba(${r}, ${g}, ${b}, ${alpha})`; } }; __publicField(_ThemeManager, "instance"); let ThemeManager = _ThemeManager; const themeManager = ThemeManager.getInstance(); export { ThemeManager, themeManager };