Forráskód Böngészése

chore: fix the error-log list as the system route

vben 4 éve
szülő
commit
b335e7511b

+ 1 - 1
src/components/Application/src/AppLocalePicker.vue

@@ -11,7 +11,7 @@
     :overlayClassName="`${prefixCls}-overlay`"
   >
     <span :class="prefixCls">
-      <Icon icon="cil:language" />
+      <Icon icon="ion:language" />
       <span v-if="showText" :class="`${prefixCls}__text`">{{ getLangText }}</span>
     </span>
   </Dropdown>

+ 1 - 1
src/components/Application/src/search/AppSearch.vue

@@ -10,7 +10,7 @@
 
   export default defineComponent({
     name: 'AppSearch',
-    components: { AppSearchModal, Tooltip, SearchOutlined },
+    components: { AppSearchModal, Tooltip },
     setup() {
       const showModal = ref(false);
       const { prefixCls } = useDesign('app-search');

+ 1 - 1
src/enums/pageEnum.ts

@@ -6,5 +6,5 @@ export enum PageEnum {
   // error page path
   ERROR_PAGE = '/exception',
   // error log page path
-  ERROR_LOG_PAGE = '/feat/error-log',
+  ERROR_LOG_PAGE = '/error-log/list',
 }

+ 0 - 2
src/layouts/default/header/components/index.ts

@@ -10,6 +10,4 @@ export const FullScreen = createAsyncComponent(() => import('./FullScreen.vue'))
 
 export const Notify = createAsyncComponent(() => import('./notify/index.vue'));
 
-export const LockItem = createAsyncComponent(() => import('./lock/index.vue'));
-
 export const ErrorAction = createAsyncComponent(() => import('./ErrorAction.vue'));

+ 0 - 30
src/layouts/default/header/components/lock/LockAction.less

@@ -1,30 +0,0 @@
-.lock-modal {
-  &__entry {
-    position: relative;
-    height: 240px;
-    padding: 130px 30px 60px 30px;
-    background: #fff;
-    border-radius: 10px;
-  }
-
-  &__header {
-    position: absolute;
-    top: 0;
-    left: calc(50% - 45px);
-    width: auto;
-    text-align: center;
-
-    &-img {
-      width: 70px;
-      border-radius: 50%;
-    }
-
-    &-name {
-      margin-top: 5px;
-    }
-  }
-
-  &__footer {
-    text-align: center;
-  }
-}

+ 0 - 72
src/layouts/default/header/components/lock/LockAction.tsx

@@ -1,72 +0,0 @@
-import './LockAction.less';
-
-import { defineComponent } from 'vue';
-import { BasicModal, useModalInner } from '/@/components/Modal/index';
-import { Button } from '/@/components/Button';
-import { BasicForm, useForm } from '/@/components/Form/index';
-
-import headerImg from '/@/assets/images/header.jpg';
-
-import { userStore } from '/@/store/modules/user';
-import { useI18n } from '/@/hooks/web/useI18n';
-import { lockStore } from '/@/store/modules/lock';
-
-const prefixCls = 'lock-modal';
-export default defineComponent({
-  name: 'LockModal',
-  setup(_, { attrs }) {
-    const { t } = useI18n();
-    const [register, { closeModal }] = useModalInner();
-
-    const [registerForm, { validateFields, resetFields }] = useForm({
-      showActionButtonGroup: false,
-      schemas: [
-        {
-          field: 'password',
-          label: t('layout.header.lockScreenPassword'),
-          component: 'InputPassword',
-          required: true,
-        },
-      ],
-    });
-
-    async function lock() {
-      const values = (await validateFields()) as any;
-      const password: string | undefined = values.password;
-      closeModal();
-
-      lockStore.commitLockInfoState({
-        isLock: true,
-        pwd: password,
-      });
-      await resetFields();
-    }
-
-    return () => (
-      <BasicModal
-        footer={null}
-        title={t('layout.header.lockScreen')}
-        {...attrs}
-        class={prefixCls}
-        onRegister={register}
-      >
-        {() => (
-          <div class={`${prefixCls}__entry`}>
-            <div class={`${prefixCls}__header`}>
-              <img src={headerImg} class={`${prefixCls}__header-img`} />
-              <p class={`${prefixCls}__header-name`}>{userStore.getUserInfoState.realName}</p>
-            </div>
-
-            <BasicForm onRegister={registerForm} />
-
-            <div class={`${prefixCls}__footer`}>
-              <Button type="primary" block class="mt-2" onClick={lock}>
-                {() => t('layout.header.lockScreenBtn')}
-              </Button>
-            </div>
-          </div>
-        )}
-      </BasicModal>
-    );
-  },
-});

+ 0 - 38
src/layouts/default/header/components/lock/index.vue

@@ -1,38 +0,0 @@
-<template>
-  <span @click="handleLock">
-    <Tooltip :title="t('layout.header.tooltipLock')" placement="bottom" :mouseEnterDelay="0.5">
-      <LockOutlined />
-    </Tooltip>
-    <LockAction @register="register" />
-  </span>
-</template>
-<script lang="ts">
-  import { defineComponent } from 'vue';
-  import { Tooltip } from 'ant-design-vue';
-  import { useI18n } from '/@/hooks/web/useI18n';
-  import { LockOutlined } from '@ant-design/icons-vue';
-  import { useModal } from '/@/components/Modal';
-  import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
-  export default defineComponent({
-    name: 'FullScreen',
-    components: {
-      LockOutlined,
-      Tooltip,
-      LockAction: createAsyncComponent(() => import('./LockModal.vue')),
-    },
-
-    setup() {
-      const { t } = useI18n();
-      const [register, { openModal }] = useModal();
-
-      function handleLock() {
-        openModal(true);
-      }
-      return {
-        t,
-        register,
-        handleLock,
-      };
-    },
-  });
-</script>

+ 27 - 12
src/layouts/default/header/components/user-dropdown/index.vue

@@ -12,18 +12,24 @@
         <MenuItem
           key="doc"
           :text="t('layout.header.dropdownItemDoc')"
-          icon="gg:loadbar-doc"
+          icon="ion:document-text-outline"
           v-if="getShowDoc"
         />
         <MenuDivider />
         <MenuItem
+          key="lock"
+          :text="t('layout.header.tooltipLock')"
+          icon="ion:lock-closed-outline"
+        />
+        <MenuItem
           key="loginOut"
           :text="t('layout.header.dropdownItemLoginOut')"
-          icon="carbon:power"
+          icon="ion:exit-outline"
         />
       </Menu>
     </template>
   </Dropdown>
+  <LockAction @register="register" />
 </template>
 <script lang="ts">
   // components
@@ -31,23 +37,21 @@
 
   import { defineComponent, computed } from 'vue';
 
-  // res
-
-  import { userStore } from '/@/store/modules/user';
-
   import { DOC_URL } from '/@/settings/siteSetting';
 
-  import { openWindow } from '/@/utils';
-
+  import { userStore } from '/@/store/modules/user';
   import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
   import { useI18n } from '/@/hooks/web/useI18n';
-
   import { useDesign } from '/@/hooks/web/useDesign';
-  import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
-  import { propTypes } from '/@/utils/propTypes';
+  import { useModal } from '/@/components/Modal';
+
   import headerImg from '/@/assets/images/header.jpg';
+  import { propTypes } from '/@/utils/propTypes';
+  import { openWindow } from '/@/utils';
+
+  import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
 
-  type MenuEvent = 'loginOut' | 'doc';
+  type MenuEvent = 'loginOut' | 'doc' | 'lock';
 
   export default defineComponent({
     name: 'UserDropdown',
@@ -56,6 +60,7 @@
       Menu,
       MenuItem: createAsyncComponent(() => import('./DropMenuItem.vue')),
       MenuDivider: Menu.Divider,
+      LockAction: createAsyncComponent(() => import('../lock/LockModal.vue')),
     },
     props: {
       theme: propTypes.oneOf(['dark', 'light']),
@@ -70,6 +75,12 @@
         return { realName, desc };
       });
 
+      const [register, { openModal }] = useModal();
+
+      function handleLock() {
+        openModal(true);
+      }
+
       //  login out
       function handleLoginOut() {
         userStore.confirmLoginOut();
@@ -88,6 +99,9 @@
           case 'doc':
             openDoc();
             break;
+          case 'lock':
+            handleLock();
+            break;
         }
       }
 
@@ -98,6 +112,7 @@
         handleMenuClick,
         getShowDoc,
         headerImg,
+        register,
       };
     },
   });

