20 changed files with 7315 additions and 227 deletions
@ -0,0 +1 @@ |
|||||
|
export const MENU_DRAG_STATE = 'MENU_DRAG_STATE'; |
||||
@ -0,0 +1,11 @@ |
|||||
|
import { tryOnUnmounted } from '/@/utils/helper/vueHelper'; |
||||
|
import {} from 'vue'; |
||||
|
import EventHub from '/@/utils/eventHub'; |
||||
|
const eventHub = new EventHub(); |
||||
|
export function useEventHub(): EventHub { |
||||
|
tryOnUnmounted(() => { |
||||
|
eventHub.clear(); |
||||
|
}); |
||||
|
|
||||
|
return eventHub; |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
class EventHub { |
||||
|
private cache: { [key: string]: Array<(data: any) => void> } = {}; |
||||
|
on(eventName: string, fn: (data: any) => void) { |
||||
|
this.cache[eventName] = this.cache[eventName] || []; |
||||
|
this.cache[eventName].push(fn); |
||||
|
} |
||||
|
|
||||
|
once(eventName: string, fn: (data: any) => void) { |
||||
|
const decor = (...args: any[]) => { |
||||
|
fn && fn.apply(this, args); |
||||
|
this.off(eventName, decor); |
||||
|
}; |
||||
|
this.on(eventName, decor); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
emit(eventName: string, data?: any) { |
||||
|
if (this.cache[eventName] === undefined) return; |
||||
|
console.log('======================'); |
||||
|
console.log(this.cache, eventName); |
||||
|
console.log('======================'); |
||||
|
this.cache[eventName].forEach((fn) => fn(data)); |
||||
|
} |
||||
|
off(eventName: string, fn: (data: any) => void) { |
||||
|
if (this.cache[eventName] === undefined || this.cache[eventName].length === 0) return; |
||||
|
const i = this.cache[eventName].indexOf(fn); |
||||
|
if (i === -1) return; |
||||
|
this.cache[eventName].splice(i, 1); |
||||
|
} |
||||
|
|
||||
|
clear() { |
||||
|
this.cache = {}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default EventHub; |
||||
@ -1,30 +0,0 @@ |
|||||
<script lang="tsx"> |
|
||||
import { defineComponent, PropOptions } from 'compatible-vue'; |
|
||||
import { BasicModal } from '@/components/modal/index'; |
|
||||
import { ErrorInfo } from '@/store/modules/error'; |
|
||||
import { Description, useDescription } from '@/components/description/index'; |
|
||||
import { getDescSchema } from './data'; |
|
||||
|
|
||||
export default defineComponent({ |
|
||||
name: 'ErrorLogDetailModal', |
|
||||
props: { |
|
||||
info: { |
|
||||
type: Object, |
|
||||
default: null, |
|
||||
} as PropOptions<ErrorInfo>, |
|
||||
}, |
|
||||
setup(props, { listeners }) { |
|
||||
const [register] = useDescription({ |
|
||||
column: 2, |
|
||||
schema: getDescSchema(), |
|
||||
}); |
|
||||
return () => { |
|
||||
return ( |
|
||||
<BasicModal width={800} title="错误详情" on={listeners}> |
|
||||
<Description data={props.info} onRegister={register} /> |
|
||||
</BasicModal> |
|
||||
); |
|
||||
}; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
@ -1,66 +0,0 @@ |
|||||
import { Tag } from 'ant-design-vue'; |
|
||||
import { BasicColumn } from '@/components/table/index'; |
|
||||
import { ErrorTypeEnum } from '@/store/modules/error'; |
|
||||
import { DescItem } from '@/components/description/index'; |
|
||||
|
|
||||
export function getColumns(): BasicColumn[] { |
|
||||
return [ |
|
||||
{ |
|
||||
dataIndex: 'type', |
|
||||
title: '类型', |
|
||||
width: 80, |
|
||||
customRender: (text: string) => { |
|
||||
const color = |
|
||||
text === ErrorTypeEnum.VUE |
|
||||
? 'green' |
|
||||
: text === ErrorTypeEnum.RESOURCE |
|
||||
? 'cyan' |
|
||||
: text === ErrorTypeEnum.PROMISE |
|
||||
? 'blue' |
|
||||
: ErrorTypeEnum.AJAX |
|
||||
? 'red' |
|
||||
: 'purple'; |
|
||||
return <Tag color={color}>{text}</Tag>; |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
dataIndex: 'url', |
|
||||
title: '地址', |
|
||||
width: 200, |
|
||||
}, |
|
||||
{ |
|
||||
dataIndex: 'time', |
|
||||
title: '时间', |
|
||||
width: 160, |
|
||||
}, |
|
||||
{ |
|
||||
dataIndex: 'file', |
|
||||
title: '文件', |
|
||||
width: 200, |
|
||||
}, |
|
||||
{ |
|
||||
dataIndex: 'name', |
|
||||
title: 'Name', |
|
||||
width: 200, |
|
||||
}, |
|
||||
{ |
|
||||
dataIndex: 'message', |
|
||||
title: '错误信息', |
|
||||
width: 300, |
|
||||
}, |
|
||||
{ |
|
||||
dataIndex: 'stack', |
|
||||
title: 'stack信息', |
|
||||
width: 300, |
|
||||
}, |
|
||||
]; |
|
||||
} |
|
||||
|
|
||||
export function getDescSchema(): DescItem[] { |
|
||||
return getColumns().map((column) => { |
|
||||
return { |
|
||||
field: column.dataIndex!, |
|
||||
label: column.title, |
|
||||
}; |
|
||||
}); |
|
||||
} |
|
||||
@ -1,108 +0,0 @@ |
|||||
<script lang="tsx"> |
|
||||
import { defineComponent, watch, ref, unref } from 'compatible-vue'; |
|
||||
|
|
||||
import DetailModal from './DetailModal.vue'; |
|
||||
import { useModal } from '@/components/modal/index'; |
|
||||
|
|
||||
import { useDesign } from '@/hooks/core/useDesign'; |
|
||||
|
|
||||
import { BasicTable, useTable } from '@/components/table/index'; |
|
||||
|
|
||||
import { errorStore, ErrorInfo } from '@/store/modules/error'; |
|
||||
|
|
||||
import { fireErrorApi } from '@/api/demo/error'; |
|
||||
|
|
||||
import { getColumns } from './data'; |
|
||||
|
|
||||
const { prefixCls } = useDesign('error-handle'); |
|
||||
|
|
||||
export default defineComponent({ |
|
||||
name: 'ErrorHandler', |
|
||||
setup() { |
|
||||
const rowInfoRef = ref<ErrorInfo>(); |
|
||||
const imgListRef = ref<string[]>([]); |
|
||||
const [register, { setTableData }] = useTable({ |
|
||||
titleHelpMessage: '只在`/src/settings/projectSetting.ts` 内的useErrorHandle=true时生效!', |
|
||||
title: '错误日志列表', |
|
||||
columns: getColumns(), |
|
||||
actionColumn: { |
|
||||
width: 80, |
|
||||
title: '操作', |
|
||||
dataIndex: 'action', |
|
||||
customRender: (text: string, recoed: ErrorInfo) => { |
|
||||
return ( |
|
||||
<a-button type="link" size="small" onClick={handleDetail.bind(null, recoed)}> |
|
||||
详情 |
|
||||
</a-button> |
|
||||
); |
|
||||
}, |
|
||||
}, |
|
||||
}); |
|
||||
|
|
||||
const [registerModal, { openModal }] = useModal(); |
|
||||
watch( |
|
||||
() => errorStore.getErrorInfoState, |
|
||||
(list: any[]) => { |
|
||||
setTableData(list); |
|
||||
}, |
|
||||
{ |
|
||||
immediate: true, |
|
||||
} |
|
||||
); |
|
||||
|
|
||||
// 查看详情 |
|
||||
function handleDetail(row: ErrorInfo) { |
|
||||
rowInfoRef.value = row; |
|
||||
openModal({ |
|
||||
visible: true, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
function fireVueError() { |
|
||||
throw new Error('fire vue error!'); |
|
||||
} |
|
||||
|
|
||||
function fireResourceError() { |
|
||||
imgListRef.value.push(`${new Date().getTime()}.png`); |
|
||||
} |
|
||||
|
|
||||
async function fireAjaxError() { |
|
||||
await fireErrorApi(); |
|
||||
} |
|
||||
|
|
||||
return () => ( |
|
||||
<div class={[prefixCls, 'p-4']}> |
|
||||
{unref(imgListRef).map((src) => { |
|
||||
return <img src={src} key={src} class="hidden" />; |
|
||||
})} |
|
||||
|
|
||||
<DetailModal info={unref(rowInfoRef)} onRegister={registerModal} /> |
|
||||
|
|
||||
<BasicTable onRegister={register} class={`${prefixCls}-table`}> |
|
||||
<template slot="toolbar"> |
|
||||
<a-button onClick={fireVueError} type="primary"> |
|
||||
点击触发vue错误 |
|
||||
</a-button> |
|
||||
<a-button onClick={fireResourceError} type="primary"> |
|
||||
点击触发resource错误 |
|
||||
</a-button> |
|
||||
<a-button onClick={fireAjaxError} type="primary"> |
|
||||
点击触发ajax错误 |
|
||||
</a-button> |
|
||||
</template> |
|
||||
</BasicTable> |
|
||||
</div> |
|
||||
); |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
<style scoped lang="less"> |
|
||||
@import (reference) '~@design'; |
|
||||
@prefix-cls: ~'@{namespace}-error-handle'; |
|
||||
|
|
||||
.@{prefix-cls} { |
|
||||
&-table { |
|
||||
background: #fff; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
File diff suppressed because it is too large
Loading…
Reference in new issue