louhangfei před 1 rokem
rodič
revize
07c2439576

+ 1 - 4
src/components/Nav.vue

@@ -7,7 +7,7 @@
         class="header__nav--item"
         v-for="item in NAV_LIST"
         :key="item.path"
-        :class="{ active: selectedKey === item?.name }"
+        :class="{ active: selectedKey === item.name }"
         @click="handleNavClick(item)"
       >
         <span>{{ item.meta?.title }}</span>
@@ -42,14 +42,11 @@
   import searchIcon from 'assets/svg/search.svg';
   import Login from '@/components/Login.vue';
   import UserInfo from '@/components/UserInfo.vue';
-  // import useMockUserStore from '@/store/modules/mockUser';
   import { useGlobSetting } from '@/hooks/setting';
 
   // import { storeToRefs } from 'pinia';
   import { useUserStore } from '@/store/modules/user';
 
-  // const mockUserStore = useMockUserStore();
-  // const { userInfo } = storeToRefs(mockUserStore);
   const userStore = useUserStore();
   const activeNav = ref(NAV_LIST[0].name);
   const router = useRouter();

+ 1 - 1
src/constant/nav.ts

@@ -2,7 +2,7 @@
  * @description 导航常量
  */
 
-import { HOME_PAGE } from '@/router';
+import { HOME_PAGE } from '@/router/full-routes';
 
 // 首页导航列表 根据后端返回权限控制(首页永远存在)
 export const NAV_LIST = [

+ 0 - 3
src/layout/components/Footer/index.ts

@@ -1,3 +0,0 @@
-import PageFooter from './index.vue';
-
-export { PageFooter };

+ 0 - 56
src/layout/components/Footer/index.vue

@@ -1,56 +0,0 @@
-<template>
-  <div class="page-footer">
-    <div class="page-footer-link">
-      <a href="https://github.com/jekip/naive-ui-admin" target="_blank"> 官网 </a>
-      <a href="https://github.com/jekip/naive-ui-admin" target="_blank"> 社区 </a>
-      <a href="https://github.com/jekip/naive-ui-admin/issues" target="_blank"> 交流 </a>
-    </div>
-    <div class="copyright"> naive-ui-admin 1.4 · Made by Ah jung </div>
-  </div>
-</template>
-
-<script>
-  export default {
-    name: 'PageFooter',
-    components: {},
-    props: {
-      collapsed: {
-        type: Boolean,
-      },
-    },
-  };
-</script>
-
-<style lang="scss" scoped>
-  .page-footer {
-    //margin: 28px 0 24px 0;
-    padding: 0 16px;
-    text-align: center;
-
-    a {
-      font-size: 14px;
-      color: #808695;
-      -webkit-transition: all 0.2s ease-in-out;
-      transition: all 0.2s ease-in-out;
-
-      &:hover {
-        color: #515a6e;
-      }
-    }
-
-    &-link {
-      display: flex;
-      justify-content: center;
-      margin-bottom: 8px;
-
-      a:not(:last-child) {
-        margin-right: 40px;
-      }
-    }
-
-    .copyright {
-      color: #808695;
-      font-size: 14px;
-    }
-  }
-</style>

+ 0 - 97
src/layout/components/Header/AmendPwd.vue

@@ -1,97 +0,0 @@
-<template>
-  <basicModal @register="modalRegister" ref="modalRef" @ok="formSubmit">
-    <template #default>
-      <div class="px-6 py-4">
-        <BasicForm @register="register" @reset="handleReset" class="basicForm" />
-      </div>
-    </template>
-  </basicModal>
-</template>
-
-<script lang="ts" setup>
-  import { ref } from 'vue';
-  import { basicModal, useModal } from '@/components/Modal';
-  import { ElMessage } from 'element-plus';
-  import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
-  import { changePassword } from '@/api/system/user';
-
-  const schemas: FormSchema[] = [
-    {
-      field: 'oldPwd',
-      component: 'Input',
-      label: '旧密码',
-      componentProps: {
-        placeholder: '请输入旧密码',
-        type: 'password',
-      },
-      rules: [{ required: true, message: '请输入旧密码', trigger: ['blur'] }],
-    },
-    {
-      field: 'newPwd',
-      component: 'Input',
-      label: '新密码',
-      componentProps: {
-        placeholder: '请输入新密码',
-        type: 'password',
-      },
-      rules: [{ required: true, message: '请输入新密码', trigger: ['blur'] }],
-    },
-    {
-      field: 'comfirmPwd',
-      component: 'Input',
-      label: '确认密码',
-      componentProps: {
-        placeholder: '请再次输入新密码',
-        type: 'password',
-      },
-      rules: [{ required: true, message: '请再次输入新密码', trigger: ['blur'] }],
-    },
-  ];
-
-  const modalRef: any = ref(null);
-
-  const [register, { submit, resetFields, getFieldsValue }] = useForm({
-    collapsedRows: 3,
-    labelWidth: 80,
-    layout: 'horizontal',
-    showActionButtonGroup: false,
-    schemas,
-  });
-
-  const [modalRegister, { openModal, closeModal, setSubLoading }] = useModal({
-    title: '修改密码',
-    subBtuText: '提交修改',
-  });
-
-  async function formSubmit() {
-    const formRes = await submit();
-    if (formRes) {
-      changePassword(getFieldsValue())
-        .then(async () => {
-          await resetFields();
-          closeModal();
-          ElMessage.success('修改成功');
-        })
-        .catch(() => {
-          setSubLoading(false);
-        });
-    } else {
-      ElMessage.error('验证失败,请填写完整信息');
-      setSubLoading(false);
-    }
-  }
-
-  function showModal() {
-    openModal();
-  }
-
-  function handleReset(values: Recordable) {
-    console.log(values);
-  }
-
-  defineExpose({
-    showModal,
-  });
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 115
src/layout/components/Header/NotifierProPlus.vue

@@ -1,115 +0,0 @@
-<template>
-  <el-popover
-    popper-class="notifier-popover"
-    placement="bottom-end"
-    :width="340"
-    trigger="hover"
-    v-if="badgeValue > 0"
-  >
-    <template #reference>
-      <el-badge :max="15" :value="badgeValue" is-dot class="bell-badge">
-        <el-icon :size="18"><bell /></el-icon>
-      </el-badge>
-    </template>
-    <el-tabs v-model="activeName" class="my-tabs" @tab-click="handleClick" :stretch="true">
-      <el-tab-pane label="通知(1)" name="notice">
-        <ul class="mx-3">
-          <li class="flex items-center py-3 border-line" v-for="i in 3" :key="i">
-            <el-avatar class="flex-shrink-0" :size="40" />
-            <dl class="min-w-0 ml-3">
-              <dt class="mb-1 text-sm truncate"
-                >约翰.维尔逊回复了你的邮件约翰.维尔逊回复了你的邮件</dt
-              >
-              <dd class="text-xs c-gray">2022-01-08 14:33:18</dd>
-            </dl>
-          </li>
-        </ul>
-        <div class="mt-4 mb-1 text-center"
-          ><el-link href="javascript:;" :underline="false" class="link"
-            ><el-icon class="mr-2"><delete /></el-icon>清空通知</el-link
-          ></div
-        >
-      </el-tab-pane>
-      <el-tab-pane label="关注(2)" name="follow">
-        <ul class="mx-3">
-          <li class="flex items-center py-3 border-line" v-for="i in 3" :key="i">
-            <el-avatar class="flex-shrink-0" :size="40" />
-            <dl class="min-w-0 ml-3">
-              <dt class="mb-1 text-sm truncate">约翰.维尔逊关注了你</dt>
-              <dd class="text-xs c-gray">2022-01-08</dd>
-            </dl>
-          </li>
-        </ul>
-        <div class="mt-4 mb-1 text-center"
-          ><el-link href="link" :underline="false" class="link"
-            ><el-icon class="mr-2"><delete /></el-icon>清空关注</el-link
-          ></div
-        >
-      </el-tab-pane>
-      <el-tab-pane label="待办(3)" name="needto">
-        <ul class="mx-3">
-          <li class="flex items-center justify-between py-3 border-line">
-            <dl class="min-w-0 ml-3">
-              <dt class="mb-1 text-sm truncate">技术部约翰.维尔逊申请离职</dt>
-              <dd class="text-xs c-gray">请在24小时之前完成</dd>
-            </dl>
-            <div class="flex-none"><el-tag type="danger">即将超时</el-tag></div>
-          </li>
-          <li class="flex items-center justify-between py-3 border-line">
-            <dl class="min-w-0 ml-3">
-              <dt class="mb-1 text-sm truncate">统计年后人员和物资</dt>
-              <dd class="text-xs c-gray">请在2021-08-31号之前完成</dd>
-            </dl>
-            <div class="flex-none"><el-tag type="success">进行中</el-tag></div>
-          </li>
-          <li class="flex items-center justify-between py-3 border-line">
-            <dl class="min-w-0 ml-3">
-              <dt class="mb-1 text-sm truncate">回访上月全部客户</dt>
-              <dd class="text-xs c-gray">请在2021-08-28号之前完成</dd>
-            </dl>
-            <div class="flex-none"><el-tag type="warning">未开始</el-tag></div>
-          </li>
-        </ul>
-        <div class="mt-4 mb-1 text-center"
-          ><el-link href="link" :underline="false" class="link"
-            ><el-icon class="mr-2"><delete /></el-icon>清空待办</el-link
-          ></div
-        >
-      </el-tab-pane>
-    </el-tabs>
-  </el-popover>
-  <template v-else>
-    <el-icon :size="18"><bell /></el-icon>
-  </template>
-</template>
-
-<script lang="ts" setup>
-  import { ref } from 'vue';
-  import { Bell, Delete } from '@element-plus/icons-vue';
-
-  const badgeValue = ref(28);
-  const activeName = ref('notice');
-
-  const handleClick = (tab: string, event: Event) => {
-    console.log(tab, event);
-  };
-</script>
-
-<style lang="scss">
-  body .el-popover.notifier-popover {
-    padding-left: 20px;
-    padding-right: 20px;
-  }
-</style>
-<style lang="scss" scoped>
-  .bell-badge {
-    position: relative;
-    top: 4px;
-  }
-  .c-gray {
-    color: var(--el-color-info-light-3);
-  }
-  .border-line {
-    border-bottom: 1px solid var(--el-border-color-base);
-  }
-</style>

+ 0 - 506
src/layout/components/Header/ProjectSetting.vue

@@ -1,506 +0,0 @@
-<template>
-  <el-drawer class="setting-drawer" v-model="isDrawer" :title="title" size="320px">
-    <div class="drawer">
-      <div class="justify-center drawer-setting-item dark-switch">
-        <el-tooltip
-          placement="bottom"
-          :content="designStore.darkTheme ? '切换浅色主题' : '切换深色主题'"
-        >
-          <el-switch
-            size="large"
-            v-model="designStore.darkTheme"
-            class="dark-theme-switch"
-            inline-prompt
-            :active-icon="SunnySharp"
-            :inactive-icon="Moon"
-          />
-        </el-tooltip>
-      </div>
-
-      <el-divider title-placement="center">自定义主题色</el-divider>
-
-      <div class="flex justify-center color-picker">
-        <el-color-picker
-          v-model="themeColor"
-          :predefine="appThemeList"
-          @change="themeColorChange"
-        />
-      </div>
-
-      <!-- <div class="drawer-setting-item align-items-top">
-        <span
-          v-for="(item, index) in appThemeList"
-          :key="index"
-          :style="{ background: item }"
-          class="theme-item"
-          @click="togTheme(item)"
-        >
-          <el-icon class="el-input__icon" v-if="item === designStore.appTheme" size="12">
-            <CheckOutlined />
-          </el-icon>
-        </span>
-      </div> -->
-
-      <el-divider title-placement="center">导航栏模式</el-divider>
-
-      <div class="drawer-setting-item align-items-top">
-        <div class="drawer-setting-item-style align-items-top">
-          <el-tooltip placement="top" content="左侧菜单模式">
-            <el-button link size="small" class="nav-pattern" @click="togNavMode('vertical')">
-              <div class="nav-pattern-item">
-                <div class="nav-pattern-item-top light-bg"></div>
-                <div class="nav-pattern-item-left dark-bg"></div>
-              </div>
-            </el-button>
-          </el-tooltip>
-          <el-badge
-            v-show="settingStore.navMode === 'vertical'"
-            type="primary"
-            :color="getAppTheme"
-            is-dot
-            class="mt-2"
-          />
-        </div>
-
-        <div class="drawer-setting-item-style">
-          <el-tooltip placement="top" content="顶部菜单模式">
-            <el-button link size="small" class="nav-pattern" @click="togNavMode('horizontal')">
-              <div class="nav-pattern-item">
-                <div class="nav-pattern-item-top dark-bg topfloor"></div>
-                <div class="nav-pattern-item-left default-bg"></div>
-              </div>
-            </el-button>
-          </el-tooltip>
-          <el-badge
-            v-show="settingStore.navMode === 'horizontal'"
-            type="primary"
-            is-dot
-            :color="getAppTheme"
-            class="mt-2"
-          />
-        </div>
-
-        <div class="drawer-setting-item-style">
-          <el-tooltip placement="top" content="顶部菜单混合模式,请开启分割菜单,查看效果">
-            <el-button link size="small" class="nav-pattern" @click="togNavMode('horizontal-mix')">
-              <div class="nav-pattern-item">
-                <div class="nav-pattern-item-top dark-bg topfloor"></div>
-                <div class="nav-pattern-item-left light-bg"></div>
-              </div>
-            </el-button>
-          </el-tooltip>
-          <el-badge
-            v-show="settingStore.navMode === 'horizontal-mix'"
-            :color="getAppTheme"
-            type="primary"
-            is-dot
-            class="mt-2"
-          />
-        </div>
-      </div>
-
-      <el-divider title-placement="center">导航栏风格</el-divider>
-
-      <div class="drawer-setting-item align-items-top">
-        <div class="drawer-setting-item-style">
-          <el-tooltip placement="top" content="暗色侧边栏">
-            <el-button
-              link
-              size="small"
-              :disabled="designStore.darkTheme"
-              class="nav-pattern"
-              @click="togNavTheme('dark')"
-            >
-              <div class="nav-pattern-item">
-                <div class="nav-pattern-item-top light-bg"></div>
-                <div class="nav-pattern-item-left dark-bg"></div>
-              </div>
-            </el-button>
-          </el-tooltip>
-          <el-badge
-            v-if="settingStore.navTheme === 'dark'"
-            :color="getAppTheme"
-            type="primary"
-            is-dot
-            class="mt-2"
-          />
-        </div>
-
-        <div class="drawer-setting-item-style">
-          <el-tooltip placement="top" content="白色侧边栏">
-            <el-button
-              link
-              size="small"
-              :disabled="designStore.darkTheme"
-              class="nav-pattern"
-              @click="togNavTheme('light')"
-            >
-              <div class="nav-pattern-item">
-                <div class="nav-pattern-item-top light-bg"></div>
-                <div class="nav-pattern-item-left light-bg"></div>
-              </div>
-            </el-button>
-          </el-tooltip>
-          <el-badge
-            v-if="settingStore.navTheme === 'light'"
-            :color="getAppTheme"
-            type="primary"
-            is-dot
-            class="mt-2"
-          />
-        </div>
-
-        <div class="drawer-setting-item-style">
-          <el-tooltip placement="top" content="暗色顶栏">
-            <el-button
-              link
-              size="small"
-              :disabled="designStore.darkTheme"
-              class="nav-pattern"
-              @click="togNavTheme('header-dark')"
-            >
-              <div class="nav-pattern-item">
-                <div class="nav-pattern-item-top dark-bg"></div>
-                <div class="nav-pattern-item-left dark-bg"></div>
-              </div>
-            </el-button>
-          </el-tooltip>
-          <el-badge
-            v-if="settingStore.navTheme === 'header-dark'"
-            :color="getAppTheme"
-            type="primary"
-            is-dot
-            class="mt-2"
-          />
-        </div>
-      </div>
-
-      <el-divider title-placement="center">界面功能</el-divider>
-
-      <div class="drawer-setting-item">
-        <div class="drawer-setting-item-title"> 分割菜单</div>
-        <div class="drawer-setting-item-action">
-          <el-tooltip trigger="hover" content="顶部菜单混合模式可用">
-            <el-switch
-              v-model="settingStore.menuSetting.mixMenu"
-              :disabled="settingStore.navMode !== 'horizontal-mix'"
-            />
-          </el-tooltip>
-        </div>
-      </div>
-
-      <div class="drawer-setting-item">
-        <div class="drawer-setting-item-title"> 菜单手风琴 </div>
-        <div class="drawer-setting-item-action">
-          <el-switch v-model="settingStore.menuSetting.uniqueOpened" />
-        </div>
-      </div>
-
-      <div class="drawer-setting-item">
-        <div class="drawer-setting-item-title"> 固定顶栏</div>
-        <div class="drawer-setting-item-action">
-          <el-switch v-model="settingStore.headerSetting.fixed" />
-        </div>
-      </div>
-
-      <div class="drawer-setting-item">
-        <div class="drawer-setting-item-title"> 固定侧边栏 </div>
-        <div class="drawer-setting-item-action">
-          <el-switch v-model="settingStore.menuSetting.fixed" />
-        </div>
-      </div>
-
-      <!--        <div class="drawer-setting-item">-->
-      <!--          <div class="drawer-setting-item-title"> 固定多页签</div>-->
-      <!--          <div class="drawer-setting-item-action">-->
-      <!--            <el-switch v-model="settingStore.multiTabsSetting.fixed" />-->
-      <!--          </div>-->
-      <!--        </div>-->
-
-      <el-divider title-placement="center">界面显示</el-divider>
-
-      <div class="drawer-setting-item">
-        <div class="drawer-setting-item-title"> 显示重载页面按钮</div>
-        <div class="drawer-setting-item-action">
-          <el-switch v-model="settingStore.headerSetting.isReload" />
-        </div>
-      </div>
-
-      <div class="drawer-setting-item">
-        <div class="drawer-setting-item-title"> 显示面包屑导航</div>
-        <div class="drawer-setting-item-action">
-          <el-switch v-model="settingStore.crumbsSetting.show" />
-        </div>
-      </div>
-
-      <div class="drawer-setting-item">
-        <div class="drawer-setting-item-title"> 显示面包屑显示图标</div>
-        <div class="drawer-setting-item-action">
-          <el-switch v-model="settingStore.crumbsSetting.showIcon" />
-        </div>
-      </div>
-
-      <div class="drawer-setting-item">
-        <div class="drawer-setting-item-title"> 显示多页签</div>
-        <div class="drawer-setting-item-action">
-          <el-switch v-model="settingStore.multiTabsSetting.show" />
-        </div>
-      </div>
-      <!--1.15废弃,没啥用,占用操作空间-->
-      <!--        <div class="drawer-setting-item">-->
-      <!--          <div class="drawer-setting-item-title"> 显示页脚 </div>-->
-      <!--          <div class="drawer-setting-item-action">-->
-      <!--            <el-switch v-model="settingStore.showFooter" />-->
-      <!--          </div>-->
-      <!--        </div>-->
-
-      <el-divider title-placement="center">动画</el-divider>
-
-      <div class="drawer-setting-item">
-        <div class="drawer-setting-item-title"> 切换动画</div>
-        <div class="drawer-setting-item-action">
-          <el-switch v-model="settingStore.isPageAnimate" />
-        </div>
-      </div>
-
-      <div class="drawer-setting-item">
-        <div class="drawer-setting-item-title"> 动画类型</div>
-        <div class="drawer-setting-item-select">
-          <el-select v-model="settingStore.pageAnimateType">
-            <el-option
-              v-for="item in animateOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </div>
-      </div>
-
-      <div class="mt-3 drawer-setting-item">
-        <el-alert :showIcon="false" type="warning">
-          <p>{{ alertText }}</p>
-        </el-alert>
-      </div>
-    </div>
-  </el-drawer>
-</template>
-
-<script lang="ts" setup>
-  import { ref, watch } from 'vue';
-  import { useProjectSettingStore } from '@/store/modules/projectSetting';
-  import { useDesignSettingStore } from '@/store/modules/designSetting';
-  import { Moon, SunnySharp } from '@vicons/ionicons5';
-  import { animates as animateOptions } from '@/settings/animateSetting';
-  import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
-  import colorTool from '@/utils/color';
-
-  defineProps({
-    title: {
-      type: String,
-      default: '项目配置',
-    },
-    width: {
-      type: Number,
-      default: 264,
-    },
-  });
-  const { getAppTheme } = useDesignSetting();
-  const settingStore = useProjectSettingStore();
-  const designStore = useDesignSettingStore();
-
-  const themeColor = ref('#409eff');
-  const isDrawer = ref(false);
-  const alertText = ref(
-    '该功能主要实时预览各种布局效果,更多完整配置在 /src/settings 中设置,自由搭配,随心所欲,极大程度满足您的个性化需求。',
-  );
-  const appThemeList = designStore.appThemeList;
-
-  watch(
-    () => designStore.darkTheme,
-    (to) => {
-      settingStore.navTheme = to ? 'header-dark' : 'dark';
-      const htmlRoot = document.getElementById('htmlRoot');
-      if (!htmlRoot) return;
-      const themeModel = to ? 'dark' : 'light';
-      htmlRoot.setAttribute('data-theme', themeModel);
-      htmlRoot.setAttribute('class', themeModel);
-    },
-  );
-
-  function openDrawer() {
-    isDrawer.value = true;
-  }
-
-  function closeDrawer() {
-    isDrawer.value = false;
-  }
-
-  function togNavTheme(theme) {
-    settingStore.navTheme = theme;
-    if (settingStore.navMode === 'horizontal' && ['light'].includes(theme)) {
-      settingStore.navTheme = 'dark';
-    }
-  }
-
-  function togNavMode(mode) {
-    settingStore.navMode = mode;
-    settingStore.menuSetting.mixMenu = false;
-  }
-
-  //主题色切换
-  function themeColorChange(color) {
-    document.documentElement.style.setProperty('--el-color-primary', color);
-    document.documentElement.style.setProperty(
-      '--el-color-primary-dark-2',
-      colorTool.darken(color, 0.2),
-    );
-    for (let c = 1; c <= 9; c++) {
-      document.documentElement.style.setProperty(
-        `--el-color-primary-light-${c}`,
-        colorTool.lighten(color, c / 10),
-      );
-    }
-    document.documentElement.style.setProperty(
-      `--el-color-primary-darken-1`,
-      colorTool.darken(color, 0.1),
-    );
-    designStore.appTheme = color;
-  }
-
-  defineExpose({
-    openDrawer,
-    closeDrawer,
-  });
-</script>
-
-<style lang="scss">
-  .setting-drawer {
-    .el-drawer__header {
-      margin-bottom: 10px;
-    }
-    .el-drawer__body {
-      padding-top: 0;
-    }
-  }
-</style>
-
-<style lang="scss" scoped>
-  .drawer {
-    .n-divider:not(.n-divider--vertical) {
-      margin: 10px 0;
-    }
-
-    &-setting-item {
-      display: flex;
-      align-items: center;
-      padding: 3px 0;
-      flex-wrap: wrap;
-
-      &-style {
-        display: inline-block;
-        position: relative;
-        margin-right: 16px;
-        cursor: pointer;
-        text-align: center;
-
-        img {
-          display: block;
-        }
-      }
-
-      &-title {
-        flex: 1 1;
-        font-size: 14px;
-      }
-
-      &-action {
-        flex: 0 0 auto;
-      }
-
-      &-select {
-        flex: 1;
-      }
-
-      .theme-item {
-        width: 20px;
-        min-width: 20px;
-        height: 20px;
-        cursor: pointer;
-        border: 1px solid #eee;
-        border-radius: 2px;
-        margin: 0 5px 5px 0;
-        text-align: center;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-
-        .n-icon {
-          color: #fff;
-        }
-      }
-    }
-
-    .align-items-top {
-      align-items: flex-start;
-      justify-content: space-around;
-      padding: 2px 0;
-    }
-
-    .justify-center {
-      justify-content: center;
-    }
-
-    .dark-switch .n-switch {
-      :deep(.n-switch__rail) {
-        background-color: #000e1c;
-      }
-    }
-
-    //css 实现导航栏风格切换
-    .nav-pattern {
-      display: block;
-      padding: 0;
-      margin: 0;
-      border: none;
-      height: auto;
-      &-item {
-        width: 50px;
-        height: 40px;
-        position: relative;
-        background-color: #f5f7f9;
-        border-radius: 3px;
-        overflow: hidden;
-        box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-        &-left {
-          width: 13px;
-          height: 40px;
-          position: absolute;
-          left: 0;
-          top: 0;
-          z-index: 1;
-        }
-        &-top {
-          width: 50px;
-          height: 13px;
-          position: absolute;
-          top: 0;
-          z-index: 1;
-        }
-        .light-bg {
-          background-color: #fff;
-        }
-        .dark-bg {
-          background-color: #001428;
-        }
-        .default-bg {
-          background-color: #f5f7f9;
-        }
-        //顶层
-        .topfloor {
-          z-index: 2;
-        }
-      }
-    }
-  }
-</style>

+ 0 - 77
src/layout/components/Header/QRcodePopover.vue

@@ -1,77 +0,0 @@
-<template>
-  <el-popover
-    popper-style="    
-    border: none;
-    padding: 0px;
-    width: 228px;
-    height: 308px;
-    background: linear-gradient(rgb(238, 246, 250), rgb(125, 194, 255));
-    "
-    placement="bottom"
-    trigger="hover"
-  >
-    <template #reference>
-      <div class="QR-btn">
-        <!-- <el-icon :size="18"><Download /></el-icon> -->
-        <el-button style="background-color: rgb(24, 144, 255); border: none" type="primary"
-          >下载APP</el-button
-        >
-      </div>
-    </template>
-    <div class="QR-body">
-      <div class="QR-text">安全管控平台</div>
-      <div style="display: flex; flex-direction: row; align-items: center">
-        <img src="@/assets/images/Android.png" style="width: 16px; height: 19px" />
-        <div class="QR-text" style="font-size: 14px; padding-left: 5px">Android客户端</div>
-      </div>
-      <!-- <img src="@/assets/images/QRcodeExample.png" style="width: 140px" /> -->
-      <QrCode :value="qrCodeUrl" :width="140" />
-      <!-- <el-button
-        style="width: 102px; background-color: rgb(24, 144, 255); border: none"
-        type="primary"
-        >保存到相册
-      </el-button> -->
-    </div>
-  </el-popover>
-</template>
-
-<script lang="ts" setup>
-  // import { Download } from '@element-plus/icons-vue';
-  import { QrCode } from '@/components/Qrcode/index';
-  import { useGlobSetting } from '@/hooks/setting';
-  import urlJoin from 'url-join';
-  import { computed, ref } from 'vue';
-  const globSetting = useGlobSetting();
-  const qrCodeUrl = computed(() => {
-    const url = globSetting.appDownloadUrl || '';
-    if (url?.startsWith('http') || url?.startsWith('//')) {
-      return url;
-    }
-    return urlJoin(window.location.origin, url);
-  });
-</script>
-
-<style scoped lang="scss">
-  .QR-btn {
-    display: flex;
-    align-items: center;
-  }
-
-  .QR-body {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: space-around;
-    height: 100%;
-    padding: 20px;
-
-    .QR-text {
-      font-weight: 600;
-      font-size: 20px;
-      color: #1890ff;
-      line-height: 28px;
-      text-align: center;
-      font-style: normal;
-    }
-  }
-</style>

+ 0 - 3
src/layout/components/Header/index.ts

@@ -1,3 +0,0 @@
-import PageHeader from './index.vue';
-
-export { PageHeader };

+ 0 - 565
src/layout/components/Header/index.vue

@@ -1,565 +0,0 @@
-<template>
-  <div
-    class="layout-header"
-    :class="{
-      'layout-header-horizontal': navMode === 'horizontal',
-    }"
-  >
-    <!--顶部菜单-->
-    <div v-if="navMode === 'horizontal' || (navMode === 'horizontal-mix' && mixMenu)" class="layout-header-left">
-      <div v-if="navMode === 'horizontal'" class="logo">
-        <img alt="" src="~@/assets/images/logo.png" />
-        <h2 v-show="!collapsed" class="title">NaiveAdmin</h2>
-      </div>
-    </div>
-    <!--左侧菜单-->
-    <div v-else class="layout-header-left">
-      <!-- 菜单收起 -->
-      <div
-        id="collapsed-trigger"
-        class="ml-1 layout-header-trigger layout-header-trigger-min collapsed-trigger"
-        @click="() => $emit('update:collapsed')"
-      >
-        <el-icon class="el-input__icon" v-if="collapsed" :size="18">
-          <MenuUnfoldOutlined />
-        </el-icon>
-        <el-icon class="el-input__icon" v-else :size="18">
-          <MenuFoldOutlined />
-        </el-icon>
-      </div>
-      <!-- 刷新 -->
-      <!-- <div
-        v-if="headerSetting.isReload"
-        class="mr-1 layout-header-trigger layout-header-trigger-min"
-        @click="reloadPage"
-      >
-        <el-icon class="el-input__icon" :size="18">
-          <ReloadOutlined />
-        </el-icon>
-      </div> -->
-      <!-- 面包屑 -->
-      <el-breadcrumb v-if="crumbsSetting.show" class="flex items-center hidden-sm-only">
-        <template v-for="routeItem in breadcrumbList" :key="routeItem.name">
-          <el-breadcrumb-item v-if="routeItem.meta.breadcrumbView != false">
-            <el-dropdown v-if="routeItem.children.length" :options="routeItem.children">
-              <span class="flex items-center link-text">
-                <el-icon class="mr-2 el-input__icon" :size="18" v-if="crumbsSetting.showIcon && routeItem.meta.icon">
-                  <component :is="routeItem.meta.icon" />
-                </el-icon>
-                <Render :ref="`renderDom_${routeItem.name}`" :value="getRender(routeItem.meta.title)" />
-              </span>
-              <template #dropdown>
-                <el-dropdown-menu>
-                  <el-dropdown-item v-for="item in routeItem.children" :key="item.name" @click="item.props.onClick">
-                    <el-icon class="el-input__icon" :size="18" v-if="crumbsSetting.showIcon && item.meta.icon">
-                      <component :is="item.meta.icon" />
-                    </el-icon>
-                    <Render :ref="`renderDom_${item.name}`" :value="getRender(item.meta.title)" />
-                  </el-dropdown-item>
-                </el-dropdown-menu>
-              </template>
-            </el-dropdown>
-            <span v-else class="link-text" @click="routeItem.props.onClick">
-              <el-icon class="el-input__icon" :size="18" v-if="crumbsSetting.showIcon && routeItem.meta.icon">
-                <component :is="routeItem.meta.icon" />
-              </el-icon>
-              <Render :ref="`renderDom_${routeItem.name}`" :value="getRender(routeItem.meta.title)" />
-            </span>
-          </el-breadcrumb-item>
-        </template>
-      </el-breadcrumb>
-    </div>
-    <div class="header-horizontal-menu">
-      <Sider
-        v-if="navMode === 'horizontal' || (navMode === 'horizontal-mix' && mixMenu)"
-        v-model:location="getMenuLocation"
-        v-bind="siderOption"
-        :inverted="getInverted"
-        mode="horizontal"
-      />
-    </div>
-    <div class="layout-header-right">
-      <!-- <div
-        v-for="item in iconList"
-        :key="item.icon.name"
-        v-on="item.eventObject || {}"
-        class="layout-header-trigger layout-header-trigger-min"
-      >
-        <el-tooltip placement="bottom" :content="item.tips">
-          <el-icon class="el-input__icon" :size="18">
-            <component :is="item.icon" />
-          </el-icon>
-        </el-tooltip>
-      </div> -->
-      <!-- 个人中心 -->
-      <div class="layout-header-trigger layout-header-trigger-min">
-        <el-dropdown trigger="hover" @command="avatarSelect">
-          <div class="flex items-center">
-            <div class="avatar">
-              <el-avatar round :src="getUserAvata || schoolboy" />
-            </div>
-            <!-- <img src="@/assets/images/chongqing-icon.png" /> -->
-            <h4 class="username">{{ getUsername }}</h4>
-            <!-- <el-divider direction="vertical" /> -->
-            <!-- <h4 class="mr-1 username">{{ getTenantName }}</h4> -->
-          </div>
-          <template #dropdown>
-            <el-dropdown-menu>
-              <!-- <el-dropdown-item command="1"
-                ><el-icon class="el-input__icon" :size="18"><UserSwitchOutlined /></el-icon
-                >个人设置</el-dropdown-item
-              > -->
-              <el-dropdown-item command="3"
-                ><el-icon class="el-input__icon" :size="18"><LockClosedOutline /></el-icon>修改密码</el-dropdown-item
-              >
-              <el-dropdown-item command="2"
-                ><el-icon class="el-input__icon" :size="18"><LogoutOutlined /></el-icon>退出登录</el-dropdown-item
-              >
-            </el-dropdown-menu>
-          </template>
-        </el-dropdown>
-      </div>
-      <!-- 弹出式二维码 -->
-      <div class="layout-header-trigger layout-header-trigger-min" v-if="appDownloadUrl">
-        <QRcodePopover />
-      </div>
-      <!-- 安全管控平台 -->
-      <div class="layout-header-trigger layout-header-trigger-min">
-        <el-button style="border: none" type="primary" @click="handleGoPlatform"> 返回平台 </el-button>
-      </div>
-      <!--切换全屏-->
-      <!-- <div class="layout-header-trigger layout-header-trigger-min">
-        <el-tooltip placement="bottom" :content="isFullscreen ? '还原' : '全屏'">
-          <el-icon class="el-input__icon" :size="18" v-if="isFullscreen" @click="toggleFullScreen">
-            <FullscreenExitOutlined />
-          </el-icon>
-          <el-icon class="el-input__icon" :size="18" v-else @click="toggleFullScreen">
-            <FullscreenOutlined />
-          </el-icon>
-        </el-tooltip>
-      </div> -->
-      <!--消息-->
-      <!-- <div class="layout-header-trigger layout-header-trigger-min notifier-plus">
-        <NotifierProPlus />
-      </div> -->
-      <!--设置-->
-      <!-- <div
-        id="setting-trigger"
-        class="layout-header-trigger layout-header-trigger-min setting-trigger"
-        @click="openSetting"
-      >
-        <el-tooltip placement="bottom-end" content="项目配置">
-          <el-icon class="el-input__icon" :size="18" style="font-weight: bold">
-            <SettingOutlined />
-          </el-icon>
-        </el-tooltip>
-      </div> -->
-    </div>
-  </div>
-
-  <!-- 搜索 -->
-  <!-- <AppSearch ref="appSearchRef" /> -->
-
-  <!--修改密码-->
-  <AmendPwd ref="amendPwdRef" />
-</template>
-
-<script lang="ts" setup>
-  import { computed, ref, unref, watch, inject } from 'vue';
-  import { useRoute, useRouter } from 'vue-router';
-  import { useUserStore } from '@/store/modules/user';
-  // import { useLockscreenStore } from '@/store/modules/lockscreen';
-  import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
-  // import { AppSearch } from '@/components/Application/index';
-  import ProjectSetting from './ProjectSetting.vue';
-  import QRcodePopover from './QRcodePopover.vue';
-  import Sider from '../Sider/Sider.vue';
-  import AmendPwd from './AmendPwd.vue';
-  import { useGo, useRedo } from '@/hooks/web/usePage';
-  import { LogoutOutlined, MenuFoldOutlined, MenuUnfoldOutlined } from '@vicons/antd';
-  import { LockClosedOutline } from '@vicons/ionicons5';
-  import { PageEnum } from '@/enums/pageEnum';
-  import schoolboy from '@/assets/images/schoolboy.png';
-  import { useFullscreen } from '@vueuse/core';
-  import { useAsyncRouteStore } from '@/store/modules/asyncRoute';
-  import { ElMessageBox, ElMessage } from 'element-plus';
-  import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
-  import { Render, getRender } from '@/components/Render';
-  import { getLogoutUrl } from '@/utils/getRedirectUrl';
-  import { useGlobSetting } from '@/hooks/setting';
-
-  defineEmits(['update:collapsed']);
-
-  const userStore = useUserStore();
-  // const useLockscreen = useLockscreenStore();
-  const appSearchRef = ref();
-  const isRefresh = ref(false);
-  const { getDarkTheme } = useDesignSetting();
-  const { getNavMode, getNavTheme, getHeaderSetting, getMenuSetting, getCrumbsSetting } = useProjectSetting();
-
-  const props = defineProps({
-    inverted: {
-      type: Boolean,
-    },
-  });
-
-  const go = useGo();
-
-  const handleGoPlatform = () => {
-    window.open(getPLUrl());
-  };
-
-  const BASE_LOGIN_NAME = PageEnum.BASE_LOGIN_NAME;
-
-  const { appPCUrl, appDownloadUrl } = useGlobSetting();
-
-  const drawerSetting = ref();
-
-  const amendPwdRef = ref();
-
-  // const username = userStore?.info ? ref(userStore?.info.username) : '';
-
-  const collapsed = inject('collapsed');
-
-  const navMode = getNavMode;
-
-  const headerSetting = getHeaderSetting;
-
-  const crumbsSetting = getCrumbsSetting;
-
-  const getUserAvata = computed(() => {
-    return userStore.getUserInfo.avatar;
-  });
-
-  const getPLUrl = () => {
-    return appPCUrl + '#/entry';
-  };
-
-  const getUsername = computed(() => {
-    // return userStore.getUserInfo.username;
-    return userStore.getUserInfo.realname;
-  });
-
-  const getTenantName = computed(() => {
-    return userStore.getUserInfo.tenantName;
-  });
-
-  const getInverted = computed(() => {
-    const navTheme = unref(getNavTheme);
-    return ['light', 'header-dark'].includes(navTheme) ? props.inverted : !props.inverted;
-  });
-
-  const siderOption = computed(() => {
-    const navTheme = unref(getNavTheme);
-    let backgroundColor = '#fff';
-    let textColor = '#333';
-    if (unref(getDarkTheme)) {
-      backgroundColor = '#18181c';
-      textColor = '#fff';
-    } else if (['header-dark'].includes(navTheme)) {
-      backgroundColor = '#001428';
-      textColor = '#bbb';
-    }
-
-    return {
-      backgroundColor,
-      textColor,
-    };
-  });
-
-  const mixMenu = computed(() => {
-    return unref(getMenuSetting).mixMenu;
-  });
-
-  const getMenuLocation = computed(() => {
-    return 'header';
-  });
-
-  const router = useRouter();
-  const route = useRoute();
-  const { isFullscreen, toggle } = useFullscreen();
-  const asyncRouteStore = useAsyncRouteStore();
-
-  const generator: any = (routerMap) => {
-    return routerMap
-      .filter((item) => {
-        return !item.meta?.hidden;
-      })
-      .map((item) => {
-        const currentMenu = {
-          ...item,
-          label: item.meta.title,
-          key: item.name,
-          disabled: item.path === '/',
-          props: {
-            onClick: () => {
-              go(item, false);
-            },
-          },
-        };
-        // 是否有子菜单,并递归处理
-        if (item.children && item.children.length > 0) {
-          // Recursion
-          currentMenu.children = generator(item.children, currentMenu);
-        }
-        return currentMenu;
-      });
-  };
-
-  watch(
-    () => route.fullPath,
-    (to) => {
-      isRefresh.value = to.indexOf('/redirect/') != -1;
-    },
-    { immediate: true },
-  );
-
-  // eslint-disable-next-line vue/return-in-computed-property
-  const breadcrumbList = computed(() => {
-    if (!isRefresh.value) return generator(route.matched);
-  });
-
-  // 刷新页面
-  async function reloadPage() {
-    const redo = useRedo(router);
-    await redo();
-  }
-
-  // 退出登录
-  const doLogout = () => {
-    ElMessageBox.confirm('您确定要退出登录吗', '提示', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-    }).then(() => {
-      userStore.logout().then(() => {
-        ElMessage({
-          type: 'success',
-          message: '成功退出登录',
-        });
-        // 移除标签页
-        localStorage.clear();
-        sessionStorage.clear();
-        asyncRouteStore.setDynamicAddedRoute(false);
-        const logoutUrl = getLogoutUrl();
-        window.location.href = logoutUrl;
-      });
-    });
-  };
-
-  // 全屏切换
-  const toggleFullScreen = () => {
-    toggle();
-  };
-
-  // 图标列表
-  // const iconList = [
-  // {
-  //   icon: SearchOutlined,
-  //   tips: '搜索',
-  //   eventObject: {
-  //     click: () => openAppSearch(),
-  //   },
-  // },
-  // {
-  //   icon: GithubOutlined,
-  //   tips: 'github',
-  //   eventObject: {
-  //     click: () => window.open('https://github.com/jekip/naive-ui-admin'),
-  //   },
-  // },
-  // {
-  //   icon: LockOutlined,
-  //   tips: '锁屏',
-  //   eventObject: {
-  //     click: () => useLockscreen.setLock(true),
-  //   },
-  // },
-  // ];
-
-  //头像下拉菜单
-  const avatarSelect = (command) => {
-    switch (command) {
-      case '1':
-        router.push({ name: 'Setting' });
-        break;
-      case '2':
-        doLogout();
-        break;
-      case '3':
-        amendPwdRef.value.showModal();
-        break;
-    }
-  };
-
-  function openSetting() {
-    const { openDrawer } = drawerSetting.value;
-    openDrawer();
-  }
-
-  function openAppSearch() {
-    appSearchRef.value && appSearchRef.value.show();
-  }
-</script>
-
-<style lang="scss" scoped>
-  .layout-header {
-    display: flex;
-    align-items: center;
-    padding: 0;
-    height: $header-height;
-    box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
-    transition: all 0.2s ease-in-out;
-    flex: 1;
-    z-index: 11;
-
-    :deep(.n-menu--horizontal) {
-      width: calc(100%);
-      overflow-x: auto;
-    }
-
-    &-left {
-      display: flex;
-      align-items: center;
-
-      .logo {
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        height: 64px;
-        line-height: 64px;
-        overflow: hidden;
-        white-space: nowrap;
-        padding-left: 10px;
-        min-width: 130px;
-
-        img {
-          width: auto;
-          height: 32px;
-          margin-right: 10px;
-        }
-
-        .title {
-          margin-bottom: 0;
-        }
-      }
-
-      :deep(.ant-breadcrumb span:last-child .link-text) {
-        color: #515a6e;
-      }
-
-      .n-breadcrumb {
-        display: inline-block;
-      }
-
-      &-menu {
-        color: var(--n-text-color);
-      }
-    }
-
-    &-right {
-      display: flex;
-      align-items: center;
-      padding-right: 20px;
-
-      .username {
-        padding: 0px 10px;
-        font-family: PingFangSC, PingFang SC;
-        font-weight: 400;
-        font-size: 14px;
-        color: rgba(0, 0, 0, 0.65);
-        line-height: 22px;
-        text-align: left;
-        font-style: normal;
-      }
-
-      .avatar {
-        display: flex;
-        align-items: center;
-        height: 64px;
-      }
-
-      > * {
-        cursor: pointer;
-      }
-    }
-
-    &-trigger {
-      display: inline-block;
-      width: 64px;
-      height: 64px;
-      text-align: center;
-      cursor: pointer;
-      transition: all 0.2s ease-in-out;
-
-      .n-icon {
-        display: flex;
-        align-items: center;
-        height: 64px;
-        line-height: 64px;
-      }
-
-      &:hover {
-        background: hsla(0, 0%, 100%, 0.08);
-      }
-
-      .anticon {
-        font-size: 16px;
-        color: #515a6e;
-      }
-    }
-
-    &-trigger-min {
-      width: auto;
-      padding: 0 12px;
-      display: flex;
-      align-items: center;
-    }
-
-    .header-horizontal-menu {
-      flex: 1;
-      overflow: hidden;
-    }
-  }
-
-  .layout-header-horizontal {
-    :deep(.n-menu--horizontal) {
-      width: calc(100% - 130px);
-      overflow-x: auto;
-    }
-  }
-
-  .layout-header-light {
-    background: #fff;
-    color: #515a6e;
-
-    .n-icon {
-      color: #515a6e;
-    }
-
-    .layout-header-left {
-      :deep(.n-breadcrumb .n-breadcrumb-item:last-child .n-breadcrumb-item__link) {
-        color: #515a6e;
-      }
-    }
-
-    .layout-header-trigger {
-      &:hover {
-        background: #f8f8f9;
-      }
-    }
-  }
-
-  .layout-header-fix {
-    position: fixed;
-    top: 0;
-    right: 0;
-    left: 200px;
-    z-index: 11;
-  }
-
-  .notifier-plus {
-    display: flex;
-    align-items: center;
-  }
-</style>