+ 2 - 12
src/layouts/default/header/index.vue

@@ -37,8 +37,6 @@
 
       <ErrorAction v-if="getUseErrorHandle" :class="`${prefixCls}-action__item error-action`" />
 
-      <LockItem v-if="getUseLockPage" :class="`${prefixCls}-action__item lock-item`" />
-
       <Notify v-if="getShowNotice" :class="`${prefixCls}-action__item notify-item`" />
 
       <FullScreen v-if="getShowFullScreen" :class="`${prefixCls}-action__item fullscreen-item`" />
@@ -61,7 +59,7 @@
 
   import { Layout } from 'ant-design-vue';
   import { AppLogo } from '/@/components/Application';
-  import LayoutMenu from '../menu';
+  import LayoutMenu from '../menu/index.vue';
   import LayoutTrigger from '../trigger/index.vue';
 
   import { AppSearch } from '/@/components/Application';
@@ -74,14 +72,7 @@
   import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
   import { AppLocalePicker } from '/@/components/Application';
 
-  import {
-    UserDropDown,
-    LayoutBreadcrumb,
-    FullScreen,
-    Notify,
-    LockItem,
-    ErrorAction,
-  } from './components';
+  import { UserDropDown, LayoutBreadcrumb, FullScreen, Notify, ErrorAction } from './components';
   import { useAppInject } from '/@/hooks/web/useAppInject';
   import { useDesign } from '/@/hooks/web/useDesign';
 
