Files
2026-10-10 12:20:37 +08:00

4.2 KiB
Raw Permalink Blame History

9.14 样式与主题定制

:::tip 概述 前端使用 WindiCSS + Less 实现样式管理,基于 @zougt/vite-plugin-theme-preprocessor 支持主题切换和暗色模式。 :::

技术栈

技术 用途
WindiCSS 原子化 CSS 框架(vite-plugin-windicss,兼容 Tailwind 语法)
Less 全局样式变量和主题
Ant Design 主题变量 组件样式覆盖(@primary-color 等 Less 变量)

全局样式文件

ui/src/styles/
├── index.less            # 全局样式入口(@import 子模块)
├── color.less            # 颜色变量定义(@white、@content-bg、--content-bg 等)
├── common.less           # 公共样式类
├── config.less           # 配置引用(@import (reference) 'color.less')
├── tailwind.css          # Tailwind 兼容指令入口(由 WindiCSS 处理)
├── theme/
│   ├── theme-default.less  # 默认主题(引入 Ant Design 默认 Less 主题)
│   └── theme-dark.less     # 暗色主题(引入 Ant Design 暗色 Less 主题)
└── transition/
    ├── index.less        # 过渡动画入口
    ├── base.less / fade.less / scale.less / slide.less / zoom.less / scroll.less

Less 变量

/* ui/src/styles/color.less */
html {
  --content-bg: #f0f2f5;
}

@white: #fff;
@content-bg: #f0f2f5;

Ant Design 组件主题通过标准 Less 变量覆盖,例如主色:

/* 覆盖主色示例 */
@primary-color: #165DFF;

主题切换

主题切换基于 @zougt/vite-plugin-theme-preprocessor,两套主题文件在构建时编译为独立作用域样式,运行时通过 toggleTheme 切换:

// build/vite/plugin/theme.ts
import themePreprocessorPlugin from '@zougt/vite-plugin-theme-preprocessor';

export function configThemePlugin(): Plugin[] {
  return [
    themePreprocessorPlugin({
      themeScopes: [
        {
          scopeName: 'theme-default',
          path: path.resolve('src/styles/theme/theme-default.less'),
        },
        {
          scopeName: 'theme-dark',
          path: path.resolve('src/styles/theme/theme-dark.less'),
        },
      ],
    }),
  ];
}

页面中通过「项目配置」抽屉切换明暗主题:

// ui/src/layout/components/Header/ProjectSetting.vue
import { toggleTheme } from '@zougt/vite-plugin-theme-preprocessor/dist/browser-utils';
import { useProjectSettingStore } from '@/store/modules/projectSetting';

const settingStore = useProjectSettingStore();

function handleToggleTheme(theme: string) {
  const isDark = theme === 'darkness';
  settingStore.darkTheme = isDark;
  updateDarkTheme(isDark ? 'dark' : 'light');
}

async function updateDarkTheme(mode: 'light' | 'dark') {
  toggleTheme({ scopeName: mode === 'dark' ? 'theme-dark' : 'theme-default' });
}

主题状态由 Pinia 的 projectSetting Store 管理(darkTheme、navTheme、headerTheme)。

主题文件

/* ui/src/styles/theme/theme-default.less */
@import "ant-design-vue/lib/style/themes/default.less";

/* ui/src/styles/theme/theme-dark.less */
@import "ant-design-vue/lib/style/themes/dark.less";

自定义组件覆盖直接追加在对应主题文件中,通过生成的作用域类(.theme-default / .theme-dark)区分明暗模式。

WindiCSS 配置

// ui/windi.config.ts
import { defineConfig } from 'vite-plugin-windicss';

export default defineConfig({
  darkMode: 'class',
  plugins: [createEnterPlugin()],
  theme: {
    extend: {
      zIndex: { '-1': '-1' },
      screens: {
        sm: '576px',
        md: '768px',
        lg: '992px',
        xl: '1200px',
        '2xl': '1600px',
      },
    },
  },
});

:::tip 说明 项目使用 vite-plugin-windicss,类名语法与 TailwindCSS 兼容(class="flex items-center justify-between"),但配置文件是 windi.config.ts 而非 tailwind.config.js。 :::

自定义全局样式

/* ui/src/styles/common.less */

// 页面容器
.page-container {
  padding: 16px;
  background: var(--content-bg);
  border-radius: 8px;
}

// 搜索表单
.search-form {
  margin-bottom: 16px;
  padding: 16px;
  background: #fafafa;
  border-radius: 4px;
}