1、状态管理新建文件:store/projectConfig.ts

import { createStorage } from '@/utils/Storage'
const Storage = createStorage({ storage: localStorage })
import { ConfigProvider } from 'ant-design-vue'
import { useMutationObserver } from '@vueuse/core'
import darkThemeCss from 'ant-design-vue/dist/antd.dark.css?raw'

// 动态加入样式
const styleDom: any = document.createElement('style')
styleDom.dataset.type = 'theme-dark'
styleDom.textContent = darkThemeCss
document.head.appendChild(styleDom)

// 观察对 DOM 树所做的更改
useMutationObserver(
  document.head,
  (mutations) => {
    const hasCustomStyleEl = mutations.some((n) => Array.from(n.addedNodes).includes(styleDom))
    if (!hasCustomStyleEl) {
      document.head.appendChild(styleDom)
      styleDom.disabled = !document.documentElement.classList.contains('dark')
    }
  },
  {
    childList: true
  }
)

/**
 * 项目默认配置项
 * primaryColor - 默认主题色, 如果修改颜色不生效,请清理 localStorage
 * navTheme - sidebar theme ['dark', 'light'] 两种主题
 * layout - 整体布局方式 ['sidemenu', 'topmenu'] 两种布局
 * fixedHeader - 固定 Header : boolean
 * fixSiderbar - 固定左侧菜单栏 : boolean
 * contentWidth - 内容区布局: 流式 |  固定
 */

/** 主题色 */
export type ThemeName = 'light' | 'dark' | 'realDark'

export const defaultConfig = {
  navTheme: 'dark', // theme for nav menu
  primaryColor: 'rgb(24, 144, 255)', // '#F5222D'
  layout: 'sidemenu',
  contentWidth: 'Fluid',
  fixedHeader: false,
  fixSiderbar: false
}

// 设置黑暗主题
const setRealDarkTheme = (Theme?: ThemeName) => {
  if (Theme === 'realDark') {
    // 黑暗
    document.documentElement.classList.add('dark')
    styleDom.disabled = false
    setRealDarkCss(Theme)
  } else {
    // 默认
    document.documentElement.classList.remove('dark')
    styleDom.disabled = true
    setRealDarkCss(Theme)
  }
}

// 设置黑暗全局样式
const setRealDarkCss = (Theme?: ThemeName) => {
  if (Theme === 'realDark') {
    changeCss('--page-bg-color', '#141414') // 页面背景
    changeCss('--head-bg-color', 'rgba(0, 0, 0, 0.5)') // 标题背景
    changeCss('--line-color', '#2e2e2e') // 链接色
    changeCss('--content-bg-color', 'rgb(255 255 255 / 4%)') // 内容背景
    changeCss('--text-color', 'rgba(255, 255, 255, 0.85)') // 主文本色
  } else {
    changeCss('--page-bg-color', '#fff')
    changeCss('--head-bg-color', 'rgba(255, 255, 255, 0.7)')
    changeCss('--line-color', '#e8e8e8')
    changeCss('--content-bg-color', '#f0f2f5')
    changeCss('--text-color', 'rgba(0, 0, 0, 0.85)')
  }
}
const changeCss = (css, value) => {
  const body = document.body.style
  body.setProperty(css, value)
}

// 获取本地存储
const getLocalThemeConfig = () => {
  return {
    Theme: Storage.get('Theme') || 'dark',
    primaryColor: '' || '#27c88e'
  }
}
const localThemeConfig = getLocalThemeConfig()
const { primaryColor, Theme } = localThemeConfig
setRealDarkTheme(Theme)

export default {
  namespaced: true,
  state: {
    Theme: Storage.get('Theme') || Theme
  },
  getters: {
    getTheme(state) {
      return state.Theme
    }
  },
  mutations: {
    setTheme: (state, Theme) => {
      state.Theme = Theme
      Storage.set('Theme', Theme)
    }
  },
  actions: {
    setTheme({ commit }, Theme) {
      setRealDarkTheme(Theme)
      commit('setTheme', Theme)
    }
  }
}

注意:引入黑暗模式文件 import darkThemeCss from 'ant-design-vue/dist/antd.dark.css?raw' ,需要引入源码文件,需配置 webpack 使用 'raw-loader'编译

config.module
      .rule('css')
      .exclude.add(resolve('node_modules/ant-design-vue/dist/antd.dark.css'))
      .end()
config.module.rule('raw-css').resourceQuery(/raw/).use('raw-loader').loader('raw-loader')

2、使用

store.dispatch('projectConfig/setTheme', theme) // theme: 'dark' | 'realDark'

Logo

前往低代码交流专区

更多推荐