30 changed files with 251 additions and 388 deletions
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 110 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 10 KiB |
@ -1,51 +0,0 @@ |
|||||
import { isServer } from '/@/utils/is'; |
|
||||
let lastTime = 0; |
|
||||
const prefixes = 'webkit moz ms o'.split(' '); |
|
||||
|
|
||||
let requestAnimationFrame: typeof window.requestAnimationFrame; |
|
||||
let cancelAnimationFrame: typeof window.cancelAnimationFrame; |
|
||||
(() => { |
|
||||
const NO_LOOP: any = () => {}; |
|
||||
const getWindowFrame = (name: string) => { |
|
||||
return name as any; |
|
||||
}; |
|
||||
if (isServer) { |
|
||||
requestAnimationFrame = cancelAnimationFrame = NO_LOOP; |
|
||||
} else { |
|
||||
requestAnimationFrame = window.requestAnimationFrame; |
|
||||
cancelAnimationFrame = window.cancelAnimationFrame; |
|
||||
let prefix; |
|
||||
for (let i = 0; i < prefixes.length; i++) { |
|
||||
if (requestAnimationFrame && cancelAnimationFrame) { |
|
||||
break; |
|
||||
} |
|
||||
prefix = prefixes[i]; |
|
||||
requestAnimationFrame = |
|
||||
requestAnimationFrame || window[getWindowFrame(prefix + 'RequestAnimationFrame')]; |
|
||||
cancelAnimationFrame = |
|
||||
cancelAnimationFrame || |
|
||||
window[getWindowFrame(prefix + 'CancelAnimationFrame')] || |
|
||||
window[getWindowFrame(prefix + 'CancelRequestAnimationFrame')]; |
|
||||
} |
|
||||
|
|
||||
// If the current browser does not support requestAnimationFrame and cancelAnimationFrame, it will fall back to setTimeout
|
|
||||
if (!requestAnimationFrame || !cancelAnimationFrame) { |
|
||||
requestAnimationFrame = function (callback: Fn) { |
|
||||
const currTime = new Date().getTime(); |
|
||||
const timeToCall = Math.max(0, 16 - (currTime - lastTime)); |
|
||||
const id = window.setTimeout(() => { |
|
||||
/* eslint-disable-next-line */ |
|
||||
callback(currTime + timeToCall); |
|
||||
}, timeToCall); |
|
||||
lastTime = currTime + timeToCall; |
|
||||
return id; |
|
||||
}; |
|
||||
|
|
||||
cancelAnimationFrame = function (id: number) { |
|
||||
window.clearTimeout(id); |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
})(); |
|
||||
|
|
||||
export { requestAnimationFrame, cancelAnimationFrame }; |
|
||||
@ -1,101 +0,0 @@ |
|||||
function getTypeVersion() { |
|
||||
const userAgent = navigator.userAgent.toLowerCase(); |
|
||||
|
|
||||
const browserTypes = { |
|
||||
IE: /(?:msie|trident.*rv).([\d.]+)/, |
|
||||
Edge: /edge.([\d.]+)/, |
|
||||
Chrome: /chrome.([\d.]+)/, |
|
||||
Firefox: /firefox.([\d.]+)/, |
|
||||
Opera: /opera.([\d.]+)/, |
|
||||
Safari: /(?:safari|version).([\d.]+)/, |
|
||||
}; |
|
||||
type BrowserKeys = keyof typeof browserTypes; |
|
||||
|
|
||||
/** browser type */ |
|
||||
let type!: BrowserKeys | null; |
|
||||
/** browser version */ |
|
||||
let version!: string | null; |
|
||||
|
|
||||
for (type in browserTypes) { |
|
||||
if ((version = browserTypes[type as BrowserKeys].exec(userAgent) as any)) { |
|
||||
version = version[1]; |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (version) { |
|
||||
if (type === 'IE') { |
|
||||
try { |
|
||||
document.execCommand('BackgroundImageCache', false, true as any); |
|
||||
} catch (error) { |
|
||||
console.log(error); |
|
||||
} |
|
||||
} |
|
||||
} else { |
|
||||
type = version = null; |
|
||||
} |
|
||||
return { type, version }; |
|
||||
} |
|
||||
|
|
||||
const { type, version } = getTypeVersion(); |
|
||||
|
|
||||
export function getType() { |
|
||||
return type; |
|
||||
} |
|
||||
|
|
||||
export function getVersion() { |
|
||||
return version; |
|
||||
} |
|
||||
|
|
||||
export function isIeFn() { |
|
||||
return type === 'IE'; |
|
||||
} |
|
||||
|
|
||||
export function isChromeFn() { |
|
||||
return type === 'Chrome'; |
|
||||
} |
|
||||
|
|
||||
export function isEdgeFn() { |
|
||||
return type === 'Edge'; |
|
||||
} |
|
||||
|
|
||||
export function isSafariFn() { |
|
||||
return type === 'Safari'; |
|
||||
} |
|
||||
|
|
||||
export function isFirefoxFn() { |
|
||||
return type === 'Firefox'; |
|
||||
} |
|
||||
|
|
||||
export function isOperaFn() { |
|
||||
return type === 'Opera'; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* set page Title |
|
||||
* @param {*} title :page Title |
|
||||
*/ |
|
||||
function setDocumentTitle(title: string) { |
|
||||
document.title = title; |
|
||||
const ua = navigator.userAgent; |
|
||||
const regex = /\bMicroMessenger\/([\d.]+)/; |
|
||||
// 兼容
|
|
||||
if (regex.test(ua) && /ip(hone|od|ad)/i.test(ua)) { |
|
||||
const i = document.createElement('iframe'); |
|
||||
i.src = '/favicon.ico'; |
|
||||
i.style.display = 'none'; |
|
||||
i.onload = function () { |
|
||||
setTimeout(function () { |
|
||||
i.remove(); |
|
||||
}, 9); |
|
||||
}; |
|
||||
document.body.appendChild(i); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export function setTitle(title: string, appTitle?: string) { |
|
||||
if (title) { |
|
||||
const _title = title ? ` ${title}-${appTitle} ` : `${appTitle}`; |
|
||||
setDocumentTitle(_title); |
|
||||
} |
|
||||
} |
|
||||
@ -1,137 +0,0 @@ |
|||||
import './exception.less'; |
|
||||
|
|
||||
import type { PropType } from 'vue'; |
|
||||
|
|
||||
import { Result, Button } from 'ant-design-vue'; |
|
||||
import { defineComponent, ref, computed, unref } from 'vue'; |
|
||||
|
|
||||
import { ExceptionEnum } from '/@/enums/exceptionEnum'; |
|
||||
|
|
||||
import netWorkImg from '/@/assets/images/exception/net-work.png'; |
|
||||
import notDataImg from '/@/assets/images/no-data.png'; |
|
||||
|
|
||||
import { useRoute } from 'vue-router'; |
|
||||
|
|
||||
import { useGo, useRedo } from '/@/hooks/web/usePage'; |
|
||||
import { PageEnum } from '/@/enums/pageEnum'; |
|
||||
import { useI18n } from '/@/hooks/web/useI18n'; |
|
||||
|
|
||||
interface MapValue { |
|
||||
title: string; |
|
||||
subTitle: string; |
|
||||
btnText?: string; |
|
||||
icon?: string; |
|
||||
handler?: Fn; |
|
||||
status?: string; |
|
||||
} |
|
||||
|
|
||||
export default defineComponent({ |
|
||||
name: 'ErrorPage', |
|
||||
props: { |
|
||||
// 状态码
|
|
||||
status: { |
|
||||
type: Number as PropType<number>, |
|
||||
default: ExceptionEnum.PAGE_NOT_FOUND, |
|
||||
}, |
|
||||
|
|
||||
title: { |
|
||||
type: String as PropType<string>, |
|
||||
default: '', |
|
||||
}, |
|
||||
|
|
||||
subTitle: { |
|
||||
type: String as PropType<string>, |
|
||||
default: '', |
|
||||
}, |
|
||||
|
|
||||
full: { |
|
||||
type: Boolean as PropType<boolean>, |
|
||||
default: false, |
|
||||
}, |
|
||||
}, |
|
||||
setup(props) { |
|
||||
const statusMapRef = ref(new Map<string | number, MapValue>()); |
|
||||
|
|
||||
const { query } = useRoute(); |
|
||||
const go = useGo(); |
|
||||
const redo = useRedo(); |
|
||||
const { t } = useI18n(); |
|
||||
|
|
||||
const getStatus = computed(() => { |
|
||||
const { status: routeStatus } = query; |
|
||||
const { status } = props; |
|
||||
return Number(routeStatus) || status; |
|
||||
}); |
|
||||
|
|
||||
const getMapValue = computed( |
|
||||
(): MapValue => { |
|
||||
return unref(statusMapRef).get(unref(getStatus)) as MapValue; |
|
||||
} |
|
||||
); |
|
||||
|
|
||||
const backLoginI18n = t('sys.exception.backLogin'); |
|
||||
const backHomeI18n = t('sys.exception.backHome'); |
|
||||
|
|
||||
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_ACCESS, { |
|
||||
title: '403', |
|
||||
status: `${ExceptionEnum.PAGE_NOT_ACCESS}`, |
|
||||
subTitle: t('sys.exception.subTitle403'), |
|
||||
btnText: props.full ? backLoginI18n : backHomeI18n, |
|
||||
handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()), |
|
||||
}); |
|
||||
|
|
||||
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_FOUND, { |
|
||||
title: '404', |
|
||||
status: `${ExceptionEnum.PAGE_NOT_FOUND}`, |
|
||||
subTitle: t('sys.exception.subTitle404'), |
|
||||
btnText: props.full ? backLoginI18n : backHomeI18n, |
|
||||
handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()), |
|
||||
}); |
|
||||
|
|
||||
unref(statusMapRef).set(ExceptionEnum.ERROR, { |
|
||||
title: '500', |
|
||||
status: `${ExceptionEnum.ERROR}`, |
|
||||
subTitle: t('sys.exception.subTitle500'), |
|
||||
btnText: backHomeI18n, |
|
||||
handler: () => go(), |
|
||||
}); |
|
||||
|
|
||||
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_DATA, { |
|
||||
title: t('sys.exception.noDataTitle'), |
|
||||
subTitle: '', |
|
||||
btnText: t('common.redo'), |
|
||||
handler: () => redo(), |
|
||||
icon: notDataImg, |
|
||||
}); |
|
||||
|
|
||||
unref(statusMapRef).set(ExceptionEnum.NET_WORK_ERROR, { |
|
||||
title: t('sys.exception.networkErrorTitle'), |
|
||||
subTitle: t('sys.exception.networkErrorSubTitle'), |
|
||||
btnText: 'Refresh', |
|
||||
handler: () => redo(), |
|
||||
icon: netWorkImg, |
|
||||
}); |
|
||||
|
|
||||
return () => { |
|
||||
const { title, subTitle, btnText, icon, handler, status } = unref(getMapValue) || {}; |
|
||||
return ( |
|
||||
<Result |
|
||||
class="exception " |
|
||||
status={status as any} |
|
||||
title={props.title || title} |
|
||||
sub-title={props.subTitle || subTitle} |
|
||||
> |
|
||||
{{ |
|
||||
extra: () => |
|
||||
btnText && ( |
|
||||
<Button type="primary" onClick={handler}> |
|
||||
{() => btnText} |
|
||||
</Button> |
|
||||
), |
|
||||
icon: () => (icon ? <img src={icon} /> : null), |
|
||||
}} |
|
||||
</Result> |
|
||||
); |
|
||||
}; |
|
||||
}, |
|
||||
}); |
|
||||
@ -0,0 +1,155 @@ |
|||||
|
<script lang="tsx"> |
||||
|
import type { PropType } from 'vue'; |
||||
|
|
||||
|
import { Result, Button } from 'ant-design-vue'; |
||||
|
import { defineComponent, ref, computed, unref } from 'vue'; |
||||
|
|
||||
|
import { ExceptionEnum } from '/@/enums/exceptionEnum'; |
||||
|
|
||||
|
import notDataSvg from '/@/assets/svg/no-data.svg'; |
||||
|
import netWorkSvg from '/@/assets/svg/net-error.svg'; |
||||
|
|
||||
|
import { useRoute } from 'vue-router'; |
||||
|
import { useDesign } from '/@/hooks/web/useDesign'; |
||||
|
import { useI18n } from '/@/hooks/web/useI18n'; |
||||
|
import { useGo, useRedo } from '/@/hooks/web/usePage'; |
||||
|
|
||||
|
import { PageEnum } from '/@/enums/pageEnum'; |
||||
|
|
||||
|
interface MapValue { |
||||
|
title: string; |
||||
|
subTitle: string; |
||||
|
btnText?: string; |
||||
|
icon?: string; |
||||
|
handler?: Fn; |
||||
|
status?: string; |
||||
|
} |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
name: 'ErrorPage', |
||||
|
props: { |
||||
|
// 状态码 |
||||
|
status: { |
||||
|
type: Number as PropType<number>, |
||||
|
default: ExceptionEnum.PAGE_NOT_FOUND, |
||||
|
}, |
||||
|
|
||||
|
title: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '', |
||||
|
}, |
||||
|
|
||||
|
subTitle: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '', |
||||
|
}, |
||||
|
|
||||
|
full: { |
||||
|
type: Boolean as PropType<boolean>, |
||||
|
default: false, |
||||
|
}, |
||||
|
}, |
||||
|
setup(props) { |
||||
|
const statusMapRef = ref(new Map<string | number, MapValue>()); |
||||
|
|
||||
|
const { query } = useRoute(); |
||||
|
const go = useGo(); |
||||
|
const redo = useRedo(); |
||||
|
const { t } = useI18n(); |
||||
|
const { prefixCls } = useDesign('app-exception-page'); |
||||
|
|
||||
|
const getStatus = computed(() => { |
||||
|
const { status: routeStatus } = query; |
||||
|
const { status } = props; |
||||
|
return Number(routeStatus) || status; |
||||
|
}); |
||||
|
|
||||
|
const getMapValue = computed( |
||||
|
(): MapValue => { |
||||
|
return unref(statusMapRef).get(unref(getStatus)) as MapValue; |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
const backLoginI18n = t('sys.exception.backLogin'); |
||||
|
const backHomeI18n = t('sys.exception.backHome'); |
||||
|
|
||||
|
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_ACCESS, { |
||||
|
title: '403', |
||||
|
status: `${ExceptionEnum.PAGE_NOT_ACCESS}`, |
||||
|
subTitle: t('sys.exception.subTitle403'), |
||||
|
btnText: props.full ? backLoginI18n : backHomeI18n, |
||||
|
handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()), |
||||
|
}); |
||||
|
|
||||
|
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_FOUND, { |
||||
|
title: '404', |
||||
|
status: `${ExceptionEnum.PAGE_NOT_FOUND}`, |
||||
|
subTitle: t('sys.exception.subTitle404'), |
||||
|
btnText: props.full ? backLoginI18n : backHomeI18n, |
||||
|
handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()), |
||||
|
}); |
||||
|
|
||||
|
unref(statusMapRef).set(ExceptionEnum.ERROR, { |
||||
|
title: '500', |
||||
|
status: `${ExceptionEnum.ERROR}`, |
||||
|
subTitle: t('sys.exception.subTitle500'), |
||||
|
btnText: backHomeI18n, |
||||
|
handler: () => go(), |
||||
|
}); |
||||
|
|
||||
|
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_DATA, { |
||||
|
title: t('sys.exception.noDataTitle'), |
||||
|
subTitle: '', |
||||
|
btnText: t('common.redo'), |
||||
|
handler: () => redo(), |
||||
|
icon: notDataSvg, |
||||
|
}); |
||||
|
|
||||
|
unref(statusMapRef).set(ExceptionEnum.NET_WORK_ERROR, { |
||||
|
title: t('sys.exception.networkErrorTitle'), |
||||
|
subTitle: t('sys.exception.networkErrorSubTitle'), |
||||
|
btnText: t('common.redo'), |
||||
|
handler: () => redo(), |
||||
|
icon: netWorkSvg, |
||||
|
}); |
||||
|
|
||||
|
return () => { |
||||
|
const { title, subTitle, btnText, icon, handler, status } = unref(getMapValue) || {}; |
||||
|
return ( |
||||
|
<Result |
||||
|
class={prefixCls} |
||||
|
status={status as any} |
||||
|
title={props.title || title} |
||||
|
sub-title={props.subTitle || subTitle} |
||||
|
> |
||||
|
{{ |
||||
|
extra: () => |
||||
|
btnText && ( |
||||
|
<Button type="primary" onClick={handler}> |
||||
|
{() => btnText} |
||||
|
</Button> |
||||
|
), |
||||
|
icon: () => (icon ? <img src={icon} /> : null), |
||||
|
}} |
||||
|
</Result> |
||||
|
); |
||||
|
}; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
|
<style lang="less"> |
||||
|
@prefix-cls: ~'@{namespace}-app-exception-page'; |
||||
|
|
||||
|
.@{prefix-cls} { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
flex-direction: column; |
||||
|
|
||||
|
.ant-result-icon { |
||||
|
img { |
||||
|
max-width: 400px; |
||||
|
max-height: 300px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -1,5 +0,0 @@ |
|||||
.exception { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
@ -1 +1 @@ |
|||||
export { default as Exception } from './Exception'; |
export { default as Exception } from './Exception.vue'; |
||||
|
|||||
Loading…
Reference in new issue