diff --git a/.env b/.env index fa204ea2..ce6d12fc 100644 --- a/.env +++ b/.env @@ -1,5 +1,5 @@ # 变量需要以VITE开头 -VITE_APP_TITLE=web-cli -VITE_APP_TITLE_LABEL=web脚手架 +VITE_APP_TITLE=SoybeanAdmin +VITE_APP_TITLE_LABEL=Soybean后台管理系统 VITE_BASE_URL=/ diff --git a/index.html b/index.html index c7c16fc4..5a9c3245 100644 --- a/index.html +++ b/index.html @@ -4,10 +4,10 @@ - Vite App + <%= title %> - +
diff --git a/public/favicon.ico b/public/favicon.ico index df36fcfb..2b47ca6e 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/src/assets/img/common/logo.png b/src/assets/img/common/logo.png new file mode 100644 index 00000000..6641c827 Binary files /dev/null and b/src/assets/img/common/logo.png differ diff --git a/src/enum/animate.ts b/src/enum/animate.ts new file mode 100644 index 00000000..04f6ab90 --- /dev/null +++ b/src/enum/animate.ts @@ -0,0 +1,9 @@ +/** 动画类型 */ +export enum EnumAnimate { + 'zoom-fade' = '渐变', + 'zoom-out' = '闪现', + 'fade-slide' = '滑动', + 'fade' = '消退', + 'fade-bottom' = '底部消退', + 'fade-scale' = '缩放消退' +} diff --git a/src/enum/common.ts b/src/enum/common.ts index 0eaaff0b..f4d81362 100644 --- a/src/enum/common.ts +++ b/src/enum/common.ts @@ -1,4 +1,4 @@ -/** 请求头的content-type类型 */ +/** http请求头的content-type类型 */ export enum ContentType { json = 'application/json', formUrlencoded = 'application/x-www-form-urlencoded', diff --git a/src/enum/index.ts b/src/enum/index.ts index 6e4371f6..99dd268d 100644 --- a/src/enum/index.ts +++ b/src/enum/index.ts @@ -1 +1,3 @@ export { ContentType } from './common'; +export { EnumAnimate } from './animate'; +export { EnumNavMode, EnumNavTheme } from './theme'; diff --git a/src/enum/theme.ts b/src/enum/theme.ts new file mode 100644 index 00000000..664dd012 --- /dev/null +++ b/src/enum/theme.ts @@ -0,0 +1,13 @@ +/** 导航模式 */ +export enum EnumNavMode { + 'vertical' = '左侧菜单模式', + 'horizontal' = '顶部菜单模式', + 'horizontal-mix' = '顶部菜单混合模式' +} + +/** 导航风格 */ +export enum EnumNavTheme { + 'dark' = '暗色侧边栏', + 'light' = '白色侧边栏', + 'header-dark' = '暗色的侧边栏和顶栏' +} diff --git a/src/interface/app.ts b/src/interface/app.ts index 5c0ad0a4..3190ac88 100644 --- a/src/interface/app.ts +++ b/src/interface/app.ts @@ -1,3 +1,5 @@ +import { EnumAnimate, EnumNavMode, EnumNavTheme } from '@/enum'; + export interface ThemeSettings { /** 深色模式 */ darkMode: boolean; @@ -7,6 +9,18 @@ export interface ThemeSettings { themeColorList: string[]; /** 其他颜色 */ otherColor: OtherColor; + /** 导航样式 */ + navStyle: NavStyle; + /** 头部样式 */ + headerStyle: HeaderStyle; + /** 菜单样式 */ + menuStyle: MenuStyle; + /** 多标签样式 */ + multiTabStyle: MultiTabStyle; + /** 面包屑样式 */ + crumbsStyle: CrumbsStyle; + /** 页面样式 */ + pageStyle: PageStyle; } interface OtherColor { @@ -19,3 +33,62 @@ interface OtherColor { /** 错误 */ error: string; } + +type NavMode = keyof typeof EnumNavMode; +type NavTheme = keyof typeof EnumNavTheme; + +interface NavStyle { + /** 导航模式 */ + mode: NavMode; + /** 导航主题 */ + theme: NavTheme; +} + +interface HeaderStyle { + /** 顶部高度 */ + height: number; + /** 背景颜色 */ + bgColor: string; + /** 固定顶部 */ + fixed: boolean; + /** 显示重载按钮 */ + showReload: boolean; +} + +interface MenuStyle { + /** 折叠菜单 */ + collapsed: boolean; + /** 菜单宽度 */ + width: number; + /** 菜单折叠时的宽度 */ + collapsedWidth: number; + /** 固定菜单 */ + fixed: boolean; + /** 分割菜单 */ + splitMenu: boolean; +} + +interface MultiTabStyle { + /** 多标签可见 */ + visible: boolean; + /** 背景颜色 */ + bgColor: string; + /** 固定标签页 */ + fixed: boolean; +} + +interface CrumbsStyle { + /** 面包屑可见 */ + visible: boolean; + /** 显示图标 */ + showIcon: boolean; +} + +type AnimateType = keyof typeof EnumAnimate; + +interface PageStyle { + /** 页面是否开启动画 */ + animate: boolean; + /** 动画类型 */ + animateType: AnimateType; +} diff --git a/src/layouts/BasicLayout/components/GlobalHeader/components/HeaderItemContainer.vue b/src/layouts/BasicLayout/components/GlobalHeader/components/HeaderItemContainer.vue new file mode 100644 index 00000000..ccec0d10 --- /dev/null +++ b/src/layouts/BasicLayout/components/GlobalHeader/components/HeaderItemContainer.vue @@ -0,0 +1,8 @@ + + + + diff --git a/src/layouts/BasicLayout/components/GlobalHeader/components/index.ts b/src/layouts/BasicLayout/components/GlobalHeader/components/index.ts new file mode 100644 index 00000000..c4911d8e --- /dev/null +++ b/src/layouts/BasicLayout/components/GlobalHeader/components/index.ts @@ -0,0 +1,3 @@ +import HeaderItemContainer from './HeaderItemContainer.vue'; + +export { HeaderItemContainer }; diff --git a/src/layouts/BasicLayout/components/GlobalHeader/index.vue b/src/layouts/BasicLayout/components/GlobalHeader/index.vue new file mode 100644 index 00000000..abd51f5a --- /dev/null +++ b/src/layouts/BasicLayout/components/GlobalHeader/index.vue @@ -0,0 +1,20 @@ + + + + diff --git a/src/layouts/BasicLayout/components/GlobalLogo/index.vue b/src/layouts/BasicLayout/components/GlobalLogo/index.vue new file mode 100644 index 00000000..157b6c60 --- /dev/null +++ b/src/layouts/BasicLayout/components/GlobalLogo/index.vue @@ -0,0 +1,16 @@ + + + + diff --git a/src/layouts/BasicLayout/components/GlobalMenu/index.vue b/src/layouts/BasicLayout/components/GlobalMenu/index.vue new file mode 100644 index 00000000..c5c27b65 --- /dev/null +++ b/src/layouts/BasicLayout/components/GlobalMenu/index.vue @@ -0,0 +1,6 @@ + + + + diff --git a/src/layouts/BasicLayout/components/SettingDrawer/components/DarkMode.vue b/src/layouts/BasicLayout/components/SettingDrawer/components/DarkMode.vue new file mode 100644 index 00000000..2becea9e --- /dev/null +++ b/src/layouts/BasicLayout/components/SettingDrawer/components/DarkMode.vue @@ -0,0 +1,25 @@ + + + + diff --git a/src/layouts/BasicLayout/components/SettingDrawer/components/ThemeStyle.vue b/src/layouts/BasicLayout/components/SettingDrawer/components/ThemeStyle.vue new file mode 100644 index 00000000..e69de29b diff --git a/src/layouts/BasicLayout/components/SettingDrawer/components/index.ts b/src/layouts/BasicLayout/components/SettingDrawer/components/index.ts new file mode 100644 index 00000000..e49edc04 --- /dev/null +++ b/src/layouts/BasicLayout/components/SettingDrawer/components/index.ts @@ -0,0 +1,3 @@ +import DarkMode from './DarkMode.vue'; + +export { DarkMode }; diff --git a/src/layouts/BasicLayout/components/SettingDrawer/index.vue b/src/layouts/BasicLayout/components/SettingDrawer/index.vue new file mode 100644 index 00000000..012c3467 --- /dev/null +++ b/src/layouts/BasicLayout/components/SettingDrawer/index.vue @@ -0,0 +1,16 @@ + + + + diff --git a/src/layouts/BasicLayout/components/index.ts b/src/layouts/BasicLayout/components/index.ts new file mode 100644 index 00000000..a4180a4c --- /dev/null +++ b/src/layouts/BasicLayout/components/index.ts @@ -0,0 +1,6 @@ +import GlobalHeader from './GlobalHeader/index.vue'; +import GlobalLogo from './GlobalLogo/index.vue'; +import GlobalMenu from './GlobalMenu/index.vue'; +import SettingDrawer from './SettingDrawer/index.vue'; + +export { GlobalHeader, GlobalLogo, GlobalMenu, SettingDrawer }; diff --git a/src/layouts/BasicLayout/index.vue b/src/layouts/BasicLayout/index.vue index b480b910..edc58f96 100644 --- a/src/layouts/BasicLayout/index.vue +++ b/src/layouts/BasicLayout/index.vue @@ -1,15 +1,67 @@ - - + + diff --git a/src/main.ts b/src/main.ts index ab02d46d..23e10a9e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,30 +3,29 @@ import App from './App.vue'; import AppProvider from './AppProvider.vue'; import { setupStore } from './store'; import { router, setupRouter } from './router'; -import { setupSmoothScroll, setupNaive } from './plugins'; +import { setupSmoothScroll, setupWindicssDarkMode } from './plugins'; import 'virtual:windi.css'; import './styles/css/global.css'; async function setupApp() { - const naiveApp = createApp(AppProvider); + const appProvider = createApp(AppProvider); const app = createApp(App); - /** 注册naive UI组件 */ - setupNaive(app); - - /** 挂载全局状态 */ + // 挂载全局状态 setupStore(app); - // 优先挂载一下 naiveApp 解决路由守卫,Axios中可使用,LoadingBar,Dialog,Message 等之类组件 - naiveApp.mount('#naiveApp', true); + // 优先挂载一下 appProvider 解决路由守卫,Axios中可使用,LoadingBar,Dialog,Message 等之类组件 + appProvider.mount('#appProvider', true); // 挂载路由 - await setupRouter(app); + setupRouter(app); // 路由准备就绪后挂载APP实例 await router.isReady(); app.mount('#app', true); + + setupWindicssDarkMode(); } setupSmoothScroll(); diff --git a/src/plugins/dark-mode.ts b/src/plugins/dark-mode.ts new file mode 100644 index 00000000..ff35c7fd --- /dev/null +++ b/src/plugins/dark-mode.ts @@ -0,0 +1,31 @@ +import { watch } from 'vue'; +import { useAppStore } from '@/store'; + +export default function setupWindicssDarkMode() { + const app = useAppStore(); + + const DARK_CLASS = 'dark'; + function getHtmlElement() { + return document.querySelector('html')!; + } + + function addDarkClass() { + const html = getHtmlElement(); + html.classList.add(DARK_CLASS); + } + function removeDarkClass() { + const html = getHtmlElement(); + html.classList.remove(DARK_CLASS); + } + + watch( + () => app.themeSettings.darkMode, + newValue => { + if (newValue) { + addDarkClass(); + } else { + removeDarkClass(); + } + } + ); +} diff --git a/src/plugins/index.ts b/src/plugins/index.ts index e0557b2e..ba9de06c 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -1,4 +1,5 @@ import setupSmoothScroll from './smooth-scroll'; import setupNaive from './naive'; +import setupWindicssDarkMode from './dark-mode'; -export { setupSmoothScroll, setupNaive }; +export { setupSmoothScroll, setupNaive, setupWindicssDarkMode }; diff --git a/src/settings/theme/index.ts b/src/settings/theme/index.ts index 5523b0c2..001694ca 100644 --- a/src/settings/theme/index.ts +++ b/src/settings/theme/index.ts @@ -23,18 +23,44 @@ const themeColorList = [ ]; const themeSettings: ThemeSettings = { - /** 深色主题 */ darkMode: false, - /** 系统主题色 */ themeColor: themeColorList[0], - /** 系统内置主题色列表 */ themeColorList, - /** 其他颜色 */ otherColor: { info: '#2080f0', success: '#67C23A', warning: '#E6A23C', error: '#F56C6C' + }, + navStyle: { + mode: 'vertical', + theme: 'light' + }, + headerStyle: { + height: 64, + bgColor: '#fff', + fixed: true, + showReload: true + }, + menuStyle: { + collapsed: false, + width: 200, + collapsedWidth: 64, + fixed: true, + splitMenu: false + }, + multiTabStyle: { + visible: true, + bgColor: '#fff', + fixed: true + }, + crumbsStyle: { + visible: true, + showIcon: false + }, + pageStyle: { + animate: true, + animateType: 'zoom-fade' } }; diff --git a/src/store/modules/app/index.ts b/src/store/modules/app/index.ts index b91e7e91..cab27621 100644 --- a/src/store/modules/app/index.ts +++ b/src/store/modules/app/index.ts @@ -1,22 +1,28 @@ import { defineStore } from 'pinia'; import type { GlobalThemeOverrides } from 'naive-ui'; -import { store } from '../../index'; import { themeSettings } from '@/settings'; import type { ThemeSettings } from '@/interface'; +import { store } from '../../index'; import { getHoverAndPressedColor } from './helpers'; interface AppState { /** 主题配置 */ themeSettings: ThemeSettings; - /** 侧边栏折叠 */ - asideCollapse: boolean; + /** 主题配置抽屉 */ + settingDrawer: SettingDrawer; +} + +interface SettingDrawer { + visible: boolean; } const appStore = defineStore({ id: 'app-store', state: (): AppState => ({ themeSettings, - asideCollapse: false + settingDrawer: { + visible: false + } }), getters: { /** naive UI主题配置 */ @@ -59,11 +65,21 @@ const appStore = defineStore({ } }, actions: { - handleAsideCollapse(collapse: boolean) { - this.asideCollapse = collapse; + /** 折叠/展开菜单 */ + handleMenuCollapse(collapsed: boolean) { + this.themeSettings.menuStyle.collapsed = collapsed; }, - toggleAside() { - this.asideCollapse = !this.asideCollapse; + /** 切换折叠/展开菜单 */ + toggleMenu() { + this.themeSettings.menuStyle.collapsed = !this.themeSettings.menuStyle.collapsed; + }, + /** 打开配置抽屉 */ + openSettingDrawer() { + this.settingDrawer.visible = true; + }, + /** 关闭配置抽屉 */ + closeSettingDrawer() { + this.settingDrawer.visible = false; } } }); diff --git a/src/views/home/index.vue b/src/views/home/index.vue index 5a5dd101..ae2718e8 100644 --- a/src/views/home/index.vue +++ b/src/views/home/index.vue @@ -25,7 +25,7 @@ +