+ 0 - 3
src/layout/components/Logo/index.ts

@@ -1,3 +0,0 @@
-import Logo from './index.vue';
-
-export { Logo };

+ 0 - 118
src/layout/components/Logo/index.vue

@@ -1,118 +0,0 @@
-<template>
-  <div
-    class="logo"
-    :class="{
-      'collapsed-login': isCollapsed,
-    }"
-  >
-    <img v-if="isCollapsed" src="~@/assets/images/skyeye-logo-img.png" alt="" :class="{ 'mr-2': !isCollapsed }" />
-    <div v-else class="openWrapper">
-      <div>
-        <img src="~@/assets/images/skyeye-logo-img.png" alt="" class="logoOpen" />
-      </div>
-      <div class="titleWrapper">
-        {{ title }}
-      </div>
-    </div>
-    <!-- <img
-      v-show="!isCollapsed || navMode === 'horizontal' || (navMode === 'horizontal-mix' && mixMenu)"
-      class="mt-0 title"
-      src="~@/assets/images/skyeye-logo-text.png"
-      alt=""
-      :class="{ 'mr-2': !isCollapsed }"
-    /> -->
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { inject, computed, unref } from 'vue';
-  import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
-  import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
-  import { useGlobSetting } from '@/hooks/setting';
-
-  // NavMode的设置按钮已禁用 这里用不上 之后有需要再放开
-  const { getNavTheme, getMenuWidth, getMenuMinWidth, getNavMode, getMenuSetting } = useProjectSetting();
-  const { getDarkTheme } = useDesignSetting();
-
-  const isCollapsed = inject('collapsed');
-  const { title } = useGlobSetting();
-  const navMode = getNavMode;
-
-  const getBgColor = computed(() => {
-    let isLight = getNavTheme.value === 'light';
-    return getDarkTheme.value ? 'rgb(24, 24, 28)' : isLight ? '#fff' : '#001428';
-  });
-
-  const getColor = computed(() => {
-    let isLight = getNavTheme.value === 'light';
-    return isLight ? '#333' : '#FFFFFF';
-  });
-
-  const mixMenu = computed(() => {
-    return unref(getMenuSetting).mixMenu;
-  });
-
-  const menuWidth = computed(() => {
-    return getMenuWidth.value + 'px';
-  });
-
-  const minMenuWidth = computed(() => {
-    return getMenuMinWidth.value + 'px';
-  });
-</script>
-
-<style lang="scss" scoped>
-  .logo {
-    width: v-bind(menuWidth);
-    display: flex;
-    align-items: center;
-    // justify-content: center;
-    height: 64px;
-    // line-height: 64px;
-    // padding-left: 20px;
-    // padding-right: 20px;
-    overflow: hidden;
-    white-space: nowrap;
-    background: v-bind(getBgColor);
-    color: v-bind(getColor);
-    transition: width 0.3s cubic-bezier(0.2, 0, 0, 1) 0s, left 0.3s cubic-bezier(0.2, 0, 0, 1) 0s, box-shadow 0.3s cubic-bezier(0.2, 0, 0, 1) 0s, border-color var(--el-transition-duration),
-      background-color var(--el-transition-duration), color var(--el-transition-duration);
-
-    img {
-      width: 157px;
-      height: auto;
-      margin: auto;
-    }
-
-    .title {
-      margin-bottom: 0;
-    }
-  }
-
-  .collapsed-login {
-    width: v-bind(minMenuWidth);
-    padding-left: 2px;
-    padding-right: 2px;
-  }
-
-  .logo .logoOpen {
-    width: 50px;
-  }
-  .titleWrapper {
-    line-height: 30px;
-    font-weight: bold;
-  }
-
-  .openWrapper {
-    width: v-bind(menuWidth);
-    overflow: hidden;
-  }
-
-  .titleWrapper {
-    // justify-content: left;
-    text-align: center;
-    margin-left: 12px;
-    margin-right: 12px;
-    overflow: hidden;
-  }
-</style>