@@ -97,7 +88,6 @@
       AppLocalePicker,
       FullScreen,
       Notify,
-      LockItem,
       AppSearch,
       ErrorAction,
     },

+ 0 - 22
src/layouts/default/menu/index.less

@@ -1,22 +0,0 @@
-@prefix-cls: ~'@{namespace}-layout-menu';
-@logo-prefix-cls: ~'@{namespace}-app-logo';
-
-.@{prefix-cls} {
-  &-logo {
-    height: @header-height;
-    padding: 10px 4px 10px 10px;
-
-    img {
-      width: @logo-width;
-      height: @logo-width;
-    }
-  }
-
-  &--mobile {
-    .@{logo-prefix-cls} {
-      &__title {
-        opacity: 1;
-      }
-    }
-  }
-}

+ 0 - 172
src/layouts/default/menu/index.tsx

@@ -1,172 +0,0 @@
-import './index.less';
-
-import type { PropType, CSSProperties } from 'vue';
-
-import { computed, defineComponent, unref, toRef } from 'vue';
-import { BasicMenu } from '/@/components/Menu';
-import { SimpleMenu } from '/@/components/SimpleMenu';
-import { AppLogo } from '/@/components/Application';
-
-import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
-
-import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
-import { ScrollContainer } from '/@/components/Container';
-
-import { useGo } from '/@/hooks/web/usePage';
-import { useSplitMenu } from './useLayoutMenu';
-import { openWindow } from '/@/utils';
-import { propTypes } from '/@/utils/propTypes';
-import { isUrl } from '/@/utils/is';
-import { useRootSetting } from '/@/hooks/setting/useRootSetting';
-import { useAppInject } from '/@/hooks/web/useAppInject';
-import { useDesign } from '/@/hooks/web/useDesign';
-
-export default defineComponent({
-  name: 'LayoutMenu',
-  props: {
-    theme: propTypes.oneOf(['light', 'dark']),
-
-    splitType: {
-      type: Number as PropType<MenuSplitTyeEnum>,
-      default: MenuSplitTyeEnum.NONE,
-    },
-
-    isHorizontal: propTypes.bool,
-    // menu Mode
-    menuMode: {
-      type: [String] as PropType<Nullable<MenuModeEnum>>,
-      default: '',
-    },
-  },
-  setup(props) {
-    const go = useGo();
-
-    const {
-      getMenuMode,
-      getMenuType,
-      getMenuTheme,
-      getCollapsed,
-      getCollapsedShowTitle,
-      getAccordion,
-      getIsHorizontal,
-      getIsSidebarType,
-    } = useMenuSetting();
-    const { getShowLogo } = useRootSetting();
-
-    const { prefixCls } = useDesign('layout-menu');
-
-    const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
-
-    const { getIsMobile } = useAppInject();
-
-    const getComputedMenuMode = computed(() =>
-      unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode)
-    );
-
-    const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme));
-
-    const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
-
-    const getUseScroll = computed(() => {
-      return (
-        !unref(getIsHorizontal) &&
-        (unref(getIsSidebarType) ||
-          props.splitType === MenuSplitTyeEnum.LEFT ||
-          props.splitType === MenuSplitTyeEnum.NONE)
-      );
-    });
-
-    const getWrapperStyle = computed(
-      (): CSSProperties => {
-        return {
-          height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`,
-        };
-      }
-    );
-
-    const getLogoClass = computed(() => {
-      return [
-        `${prefixCls}-logo`,
-        unref(getComputedMenuTheme),
-        {
-          [`${prefixCls}--mobile`]: unref(getIsMobile),
-        },
-      ];
-    });
-    /**
-     * click menu
-     * @param menu
-     */
-
-    function handleMenuClick(path: string) {
-      go(path);
-    }
-
-    /**
-     * before click menu
-     * @param menu
-     */
-    async function beforeMenuClickFn(path: string) {
-      if (!isUrl(path)) {
-        return true;
-      }
-      openWindow(path);
-      return false;
-    }
-
-    function renderHeader() {
-      if (!unref(getIsShowLogo) && !unref(getIsMobile)) return null;
-
-      return (
-        <AppLogo
-          showTitle={!unref(getCollapsed)}
-          class={unref(getLogoClass)}
-          theme={unref(getComputedMenuTheme)}
-        />
-      );
-    }
-
-    function renderMenu() {
-      const menus = unref(menusRef);
-      // console.log(menus);
-      if (!menus || !menus.length) return null;
-      return !props.isHorizontal ? (
-        <SimpleMenu
-          beforeClickFn={beforeMenuClickFn}
-          items={menus}
-          theme={unref(getComputedMenuTheme)}
-          accordion={unref(getAccordion)}
-          collapse={unref(getCollapsed)}
-          collapsedShowTitle={unref(getCollapsedShowTitle)}
-          onMenuClick={handleMenuClick}
-        />
-      ) : (
-        <BasicMenu
-          beforeClickFn={beforeMenuClickFn}
-          isHorizontal={props.isHorizontal}
-          type={unref(getMenuType)}
-          collapsedShowTitle={unref(getCollapsedShowTitle)}
-          showLogo={unref(getIsShowLogo)}
-          mode={unref(getComputedMenuMode)}
-          theme={unref(getComputedMenuTheme)}
-          items={menus}
-          accordion={unref(getAccordion)}
-          onMenuClick={handleMenuClick}
-        />
-      );
-    }
-
-    return () => {
-      return (
-        <>
-          {renderHeader()}
-          {unref(getUseScroll) ? (
-            <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer>
-          ) : (
-            renderMenu()
-          )}
-        </>
-      );
-    };
-  },
-});

+ 196 - 0
src/layouts/default/menu/index.vue

@@ -0,0 +1,196 @@
+<script lang="tsx">
+  import type { PropType, CSSProperties } from 'vue';
+
+  import { computed, defineComponent, unref, toRef } from 'vue';
+  import { BasicMenu } from '/@/components/Menu';
+  import { SimpleMenu } from '/@/components/SimpleMenu';
+  import { AppLogo } from '/@/components/Application';
+
+  import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
+
+  import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
+  import { ScrollContainer } from '/@/components/Container';
+
+  import { useGo } from '/@/hooks/web/usePage';
+  import { useSplitMenu } from './useLayoutMenu';
+  import { openWindow } from '/@/utils';
+  import { propTypes } from '/@/utils/propTypes';
+  import { isUrl } from '/@/utils/is';
+  import { useRootSetting } from '/@/hooks/setting/useRootSetting';
+  import { useAppInject } from '/@/hooks/web/useAppInject';
+  import { useDesign } from '/@/hooks/web/useDesign';
+
+  export default defineComponent({
+    name: 'LayoutMenu',
+    props: {
+      theme: propTypes.oneOf(['light', 'dark']),
+
+      splitType: {
+        type: Number as PropType<MenuSplitTyeEnum>,
+        default: MenuSplitTyeEnum.NONE,
+      },
+
+      isHorizontal: propTypes.bool,
+      // menu Mode
+      menuMode: {
+        type: [String] as PropType<Nullable<MenuModeEnum>>,
+        default: '',
+      },
+    },
+    setup(props) {
+      const go = useGo();
+
+      const {
+        getMenuMode,
+        getMenuType,
+        getMenuTheme,
+        getCollapsed,
+        getCollapsedShowTitle,
+        getAccordion,
+        getIsHorizontal,
+        getIsSidebarType,
+      } = useMenuSetting();
+      const { getShowLogo } = useRootSetting();
+
+      const { prefixCls } = useDesign('layout-menu');
+
+      const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
+
+      const { getIsMobile } = useAppInject();
+
+      const getComputedMenuMode = computed(() =>
+        unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode)
+      );
+
+      const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme));
+
+      const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
+
+      const getUseScroll = computed(() => {
+        return (
+          !unref(getIsHorizontal) &&
+          (unref(getIsSidebarType) ||
+            props.splitType === MenuSplitTyeEnum.LEFT ||
+            props.splitType === MenuSplitTyeEnum.NONE)
+        );
+      });
+
+      const getWrapperStyle = computed(
+        (): CSSProperties => {
+          return {
+            height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`,
+          };
+        }
+      );
+
+      const getLogoClass = computed(() => {
+        return [
+          `${prefixCls}-logo`,
+          unref(getComputedMenuTheme),
+          {
+            [`${prefixCls}--mobile`]: unref(getIsMobile),
+          },
+        ];
+      });
+      /**
+       * click menu
+       * @param menu
+       */
+
+      function handleMenuClick(path: string) {
+        go(path);
+      }
+
+      /**
+       * before click menu
+       * @param menu
+       */
+      async function beforeMenuClickFn(path: string) {
+        if (!isUrl(path)) {
+          return true;
+        }
+        openWindow(path);
+        return false;
+      }
+
+      function renderHeader() {
+        if (!unref(getIsShowLogo) && !unref(getIsMobile)) return null;
+
+        return (
+          <AppLogo
+            showTitle={!unref(getCollapsed)}
+            class={unref(getLogoClass)}
+            theme={unref(getComputedMenuTheme)}
+          />
+        );
+      }
+
+      function renderMenu() {
+        const menus = unref(menusRef);
+        // console.log(menus);
+        if (!menus || !menus.length) return null;
+        return !props.isHorizontal ? (
+          <SimpleMenu
+            beforeClickFn={beforeMenuClickFn}
+            items={menus}
+            theme={unref(getComputedMenuTheme)}
+            accordion={unref(getAccordion)}
+            collapse={unref(getCollapsed)}
+            collapsedShowTitle={unref(getCollapsedShowTitle)}
+            onMenuClick={handleMenuClick}
+          />
+        ) : (
+          <BasicMenu
+            beforeClickFn={beforeMenuClickFn}
+            isHorizontal={props.isHorizontal}
+            type={unref(getMenuType)}
+            collapsedShowTitle={unref(getCollapsedShowTitle)}
+            showLogo={unref(getIsShowLogo)}
+            mode={unref(getComputedMenuMode)}
+            theme={unref(getComputedMenuTheme)}
+            items={menus}
+            accordion={unref(getAccordion)}
+            onMenuClick={handleMenuClick}
+          />
+        );
+      }
+
+      return () => {
+        return (
+          <>
+            {renderHeader()}
+            {unref(getUseScroll) ? (
+              <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer>
+            ) : (
+              renderMenu()
+            )}
+          </>
+        );
+      };
+    },
+  });
+</script>
+<style lang="less">
+  @prefix-cls: ~'@{namespace}-layout-menu';
+  @logo-prefix-cls: ~'@{namespace}-app-logo';
+
+  .@{prefix-cls} {
+    &-logo {
+      height: @header-height;
+      padding: 10px 4px 10px 10px;
+
+      img {
+        width: @logo-width;
+        height: @logo-width;
+      }
+    }
+
+    &--mobile {
+      .@{logo-prefix-cls} {
+        &__title {
+          opacity: 1;
+        }
+      }
+    }
+  }
+</style>

