dm-vue3-ui
Version:
This Components Library will help get you started developing in Vue 3.
364 lines (350 loc) • 11.7 kB
JavaScript
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
};