useTheme.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import { storeToRefs } from "pinia";
  2. import { Theme } from "./interface";
  3. import { ElMessage } from "element-plus";
  4. import { DEFAULT_PRIMARY } from "@/config";
  5. import { useGlobalStore } from "@/stores/modules/global";
  6. import { getLightColor, getDarkColor } from "@/utils/color";
  7. import { asideTheme, AsideThemeType } from "@/styles/theme/aside";
  8. /**
  9. * @description 全局主题 hooks
  10. * */
  11. export const useTheme = () => {
  12. const globalStore = useGlobalStore();
  13. const { primary, isDark, isGrey, isWeak, asideInverted, layout } = storeToRefs(globalStore);
  14. // 切换暗黑模式 ==> 并带修改主题颜色、侧边栏颜色
  15. const switchDark = () => {
  16. const html = document.documentElement as HTMLElement;
  17. if (isDark.value) {
  18. html.setAttribute("class", "dark");
  19. html.style.background = "#141414";
  20. } else {
  21. html.setAttribute("class", "");
  22. html.style.background = "";
  23. }
  24. changePrimary(primary.value);
  25. setAsideTheme();
  26. };
  27. // 修改主题颜色
  28. const changePrimary = (val: string | null) => {
  29. if (!val) {
  30. val = DEFAULT_PRIMARY;
  31. ElMessage({ type: "success", message: `主题颜色已重置为 ${DEFAULT_PRIMARY}` });
  32. }
  33. // 计算主题颜色变化
  34. document.documentElement.style.setProperty("--el-color-primary", val);
  35. document.documentElement.style.setProperty(
  36. "--el-color-primary-dark-2",
  37. isDark.value ? `${getLightColor(val, 0.2)}` : `${getDarkColor(val, 0.3)}`
  38. );
  39. for (let i = 1; i <= 9; i++) {
  40. const primaryColor = isDark.value ? `${getDarkColor(val, i / 10)}` : `${getLightColor(val, i / 10)}`;
  41. document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, primaryColor);
  42. }
  43. globalStore.setGlobalState("primary", val);
  44. };
  45. // 灰色和弱色切换
  46. const changeGreyOrWeak = (type: Theme.GreyOrWeakType, value: boolean) => {
  47. const body = document.body as HTMLElement;
  48. if (!value) return body.removeAttribute("style");
  49. const styles: Record<Theme.GreyOrWeakType, string> = {
  50. grey: "filter: grayscale(1)",
  51. weak: "filter: invert(80%)"
  52. };
  53. body.setAttribute("style", styles[type]);
  54. const propName = type === "grey" ? "isWeak" : "isGrey";
  55. globalStore.setGlobalState(propName, false);
  56. };
  57. // 设置侧边栏样式 ==> light、inverted、dark
  58. const setAsideTheme = () => {
  59. // 默认所有侧边栏为 light 模式
  60. let type: AsideThemeType = "light";
  61. // transverse 布局下菜单栏为 inverted 模式
  62. if (layout.value == "transverse") type = "inverted";
  63. // 侧边栏反转色目前只支持在 vertical 布局模式下生效
  64. const body = document.body as HTMLElement;
  65. let clsVal = body.getAttribute("class") || "";
  66. if (layout.value == "vertical" && asideInverted.value) {
  67. type = "inverted";
  68. clsVal = clsVal.concat(" inverted");
  69. } else {
  70. clsVal = clsVal.replace("inverted", "");
  71. }
  72. body.setAttribute("class", clsVal);
  73. // 侧边栏 dark 模式
  74. if (isDark.value) type = "dark";
  75. const theme = asideTheme[type!];
  76. for (const [key, value] of Object.entries(theme)) {
  77. document.documentElement.style.setProperty(key, value);
  78. }
  79. };
  80. // init theme
  81. const initTheme = () => {
  82. switchDark();
  83. if (isGrey.value) changeGreyOrWeak("grey", true);
  84. if (isWeak.value) changeGreyOrWeak("weak", true);
  85. };
  86. return {
  87. initTheme,
  88. switchDark,
  89. changePrimary,
  90. changeGreyOrWeak,
  91. setAsideTheme
  92. };
  93. };