网站配置 这部份的配置信息,不需要也不能动态的变更,直接使用即可。
项目的Logo信息,可在这里进行修改,Vite方式忽略
创建src/config/website.config.js
文件,写入以下内容:
config/website.config.js import logoImage from '@/assets/images/logo.png' ;import loginImage from '@/assets/images/account-logo.png' ;export const websiteConfig = Object .freeze ({ title : 'CloudUpOA' , logo : logoImage, loginImage : loginImage, loginDesc : '云尚办公后台管理系统' , });
projectSetting 默认设置 创建src/settings/projectSetting.js
文件,写入以下内容:
settings/projectSetting.js const setting = { navMode : 'vertical' , navTheme : 'dark' , isMobile : false , headerSetting : { bgColor : '#fff' , fixed : true , isReload : true , }, showFooter : true , multiTabsSetting : { bgColor : '#fff' , show : true , fixed : true , }, menuSetting : { minMenuWidth : 64 , menuWidth : 200 , fixed : true , mixMenu : false , mobileWidth : 800 , collapsed : false , }, crumbsSetting : { show : true , showIcon : false , }, permissionMode : 'FIXED' , isPageAnimate : true , pageAnimateType : 'zoom-fade' , };export default setting;
状态保存
使用Store,保存当前菜单设置的状态,方便提供动态修改页面效果的功能
创建src/store/modules/projectSetting.js
,写入以下内容:
store/modules/projectSetting.js import { defineStore } from 'pinia' import { store } from '@/store' ;import projectSetting from '@/settings/projectSetting' ;const { navMode, navTheme, isMobile, headerSetting, showFooter, menuSetting, multiTabsSetting, crumbsSetting, permissionMode, isPageAnimate, pageAnimateType, } = projectSettingexport const useProjectSettingStore = defineStore ({ id : 'app-project-setting' , state : () => ({ navMode : navMode, navTheme, isMobile, headerSetting, showFooter, menuSetting, multiTabsSetting, crumbsSetting, permissionMode, isPageAnimate, pageAnimateType, }), getters : { getNavMode ( ) { return this .navMode ; }, getNavTheme ( ) { return this .navTheme ; }, getIsMobile ( ) { return this .isMobile ; }, getHeaderSetting ( ) { return this .headerSetting ; }, getShowFooter ( ) { return this .showFooter ; }, getMenuSetting ( ) { return this .menuSetting ; }, getMultiTabsSetting ( ) { return this .multiTabsSetting ; }, getCrumbsSetting ( ) { return this .multiTabsSetting ; }, getPermissionMode ( ) { return this .permissionMode ; }, getIsPageAnimate ( ) { return this .isPageAnimate ; }, getPageAnimateType ( ) { return this .pageAnimateType ; }, }, actions : { setNavTheme (value ) { this .navTheme = value; }, setIsMobile (value ) { this .isMobile = value }, }, });export function useProjectSettingStoreWithOut ( ) { return useProjectSettingStore (store); }
监听读取 当Store中的数据变化时,我们需要及时通知页面做出更改,因此需要监听其变化。
使用computed监听数据变化
创建src/hooks/setting/useProjectSetting.js
hooks/setting/useProjectSetting.js import { computed } from 'vue' ;import { useProjectSettingStore } from '@/store/modules/projectSetting' ;export function useProjectSetting ( ) { const projectStore = useProjectSettingStore (); const getNavMode = computed (() => projectStore.navMode ); const getNavTheme = computed (() => projectStore.navTheme ); const getIsMobile = computed (() => projectStore.isMobile ); const getHeaderSetting = computed (() => projectStore.headerSetting ); const getMultiTabsSetting = computed (() => projectStore.multiTabsSetting ); const getMenuSetting = computed (() => projectStore.menuSetting ); const getCrumbsSetting = computed (() => projectStore.crumbsSetting ); const getPermissionMode = computed (() => projectStore.permissionMode ); const getShowFooter = computed (() => projectStore.showFooter ); const getIsPageAnimate = computed (() => projectStore.isPageAnimate ); const getPageAnimateType = computed (() => projectStore.pageAnimateType ); return { getNavMode, getNavTheme, getIsMobile, getHeaderSetting, getMultiTabsSetting, getMenuSetting, getCrumbsSetting, getPermissionMode, getShowFooter, getIsPageAnimate, getPageAnimateType, }; }
designSetting 默认设置 创建src/settings/designSetting.js
文件,写入以下内容:
settings/designSetting.js export const appThemeList = [ "#2d8cf0" , "#0960bd" , "#0084f4" , "#009688" , "#536dfe" , "#ff5c93" , "#ee4f12" , "#0096c7" , "#9c27b0" , "#ff9800" , "#FF3D68" , "#00C1D4" , "#71EFA3" , "#171010" , "#78DEC7" , "#1768AC" , "#FB9300" , "#FC5404" , ];const setting = { darkTheme : false , appTheme : "#2d8cf0" , appThemeList, };export default setting;
状态保存 创建src/store/modules/designSetting.js
,写入以下内容:
store/modules/designSetting.js import { defineStore } from "pinia" ;import { store } from "@/store" ;import designSetting from "@/settings/designSetting" ;const { darkTheme, appTheme, appThemeList } = designSetting;export const useDesignSettingStore = defineStore ({ id : "app-design-setting" , state : () => ({ darkTheme, appTheme, appThemeList, }), getters : { getDarkTheme ( ) { return this .darkTheme ; }, getAppTheme ( ) { return this .appTheme ; }, getAppThemeList ( ) { return this .appThemeList ; }, }, actions : {}, });export function useDesignSettingWithOut ( ) { return useDesignSettingStore (store); }
监听读取 当Store中的数据变化时,我们需要及时通知页面做出更改,因此需要监听其变化。
使用computed监听数据变化
创建src/hooks/setting/useDesignSetting.js
hooks/setting/useDesignSetting.js import { computed } from 'vue' ;import { useDesignSettingStore } from '@/store/modules/designSetting' ;export function useDesignSetting ( ) { const designStore = useDesignSettingStore (); const getDarkTheme = computed (() => designStore.darkTheme ); const getAppTheme = computed (() => designStore.appTheme ); const getAppThemeList = computed (() => designStore.appThemeList ); return { getDarkTheme, getAppTheme, getAppThemeList, }; }
环境ENV 关于文件名:必须以如下方式命名,不要乱起名,也无需专门手动控制加载哪个文件
.env
:全局默认配置文件,不论什么环境都会加载合并
.env.development
:开发环境下的配置文件
.env.production
:生产环境下的配置文件
Webpack 注意:属性名必须以VUE_APP_开头,比如VUE_APP_XXX
创建src/.env
# port PORT = 8001 # spa-title VUE_APP_TITLE = CloudUpOA # spa shortname VUE_APP_SHORT_NAME = CloudUpOA
创建src/.env.development
NODE_ENV = 'development' # 网站根目录 VUE_APP_PUBLIC_PATH = / # 是否开启mock VUE_APP_USE_MOCK = true # 网站前缀 VUE_APP_BASE_URL = / # 是否删除console VUE_APP_DROP_CONSOLE = true # API 接口地址 VUE_APP_API_URL = # 图片上传地址 VUE_APP_UPLOAD_URL= # 图片前缀地址 VUE_APP_IMG_URL= # 接口前缀 VUE_APP_API_URL_PREFIX = /dev-api
输出控制台 创建src/utils/logs.js
utils/logs.js const projectName = process.env .VUE_APP_TITLE ;export function warn (message ) { console .warn (`[${projectName} warn]:${message} ` ); }export function error (message ) { throw new Error (`[${projectName} error]:${message} ` ); }
获取方法 创建src/utils/env.js
,写入以下内容:
utils/env.js import { warn } from '@/utils/log' ;export function getAppEnvConfig ( ) { const ENV = process.env ; const { VUE_APP_TITLE , VUE_APP_API_URL , VUE_APP_SHORT_NAME , VUE_APP_API_URL_PREFIX , VUE_APP_UPLOAD_URL , VUE_APP_PROD_MOCK , VUE_APP_IMG_URL , } = ENV ; if (!/^[a-zA-Z_]*$/ .test (VUE_APP_SHORT_NAME )) { warn ( `VUE_APP_SHORT_NAME Variables can only be characters/underscores, please modify in the environment variables and re-running.` ); } return { VUE_APP_TITLE , VUE_APP_API_URL , VUE_APP_SHORT_NAME , VUE_APP_API_URL_PREFIX , VUE_APP_UPLOAD_URL , VUE_APP_PROD_MOCK , VUE_APP_IMG_URL , }; }export const devMode = 'development' ;export const prodMode = 'production' ;export function getEnv ( ) { return process.env .NODE_ENV ; }export function isDevMode ( ) { return process.env .NODE_ENV === devMode; }export function isProdMode ( ) { return import .meta .env .NODE_ENV === devMode; }
换名读取 以VUE_APP_XXX的方式在项目中使用,终归是不方便。这里我们提供一种读取方式,更换其名称。
创建src/hooks/setting/index.js
hooks/setting/index.js import { warn } from '@/utils/log' ;import { getAppEnvConfig } from '@/utils/env' ;export const useGlobSetting = ( ) => { const { VUE_APP_TITLE , VUE_APP_API_URL , VUE_APP_SHORT_NAME , VUE_APP_API_URL_PREFIX , VUE_APP_UPLOAD_URL , VUE_APP_PROD_MOCK , VUE_APP_IMG_URL , } = getAppEnvConfig (); if (!/[a-zA-Z_]*/ .test (VUE_APP_SHORT_NAME )) { warn ( `VUE_APP_APP_SHORT_NAME Variables can only be characters/underscores, please modify in the environment variables and re-running.` ); } const glob = { title : VUE_APP_TITLE , apiUrl : VUE_APP_API_URL , shortName : VUE_APP_SHORT_NAME , urlPrefix : VUE_APP_API_URL_PREFIX , uploadUrl : VUE_APP_UPLOAD_URL , prodMock : VUE_APP_PROD_MOCK , imgUrl : VUE_APP_IMG_URL , }; return glob; };
Vite 注意:属性名必须以VITE_开头,比如VUE_XXX
创建src/.env
VITE_PORT = 8001 VITE_GLOB_APP_TITLE = 医院管理系统 VITE_GLOB_APP_SHORT_NAME = 医院管理系统
创建src/.env.development
VITE_PORT = 8001 VITE_PUBLIC_PATH = / VITE_BASE_URL = / VITE_PROXY =[["/api","http://localhost:9000"]] VITE_GLOB_API_URL =VITE_GLOB_UPLOAD_URL =VITE_GLOB_IMG_URL =VITE_GLOB_API_URL_PREFIX = /api
输出控制台 创建src/utils/log.js
utils/logs.js const projectName = import .meta .env .VITE_GLOB_APP_TITLE ;export function warn (message ) { console .warn (`[${projectName} warn]:${message} ` ); }export function error (message ) { throw new Error (`[${projectName} error]:${message} ` ); }
获取方法 创建src/utils/env.js
,写入以下内容:
@/build/getConfigFileName
getConfigFileName.js export const getConfigFileName = (env ) => { return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP' } __CONF__` .toUpperCase () .replace (/\s/g , '' ); };
utils/env.js import { warn } from '@/utils/log' ;import pkg from '../../package.json' ;import { getConfigFileName } from '../../build/getConfigFileName' ;export function getCommonStoragePrefix ( ) { const { VITE_GLOB_APP_SHORT_NAME } = getAppEnvConfig (); return `${VITE_GLOB_APP_SHORT_NAME} __${getEnv()} ` .toUpperCase (); }export function getStorageShortName ( ) { return `${getCommonStoragePrefix()} ${`__${pkg.version} ` } __` .toUpperCase (); }export function getAppEnvConfig ( ) { const ENV_NAME = getConfigFileName (import .meta .env ); const ENV = (import .meta .env .DEV ? (import .meta .env ) : window [ENV_NAME ]); const { VITE_GLOB_APP_TITLE , VITE_GLOB_API_URL , VITE_GLOB_APP_SHORT_NAME , VITE_GLOB_API_URL_PREFIX , VITE_GLOB_UPLOAD_URL , VITE_GLOB_PROD_MOCK , VITE_GLOB_IMG_URL , } = ENV ; if (!/^[a-zA-Z\_]*$/ .test (VITE_GLOB_APP_SHORT_NAME )) { warn ( `VITE_GLOB_APP_SHORT_NAME Variables can only be characters/underscores, please modify in the environment variables and re-running.` ); } return { VITE_GLOB_APP_TITLE , VITE_GLOB_API_URL , VITE_GLOB_APP_SHORT_NAME , VITE_GLOB_API_URL_PREFIX , VITE_GLOB_UPLOAD_URL , VITE_GLOB_PROD_MOCK , VITE_GLOB_IMG_URL , }; }export const devMode = 'development' ;export const prodMode = 'production' ;export function getEnv ( ) { return import .meta .env .MODE ; }export function isDevMode ( ) { return import .meta .env .DEV ; }export function isProdMode ( ) { return import .meta .env .PROD ; }
换名读取 以VITE_XXX的方式在项目中使用,终归是不方便。这里我们提供一种读取方式,更换其名称。
创建src/hooks/setting/index.js
hooks/setting/index.js import { warn } from '@/utils/log' ;import { getAppEnvConfig } from '@/utils/env' ;export const useGlobSetting = ( ) => { const { VITE_GLOB_APP_TITLE , VITE_GLOB_API_URL , VITE_GLOB_APP_SHORT_NAME , VITE_GLOB_API_URL_PREFIX , VITE_GLOB_UPLOAD_URL , VITE_GLOB_PROD_MOCK , VITE_GLOB_IMG_URL , } = getAppEnvConfig (); if (!/[a-zA-Z\_]*/ .test (VITE_GLOB_APP_SHORT_NAME )) { warn ( `VITE_GLOB_APP_SHORT_NAME Variables can only be characters/underscores, please modify in the environment variables and re-running.` ); } const glob = { title : VITE_GLOB_APP_TITLE , apiUrl : VITE_GLOB_API_URL , shortName : VITE_GLOB_APP_SHORT_NAME , urlPrefix : VITE_GLOB_API_URL_PREFIX , uploadUrl : VITE_GLOB_UPLOAD_URL , prodMock : VITE_GLOB_PROD_MOCK , imgUrl : VITE_GLOB_IMG_URL , }; return glob; };
Env解析工具 根目录创建build/utils.js
文件,用来获取所有.env.*
的配置信息,内容如下
安装工具
npm install dotenv --save-dev
utils.js import fs from 'fs' ;import path from 'path' ;import dotenv from 'dotenv' ;export function isDevFn (mode ) { return mode === 'development' ; }export function isProdFn (mode ) { return mode === 'production' ; }export function isReportMode ( ) { return process.env .REPORT === 'true' ; }export function wrapperEnv (envConf ) { const ret = {}; for (const envName of Object .keys (envConf)) { let realName = envConf[envName].replace (/\\n/g , '\n' ); realName = realName === 'true' ? true : realName === 'false' ? false : realName; if (envName === 'VITE_PORT' ) { realName = Number (realName); } if (envName === 'VITE_PROXY' ) { try { realName = JSON .parse (realName); } catch (error) {} } ret[envName] = realName; process.env [envName] = realName; } return ret; }export function getEnvConfig (match = 'VITE_GLOB_' , confFiles = ['.env' , '.env.production' ] ) { let envConfig = {}; confFiles.forEach ((item ) => { try { const env = dotenv.parse (fs.readFileSync (path.resolve (process.cwd (), item))); envConfig = { ...envConfig, ...env }; } catch (error) {} }); Object .keys (envConfig).forEach ((key ) => { const reg = new RegExp (`^(${match} )` ); if (!reg.test (key)) { Reflect .deleteProperty (envConfig, key); } }); return envConfig; }export function getRootPath (...dir ) { return path.resolve (process.cwd (), ...dir); }
挂载Naive UI上下文 挂载 Naive-ui 脱离上下文的 API,在 setup 外使用 useDialog、useMessage、useNotification、useLoadingBar,可以通过 createDiscreteApi 来构建对应的 API。
在plugins/
目录创建 naiveDiscreateApi.js
naiveDiscreateApi.js import * as NaiveUI from 'naive-ui' ;import { computed } from 'vue' ;import { useDesignSettingWithOut } from '@/store/modules/designSetting' ;import { lighten } from '@/utils/index' ;export function setupNaiveDiscreteApi ( ) { const designStore = useDesignSettingWithOut (); const configProviderPropsRef = computed (() => ({ theme : designStore.darkTheme ? NaiveUI .darkTheme : undefined , themeOverrides : { common : { primaryColor : designStore.appTheme , primaryColorHover : lighten (designStore.appTheme , 6 ), primaryColorPressed : lighten (designStore.appTheme , 6 ), }, LoadingBar : { colorLoading : designStore.appTheme , }, }, })); const { message, dialog, notification, loadingBar } = NaiveUI .createDiscreteApi ( ['message' , 'dialog' , 'notification' , 'loadingBar' ], { configProviderProps : configProviderPropsRef, } ); window ['$message' ] = message; window ['$dialog' ] = dialog; window ['$notification' ] = notification; window ['$loading' ] = loadingBar; }
修改plugins/index.js
,添加如下代码
index.js export { setupNaive } from '@/plugins/naive' ;export { setupNaiveDiscreteApi } from '@/plugins/naiveDiscreteApi' ;
修改main.js
,添加如下代码
main.js import { createApp } from 'vue' import App from './App.vue' import { setupStore } from './store' import { setupNaive, setupNaiveDiscreteApi } from './plugins' import router, { setupRouter } from './router' ;async function bootstrap ( ) { const app = createApp (App ); setupStore (app); setupNaive (app); setupNaiveDiscreteApi (); setupRouter (app); await router.isReady (); app.mount ('#app' , true ); }bootstrap ();