mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-28 13:10:08 +08:00
feat: add error handle
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { defineComponent, unref, computed } from 'vue';
|
||||
import { Layout, Tooltip } from 'ant-design-vue';
|
||||
import { Layout, Tooltip, Badge } from 'ant-design-vue';
|
||||
import Logo from '/@/layouts/Logo.vue';
|
||||
import UserDropdown from './UserDropdown';
|
||||
import LayoutMenu from './LayoutMenu';
|
||||
@@ -12,12 +12,15 @@ import {
|
||||
FullscreenOutlined,
|
||||
GithubFilled,
|
||||
LockOutlined,
|
||||
BugOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
import { useFullscreen } from '/@/hooks/web/useFullScreen';
|
||||
import { useTabs } from '/@/hooks/web/useTabs';
|
||||
import { GITHUB_URL } from '/@/settings/siteSetting';
|
||||
import LockAction from './actions/LockActionItem';
|
||||
import { useModal } from '/@/components/Modal/index';
|
||||
import { errorStore } from '/@/store/modules/error';
|
||||
import { useGo } from '/@/hooks/web/usePage';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DefaultLayoutHeader',
|
||||
@@ -25,6 +28,7 @@ export default defineComponent({
|
||||
const { refreshPage } = useTabs();
|
||||
const [register, { openModal }] = useModal();
|
||||
const { toggleFullscreen, isFullscreenRef } = useFullscreen();
|
||||
const go = useGo();
|
||||
const getProjectConfigRef = computed(() => {
|
||||
return appStore.getProjectConfig;
|
||||
});
|
||||
@@ -37,6 +41,12 @@ export default defineComponent({
|
||||
const theme = unref(getProjectConfigRef).headerSetting.theme;
|
||||
return theme ? `layout-header__header--${theme}` : '';
|
||||
});
|
||||
|
||||
function handleToErrorList() {
|
||||
errorStore.commitErrorListCountState(0);
|
||||
go('/exception/error-log');
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 锁定屏幕
|
||||
*/
|
||||
@@ -46,9 +56,9 @@ export default defineComponent({
|
||||
return () => {
|
||||
const getProjectConfig = unref(getProjectConfigRef);
|
||||
const {
|
||||
// useErrorHandle,
|
||||
useErrorHandle,
|
||||
showLogo,
|
||||
headerSetting: { theme: headerTheme, showRedo, showGithub, showFullScreen },
|
||||
headerSetting: { theme: headerTheme, useLockPage, showRedo, showGithub, showFullScreen },
|
||||
menuSetting: { mode, type: menuType, split: splitMenu, topMenuAlign },
|
||||
showBreadCrumb,
|
||||
} = getProjectConfig;
|
||||
@@ -77,8 +87,28 @@ export default defineComponent({
|
||||
</div>
|
||||
|
||||
<div class={`layout-header__action`}>
|
||||
{useErrorHandle && (
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => '错误日志',
|
||||
default: () => (
|
||||
<Badge
|
||||
count={errorStore.getErrorListCountState}
|
||||
offset={[0, 10]}
|
||||
overflowCount={99}
|
||||
>
|
||||
{() => (
|
||||
<div class={`layout-header__action-item`} onClick={handleToErrorList}>
|
||||
<BugOutlined class={`layout-header__action-icon`} />
|
||||
</div>
|
||||
)}
|
||||
</Badge>
|
||||
),
|
||||
}}
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{showGithub && (
|
||||
// @ts-ignore
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => 'github',
|
||||
@@ -90,8 +120,7 @@ export default defineComponent({
|
||||
}}
|
||||
</Tooltip>
|
||||
)}
|
||||
{showGithub && (
|
||||
// @ts-ignore
|
||||
{useLockPage && (
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => '锁定屏幕',
|
||||
@@ -104,7 +133,6 @@ export default defineComponent({
|
||||
</Tooltip>
|
||||
)}
|
||||
{showRedo && (
|
||||
// @ts-ignore
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => '刷新',
|
||||
@@ -117,7 +145,6 @@ export default defineComponent({
|
||||
</Tooltip>
|
||||
)}
|
||||
{showFullScreen && (
|
||||
// @ts-ignore
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => (unref(isFullscreenRef) ? '退出全屏' : '全屏'),
|
||||
|
@@ -40,10 +40,11 @@ export default defineComponent({
|
||||
let password: string | undefined = '';
|
||||
|
||||
try {
|
||||
const values = (await validateFields()) as any;
|
||||
password = values.password;
|
||||
if (!valid) {
|
||||
password = undefined;
|
||||
} else {
|
||||
const values = (await validateFields()) as any;
|
||||
password = values.password;
|
||||
}
|
||||
setModalProps({
|
||||
visible: false,
|
||||
|
68
src/layouts/default/actions/notice/NoticeActionItem.tsx
Normal file
68
src/layouts/default/actions/notice/NoticeActionItem.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { Popover, Tabs } from 'ant-design-vue';
|
||||
|
||||
import NoticeList from './NoticeList';
|
||||
import { NoticeTabItem, NoticeListItem, noticeTabListData, noticeListData } from './data';
|
||||
import './index.less';
|
||||
|
||||
const prefixCls = 'notice-popover';
|
||||
export default defineComponent({
|
||||
name: 'NoticePopover',
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props, { attrs }) {
|
||||
// 渲染卡片内容
|
||||
function renderContent() {
|
||||
return (
|
||||
<Tabs class={`${prefixCls}__tabs`}>
|
||||
{() => {
|
||||
return noticeTabListData.map((item: NoticeTabItem) => {
|
||||
const { key, name } = item;
|
||||
return (
|
||||
<Tabs.TabPane key={key} tab={renderTab(key, name)}>
|
||||
{() => <NoticeList list={getListData(key)} />}
|
||||
</Tabs.TabPane>
|
||||
);
|
||||
});
|
||||
}}
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
|
||||
// tab标题渲染
|
||||
function renderTab(key: string, name: string) {
|
||||
const list = getListData(key);
|
||||
const unreadlist = list.filter((item: NoticeListItem) => !item.read);
|
||||
return (
|
||||
<div>
|
||||
{name}
|
||||
{unreadlist.length > 0 && <span>({unreadlist.length})</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
function getListData(type: string) {
|
||||
return noticeListData.filter((item: NoticeListItem) => item.type === type);
|
||||
}
|
||||
|
||||
return () => {
|
||||
const { visible } = props;
|
||||
return (
|
||||
<Popover
|
||||
title=""
|
||||
{...{
|
||||
...attrs,
|
||||
visible,
|
||||
}}
|
||||
content={renderContent}
|
||||
class={prefixCls}
|
||||
/>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
73
src/layouts/default/actions/notice/NoticeList.tsx
Normal file
73
src/layouts/default/actions/notice/NoticeList.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { List, Avatar, Tag } from 'ant-design-vue';
|
||||
|
||||
import { NoticeListItem } from './data';
|
||||
import './index.less';
|
||||
|
||||
const prefixCls = 'notice-popover';
|
||||
export default defineComponent({
|
||||
name: 'NoticeList',
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
// 头像渲染
|
||||
function renderAvatar(avatar: string) {
|
||||
return avatar ? <Avatar class="avatar" src={avatar} /> : <span>{avatar}</span>;
|
||||
}
|
||||
|
||||
// 描述渲染
|
||||
function renderDescription(description: string, datetime: string) {
|
||||
return (
|
||||
<div>
|
||||
<div class="description">{description}</div>
|
||||
<div class="datetime">{datetime}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 标题渲染
|
||||
function renderTitle(title: string, extra?: string, color?: string) {
|
||||
return (
|
||||
<div class="title">
|
||||
{title}
|
||||
{extra && (
|
||||
<div class="extra">
|
||||
<Tag class="tag" color={color}>
|
||||
{() => extra}
|
||||
</Tag>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return () => {
|
||||
const { list } = props;
|
||||
return (
|
||||
<List dataSource={list} class={`${prefixCls}__list`}>
|
||||
{() => {
|
||||
return list.map((item: NoticeListItem) => {
|
||||
const { id, avatar, title, description, datetime, extra, read, color } = item;
|
||||
return (
|
||||
<List.Item key={id} class={`${prefixCls}__list-item ${read ? 'read' : ''}`}>
|
||||
{() => (
|
||||
<List.Item.Meta
|
||||
class="meta"
|
||||
avatar={renderAvatar(avatar)}
|
||||
title={renderTitle(title, extra, color)}
|
||||
description={renderDescription(description, datetime)}
|
||||
/>
|
||||
)}
|
||||
</List.Item>
|
||||
);
|
||||
});
|
||||
}}
|
||||
</List>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
@@ -102,12 +102,12 @@
|
||||
.setting-button {
|
||||
top: 45%;
|
||||
right: 0;
|
||||
padding: 14px;
|
||||
padding: 8px;
|
||||
border-radius: 6px 0 0 6px;
|
||||
|
||||
svg {
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
// padding: 10px;
|
||||
color: @white;
|
||||
cursor: pointer;
|
||||
background: @primary-color;
|
||||
|
@@ -54,6 +54,7 @@ export default defineComponent({
|
||||
{...on}
|
||||
name={name || route.meta.transitionName || routerTransition}
|
||||
mode="out-in"
|
||||
appear={true}
|
||||
>
|
||||
{() => Content}
|
||||
</Transition>
|
||||
|
Reference in New Issue
Block a user