mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-28 05:39:34 +08:00
chore: add some notes
This commit is contained in:
86
src/setup/Application.ts
Normal file
86
src/setup/Application.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Application configuration
|
||||
*/
|
||||
|
||||
import type { ProjectConfig } from '/@/types/config';
|
||||
import type { App } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { ThemeModeEnum } from '/@/enums/appEnum';
|
||||
import { PROJ_CFG_KEY } from '/@/enums/cacheEnum';
|
||||
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
import { getLocal } from '/@/utils/helper/persistent';
|
||||
import { isUnDef, isNull } from '/@/utils/is';
|
||||
import {
|
||||
updateGrayMode,
|
||||
updateColorWeak,
|
||||
updateHeaderBgColor,
|
||||
updateSidebarBgColor,
|
||||
} from '/@/setup/theme';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
|
||||
// Used to share global app instances
|
||||
let app: App;
|
||||
|
||||
export function setApp(_app: App): void {
|
||||
app = _app;
|
||||
}
|
||||
|
||||
export function getApp(): App {
|
||||
return app;
|
||||
}
|
||||
|
||||
// TODO Theme switching
|
||||
export function useThemeMode(mode: ThemeModeEnum) {
|
||||
const modeRef = ref(mode);
|
||||
const html = document.documentElement;
|
||||
const clsList = html.classList;
|
||||
|
||||
const change = () => {
|
||||
clsList.contains(mode) ? clsList.remove(mode) : clsList.add(mode);
|
||||
};
|
||||
return {
|
||||
runChangeThemeMode: change,
|
||||
mode: computed(() => modeRef.value),
|
||||
};
|
||||
}
|
||||
|
||||
// Initial project configuration
|
||||
export function initAppConfigStore() {
|
||||
let projCfg: ProjectConfig = getLocal(PROJ_CFG_KEY) as ProjectConfig;
|
||||
if (!projCfg) {
|
||||
projCfg = projectSetting;
|
||||
}
|
||||
const { colorWeak, grayMode, headerBgColor, menuBgColor } = projCfg;
|
||||
try {
|
||||
// if (
|
||||
// themeColor !== primaryColor &&
|
||||
// themeColor &&
|
||||
// process.env.VUE_APP_USE_THEME_REPLACER !== 'TRUE'
|
||||
// ) {
|
||||
// updateTheme(themeColor);
|
||||
// }
|
||||
headerBgColor && updateHeaderBgColor(headerBgColor);
|
||||
menuBgColor && updateSidebarBgColor(menuBgColor);
|
||||
grayMode && updateGrayMode(grayMode);
|
||||
colorWeak && updateColorWeak(colorWeak);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
appStore.commitProjectConfigState(projCfg);
|
||||
}
|
||||
|
||||
// antdv Config Provider
|
||||
export function getConfigProvider() {
|
||||
function transformCellText({ text }: { text: string }) {
|
||||
if (isNull(text) || isUnDef(text)) {
|
||||
return ' - ';
|
||||
}
|
||||
return text;
|
||||
}
|
||||
return {
|
||||
transformCellText,
|
||||
};
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
// Load on demand
|
||||
|
||||
// This module only introduces components globally before login
|
||||
import type { App } from 'vue';
|
||||
|
||||
import {
|
||||
|
@@ -1,14 +0,0 @@
|
||||
@import (reference) '../../design/index.less';
|
||||
|
||||
.app-svg-loading {
|
||||
position: relative;
|
||||
width: auto;
|
||||
|
||||
&__tip {
|
||||
display: block;
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
color: #303133;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
@@ -1,11 +1,16 @@
|
||||
import { Spin } from 'ant-design-vue';
|
||||
import svgImg from '/@/assets/images/loading.svg';
|
||||
|
||||
import './spin.less';
|
||||
Spin.setDefaultIndicator({
|
||||
indicator: () => {
|
||||
return (
|
||||
<div class="app-svg-loading">
|
||||
<div
|
||||
class="app-svg-loading"
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: 'auto',
|
||||
}}
|
||||
>
|
||||
<img src={svgImg} alt="" height="32" width="32" class="g-loading" />
|
||||
</div>
|
||||
);
|
||||
|
86
src/setup/application.ts
Normal file
86
src/setup/application.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Application configuration
|
||||
*/
|
||||
|
||||
import type { ProjectConfig } from '/@/types/config';
|
||||
import type { App } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { ThemeModeEnum } from '/@/enums/appEnum';
|
||||
import { PROJ_CFG_KEY } from '/@/enums/cacheEnum';
|
||||
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
import { getLocal } from '/@/utils/helper/persistent';
|
||||
import { isUnDef, isNull } from '/@/utils/is';
|
||||
import {
|
||||
updateGrayMode,
|
||||
updateColorWeak,
|
||||
updateHeaderBgColor,
|
||||
updateSidebarBgColor,
|
||||
} from '/@/setup/theme';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
|
||||
// Used to share global app instances
|
||||
let app: App;
|
||||
|
||||
export function setApp(_app: App): void {
|
||||
app = _app;
|
||||
}
|
||||
|
||||
export function getApp(): App {
|
||||
return app;
|
||||
}
|
||||
|
||||
// TODO Theme switching
|
||||
export function useThemeMode(mode: ThemeModeEnum) {
|
||||
const modeRef = ref(mode);
|
||||
const html = document.documentElement;
|
||||
const clsList = html.classList;
|
||||
|
||||
const change = () => {
|
||||
clsList.contains(mode) ? clsList.remove(mode) : clsList.add(mode);
|
||||
};
|
||||
return {
|
||||
runChangeThemeMode: change,
|
||||
mode: computed(() => modeRef.value),
|
||||
};
|
||||
}
|
||||
|
||||
// Initial project configuration
|
||||
export function initAppConfigStore() {
|
||||
let projCfg: ProjectConfig = getLocal(PROJ_CFG_KEY) as ProjectConfig;
|
||||
if (!projCfg) {
|
||||
projCfg = projectSetting;
|
||||
}
|
||||
const { colorWeak, grayMode, headerBgColor, menuBgColor } = projCfg;
|
||||
try {
|
||||
// if (
|
||||
// themeColor !== primaryColor &&
|
||||
// themeColor &&
|
||||
// process.env.VUE_APP_USE_THEME_REPLACER !== 'TRUE'
|
||||
// ) {
|
||||
// updateTheme(themeColor);
|
||||
// }
|
||||
headerBgColor && updateHeaderBgColor(headerBgColor);
|
||||
menuBgColor && updateSidebarBgColor(menuBgColor);
|
||||
grayMode && updateGrayMode(grayMode);
|
||||
colorWeak && updateColorWeak(colorWeak);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
appStore.commitProjectConfigState(projCfg);
|
||||
}
|
||||
|
||||
// antdv Config Provider
|
||||
export function getConfigProvider() {
|
||||
function transformCellText({ text }: { text: string }) {
|
||||
if (isNull(text) || isUnDef(text)) {
|
||||
return ' - ';
|
||||
}
|
||||
return text;
|
||||
}
|
||||
return {
|
||||
transformCellText,
|
||||
};
|
||||
}
|
@@ -1,5 +1,9 @@
|
||||
/**
|
||||
* Configure and register global directives
|
||||
*/
|
||||
import type { App } from 'vue';
|
||||
import { setupPermissionDirective } from './permission';
|
||||
export function setupDirectives(app: App) {
|
||||
|
||||
export function setupGlobDirectives(app: App) {
|
||||
setupPermissionDirective(app);
|
||||
}
|
||||
|
@@ -1,5 +1,11 @@
|
||||
/**
|
||||
* Global authority directive
|
||||
* Used for fine-grained control of component permissions
|
||||
* @Example v-auth="RoleEnum.TEST"
|
||||
*/
|
||||
import type { App, Directive, DirectiveBinding } from 'vue';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import type { App } from 'vue';
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
import { PermissionModeEnum } from '/@/enums/appEnum';
|
||||
const { hasPermission } = usePermission();
|
||||
@@ -13,18 +19,28 @@ function isAuth(el: Element, binding: any) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isBackMode() {
|
||||
return appStore.getProjectConfig.permissionMode === PermissionModeEnum.BACK;
|
||||
}
|
||||
|
||||
const mounted = (el: Element, binding: DirectiveBinding<any>) => {
|
||||
if (isBackMode()) return;
|
||||
isAuth(el, binding);
|
||||
};
|
||||
|
||||
const updated = (el: Element, binding: DirectiveBinding<any>) => {
|
||||
if (!isBackMode()) return;
|
||||
isAuth(el, binding);
|
||||
};
|
||||
|
||||
const authDirective: Directive = {
|
||||
mounted,
|
||||
updated,
|
||||
};
|
||||
|
||||
export function setupPermissionDirective(app: App) {
|
||||
app.directive('auth', {
|
||||
mounted(el: Element, binding) {
|
||||
if (isBackMode()) return;
|
||||
isAuth(el, binding);
|
||||
},
|
||||
updated(el: Element, binding) {
|
||||
if (!isBackMode()) return;
|
||||
isAuth(el, binding);
|
||||
},
|
||||
});
|
||||
app.directive('auth', authDirective);
|
||||
}
|
||||
|
||||
export default authDirective;
|
||||
|
@@ -1,11 +1,16 @@
|
||||
/**
|
||||
* Prevent repeated clicks
|
||||
* @Example v-repeat-click="()=>{}"
|
||||
*/
|
||||
import { on, once } from '/@/utils/domUtils';
|
||||
import type { Directive, DirectiveBinding } from 'vue';
|
||||
|
||||
export default {
|
||||
beforeMount(el: Element, binding: any) {
|
||||
let interval: ReturnType<typeof setInterval> | null = null;
|
||||
const repeatDirective: Directive = {
|
||||
beforeMount(el: Element, binding: DirectiveBinding<any>) {
|
||||
let interval: Nullable<IntervalHandle> = null;
|
||||
let startTime = 0;
|
||||
const handler = () => binding.value && binding.value();
|
||||
const clear = () => {
|
||||
const handler = (): void => binding.value && binding.value();
|
||||
const clear = (): void => {
|
||||
if (Date.now() - startTime < 100) {
|
||||
handler();
|
||||
}
|
||||
@@ -13,7 +18,7 @@ export default {
|
||||
interval = null;
|
||||
};
|
||||
|
||||
on(el, 'mousedown', (e) => {
|
||||
on(el, 'mousedown', (e: MouseEvent): void => {
|
||||
if ((e as any).button !== 0) return;
|
||||
startTime = Date.now();
|
||||
once(document as any, 'mouseup', clear);
|
||||
@@ -22,3 +27,5 @@ export default {
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default repeatDirective;
|
||||
|
@@ -1,19 +1,28 @@
|
||||
/**
|
||||
* Used to configure the global error handling function, which can monitor vue errors, script errors, static resource errors and Promise errors
|
||||
*/
|
||||
|
||||
import { errorStore, ErrorInfo } from '/@/store/modules/error';
|
||||
import { useSetting } from '/@/hooks/core/useSetting';
|
||||
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
|
||||
import { App } from 'vue';
|
||||
|
||||
/**
|
||||
* Handling error stack information
|
||||
* @param error
|
||||
*/
|
||||
function processStackMsg(error: Error) {
|
||||
if (!error.stack) {
|
||||
return '';
|
||||
}
|
||||
let stack = error.stack
|
||||
.replace(/\n/gi, '') // 去掉换行,节省传输内容大小
|
||||
.replace(/\bat\b/gi, '@') // chrome中是at,ff中是@
|
||||
.split('@') // 以@分割信息
|
||||
.slice(0, 9) // 最大堆栈长度(Error.stackTraceLimit = 10),所以只取前10条
|
||||
.map((v) => v.replace(/^\s*|\s*$/g, '')) // 去除多余空格
|
||||
.join('~') // 手动添加分隔符,便于后期展示
|
||||
.replace(/\?[^:]+/gi, ''); // 去除js文件链接的多余参数(?x=1之类)
|
||||
.replace(/\n/gi, '') // Remove line breaks to save the size of the transmitted content
|
||||
.replace(/\bat\b/gi, '@') // At in chrome, @ in ff
|
||||
.split('@') // Split information with @
|
||||
.slice(0, 9) // The maximum stack length (Error.stackTraceLimit = 10), so only take the first 10
|
||||
.map((v) => v.replace(/^\s*|\s*$/g, '')) // Remove extra spaces
|
||||
.join('~') // Manually add separators for later display
|
||||
.replace(/\?[^:]+/gi, ''); // Remove redundant parameters of js file links (?x=1 and the like)
|
||||
const msg = error.toString();
|
||||
if (stack.indexOf(msg) < 0) {
|
||||
stack = msg + '@' + stack;
|
||||
@@ -21,6 +30,10 @@ function processStackMsg(error: Error) {
|
||||
return stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* get comp name
|
||||
* @param vm
|
||||
*/
|
||||
function formatComponentName(vm: any) {
|
||||
if (vm.$root === vm) {
|
||||
return {
|
||||
@@ -43,6 +56,10 @@ function formatComponentName(vm: any) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Vue error handling function
|
||||
*/
|
||||
|
||||
function vueErrorHandler(err: Error, vm: any, info: string) {
|
||||
const { name, path } = formatComponentName(vm);
|
||||
errorStore.commitErrorInfoState({
|
||||
@@ -56,6 +73,9 @@ function vueErrorHandler(err: Error, vm: any, info: string) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure script error handling function
|
||||
*/
|
||||
export function scriptErrorHandler(
|
||||
event: Event | string,
|
||||
source?: string,
|
||||
@@ -86,6 +106,9 @@ export function scriptErrorHandler(
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Promise error handling function
|
||||
*/
|
||||
function registerPromiseErrorHandler() {
|
||||
window.addEventListener(
|
||||
'unhandledrejection',
|
||||
@@ -104,8 +127,11 @@ function registerPromiseErrorHandler() {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure monitoring resource loading error handling function
|
||||
*/
|
||||
function registerResourceErrorHandler() {
|
||||
// 监控资源加载错误(img,script,css,以及jsonp)
|
||||
// Monitoring resource loading error(img,script,css,and jsonp)
|
||||
window.addEventListener(
|
||||
'error',
|
||||
function (e: Event) {
|
||||
@@ -129,19 +155,23 @@ function registerResourceErrorHandler() {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure global error handling
|
||||
* @param app
|
||||
*/
|
||||
export function setupErrorHandle(app: App) {
|
||||
const { projectSetting } = useSetting();
|
||||
const { useErrorHandle } = projectSetting;
|
||||
if (!useErrorHandle) {
|
||||
return;
|
||||
}
|
||||
// Vue异常监控;
|
||||
if (!useErrorHandle) return;
|
||||
// Vue exception monitoring;
|
||||
app.config.errorHandler = vueErrorHandler;
|
||||
// js错误
|
||||
|
||||
// script error
|
||||
window.onerror = scriptErrorHandler;
|
||||
// promise 异常
|
||||
|
||||
// promise exception
|
||||
registerPromiseErrorHandler();
|
||||
|
||||
// 静态资源异常
|
||||
// Static resource exception
|
||||
registerResourceErrorHandler();
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { isHexColor, colorIsDark, lighten, darken } from '/@/utils/color';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { MenuThemeEnum } from '/@/enums/menuEnum';
|
||||
import { ThemeEnum } from '/@/enums/appEnum';
|
||||
|
||||
const HEADER_BG_COLOR_VAR = '--header-bg-color';
|
||||
const HEADER_BG_HOVER_COLOR_VAR = '--header-bg-hover-color';
|
||||
@@ -22,14 +22,26 @@ function toggleClass(flag: boolean, clsName: string) {
|
||||
document.body.className = flag ? `${className} ${clsName} ` : className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the status of the project's color weakness mode
|
||||
* @param gray
|
||||
*/
|
||||
export const updateColorWeak = (colorWeak: boolean) => {
|
||||
toggleClass(colorWeak, 'color-weak');
|
||||
};
|
||||
|
||||
/**
|
||||
* Change project gray mode status
|
||||
* @param gray
|
||||
*/
|
||||
export const updateGrayMode = (gray: boolean) => {
|
||||
toggleClass(gray, 'gray-mode');
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the background color of the top header
|
||||
* @param color
|
||||
*/
|
||||
export function updateHeaderBgColor(color: string) {
|
||||
if (!isHexColor(color)) return;
|
||||
// bg color
|
||||
@@ -40,15 +52,20 @@ export function updateHeaderBgColor(color: string) {
|
||||
setCssVar(HEADER_BG_HOVER_COLOR_VAR, hoverColor);
|
||||
setCssVar(HEADER_MENU_ACTIVE_BG_COLOR_VAR, hoverColor);
|
||||
|
||||
// Determine the depth of the color value and automatically switch the theme
|
||||
const isDark = colorIsDark(color);
|
||||
|
||||
appStore.commitProjectConfigState({
|
||||
headerSetting: {
|
||||
theme: isDark ? MenuThemeEnum.DARK : MenuThemeEnum.LIGHT,
|
||||
theme: isDark ? ThemeEnum.DARK : ThemeEnum.LIGHT,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the background color of the left menu
|
||||
* @param color bg color
|
||||
*/
|
||||
export function updateSidebarBgColor(color: string) {
|
||||
if (!isHexColor(color)) return;
|
||||
|
||||
@@ -58,11 +75,12 @@ export function updateSidebarBgColor(color: string) {
|
||||
setCssVar(SIDER_LIGHTEN_2_BG_COLOR, lighten(color, 8));
|
||||
|
||||
// only #ffffff is light
|
||||
// Only when the background color is #fff, the theme of the menu will be changed to light
|
||||
const isLight = ['#fff', '#ffffff'].includes(color.toLowerCase());
|
||||
|
||||
appStore.commitProjectConfigState({
|
||||
menuSetting: {
|
||||
theme: isLight ? MenuThemeEnum.LIGHT : MenuThemeEnum.DARK,
|
||||
theme: isLight ? ThemeEnum.LIGHT : ThemeEnum.DARK,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user