+ 0 - 3
src/layout/components/Main/index.ts

@@ -1,3 +0,0 @@
-import MainView from './index.vue';
-
-export { MainView };

+ 0 - 30
src/layout/components/Main/index.vue

@@ -1,30 +0,0 @@
-<template>
-  <RouterView>
-    <template #default="{ Component, route }">
-      <transition :name="getTransitionName" appear mode="out-in">
-        <keep-alive v-if="keepAliveComponents" :include="keepAliveComponents">
-          <component :is="Component" :key="route.hash" />
-        </keep-alive>
-        <component :is="Component" v-else :key="route.hash" />
-      </transition>
-    </template>
-  </RouterView>
-</template>
-
-<script lang="ts" setup>
-  import { computed, unref } from 'vue';
-  import { useAsyncRouteStore } from '@/store/modules/asyncRoute';
-  import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
-
-  const { getIsPageAnimate, getPageAnimateType } = useProjectSetting();
-  const asyncRouteStore = useAsyncRouteStore();
-
-  // 需要缓存的路由组件
-  const keepAliveComponents = computed(() => asyncRouteStore.keepAliveComponents);
-
-  const getTransitionName = computed(() => {
-    return unref(getIsPageAnimate) ? unref(getPageAnimateType) : '';
-  });
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 3
src/layout/components/TagsView/index.ts

