mirror of
https://gitee.com/bootx/dax-pay-ui.git
synced 2025-09-24 13:05:02 +00:00
wip: code adjustment and optimization
This commit is contained in:
@@ -9,14 +9,13 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { ConfigProvider } from 'ant-design-vue';
|
||||
import { AppProvider } from '/@/components/Application';
|
||||
|
||||
import { initAppConfigStore } from '/@/logics/initAppConfig';
|
||||
|
||||
import { useLockPage } from '/@/hooks/web/useLockPage';
|
||||
import { useLocale } from '/@/locales/useLocale';
|
||||
|
||||
import { AppProvider } from '/@/components/Application';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'App',
|
||||
components: { ConfigProvider, AppProvider },
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 9.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
Binary file not shown.
Before Width: | Height: | Size: 110 KiB |
1
src/assets/svg/net-error.svg
Normal file
1
src/assets/svg/net-error.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 25 KiB |
1
src/assets/svg/no-data.svg
Normal file
1
src/assets/svg/no-data.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 10 KiB |
@@ -7,7 +7,6 @@
|
||||
import { defineComponent, reactive, computed, watch, onMounted, unref, toRef } from 'vue';
|
||||
import { countToProps } from './props';
|
||||
import { isNumber } from '/@/utils/is';
|
||||
import { requestAnimationFrame, cancelAnimationFrame } from '/@/utils/animation';
|
||||
export default defineComponent({
|
||||
name: 'CountTo',
|
||||
props: countToProps,
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import { isFunction, isUnDef } from '/@/utils/is';
|
||||
import { ref, unref } from 'vue';
|
||||
import { requestAnimationFrame } from '/@/utils/animation';
|
||||
|
||||
export interface ScrollToParams {
|
||||
el: HTMLElement;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import type { AppRouteRecordRaw } from '/@/router/types';
|
||||
import ParentLayout from '/@/layouts/page/ParentView.vue';
|
||||
|
||||
const EXCEPTION_COMPONENT = () => import('../views/sys/exception/Exception');
|
||||
const EXCEPTION_COMPONENT = () => import('../views/sys/exception/Exception.vue');
|
||||
|
||||
/**
|
||||
* @description: default layout
|
||||
|
@@ -2,7 +2,7 @@ import type { Router } from 'vue-router';
|
||||
|
||||
import { useGlobSetting } from '/@/hooks/setting';
|
||||
|
||||
import { setTitle } from '/@/utils/browser';
|
||||
import { setTitle } from '/@/utils';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
import { REDIRECT_NAME } from '/@/router/constant';
|
||||
|
@@ -4,7 +4,7 @@ import { getParentLayout, LAYOUT } from '/@/router/constant';
|
||||
import { ExceptionEnum } from '/@/enums/exceptionEnum';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
|
||||
const ExceptionPage = () => import('/@/views/sys/exception/Exception');
|
||||
const ExceptionPage = () => import('/@/views/sys/exception/Exception.vue');
|
||||
|
||||
const page: AppRouteModule = {
|
||||
path: '/page-demo',
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -6,7 +6,7 @@
|
||||
* @return Boolean
|
||||
*/
|
||||
export function isHexColor(color: string) {
|
||||
const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
|
||||
const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/;
|
||||
return reg.test(color);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export function hexToRGB(hex: string) {
|
||||
}
|
||||
sHex = sColorNew;
|
||||
}
|
||||
const sColorChange = [];
|
||||
const sColorChange: number[] = [];
|
||||
for (let i = 1; i < 7; i += 2) {
|
||||
sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2)));
|
||||
}
|
||||
|
@@ -14,27 +14,4 @@ export function formatToDate(date: moment.MomentInput = null, format = DATE_FORM
|
||||
return moment(date).format(format);
|
||||
}
|
||||
|
||||
export function formatAgo(str: string | number) {
|
||||
if (!str) return '';
|
||||
const date = new Date(Number(str));
|
||||
const time = new Date().getTime() - date.getTime(); // 现在的时间-传入的时间 = 相差的时间(单位 = 毫秒)
|
||||
if (time < 0) {
|
||||
return '';
|
||||
} else if (time / 1000 < 30) {
|
||||
return '刚刚';
|
||||
} else if (time / 1000 < 60) {
|
||||
return parseInt(String(time / 1000)) + '秒前';
|
||||
} else if (time / 60000 < 60) {
|
||||
return parseInt(String(time / 60000)) + '分钟前';
|
||||
} else if (time / 3600000 < 24) {
|
||||
return parseInt(String(time / 3600000)) + '小时前';
|
||||
} else if (time / 86400000 < 31) {
|
||||
return parseInt(String(time / 86400000)) + '天前';
|
||||
} else if (time / 2592000000 < 12) {
|
||||
return parseInt(String(time / 2592000000)) + '月前';
|
||||
} else {
|
||||
return parseInt(String(time / 31536000000)) + '年前';
|
||||
}
|
||||
}
|
||||
|
||||
export const dateUtil = moment;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import { createStorage } from '/@/utils/cache';
|
||||
import { isIeFn } from '/@/utils/browser';
|
||||
|
||||
import { BASE_LOCAL_CACHE_KEY, BASE_SESSION_CACHE_KEY } from '/@/enums/cacheEnum';
|
||||
|
||||
@@ -127,9 +126,5 @@ export function persistentCache() {
|
||||
}
|
||||
}
|
||||
|
||||
if (isIeFn() && (document as any).attachEvent) {
|
||||
(document as any).attachEvent('onstorage', storageChange);
|
||||
} else {
|
||||
window.addEventListener('storage', storageChange);
|
||||
}
|
||||
})();
|
||||
|
@@ -81,7 +81,9 @@ export class VAxios {
|
||||
// 请求拦截器配置处理
|
||||
this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
|
||||
// If cancel repeat request is turned on, then cancel repeat request is prohibited
|
||||
const { headers: { ignoreCancelToken } = { ignoreCancelToken: false } } = config;
|
||||
const {
|
||||
headers: { ignoreCancelToken = false },
|
||||
} = config;
|
||||
!ignoreCancelToken && axiosCanceler.addPending(config);
|
||||
if (requestInterceptors && isFunction(requestInterceptors)) {
|
||||
config = requestInterceptors(config);
|
||||
|
@@ -99,3 +99,32 @@ export function getLastItem<T extends any>(list: T) {
|
||||
return Array.from(list.values()).slice(-1)[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
@@ -86,21 +86,7 @@ export function isElement(val: unknown): val is Element {
|
||||
|
||||
export const isServer = typeof window === 'undefined';
|
||||
|
||||
export const isClient = typeof window !== 'undefined';
|
||||
|
||||
export function isImageDom(o: Element) {
|
||||
return o && ['IMAGE', 'IMG'].includes(o.tagName);
|
||||
}
|
||||
|
||||
export function isTextarea(element: Element | null): element is HTMLTextAreaElement {
|
||||
return element !== null && element.tagName.toLowerCase() === 'textarea';
|
||||
}
|
||||
|
||||
export function isMobile(): boolean {
|
||||
return !!navigator.userAgent.match(
|
||||
/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
|
||||
);
|
||||
}
|
||||
export const isClient = !isServer;
|
||||
|
||||
export function isUrl(path: string): boolean {
|
||||
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
|
||||
|
@@ -4,13 +4,16 @@
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicModal } from '/@/components/Modal/index';
|
||||
import { ErrorInfo } from '/@/store/modules/error';
|
||||
import { Description, useDescription } from '/@/components/Description/index';
|
||||
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
import { ErrorInfo } from '/@/store/modules/error';
|
||||
|
||||
import { getDescSchema } from './data';
|
||||
|
||||
export default defineComponent({
|
||||
@@ -24,10 +27,12 @@
|
||||
},
|
||||
setup() {
|
||||
const { t } = useI18n();
|
||||
|
||||
const [register] = useDescription({
|
||||
column: 2,
|
||||
schema: getDescSchema(),
|
||||
});
|
||||
|
||||
return {
|
||||
register,
|
||||
useI18n,
|
||||
|
@@ -53,7 +53,6 @@ export function getColumns(): BasicColumn[] {
|
||||
{
|
||||
dataIndex: 'stack',
|
||||
title: t('sys.errorLog.tableColumnStackMsg'),
|
||||
width: 300,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<template v-for="src in imgListRef" :key="src">
|
||||
<template v-for="src in imgList" :key="src">
|
||||
<img :src="src" v-show="false" />
|
||||
</template>
|
||||
<DetailModal :info="rowInfoRef" @register="registerModal" />
|
||||
<DetailModal :info="rowInfo" @register="registerModal" />
|
||||
<BasicTable @register="register" class="error-handle-table">
|
||||
<template #toolbar>
|
||||
<a-button @click="fireVueError" type="primary">
|
||||
@@ -50,8 +50,8 @@
|
||||
name: 'ErrorHandler',
|
||||
components: { DetailModal, BasicTable, TableAction },
|
||||
setup() {
|
||||
const rowInfoRef = ref<ErrorInfo>();
|
||||
const imgListRef = ref<string[]>([]);
|
||||
const rowInfo = ref<ErrorInfo>();
|
||||
const imgList = ref<string[]>([]);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
}
|
||||
// 查看详情
|
||||
function handleDetail(row: ErrorInfo) {
|
||||
rowInfoRef.value = row;
|
||||
rowInfo.value = row;
|
||||
openModal(true);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
}
|
||||
|
||||
function fireResourceError() {
|
||||
imgListRef.value.push(`${new Date().getTime()}.png`);
|
||||
imgList.value.push(`${new Date().getTime()}.png`);
|
||||
}
|
||||
|
||||
async function fireAjaxError() {
|
||||
@@ -107,8 +107,8 @@
|
||||
fireVueError,
|
||||
fireResourceError,
|
||||
fireAjaxError,
|
||||
imgListRef,
|
||||
rowInfoRef,
|
||||
imgList,
|
||||
rowInfo,
|
||||
t,
|
||||
};
|
||||
},
|
||||
|
@@ -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>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
155
src/views/sys/exception/Exception.vue
Normal file
155
src/views/sys/exception/Exception.vue
Normal file
@@ -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';
|
||||
|
@@ -1,31 +1,44 @@
|
||||
<template>
|
||||
<div class="iframe-page" :style="getWrapStyle">
|
||||
<div :class="prefixCls" :style="getWrapStyle">
|
||||
<Spin :spinning="loading" size="large" :style="getWrapStyle">
|
||||
<iframe :src="frameSrc" class="iframe-page__main" ref="frameRef"></iframe>
|
||||
<iframe :src="frameSrc" :class="`${prefixCls}__main`" ref="frameRef"></iframe>
|
||||
</Spin>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, ref, unref, onMounted, nextTick, computed } from 'vue';
|
||||
import type { CSSProperties } from 'vue';
|
||||
import { defineComponent, ref, unref, onMounted, nextTick, computed } from 'vue';
|
||||
import { Spin } from 'ant-design-vue';
|
||||
|
||||
import { getViewportOffset } from '/@/utils/domUtils';
|
||||
|
||||
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
|
||||
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'IFrame',
|
||||
components: { Spin },
|
||||
props: {
|
||||
frameSrc: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
frameSrc: propTypes.string.def(''),
|
||||
},
|
||||
setup() {
|
||||
const loadingRef = ref(false);
|
||||
const loading = ref(false);
|
||||
const topRef = ref(50);
|
||||
const heightRef = ref(window.innerHeight);
|
||||
const frameRef = ref<HTMLElement | null>(null);
|
||||
const frameRef = ref<HTMLFrameElement | null>(null);
|
||||
|
||||
const { prefixCls } = useDesign('iframe-page');
|
||||
useWindowSizeFn(calcHeight, 150, { immediate: true });
|
||||
|
||||
const getWrapStyle = computed(
|
||||
(): CSSProperties => {
|
||||
return {
|
||||
height: `${unref(heightRef)}px`,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
function calcHeight() {
|
||||
const iframe = unref(frameRef);
|
||||
@@ -40,21 +53,19 @@
|
||||
iframe.style.height = `${clientHeight}px`;
|
||||
}
|
||||
|
||||
useWindowSizeFn(calcHeight, 150, { immediate: true });
|
||||
|
||||
function hideLoading() {
|
||||
loadingRef.value = false;
|
||||
loading.value = false;
|
||||
calcHeight();
|
||||
}
|
||||
|
||||
function init() {
|
||||
nextTick(() => {
|
||||
const iframe = unref(frameRef);
|
||||
if (!iframe) {
|
||||
return;
|
||||
}
|
||||
if ((iframe as any).attachEvent) {
|
||||
(iframe as any).attachEvent('onload', () => {
|
||||
if (!iframe) return;
|
||||
|
||||
const _frame = iframe as any;
|
||||
if (_frame.attachEvent) {
|
||||
_frame.attachEvent('onload', () => {
|
||||
hideLoading();
|
||||
});
|
||||
} else {
|
||||
@@ -65,23 +76,23 @@
|
||||
});
|
||||
}
|
||||
onMounted(() => {
|
||||
loadingRef.value = true;
|
||||
loading.value = true;
|
||||
init();
|
||||
});
|
||||
|
||||
return {
|
||||
getWrapStyle: computed(() => {
|
||||
return {
|
||||
height: `${unref(heightRef)}px`,
|
||||
};
|
||||
}),
|
||||
loading: loadingRef,
|
||||
getWrapStyle,
|
||||
loading,
|
||||
frameRef,
|
||||
prefixCls,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.iframe-page {
|
||||
@prefix-cls: ~'@{namespace}-iframe-page';
|
||||
|
||||
.@{prefix-cls} {
|
||||
.ant-spin-nested-loading {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
@@ -203,15 +203,12 @@
|
||||
display: flex;
|
||||
width: 40%;
|
||||
height: 74%;
|
||||
// font-size: 50em;
|
||||
font-weight: 700;
|
||||
color: #bababa;
|
||||
background: #141313;
|
||||
border-radius: 30px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
// .respond-to(large-only, { font-size: 25em;});
|
||||
// .respond-to(large-only, { font-size: 30em;});
|
||||
@media (min-width: @screen-xxxl-min) {
|
||||
font-size: 46em;
|
||||
}
|
||||
|
@@ -12,7 +12,9 @@
|
||||
|
||||
const { params, query } = unref(currentRoute);
|
||||
const { path } = params;
|
||||
|
||||
const _path = Array.isArray(path) ? path.join('/') : path;
|
||||
|
||||
replace({
|
||||
path: '/' + _path,
|
||||
query,
|
||||
|
Reference in New Issue
Block a user