# 9.14 样式与主题定制 :::tip 概述 前端使用 WindiCSS + Less 实现样式管理,基于 `@zougt/vite-plugin-theme-preprocessor` 支持主题切换和暗色模式。 ::: ## 技术栈 | 技术 | 用途 | |------|------| | WindiCSS | 原子化 CSS 框架(`vite-plugin-windicss`,兼容 Tailwind 语法) | | Less | 全局样式变量和主题 | | Ant Design 主题变量 | 组件样式覆盖(`@primary-color` 等 Less 变量) | ## 全局样式文件 ```text 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 变量 ```less /* ui/src/styles/color.less */ html { --content-bg: #f0f2f5; } @white: #fff; @content-bg: #f0f2f5; ``` Ant Design 组件主题通过标准 Less 变量覆盖,例如主色: ```less /* 覆盖主色示例 */ @primary-color: #165DFF; ``` ## 主题切换 主题切换基于 `@zougt/vite-plugin-theme-preprocessor`,两套主题文件在构建时编译为独立作用域样式,运行时通过 `toggleTheme` 切换: ```typescript // 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'), }, ], }), ]; } ``` 页面中通过「项目配置」抽屉切换明暗主题: ```typescript // 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`)。 ## 主题文件 ```less /* 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 配置 ```typescript // 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`。 ::: ## 自定义全局样式 ```less /* 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; } ```