+ 3 - 3
src/layouts/default/setting/index.vue

@@ -1,20 +1,20 @@
 <template>
   <div @click="openDrawer" :class="prefixCls">
-    <SettingOutlined />
+    <Icon icon="ion:settings-outline" />
     <SettingDrawer @register="register" />
   </div>
 </template>
 <script lang="ts">
   import { defineComponent } from 'vue';
-  import { SettingOutlined } from '@ant-design/icons-vue';
   import SettingDrawer from './SettingDrawer';
+  import Icon from '/@/components/Icon';
 
   import { useDrawer } from '/@/components/Drawer';
   import { useDesign } from '/@/hooks/web/useDesign';
 
   export default defineComponent({
     name: 'SettingButton',
-    components: { SettingOutlined, SettingDrawer },
+    components: { SettingDrawer, Icon },
     setup() {
       const [register, { openDrawer }] = useDrawer();
 

+ 1 - 1
src/layouts/default/sider/LayoutSider.vue

@@ -29,7 +29,7 @@
   import { computed, defineComponent, ref, unref, CSSProperties } from 'vue';
 
   import { Layout } from 'ant-design-vue';
-  import LayoutMenu from '../menu';
+  import LayoutMenu from '../menu/index.vue';
   import LayoutTrigger from '/@/layouts/default/trigger/index.vue';
 
   import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';

+ 2 - 1
src/layouts/default/sider/index.vue

@@ -17,8 +17,9 @@
   import { defineComponent } from 'vue';
 
   import Sider from './LayoutSider.vue';
-  import { Drawer } from 'ant-design-vue';
   import MixSider from './MixSider.vue';
+  import { Drawer } from 'ant-design-vue';
+
   import { useAppInject } from '/@/hooks/web/useAppInject';
   import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
   import { useDesign } from '/@/hooks/web/useDesign';

+ 3 - 2
src/layouts/default/tabs/components/TabContent.vue

@@ -5,7 +5,7 @@
     </div>
 
     <span :class="`${prefixCls}__extra-quick`" v-else @click="handleContext">
-      <RightOutlined />
+      <Icon icon="ion:chevron-down"></Icon>
     </span>
   </Dropdown>
 </template>
@@ -14,6 +14,7 @@
 
   import { defineComponent, computed } from 'vue';
   import { Dropdown } from '/@/components/Dropdown/index';
+  import Icon from '/@/components/Icon';
 
   import { TabContentProps, TabContentEnum } from '../types';
 
@@ -26,7 +27,7 @@
   import { RouteLocationNormalized } from 'vue-router';
   export default defineComponent({
     name: 'TabContent',
-    components: { Dropdown, RightOutlined },
+    components: { Dropdown, RightOutlined, Icon },
     props: {
       tabItem: {
         type: Object as PropType<RouteLocationNormalized>,

+ 1 - 0
src/locales/lang/en/routes/basic.ts

@@ -1,3 +1,4 @@
 export default {
   login: 'Login',
+  errorLogList: 'Error Log',
 };

+ 1 - 0
src/locales/lang/zh_CN/routes/basic.ts

@@ -1,3 +1,4 @@
 export default {
   login: '登录',
+  errorLogList: '错误日志列表',
 };

+ 22 - 0
src/router/constant.ts

@@ -1,5 +1,6 @@
 import type { AppRouteRecordRaw } from '/@/router/types';
 import ParentLayout from '/@/layouts/page/ParentView.vue';
+import { t } from '/@/hooks/web/useI18n';
 
 const EXCEPTION_COMPONENT = () => import('../views/sys/exception/Exception.vue');
 
@@ -65,3 +66,24 @@ export const REDIRECT_ROUTE: AppRouteRecordRaw = {
     },
   ],
 };
+
+export const ERROR_LOG_ROUTE: AppRouteRecordRaw = {
+  path: '/error-log',
+  name: 'errorLog',
+  component: LAYOUT,
+  meta: {
+    title: 'ErrorLog',
+    hideBreadcrumb: true,
+  },
+  children: [
+    {
+      path: 'list',
+      name: 'errorLogList',
+      component: () => import('/@/views/sys/error-log/index.vue'),
+      meta: {
+        title: t('routes.basic.errorLogList'),
+        hideBreadcrumb: true,
+      },
+    },
+  ],
+};

+ 2 - 2
src/store/modules/permission.ts

@@ -18,9 +18,8 @@ import { transformObjToRoute } from '/@/router/helper/routeHelper';
 import { transformRouteToMenu } from '/@/router/helper/menuHelper';
 
 import { useMessage } from '/@/hooks/web/useMessage';
-// import { warn } from '/@/utils/log';
 import { useI18n } from '/@/hooks/web/useI18n';
-import { PAGE_NOT_FOUND_ROUTE } from '/@/router/constant';
+import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/constant';
 
 const { createMessage } = useMessage();
 const NAME = 'permission';
@@ -121,6 +120,7 @@ class Permission extends VuexModule {
 
       routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
     }
+    routes.push(ERROR_LOG_ROUTE);
     return routes;
   }
 }

+ 1 - 1
src/views/demo/page/list/card/index.vue

@@ -5,7 +5,7 @@
       <div :class="`${prefixCls}__link`">
         <a><Icon icon="bx:bx-paper-plane" color="#1890ff" /><span>开始</span></a>
         <a><Icon icon="carbon:warning" color="#1890ff" /><span>简介</span></a>
-        <a><Icon icon="gg:loadbar-doc" color="#1890ff" /><span>文档</span></a>
+        <a><Icon icon="ion:document-text-outline" color="#1890ff" /><span>文档</span></a>
       </div>
     </template>