@@ -1,3 +0,0 @@
-import TabsView from './index.vue';
-
-export { TabsView };

+ 0 - 676
src/layout/components/TagsView/index.vue

@@ -1,676 +0,0 @@
-<template>
-  <div
-    :class="{
-      'tabs-view-default-background': getDarkTheme === false,
-      'tabs-view-dark-background': getDarkTheme === true,
-    }"
-    :style="getChangeStyle"
-    class="tabs-view"
-  >
-    <div class="tabs-view-main">
-      <div ref="navWrap" :class="{ 'tabs-card-scrollable': scrollable }" class="tabs-card">
-        <span :class="{ 'tabs-card-prev-hide': !scrollable }" class="tabs-card-prev" @click="scrollPrev">
-          <el-icon class="el-input__icon" size="16">
-            <LeftOutlined />
-          </el-icon>
-        </span>
-        <span :class="{ 'tabs-card-next-hide': !scrollable }" class="tabs-card-next" @click="scrollNext">
-          <el-icon class="el-input__icon" size="16">
-            <RightOutlined />
-          </el-icon>
-        </span>
-        <div ref="navScroll" class="tabs-card-scroll">
-          <Draggable :list="tabsList" animation="300" class="flex" item-key="fullPath">
-            <template #item="{ element, index }">
-              <div
-                :id="`tag${element.fullPath.split('/').join('\/')}`"
-                :class="{ 'active-item': activeKey === element.fullPath }"
-                class="shadow-sm tabs-card-scroll-item"
-                @contextmenu="handleContextMenu($event, element, index)"
-                @click.stop="goPage(element)"
-              >
-                <Render :ref="`renderDom_${index}`" :value="getRender(element.meta.title)" />
-                <el-badge
-                  class="ml-1"
-                  style="vertical-align: -webkit-baseline-middle"
-                  v-if="element.meta.state === 'undone'"
-                  type="warning"
-                  is-dot
-                />
-                <el-icon
-                  class="el-input__icon"
-                  v-if="!element.meta.affix"
-                  size="14"
-                  @click.stop="closeTabItem(element)"
-                >
-                  <CloseOutlined />
-                </el-icon>
-              </div>
-            </template>
-          </Draggable>
-        </div>
-      </div>
-      <div class="tabs-close">
-        <el-dropdown trigger="hover" @command="closeHandleSelect">
-          <div class="tabs-close-btn">
-            <el-icon class="el-input__icon" size="16">
-              <DownOutlined />
-            </el-icon>
-          </div>
-          <template #dropdown>
-            <el-dropdown-menu>
-              <el-dropdown-item command="7">
-                <el-icon class="el-input__icon" size="16" v-if="getPageFullScreen">
-                  <CompressOutlined />
-                </el-icon>
-                <el-icon class="el-input__icon" size="16" v-else>
-                  <ExpandOutlined />
-                </el-icon>
-                {{ getPageFullScreen ? '退出全屏' : '内容全屏' }}
-              </el-dropdown-item>
-              <el-dropdown-item :disabled="refreshCurrent" command="1">
-                <el-icon class="el-input__icon" size="16">
-                  <ReloadOutlined />
-                </el-icon>
-                刷新当前
-              </el-dropdown-item>
-              <el-dropdown-item :disabled="closeCurrent || isDisabled" command="2">
-                <el-icon class="el-input__icon" size="16"> <MinusOutlined /> </el-icon>关闭当前
-              </el-dropdown-item>
-              <el-dropdown-item :disabled="isDisabled" command="3">
-                <el-icon class="el-input__icon" size="16"> <SwapOutlined /> </el-icon>关闭其他</el-dropdown-item
-              >
-              <el-dropdown-item :disabled="closeLeftTab" command="5">
-                <el-icon class="el-input__icon" size="16"> <DoubleLeftOutlined /> </el-icon>关闭左侧</el-dropdown-item
-              >
-              <el-dropdown-item :disabled="closeRightTab" command="6">
-                <el-icon class="el-input__icon" size="16"> <DoubleRightOutlined /> </el-icon>关闭右侧</el-dropdown-item
-              >
-              <el-dropdown-item :disabled="isDisabled" command="4">
-                <el-icon class="el-input__icon" size="16"> <CloseOutlined /> </el-icon>关闭全部</el-dropdown-item
-              >
-            </el-dropdown-menu>
-          </template>
-        </el-dropdown>
-      </div>
-      <!-- <el-dropdown
-        :options="TabsMenuOptions"
-        :show="showDropdown"
-        :x="dropdownX"
-        :y="dropdownY"
-        placement="bottom-start"
-        @clickoutside="onClickOutside"
-        @select="closeHandleSelect"
-      /> -->
-    </div>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { computed, ref, unref, provide, watch, onMounted, nextTick, toRaw, inject } from 'vue';
-  import { useRoute, useRouter } from 'vue-router';
-  import { storage } from '@/utils/Storage';
-  import { TABS_ROUTES } from '@/store/mutation-types';
-  import { useTabsViewStore } from '@/store/modules/tabsView';
-  import { useAsyncRouteStore } from '@/store/modules/asyncRoute';
-  import { RouteItem } from '@/store/modules/tabsView';
-  import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
-  import { ElMessage, ElMessageBox } from 'element-plus';
-  import Draggable from 'vuedraggable';
-  import { PageEnum } from '@/enums/pageEnum';
-  import {
-    DownOutlined,
-    ReloadOutlined,
-    CloseOutlined,
-    SwapOutlined,
-    LeftOutlined,
-    RightOutlined,
-    DoubleLeftOutlined,
-    DoubleRightOutlined,
-    MinusOutlined,
-    CompressOutlined,
-    ExpandOutlined,
-  } from '@vicons/antd';
-  // import { renderIcon } from '@/utils/index';
-  import elementResizeDetectorMaker from 'element-resize-detector';
-  import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
-  import { useProjectSettingStore } from '@/store/modules/projectSetting';
-  import { useGo, useRedo } from '@/hooks/web/usePage';
-  import { Render, getRender } from '@/components/Render';
-
-  const props = defineProps({
-    collapsed: {
-      type: Boolean,
-    },
-  });
-
-  const emit = defineEmits(['pageFullScreen']);
-
-  const { getDarkTheme, getAppTheme } = useDesignSetting();
-  const { getNavMode, getMenuSetting } = useProjectSetting();
-  const settingStore = useProjectSettingStore();
-  const go = useGo();
-  const route = useRoute();
-  const router = useRouter();
-  const tabsViewStore = useTabsViewStore();
-  const asyncRouteStore = useAsyncRouteStore();
-  const navScroll: any = ref(null);
-  const navWrap: any = ref(null);
-  const activeKey = ref(route.fullPath);
-  const scrollable = ref(false);
-  const dropdownX = ref(0);
-  const dropdownY = ref(0);
-  const showDropdown = ref(false);
-  const closeLeftTab = ref(false);
-  const closeRightTab = ref(false);
-  const closeCurrent = ref(false);
-  const currentTabRoute = ref(null);
-  const refreshCurrent = ref(true);
-
-  // 获取简易的路由对象
-  const getSimpleRoute = (route): RouteItem => {
-    const { fullPath, hash, meta, name, params, path, query } = route;
-    return { fullPath, hash, meta, name, params, path, query };
-  };
-
-  const isMixMenuNoneSub = computed(() => {
-    const mixMenu = settingStore.menuSetting.mixMenu;
-    const currentRoute = useRoute();
-    const navMode = unref(getNavMode);
-    if (unref(navMode) != 'horizontal-mix') return true;
-    if (unref(navMode) === 'horizontal-mix' && mixMenu && currentRoute.meta.isRoot) {
-      return false;
-    }
-    return true;
-  });
-
-  //动态组装样式 菜单缩进
-  const getChangeStyle = computed(() => {
-    const { collapsed } = props;
-    const navMode = unref(getNavMode);
-    const { minMenuWidth, menuWidth }: any = unref(getMenuSetting);
-    let lenNum =
-      navMode === 'horizontal' || !isMixMenuNoneSub.value ? '0px' : collapsed ? `${minMenuWidth}px` : `${menuWidth}px`;
-    return {
-      left: lenNum,
-      width: `calc(100%)`,
-    };
-  });
-
-  const getPageFullScreen = inject('isPageFullScreen');
-
-  //tags 右键右侧下拉菜单
-  // const TabsMenuOptions = computed(() => {
-  //   const disabled = unref(tabsList).length === 1;
-  //   return [
-  //     {
-  //       label: unref(getPageFullScreen) ? '退出全屏' : '内容全屏',
-  //       key: '7',
-  //       icon: getPageFullScreen ? renderIcon(CompressOutlined) : renderIcon(ExpandOutlined),
-  //     },
-  //     {
-  //       label: '刷新当前',
-  //       key: '1',
-  //       icon: renderIcon(ReloadOutlined),
-  //       disabled: refreshCurrent.value,
-  //     },
-  //     {
-  //       label: `关闭当前`,
-  //       key: '2',
-  //       disabled: closeCurrent.value || disabled,
-  //       icon: renderIcon(MinusOutlined),
-  //     },
-  //     {
-  //       label: '关闭其他',
-  //       key: '3',
-  //       disabled: disabled,
-  //       icon: renderIcon(SwapOutlined),
-  //     },
-  //     {
-  //       label: '关闭左侧',
-  //       key: '5',
-  //       disabled: closeLeftTab.value,
-  //       icon: renderIcon(DoubleLeftOutlined),
-  //     },
-  //     {
-  //       label: '关闭右侧',
-  //       key: '6',
-  //       disabled: closeRightTab.value,
-  //       icon: renderIcon(DoubleRightOutlined),
-  //     },
-  //     {
-  //       label: '关闭全部',
-  //       key: '4',
-  //       disabled: disabled,
-  //       icon: renderIcon(CloseOutlined),
-  //     },
-  //   ];
-  // });
-
-  let routes: RouteItem[] = [];
-  try {
-    const routesStr = storage.get(TABS_ROUTES) as string | null | undefined;
-    routes = routesStr ? JSON.parse(routesStr) : [getSimpleRoute(route)];
-  } catch (e) {
-    routes = [getSimpleRoute(route)];
-  }
-  // 初始化标签页
-  tabsViewStore.initTabs(routes);
-
-  // 移除缓存组件名称
-  const delKeepAliveCompName = () => {
-    if (route.meta.keepAlive) {
-      const name = router.currentRoute.value.matched.find((item) => item.name == route.name)?.components?.default.name;
-      if (name) {
-        asyncRouteStore.keepAliveComponents = asyncRouteStore.keepAliveComponents.filter((item) => item != name);
-      }
-    }
-  };
-
-  // 标签页列表
-  const tabsList: any = computed(() => tabsViewStore.tabsList);
-  const whiteList: string[] = [PageEnum.BASE_LOGIN_NAME, PageEnum.REDIRECT_NAME, PageEnum.ERROR_PAGE_NAME];
-
-  const isDisabled = computed(() => unref(tabsList).length === 1);
-
-  watch(
-    () => route.fullPath,
-    (to) => {
-      // 如果您用的路由模式是 hash 请去掉,|| route.hash 判断条件
-      if (whiteList.includes(route.name as string) || route.hash || route.meta.tagView === false) return;
-      activeKey.value = to;
-      currentTabRoute.value = null;
-      refreshCurrent.value = false;
-      tabsViewStore.addTabs(getSimpleRoute(route));
-      nextTick().then(() => {
-        updateNavScroll(true);
-        refreshTabDisabled(getTabIndex());
-      });
-    },
-    { immediate: true },
-  );
-  // 在页面关闭或刷新之前,保存数据
-  window.addEventListener('beforeunload', () => {
-    storage.set(TABS_ROUTES, JSON.stringify(tabsList.value));
-  });
-  // 关闭当前页面
-  const removeTab = (route) => {
-    if (tabsList.value.length === 1) {
-      return ElMessage({
-        message: '这已经是最后一页,不能再关闭了!',
-        type: 'warning',
-      });
-    }
-    const routeInfo = unref(route);
-    //判断当前页标签状态 阻止关闭 只是提供思路,更多个性化功能,自行调整
-    if (routeInfo.meta.state && routeInfo.meta.state === 'undone') {
-      const { content } = routeInfo.meta.dialogOptions;
-      ElMessageBox.confirm(content, '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning',
-        center: true,
-      }).then(() => {
-        directRemoveTab(route);
-      });
-    } else directRemoveTab(route);
-  };
-
-  function directRemoveTab(route) {
-    delKeepAliveCompName();
-    tabsViewStore.closeCurrentTab(route);
-    asyncRouteStore.removeKeepAliveComponents([route.value.name]);
-    // 如果关闭的是当前页
-    if (activeKey.value === route.value.fullPath) {
-      const currentRoute = tabsList.value[Math.max(0, tabsList.value.length - 1)];
-      activeKey.value = currentRoute.fullPath;
-      router.push(currentRoute);
-    }
-    updateNavScroll();
-  }
-
-  // 刷新页面
-  async function reloadPage() {
-    delKeepAliveCompName();
-    const redo = useRedo(router);
-    await redo();
-  }
-
-  // 注入刷新页面方法
-  provide('reloadPage', reloadPage);
-
-  // 关闭左侧
-  const closeLeft = (route) => {
-    tabsViewStore.closeLeftTabs(route, activeKey.value);
-    router.replace(route.fullPath);
-    updateNavScroll();
-  };
-
-  // 关闭右侧
-  const closeRight = (route) => {
-    tabsViewStore.closeRightTabs(route, activeKey.value);
-    router.replace(route.fullPath);
-    updateNavScroll();
-  };
-  // 关闭其他
-  const closeOther = (route) => {
-    tabsViewStore.closeOtherTabs(route, activeKey.value);
-    router.replace(route.fullPath);
-    updateNavScroll();
-  };
-  // 关闭全部
-  const closeAll = () => {
-    tabsViewStore.closeAllTabs();
-    router.replace(PageEnum.BASE_HOME_REDIRECT);
-    updateNavScroll();
-  };
-
-  //当前路由对象 或者 右键选择tab路由对象
-  const getCurrentTabRoute = computed(() => (currentTabRoute.value ? currentTabRoute.value : route));
-
-  //tab 操作
-  const closeHandleSelect = (key) => {
-    switch (key) {
-      //刷新
-      case '1':
-        reloadPage();
-        break;
-      //关闭
-      case '2':
-        removeTab(getCurrentTabRoute);
-        break;
-      //关闭其他
-      case '3':
-        closeOther(getCurrentTabRoute);
-        break;
-      //关闭所有
-      case '4':
-        closeAll();
-        break;
-      //关闭左侧
-      case '5':
-        closeLeft(getCurrentTabRoute);
-        break;
-      //关闭右侧
-      case '6':
-        closeRight(getCurrentTabRoute);
-        break;
-      //内容页全屏
-      case '7':
-        emit('pageFullScreen');
-        break;
-    }
-    updateNavScroll();
-    showDropdown.value = false;
-  };
-
-  /**
-   * @param value 要滚动到的位置
-   * @param amplitude 每次滚动的长度
-   */
-  function scrollTo(value: number, amplitude: number) {
-    const currentScroll = navScroll.value.scrollLeft;
-    const scrollWidth =
-      (amplitude > 0 && currentScroll + amplitude >= value) || (amplitude < 0 && currentScroll + amplitude <= value)
-        ? value
-        : currentScroll + amplitude;
-    navScroll.value && navScroll.value.scrollTo(scrollWidth, 0);
-    if (scrollWidth === value) return;
-    return window.requestAnimationFrame(() => scrollTo(value, amplitude));
-  }
-
-  function scrollPrev() {
-    const containerWidth = navScroll.value.offsetWidth;
-    const currentScroll = navScroll.value.scrollLeft;
-    if (!currentScroll) return;
-    const scrollLeft = currentScroll > containerWidth ? currentScroll - containerWidth : 0;
-    scrollTo(scrollLeft, (scrollLeft - currentScroll) / 20);
-  }
-
-  function scrollNext() {
-    const containerWidth = navScroll.value.offsetWidth;
-    const navWidth = navScroll.value.scrollWidth;
-    const currentScroll = navScroll.value.scrollLeft;
-    if (navWidth - currentScroll / 2 <= containerWidth) return;
-    const scrollLeft =
-      navWidth - currentScroll > containerWidth * 2 ? currentScroll + containerWidth : navWidth - containerWidth;
-    scrollTo(scrollLeft, (scrollLeft - currentScroll) / 20);
-  }
-
-  /**
-   * @param autoScroll 是否开启自动滚动功能
-   */
-  function updateNavScroll(autoScroll?: boolean) {
-    if (!navScroll.value) return;
-    const containerWidth = navScroll.value.offsetWidth;
-    const navWidth = navScroll.value.scrollWidth;
-    if (containerWidth < navWidth) {
-      scrollable.value = true;
-      if (autoScroll) {
-        let tagList = navScroll.value.querySelectorAll('.tabs-card-scroll-item') || [];
-        [...tagList].forEach((tag: HTMLElement) => {
-          // fix SyntaxError
-          if (tag.id === `tag${activeKey.value.split('/').join('\/')}`) {
-            tag.scrollIntoView && tag.scrollIntoView();
-          }
-        });
-      }
-    } else {
-      scrollable.value = false;
-    }
-  }
-
-  function handleResize() {
-    updateNavScroll(true);
-  }
-
-  function handleContextMenu(e, item, index) {
-    e.preventDefault();
-    showDropdown.value = false;
-    currentTabRoute.value = toRaw(item);
-    refreshCurrent.value = !(activeKey.value === item.fullPath);
-    refreshTabDisabled(index);
-
-    nextTick().then(() => {
-      showDropdown.value = true;
-      dropdownX.value = e.clientX;
-      dropdownY.value = e.clientY;
-    });
-  }
-
-  function getTabIndex() {
-    return unref(tabsList).findIndex((item) => item.fullPath === activeKey.value);
-  }
-
-  // function onClickOutside() {
-  //   showDropdown.value = false;
-  //   currentTabRoute.value = null;
-  //   refreshCurrent.value = false;
-  //   const index = getTabIndex();
-  //   refreshTabDisabled(index);
-  // }
-
-  function refreshTabDisabled(index) {
-    closeCurrent.value = unref(tabsList)[index].meta?.affix ?? false;
-    closeLeftTab.value = !(unref(tabsList).length > 0 && index > 0);
-    closeRightTab.value = !(index < unref(tabsList).length && index != unref(tabsList).length - 1);
-  }
-
-  //tags 跳转页面
-  function goPage(e) {
-    const { fullPath } = e;
-    closeCurrent.value = e.meta?.affix ?? false;
-    if (fullPath === route.fullPath) return;
-    activeKey.value = fullPath;
-    go(e, true);
-  }
-
-  //删除tab
-  function closeTabItem(e) {
-    const { fullPath } = e;
-    const routeInfo = ref(tabsList.value.find((item) => item.fullPath == fullPath));
-    removeTab(routeInfo);
-  }
-
-  onMounted(() => {
-    onElementResize();
-  });
-
-  function onElementResize() {
-    let observer;
-    observer = elementResizeDetectorMaker();
-    observer.listenTo(navWrap.value, handleResize);
-  }
-</script>
-
-<style lang="scss" scoped>
-  .tabs-view {
-    width: 100%;
-    padding: 6px 0;
-    display: flex;
-    transition: all 0.2s ease-in-out;
-
-    &-main {
-      height: 32px;
-      display: flex;
-      max-width: 100%;
-      min-width: 100%;
-      padding: 0 10px;
-      box-sizing: border-box;
-
-      .tabs-card {
-        -webkit-box-flex: 1;
-        flex-grow: 1;
-        flex-shrink: 1;
-        overflow: hidden;
-        position: relative;
-
-        .tabs-card-prev,
-        .tabs-card-next {
-          width: 32px;
-          text-align: center;
-          position: absolute;
-          line-height: 32px;
-          cursor: pointer;
-
-          .n-icon {
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            height: 32px;
-            width: 32px;
-          }
-        }
-
-        .tabs-card-prev {
-          left: 0;
-        }
-
-        .tabs-card-next {
-          right: 0;
-        }
-
-        .tabs-card-next-hide,
-        .tabs-card-prev-hide {
-          display: none;
-        }
-
-        &-scroll {
-          white-space: nowrap;
-          overflow: hidden;
-
-          &-item {
-            // background: v-bind(getCardColor);
-            // color: v-bind(getBaseColor);
-            background: #fff;
-            color: #333;
-            height: 32px;
-            padding: 6px 16px 4px;
-            border-radius: 3px;
-            margin-right: 6px;
-            cursor: pointer;
-            display: inline-block;
-            position: relative;
-            flex: 0 0 auto;
-
-            span {
-              float: left;
-              vertical-align: middle;
-            }
-
-            &:hover {
-              color: #515a6e;
-            }
-
-            .el-icon {
-              height: 22px;
-              width: 21px;
-              margin-right: -6px;
-              position: relative;
-              vertical-align: middle;
-              text-align: center;
-              color: #808695;
-
-              &:hover {
-                color: #515a6e !important;
-              }
-
-              svg {
-                height: 21px;
-                display: inline-block;
-              }
-            }
-          }
-
-          .active-item {
-            color: v-bind(getAppTheme);
-          }
-        }
-      }
-
-      .tabs-card-scrollable {
-        padding: 0 32px;
-        overflow: hidden;
-      }
-    }
-
-    .tabs-close {
-      min-width: 32px;
-      width: 32px;
-      height: 32px;
-      line-height: 32px;
-      text-align: center;
-      display: flex;
-      justify-content: center;
-      background: #fff;
-      border-radius: 2px;
-      cursor: pointer;
-      //margin-right: 10px;
-      &-btn {
-        height: 100%;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-      }
-    }
-  }
-
-  .tabs-view-default-background {
-    background: #f5f7f9;
-  }
-
-  .tabs-view-dark-background {
-    background: #101014;
-  }
-
-  .tabs-view-fix {
-    position: fixed;
-    z-index: 5;
-    padding: 6px 19px 6px 10px;
-    left: 200px;
-  }
-
-  .tabs-view-fixed-header {
-    top: 0;
-  }
-</style>

