chore: add some notes

This commit is contained in:
vben
2020-11-18 22:41:59 +08:00
parent 815250ed34
commit 46e0875374
87 changed files with 926 additions and 728 deletions

86
src/setup/Application.ts Normal file
View 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,
};
}

View File

@@ -1,5 +1,5 @@
// Load on demand
// This module only introduces components globally before login
import type { App } from 'vue';
import {

View File

@@ -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;
}
}

View File

@@ -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
View 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,
};
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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中是atff中是@
.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();
}

View File

@@ -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,
},
});
}