mirror of
https://github.com/m-xlsea/ruoyi-plus-soybean.git
synced 2025-09-24 07:49:47 +08:00
feat(projects): 新增主题配置
This commit is contained in:
15
src/App.vue
15
src/App.vue
@ -1,11 +1,16 @@
|
||||
<template>
|
||||
<el-config-provider :locale="locale">
|
||||
<router-view />
|
||||
</el-config-provider>
|
||||
<n-config-provider :locale="zhCN" :date-locale="dateZhCN" :theme-overrides="app.themeOverrids">
|
||||
<naive-app>
|
||||
<router-view />
|
||||
</naive-app>
|
||||
</n-config-provider>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElConfigProvider } from 'element-plus';
|
||||
import locale from 'element-plus/lib/locale/lang/zh-cn';
|
||||
import { NConfigProvider, zhCN, dateZhCN } from 'naive-ui';
|
||||
import { NaiveApp } from '@/components';
|
||||
import { useAppStore } from '@/store';
|
||||
|
||||
const app = useAppStore();
|
||||
</script>
|
||||
<style></style>
|
||||
|
17
src/components/common/NaiveApp/NaiveContent.vue
Normal file
17
src/components/common/NaiveApp/NaiveContent.vue
Normal file
@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useLoadingBar, useDialog, useMessage, useNotification } from 'naive-ui';
|
||||
|
||||
function registerNaiveTool() {
|
||||
window.$loadingBar = useLoadingBar();
|
||||
window.$dialog = useDialog();
|
||||
window.$message = useMessage();
|
||||
window.$notification = useNotification();
|
||||
}
|
||||
|
||||
registerNaiveTool();
|
||||
</script>
|
||||
<style scoped></style>
|
18
src/components/common/NaiveApp/index.vue
Normal file
18
src/components/common/NaiveApp/index.vue
Normal file
@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<n-loading-bar-provider>
|
||||
<n-dialog-provider>
|
||||
<n-notification-provider>
|
||||
<n-message-provider>
|
||||
<slot></slot>
|
||||
<naive-content />
|
||||
</n-message-provider>
|
||||
</n-notification-provider>
|
||||
</n-dialog-provider>
|
||||
</n-loading-bar-provider>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { NLoadingBarProvider, NDialogProvider, NNotificationProvider, NMessageProvider } from 'naive-ui';
|
||||
import NaiveContent from './NaiveContent.vue';
|
||||
</script>
|
||||
<style scoped></style>
|
3
src/components/common/index.ts
Normal file
3
src/components/common/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import NaiveApp from './NaiveApp/index.vue';
|
||||
|
||||
export { NaiveApp };
|
@ -0,0 +1 @@
|
||||
export { NaiveApp } from './common';
|
||||
|
8
src/interface/app.ts
Normal file
8
src/interface/app.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export interface ThemeSettings {
|
||||
/** 深色模式 */
|
||||
darkMode: boolean;
|
||||
/** 主题颜色 */
|
||||
themeColor: string;
|
||||
/** 主题颜色列表 */
|
||||
themeColorList: string[];
|
||||
}
|
0
src/interface/common.ts
Normal file
0
src/interface/common.ts
Normal file
@ -1 +1,2 @@
|
||||
export { UserInfo } from './business';
|
||||
export { ThemeSettings } from './app';
|
||||
|
8
src/layouts/BasicLayout.vue
Normal file
8
src/layouts/BasicLayout.vue
Normal file
@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup></script>
|
||||
<style scoped></style>
|
@ -0,0 +1,3 @@
|
||||
import BasicLayout from './BasicLayout.vue';
|
||||
|
||||
export { BasicLayout };
|
||||
|
34
src/main.ts
34
src/main.ts
@ -1,13 +1,33 @@
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
import { setupRouter } from './router';
|
||||
import { setupSmoothScroll, setupElementPlus } from './plugins';
|
||||
import { setupStore } from './store';
|
||||
import { router, setupRouter } from './router';
|
||||
import { setupSmoothScroll, setupNaive } from './plugins';
|
||||
import { NaiveApp } from './components';
|
||||
import 'virtual:windi.css';
|
||||
import './styles/css/global.css';
|
||||
|
||||
const app = createApp(App);
|
||||
setupSmoothScroll();
|
||||
setupElementPlus(app);
|
||||
setupRouter(app);
|
||||
async function setupApp() {
|
||||
const naiveApp = createApp(NaiveApp);
|
||||
const app = createApp(App);
|
||||
|
||||
app.mount('#app');
|
||||
/** 注册naive UI组件 */
|
||||
setupNaive(app);
|
||||
|
||||
/** 挂载全局状态 */
|
||||
setupStore(app);
|
||||
|
||||
// 优先挂载一下 naiveApp 解决路由守卫,Axios中可使用,Dialog,Message 等之类组件
|
||||
naiveApp.mount('#naiveApp', true);
|
||||
|
||||
// 挂载路由
|
||||
setupRouter(app);
|
||||
|
||||
// 路由准备就绪后挂载APP实例
|
||||
await router.isReady();
|
||||
|
||||
app.mount('#app', true);
|
||||
}
|
||||
|
||||
setupSmoothScroll();
|
||||
setupApp();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import setupSmoothScroll from './smooth-scroll';
|
||||
import setupElementPlus from './element-plus';
|
||||
import setupNaive from './naive';
|
||||
import NProgress from './nprogress';
|
||||
|
||||
export { setupSmoothScroll, setupElementPlus, NProgress };
|
||||
export { setupSmoothScroll, setupNaive, NProgress };
|
||||
|
9
src/plugins/naive.ts
Normal file
9
src/plugins/naive.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { create, NSpace, NButton, NDatePicker, NInput } from 'naive-ui';
|
||||
import type { App } from 'vue';
|
||||
|
||||
export default function setupNaive(app: App) {
|
||||
const naive = create({
|
||||
components: [NSpace, NButton, NDatePicker, NInput]
|
||||
});
|
||||
app.use(naive);
|
||||
}
|
@ -6,7 +6,7 @@ import createRouterGuide from './permission';
|
||||
|
||||
const routes: Array<RouteRecordRaw> = [...customRoutes];
|
||||
|
||||
const router = createRouter({
|
||||
export const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
import type { Router } from 'vue-router';
|
||||
import { NProgress } from '@/plugins';
|
||||
|
||||
/**
|
||||
* 路由守卫函数
|
||||
@ -7,10 +6,10 @@ import { NProgress } from '@/plugins';
|
||||
*/
|
||||
export default function createRouterGuide(router: Router) {
|
||||
router.beforeEach((to, from, next) => {
|
||||
NProgress.start();
|
||||
window.$loadingBar?.start();
|
||||
next();
|
||||
});
|
||||
router.afterEach(() => {
|
||||
NProgress.done();
|
||||
window.$loadingBar?.finish();
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
import { BasicLayout } from '@/layouts';
|
||||
|
||||
/**
|
||||
* 自定义路由
|
||||
@ -7,16 +8,19 @@ export const customRoutes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
name: 'root',
|
||||
path: '/',
|
||||
redirect: 'home'
|
||||
},
|
||||
{
|
||||
name: 'home',
|
||||
path: '/home',
|
||||
component: () => import('@/views/home/index.vue')
|
||||
},
|
||||
{
|
||||
name: 'system',
|
||||
path: '/system',
|
||||
component: () => import('@/views/system/index.vue')
|
||||
redirect: '/home',
|
||||
component: BasicLayout,
|
||||
children: [
|
||||
{
|
||||
name: 'home',
|
||||
path: '/home',
|
||||
component: () => import('@/views/home/index.vue')
|
||||
},
|
||||
{
|
||||
name: 'system',
|
||||
path: '/system',
|
||||
component: () => import('@/views/system/index.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
3
src/settings/index.ts
Normal file
3
src/settings/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import themeSettings from './theme';
|
||||
|
||||
export { themeSettings };
|
33
src/settings/theme/index.ts
Normal file
33
src/settings/theme/index.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import type { ThemeSettings } from '@/interface';
|
||||
|
||||
const themeColorList = [
|
||||
'#2d8cf0',
|
||||
'#0960bd',
|
||||
'#0084f4',
|
||||
'#009688',
|
||||
'#536dfe',
|
||||
'#ff5c93',
|
||||
'#ee4f12',
|
||||
'#0096c7',
|
||||
'#9c27b0',
|
||||
'#ff9800',
|
||||
'#FF3D68',
|
||||
'#00C1D4',
|
||||
'#71EFA3',
|
||||
'#171010',
|
||||
'#78DEC7',
|
||||
'#1768AC',
|
||||
'#FB9300',
|
||||
'#FC5404'
|
||||
];
|
||||
|
||||
const themeSettings: ThemeSettings = {
|
||||
/** 深色主题 */
|
||||
darkMode: false,
|
||||
/** 系统主题色 */
|
||||
themeColor: themeColorList[0],
|
||||
/** 系统内置主题色列表 */
|
||||
themeColorList
|
||||
};
|
||||
|
||||
export default themeSettings;
|
@ -1,7 +1,13 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import type { GlobalThemeOverrides } from 'naive-ui';
|
||||
import { store } from '../../index';
|
||||
import { themeSettings } from '@/settings';
|
||||
import type { ThemeSettings } from '@/interface';
|
||||
import { brightenColor } from '@/utils';
|
||||
|
||||
interface AppState {
|
||||
/** 主题配置 */
|
||||
themeSettings: ThemeSettings;
|
||||
/** 侧边栏折叠 */
|
||||
asideCollapse: boolean;
|
||||
}
|
||||
@ -9,8 +15,29 @@ interface AppState {
|
||||
const appStore = defineStore({
|
||||
id: 'app-store',
|
||||
state: (): AppState => ({
|
||||
themeSettings,
|
||||
asideCollapse: false
|
||||
}),
|
||||
getters: {
|
||||
/** naive UI主题配置 */
|
||||
themeOverrids(): GlobalThemeOverrides {
|
||||
const primaryColor = this.themeSettings.themeColor;
|
||||
const primaryColorHover = brightenColor(primaryColor);
|
||||
const primaryColorPressed = primaryColorHover;
|
||||
const colorLoading = primaryColor;
|
||||
|
||||
return {
|
||||
common: {
|
||||
primaryColor,
|
||||
primaryColorHover,
|
||||
primaryColorPressed
|
||||
},
|
||||
LoadingBar: {
|
||||
colorLoading
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
handleAsideCollapse(collapse: boolean) {
|
||||
this.asideCollapse = collapse;
|
||||
|
15
src/typings/window.d.ts
vendored
Normal file
15
src/typings/window.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
import type {
|
||||
LoadingBarProviderInst,
|
||||
DialogProviderInst,
|
||||
MessageProviderInst,
|
||||
NotificationProviderInst
|
||||
} from 'naive-ui';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
$loadingBar?: LoadingBarProviderInst;
|
||||
$dialog?: DialogProviderInst;
|
||||
$message?: MessageProviderInst;
|
||||
$notification?: NotificationProviderInst;
|
||||
}
|
||||
}
|
9
src/utils/common/color.ts
Normal file
9
src/utils/common/color.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import chroma from 'chroma-js';
|
||||
|
||||
/**
|
||||
* 更亮的颜色
|
||||
* @param color
|
||||
*/
|
||||
export function brightenColor(color: string) {
|
||||
return chroma(color).brighten(0.5).hex();
|
||||
}
|
@ -11,3 +11,5 @@ export {
|
||||
isSet,
|
||||
isMap
|
||||
} from './typeof';
|
||||
|
||||
export { brightenColor } from './color';
|
||||
|
@ -10,5 +10,6 @@ export {
|
||||
isDate,
|
||||
isRegExp,
|
||||
isSet,
|
||||
isMap
|
||||
isMap,
|
||||
brightenColor
|
||||
} from './common';
|
||||
|
@ -1,6 +1,49 @@
|
||||
<template>
|
||||
<div>Home</div>
|
||||
<div>
|
||||
<n-space>
|
||||
<n-button v-for="item in actions" :key="item.key" type="primary" @click="handleClick(item.key)">
|
||||
{{ item.label }}
|
||||
</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup></script>
|
||||
<script lang="ts" setup>
|
||||
import { useLoadingBar, useDialog, useNotification, useMessage } from 'naive-ui';
|
||||
|
||||
type ActionType = 'loading-bar' | 'dialog' | 'notification' | 'message';
|
||||
interface Action {
|
||||
key: ActionType;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const loadingBar = useLoadingBar();
|
||||
const dialog = useDialog();
|
||||
const notification = useNotification();
|
||||
const message = useMessage();
|
||||
|
||||
const actions: Action[] = [
|
||||
{ key: 'loading-bar', label: 'loading bar' },
|
||||
{ key: 'dialog', label: 'dialog' },
|
||||
{ key: 'notification', label: 'notification' },
|
||||
{ key: 'message', label: 'message' }
|
||||
];
|
||||
function handleClick(type: ActionType) {
|
||||
if (type === 'loading-bar') {
|
||||
loadingBar.start();
|
||||
setTimeout(() => {
|
||||
loadingBar.finish();
|
||||
}, 5000);
|
||||
}
|
||||
if (type === 'dialog') {
|
||||
dialog.info({ content: '弹窗示例!' });
|
||||
}
|
||||
if (type === 'notification') {
|
||||
notification.info({ content: '通知示例!' });
|
||||
}
|
||||
if (type === 'message') {
|
||||
message.info('消息示例!');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
||||
|
Reference in New Issue
Block a user