+ 4 - 463
src/layout/index.vue

@@ -1,468 +1,9 @@
 <template>
-  <div
-    class="admin-layout"
-    :inverted="inverted"
-    :class="{
-      'admin-layout-fix-header': fixedHeader,
-      'admin-layout-fix-side': fixedSide,
-      'admin-layout-fix-body': true,
-      'admin-layout-side-horizontal': navMode === 'horizontal',
-      'admin-layout-hide-side': !isMixMenuNoneSub,
-      'admin-layout-show-tabs': isMultiTabs,
-      'admin-layout-collapse': collapsed,
-      'admin-layout-theme-light': getNavTheme === 'light',
-      'admin-layout-header-dark': getNavTheme === 'header-dark',
-    }"
-  >
-    <div class="admin-layout-header">
-      <Logo v-if="navMode != 'horizontal'" />
-      <PageHeader @update:collapsed="updateCollapsed" :inverted="inverted" />
-    </div>
-
-    <div class="admin-layout-content">
-      <div
-        v-if="isMixMenuNoneSub && (navMode === 'vertical' || navMode === 'horizontal-mix')"
-        show-trigger="arrow-circle"
-        @collapse="collapsed = true"
-        @expand="collapsed = false"
-        :native-scrollbar="false"
-        :collapsed="collapsed"
-        collapse-mode="width"
-        :collapsed-width="64"
-        :width="leftMenuWidth"
-        :inverted="inverted"
-        class="admin-layout-sider"
-      >
-        <el-scrollbar>
-          <Sider v-model:location="getMenuLocation" class="left-menu" v-bind="siderOption" />
-        </el-scrollbar>
-      </div>
-
-      <div
-        embedded
-        :inverted="inverted"
-        class="admin-layout-content-son"
-        :class="{
-          'layout-content-inverted': getDarkTheme,
-          'page-full-screen': isFullscreen && !getDarkTheme,
-        }"
-      >
-        <TabsView v-if="isMultiTabs" v-model:collapsed="collapsed" @page-full-screen="togglePageFullScreen" />
-        <div class="admin-layout-content-main">
-          <div class="main-view" ref="adminBodyRef">
-            <MainView />
-          </div>
-        </div>
-        <!-- <el-back-top :right="100" /> -->
-      </div>
-    </div>
-
-    <div class="admin-layout-shade"></div>
-
-    <!-- <InvalidAuth /> -->
-  </div>
-
-  <!--项目配置-->
-  <template v-if="getIsProjectSetting">
-    <ProjectSetting ref="drawerSetting" />
-
-    <div class="shadow-lg circular" @click="openSetting">
-      <el-icon class="el-input__icon" :size="20">
-        <SettingOutlined class="transition ease-in-out delay-150 transform hover:animate-spin" />
-      </el-icon>
-    </div>
-  </template>
+  <router-view />
 </template>
 
-<script lang="ts" setup>
-  import { ref, unref, computed, onMounted, watch, provide } from 'vue';
-  import { Logo } from './components/Logo';
-  import { TabsView } from './components/TagsView';
-  import { MainView } from './components/Main';
-  import { PageHeader } from './components/Header';
-  import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
-  import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
-  import { useRoute } from 'vue-router';
-  import { useProjectSettingStore } from '@/store/modules/projectSetting';
-  import ProjectSetting from './components/Header/ProjectSetting.vue';
-  import { useFullscreen } from '@vueuse/core';
-  import { useDesignSettingStore } from '@/store/modules/designSetting';
-  import { SettingOutlined } from '@vicons/antd';
-  import Sider from './components/Sider/Sider.vue';
-  // import InvalidAuth from '@/components/InvalidAuth/InvalidAuth.vue';
-
-  const { getDarkTheme } = useDesignSetting();
-  const {
-    getNavMode,
-    getMenuWidth,
-    getMenuMinWidth,
-    getNavTheme,
-    getHeaderSetting,
-    getMenuSetting,
-    getMultiTabsSetting,
-    getIsProjectSetting,
-  } = useProjectSetting();
-
-  const settingStore = useProjectSettingStore();
-  const designStore = useDesignSettingStore();
-
-  const navMode = getNavMode;
-
-  const drawerSetting = ref();
-  const collapsed = ref<boolean>(false);
-  const adminBodyRef = ref<HTMLElement | null>(null);
-
-  const { isFullscreen, toggle } = useFullscreen(adminBodyRef);
-
-  provide('isPageFullScreen', isFullscreen);
-  provide('collapsed', collapsed);
-  provide('openSetting', openSetting);
-
-  watch(
-    () => collapsed.value,
-    (to) => {
-      settingStore.setMenuSetting({ collapsed: to });
-    },
-    { immediate: true },
-  );
-
-  //固定顶部
-  const fixedHeader = computed(() => {
-    const { fixed } = unref(getHeaderSetting);
-    return fixed;
-  });
-
-  //固定侧边栏
-  const fixedSide = computed(() => {
-    const { fixed } = unref(getMenuSetting);
-    return fixed;
-  });
-
-  //切换内容页全屏
-  function togglePageFullScreen() {
-    toggle();
-  }
-
-  //菜单折叠
-  function updateCollapsed() {
-    collapsed.value = !collapsed.value;
-  }
-
-  //打开设置
-  function openSetting() {
-    const { openDrawer } = drawerSetting.value;
-    openDrawer();
-  }
-
-  //获取主题风格色
-  const getAppTheme = computed(() => {
-    return designStore.appTheme;
-  });
-
-  const isMixMenuNoneSub = computed(() => {
-    const mixMenu = settingStore.menuSetting.mixMenu;
-    const currentRoute = useRoute();
-    if (unref(navMode) != 'horizontal-mix') return true;
-    if (unref(navMode) === 'horizontal-mix' && mixMenu && currentRoute.meta.isRoot) {
-      return false;
-    }
-    return true;
-  });
-
-  const isMultiTabs = computed(() => {
-    return unref(getMultiTabsSetting).show;
-  });
-
-  const inverted = computed(() => {
-    return ['dark', 'header-dark'].includes(unref(getNavTheme));
-  });
-
-  const siderOption = computed(() => {
-    const navTheme = unref(getNavTheme);
-    let backgroundColor = '#001428';
-    let textColor = '#bbb';
-    if (unref(getDarkTheme)) {
-      backgroundColor = '#18181c';
-      textColor = '#fff';
-    } else if (['light'].includes(navTheme)) {
-      backgroundColor = '#fff';
-      textColor = '#333';
-    }
-
-    return {
-      backgroundColor,
-      textColor,
-    };
-  });
-
-  const leftMenuWidth = computed(() => {
-    const { minMenuWidth, menuWidth } = unref(getMenuSetting);
-    return collapsed.value ? minMenuWidth : menuWidth;
-  });
-
-  const getMenuLocation = computed(() => {
-    return 'left';
-  });
-
-  const menuWidth = computed(() => {
-    return getMenuWidth.value + 'px';
-  });
-
-  const minMenuWidth = computed(() => {
-    return getMenuMinWidth.value + 'px';
-  });
-
-  //看自身需求是否保留吧,这个用处不是很大
-  const watchWidth = () => {
-    const { isFullscreen: isFullscreen } = useFullscreen();
-    if (isFullscreen.value) return;
-    const Width = document.body.clientWidth;
-    if (Width < 750) {
-      collapsed.value = true;
-    }
+<script lang="ts">
+  export default {
+    name: 'Layout',
   };
-
-  onMounted(() => {
-    window.addEventListener('resize', watchWidth);
-  });
 </script>
-
-<style lang="scss" scoped>
-  .admin-layout {
-    color: rgb(51, 54, 57);
-    background-color: #fff;
-    box-sizing: border-box;
-    position: relative;
-    z-index: auto;
-    transition: box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
-      color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
-    &-shade {
-      position: fixed;
-      top: 0;
-      left: 0;
-      right: 0;
-      bottom: 0;
-      z-index: 101;
-      transition: background-color 0.3s cubic-bezier(0.2, 0, 0, 1) 0s, left 0.3s cubic-bezier(0.2, 0, 0, 1) 0s;
-      visibility: hidden;
-    }
-    //侧边栏
-    &-sider {
-      min-height: calc(100vh - 64px);
-      box-shadow: 2px 0 8px 0 rgb(29 35 41 / 5%);
-      position: relative;
-      z-index: 13;
-      transition: width 0.3s cubic-bezier(0.2, 0, 0, 1) 0s, left 0.3s cubic-bezier(0.2, 0, 0, 1) 0s,
-        box-shadow 0.3s cubic-bezier(0.2, 0, 0, 1) 0s, border-color var(--el-transition-duration),
-        background-color var(--el-transition-duration), color var(--el-transition-duration);
-      background-color: #001428;
-      width: v-bind(menuWidth);
-      :deep(.el-menu) {
-        border-right: none;
-      }
-    }
-
-    //主体内容区域
-    &-content {
-      width: 100%;
-      :deep(.n-layout-scroll-container) {
-        overflow: hidden;
-      }
-
-      &-main {
-        background: #f5f7f9;
-        padding: 10px;
-        overflow-x: hidden;
-      }
-
-      &-son {
-        flex: 1;
-        transition: padding-left 0.3s cubic-bezier(0.2, 0, 0, 1) 0s, box-shadow 0.3s cubic-bezier(0.2, 0, 0, 1) 0s;
-      }
-    }
-
-    //深色主题
-    .layout-content-inverted {
-      background: rgb(16, 16, 20);
-    }
-
-    .n-layout-header.n-layout-header--absolute-positioned {
-      z-index: 11;
-    }
-
-    .n-layout-footer {
-      background: none;
-    }
-
-    // 固定顶部
-    &-fix-header {
-      position: fixed;
-      top: 0;
-      left: 0;
-      right: 0;
-
-      .admin-layout-content {
-        flex: auto;
-        min-height: calc(100vh - 64px);
-        &-son {
-          :deep(.n-layout-scroll-container) {
-            overflow: hidden;
-          }
-        }
-
-        &-main {
-          padding: 12px 12px 0 12px;
-          height: calc(100vh - 64px);
-          position: relative;
-          overflow-y: auto;
-        }
-      }
-    }
-
-    //固定侧栏
-    &-fix-side {
-      .admin-layout-sider {
-        position: fixed;
-        left: 0;
-        bottom: 0;
-        top: 64px;
-      }
-
-      .admin-layout-content-son {
-        padding-left: v-bind(menuWidth);
-      }
-
-      .admin-layout-header {
-        .logo {
-          position: fixed;
-          left: 0;
-          top: 0;
-          z-index: 15;
-        }
-        :deep(.layout-header) {
-          padding-left: v-bind(menuWidth);
-        }
-      }
-    }
-
-    //折叠
-    &-collapse {
-      .admin-layout-content-son {
-        padding-left: v-bind(minMenuWidth);
-      }
-
-      .admin-layout-header {
-        :deep(.layout-header) {
-          padding-left: v-bind(minMenuWidth);
-        }
-      }
-
-      .admin-layout-sider {
-        width: v-bind(minMenuWidth);
-      }
-    }
-
-    //没有左侧菜单
-    &-hide-side {
-      .admin-layout-content-son {
-        padding-left: 0px;
-      }
-    }
-
-    //显示多标签
-    &-show-tabs {
-      .admin-layout-content {
-        &-main {
-          padding: 0 10px 10px 10px;
-        }
-      }
-    }
-    &-fix-header.admin-layout-show-tabs {
-      .admin-layout-content {
-        &-main {
-          height: calc(100vh - 64px - 44px);
-          //padding: 0 10px 10px 10px;
-        }
-      }
-    }
-
-    //横向菜单
-    &-side-horizontal {
-      //处理顶部菜单
-      .admin-layout-header {
-        .logo {
-          position: fixed;
-          left: 0;
-          top: 0;
-          z-index: 15;
-        }
-        :deep(.layout-header) {
-          padding-left: 0px;
-        }
-      }
-
-      //处理内容区域
-      .admin-layout-content-son {
-        padding-left: 0px;
-      }
-    }
-
-    &-theme-light {
-      .admin-layout-content .admin-layout-sider {
-        background-color: #fff;
-      }
-      .el-menu {
-        --el-menu-bg-color: #fff;
-        --el-menu-text-color: rgb(51, 54, 57);
-        --el-menu-hover-bg-color: #2d8cf0;
-        --el-menu-hover-text-color: #fff;
-      }
-    }
-
-    //暗色顶栏
-    &-header-dark {
-      .admin-layout-header {
-        :deep(.layout-header) {
-          background-color: #001428;
-          color: #fff;
-          .link-text {
-            color: #fff;
-          }
-        }
-      }
-    }
-  }
-
-  //内容全屏
-  .page-full-screen {
-    .main-view {
-      background: #f0f2f5;
-    }
-  }
-
-  .dark {
-    .page-full-screen {
-      .main-view {
-        background: #000;
-      }
-    }
-  }
-
-  .circular {
-    position: fixed;
-    right: -2px;
-    top: 50%;
-    transform: translateY(-50%);
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    width: 40px;
-    height: 40px;
-    background-color: v-bind(getAppTheme);
-    font-size: 24px;
-    color: #fff;
-    border-radius: 10px 0 0 10px;
-    cursor: pointer;
-    z-index: 200;
-  }
-</style>

+ 24 - 0
src/router/full-routes.ts

@@ -7,6 +7,30 @@
 import { AppRouteRecordRaw } from './types';
 import { getTreeItem } from '@/utils';
 import { cloneDeep } from 'lodash-es';
+import { RouteRecordRaw } from 'vue-router';
+import { PageEnum } from '@/enums/pageEnum';
+
+type RouteRecordString = Omit<AppRouteRecordRaw, 'component'> & { component?: string };
+
+export const RootRoute: RouteRecordString = {
+  path: '/',
+  name: 'Root',
+  redirect: PageEnum.BASE_HOME,
+  meta: {
+    title: 'Root',
+  },
+};
+
+export const HOME_PAGE: RouteRecordString = {
+  // 模板管理
+  path: '/home',
+  name: 'HomePage',
+  component: '/home/PageHome',
+  meta: {
+    icon: '',
+    title: '公司主页',
+  },
+};
 
 /** 灾害防范的路由 */
 export const disasterPreventionRoute = {

+ 2 - 22
src/router/index.ts

@@ -3,7 +3,7 @@ import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
 import { RedirectRoute } from '@/router/base';
 import { PageEnum } from '@/enums/pageEnum';
 import { createRouterGuards } from './router-guards';
-import { disasterPreventionRoute } from './full-routes';
+import { disasterPreventionRoute, HOME_PAGE, RootRoute } from './full-routes';
 import { asyncImportRoute, routerGenerator } from './generator-routers';
 
 const modules: any = import.meta.glob('./modules/**/*.ts', { eager: true });
@@ -22,28 +22,8 @@ function sortRoute(a, b) {
 
 routeModuleList.sort(sortRoute);
 
-export const RootRoute: RouteRecordRaw = {
-  path: '/',
-  name: 'Root',
-  redirect: PageEnum.BASE_HOME,
-  meta: {
-    title: 'Root',
-  },
-};
-
-export const HOME_PAGE: RouteRecordRaw = {
-  // 模板管理
-  path: '/home',
-  name: 'HomePage',
-  component: '/home/PageHome.vue',
-  meta: {
-    icon: '',
-    title: '公司主页',
-  },
-};
-
 const { children, ...disasterPreventionTopRoute } = disasterPreventionRoute;
-const navRoutes = [HOME_PAGE, disasterPreventionTopRoute, RedirectRoute];
+const navRoutes = [RootRoute, HOME_PAGE, disasterPreventionTopRoute, RedirectRoute];
 
 //需要验证权限
 export const asyncRoutes = [...routeModuleList];