UPDATE: 处理控制台警告问题
This commit is contained in:
@@ -1,115 +1,104 @@
|
||||
<template>
|
||||
<div class="footer flx-align-center pl10">
|
||||
<el-dropdown>
|
||||
<!-- <span class="el-dropdown-link">
|
||||
<div class="footer flx-align-center pl10">
|
||||
<el-dropdown>
|
||||
<!-- <span class="el-dropdown-link">
|
||||
{{ title }}
|
||||
<el-icon class="el-icon--right">
|
||||
<arrow-down />
|
||||
</el-icon>
|
||||
</span> -->
|
||||
<!-- <el-button dictType="primary"> -->
|
||||
<div class="change_mode">
|
||||
{{ title }}
|
||||
<el-icon class="el-icon--right change_mode_down"
|
||||
><arrow-down
|
||||
/></el-icon>
|
||||
<el-icon class="el-icon--right change_mode_up"><arrow-up /></el-icon>
|
||||
</div>
|
||||
<!-- </el-button> -->
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="handelOpen('模拟式')"
|
||||
>模拟式模块</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item @click="handelOpen('数字式')"
|
||||
>数字式模块</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item @click="handelOpen('比对式')"
|
||||
>比对式模块</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<p style="margin: 0;" >
|
||||
<a href="http://www.shining-electric.com/" target="_blank">
|
||||
2024 © 南京灿能电力自动化股份有限公司
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<!-- <el-button dictType="primary"> -->
|
||||
<div class="change_mode">
|
||||
{{ title }}
|
||||
<el-icon class="el-icon--right change_mode_down"><arrow-down /></el-icon>
|
||||
<el-icon class="el-icon--right change_mode_up"><arrow-up /></el-icon>
|
||||
</div>
|
||||
<!-- </el-button> -->
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="handelOpen('模拟式')">模拟式模块</el-dropdown-item>
|
||||
<el-dropdown-item @click="handelOpen('数字式')">数字式模块</el-dropdown-item>
|
||||
<el-dropdown-item @click="handelOpen('比对式')">比对式模块</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<p style="margin: 0">
|
||||
<a href="http://www.shining-electric.com/" target="_blank">2024 © 南京灿能电力自动化股份有限公司</a>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, onMounted, watch } from "vue";
|
||||
import { useAuthStore } from "@/stores/modules/auth";
|
||||
import { useModeStore } from '@/stores/modules/mode'; // 引入模式 store
|
||||
import { useRouter } from "vue-router";
|
||||
const router = useRouter();
|
||||
const authStore = useAuthStore();
|
||||
const modeStore = useModeStore();
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '@/stores/modules/auth'
|
||||
import { useModeStore } from '@/stores/modules/mode' // 引入模式 store
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const authStore = useAuthStore()
|
||||
const modeStore = useModeStore()
|
||||
|
||||
const title = computed(() => {
|
||||
return modeStore.currentMode=== ''? '模拟式模块' : modeStore.currentMode+'模块';
|
||||
});
|
||||
return modeStore.currentMode === '' ? '模拟式模块' : modeStore.currentMode + '模块'
|
||||
})
|
||||
|
||||
const handelOpen = async (item: string) => {
|
||||
await authStore.setShowMenu();
|
||||
modeStore.setCurrentMode(item); // 将模式code存入 store
|
||||
|
||||
//if (router.currentRoute.value.path === '/home/index') {
|
||||
// 强制刷新页面
|
||||
window.location.reload();
|
||||
//} else {
|
||||
// router.push({ path: '/home/index' });
|
||||
//}
|
||||
|
||||
};
|
||||
await authStore.setShowMenu()
|
||||
modeStore.setCurrentMode(item) // 将模式code存入 store
|
||||
|
||||
//if (router.currentRoute.value.path === '/home/index') {
|
||||
// 强制刷新页面
|
||||
window.location.reload()
|
||||
//} else {
|
||||
// router.push({ path: '/home/index' });
|
||||
//}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@import "./index.scss";
|
||||
@use './index.scss';
|
||||
.footer {
|
||||
position: relative;
|
||||
background-color: var(--el-color-primary);
|
||||
// .el-button:hover {
|
||||
// background-color: var(--el-color-primary) !important;
|
||||
// border: none !important;
|
||||
// outline: none !important;
|
||||
// }
|
||||
.change_mode {
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
height: 100%;
|
||||
width: auto;
|
||||
font-size: 14px;
|
||||
.change_mode_down {
|
||||
display: block;
|
||||
position: relative;
|
||||
background-color: var(--el-color-primary);
|
||||
// .el-button:hover {
|
||||
// background-color: var(--el-color-primary) !important;
|
||||
// border: none !important;
|
||||
// outline: none !important;
|
||||
// }
|
||||
.change_mode {
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
height: 100%;
|
||||
width: auto;
|
||||
font-size: 14px;
|
||||
.change_mode_down {
|
||||
display: block;
|
||||
}
|
||||
.change_mode_up {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.change_mode_up {
|
||||
display: none;
|
||||
.change_mode:hover {
|
||||
.change_mode_down {
|
||||
display: none;
|
||||
}
|
||||
.change_mode_up {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.change_mode:hover {
|
||||
.change_mode_down {
|
||||
display: none;
|
||||
.el-dropdown {
|
||||
z-index: 1001;
|
||||
}
|
||||
.change_mode_up {
|
||||
display: block;
|
||||
p {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: right;
|
||||
line-height: 40px;
|
||||
a {
|
||||
color: #fff;
|
||||
margin-right: 25px; // 增加右边距
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-dropdown {
|
||||
z-index: 1001;
|
||||
}
|
||||
p {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: right;
|
||||
line-height: 40px;
|
||||
a {
|
||||
color: #fff;
|
||||
margin-right: 25px; // 增加右边距
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,83 +1,81 @@
|
||||
<template>
|
||||
<Maximize v-show="maximize" />
|
||||
<Tabs v-if="tabs && showMenuFlag" />
|
||||
<el-main>
|
||||
<router-view v-slot="{ Component, route }" style="height:100%;">
|
||||
<!-- {{ keepAliveName}} -->
|
||||
<!-- <transition name="slide-right" mode="out-in"> -->
|
||||
<keep-alive :include="tabsMenuList" >
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
<!-- </transition> -->
|
||||
</router-view>
|
||||
</el-main>
|
||||
<el-footer>
|
||||
<Footer />
|
||||
</el-footer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onBeforeUnmount, provide, watch, computed } from "vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useDebounceFn } from "@vueuse/core";
|
||||
import { useGlobalStore } from "@/stores/modules/global";
|
||||
import { useKeepAliveStore } from "@/stores/modules/keepAlive";
|
||||
import Maximize from "./components/Maximize.vue";
|
||||
import Tabs from "@/layouts/components/Tabs/index.vue";
|
||||
import Footer from "@/layouts/components/Footer/index.vue";
|
||||
import { useAuthStore } from "@/stores/modules/auth";
|
||||
import { useTabsStore } from '@/stores/modules/tabs'
|
||||
const tabStore = useTabsStore()
|
||||
const globalStore = useGlobalStore();
|
||||
const tabsMenuList = computed(() => tabStore.tabsMenuList.map(item => item.name))
|
||||
const authStore = useAuthStore();
|
||||
const { maximize, isCollapse, layout, tabs, footer } = storeToRefs(globalStore);
|
||||
const keepAliveStore = useKeepAliveStore();
|
||||
const { keepAliveName } = storeToRefs(keepAliveStore);
|
||||
//是否显示导航栏
|
||||
const showMenuFlag = computed(() => authStore.showMenuFlagGet);
|
||||
// 注入刷新页面方法
|
||||
const isRouterShow = ref(true);
|
||||
const refreshCurrentPage = (val: boolean) => (isRouterShow.value = val);
|
||||
provide("refresh", refreshCurrentPage);
|
||||
|
||||
// 监听当前页面是否最大化,动态添加 class
|
||||
watch(
|
||||
() => maximize.value,
|
||||
() => {
|
||||
const app = document.getElementById("app") as HTMLElement;
|
||||
if (maximize.value) app.classList.add("main-maximize");
|
||||
else app.classList.remove("main-maximize");
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 监听布局变化,在 body 上添加相对应的 layout class
|
||||
watch(
|
||||
() => layout.value,
|
||||
() => {
|
||||
const body = document.body as HTMLElement;
|
||||
body.setAttribute("class", layout.value);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
|
||||
// 监听窗口大小变化,折叠侧边栏
|
||||
const screenWidth = ref(0);
|
||||
const listeningWindow = useDebounceFn(() => {
|
||||
screenWidth.value = document.body.clientWidth;
|
||||
if (!isCollapse.value && screenWidth.value < 1200)
|
||||
globalStore.setGlobalState("isCollapse", true);
|
||||
if (isCollapse.value && screenWidth.value > 1200)
|
||||
globalStore.setGlobalState("isCollapse", false);
|
||||
}, 100);
|
||||
window.addEventListener("resize", listeningWindow, false);
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener("resize", listeningWindow);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./index.scss";
|
||||
</style>
|
||||
<template>
|
||||
<Maximize v-show="maximize" />
|
||||
<Tabs v-if="tabs && showMenuFlag" />
|
||||
<el-main>
|
||||
<router-view v-slot="{ Component, route }" style="height: 100%">
|
||||
<!-- {{ keepAliveName}} -->
|
||||
<!-- <transition name="slide-right" mode="out-in"> -->
|
||||
<keep-alive :include="tabsMenuList">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
<!-- </transition> -->
|
||||
</router-view>
|
||||
</el-main>
|
||||
<el-footer>
|
||||
<Footer />
|
||||
</el-footer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, provide, ref, watch } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
import { useGlobalStore } from '@/stores/modules/global'
|
||||
import { useKeepAliveStore } from '@/stores/modules/keepAlive'
|
||||
import Maximize from './components/Maximize.vue'
|
||||
import Tabs from '@/layouts/components/Tabs/index.vue'
|
||||
import Footer from '@/layouts/components/Footer/index.vue'
|
||||
import { useAuthStore } from '@/stores/modules/auth'
|
||||
import { useTabsStore } from '@/stores/modules/tabs'
|
||||
|
||||
const tabStore = useTabsStore()
|
||||
const globalStore = useGlobalStore()
|
||||
const tabsMenuList = computed(() => tabStore.tabsMenuList.map(item => item.name))
|
||||
const authStore = useAuthStore()
|
||||
const { maximize, isCollapse, layout, tabs, footer } = storeToRefs(globalStore)
|
||||
const keepAliveStore = useKeepAliveStore()
|
||||
const { keepAliveName } = storeToRefs(keepAliveStore)
|
||||
//是否显示导航栏
|
||||
const showMenuFlag = computed(() => authStore.showMenuFlagGet)
|
||||
// 注入刷新页面方法
|
||||
const isRouterShow = ref(true)
|
||||
const refreshCurrentPage = (val: boolean) => (isRouterShow.value = val)
|
||||
provide('refresh', refreshCurrentPage)
|
||||
|
||||
// 监听当前页面是否最大化,动态添加 class
|
||||
watch(
|
||||
() => maximize.value,
|
||||
() => {
|
||||
const app = document.getElementById('app') as HTMLElement
|
||||
if (maximize.value) app.classList.add('main-maximize')
|
||||
else app.classList.remove('main-maximize')
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// 监听布局变化,在 body 上添加相对应的 layout class
|
||||
watch(
|
||||
() => layout.value,
|
||||
() => {
|
||||
const body = document.body as HTMLElement
|
||||
body.setAttribute('class', layout.value)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// 监听窗口大小变化,折叠侧边栏
|
||||
const screenWidth = ref(0)
|
||||
const listeningWindow = useDebounceFn(() => {
|
||||
screenWidth.value = document.body.clientWidth
|
||||
if (!isCollapse.value && screenWidth.value < 1200) globalStore.setGlobalState('isCollapse', true)
|
||||
if (isCollapse.value && screenWidth.value > 1200) globalStore.setGlobalState('isCollapse', false)
|
||||
}, 100)
|
||||
window.addEventListener('resize', listeningWindow, false)
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', listeningWindow)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use './index.scss';
|
||||
</style>
|
||||
|
||||
@@ -1,81 +1,88 @@
|
||||
<template>
|
||||
<el-dropdown trigger="click" :teleported="false">
|
||||
<div class="more-button">
|
||||
<i :class="'iconfont icon-xiala'"></i>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="refresh">
|
||||
<el-icon><Refresh /></el-icon>{{ $t("tabs.refresh") }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="maximize">
|
||||
<el-icon><FullScreen /></el-icon>{{ $t("tabs.maximize") }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item divided @click="closeCurrentTab">
|
||||
<el-icon><Remove /></el-icon>{{ $t("tabs.closeCurrent") }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="tabStore.closeTabsOnSide(route.fullPath, 'left')">
|
||||
<el-icon><DArrowLeft /></el-icon>{{ $t("tabs.closeLeft") }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="tabStore.closeTabsOnSide(route.fullPath, 'right')">
|
||||
<el-icon><DArrowRight /></el-icon>{{ $t("tabs.closeRight") }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item divided @click="tabStore.closeMultipleTab(route.fullPath)">
|
||||
<el-icon><CircleClose /></el-icon>{{ $t("tabs.closeOther") }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="closeAllTab">
|
||||
<el-icon><FolderDelete /></el-icon>{{ $t("tabs.closeAll") }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-dropdown trigger="click" :teleported="false">
|
||||
<div class="more-button">
|
||||
<i :class="'iconfont icon-xiala'"></i>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="refresh">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
{{ $t('tabs.refresh') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="maximize">
|
||||
<el-icon><FullScreen /></el-icon>
|
||||
{{ $t('tabs.maximize') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item divided @click="closeCurrentTab">
|
||||
<el-icon><Remove /></el-icon>
|
||||
{{ $t('tabs.closeCurrent') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="tabStore.closeTabsOnSide(route.fullPath, 'left')">
|
||||
<el-icon><DArrowLeft /></el-icon>
|
||||
{{ $t('tabs.closeLeft') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="tabStore.closeTabsOnSide(route.fullPath, 'right')">
|
||||
<el-icon><DArrowRight /></el-icon>
|
||||
{{ $t('tabs.closeRight') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item divided @click="tabStore.closeMultipleTab(route.fullPath)">
|
||||
<el-icon><CircleClose /></el-icon>
|
||||
{{ $t('tabs.closeOther') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="closeAllTab">
|
||||
<el-icon><FolderDelete /></el-icon>
|
||||
{{ $t('tabs.closeAll') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { inject, nextTick } from "vue";
|
||||
import { HOME_URL } from "@/config";
|
||||
import { useTabsStore } from "@/stores/modules/tabs";
|
||||
import { useGlobalStore } from "@/stores/modules/global";
|
||||
import { useKeepAliveStore } from "@/stores/modules/keepAlive";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { inject, nextTick } from 'vue'
|
||||
import { HOME_URL } from '@/config'
|
||||
import { useTabsStore } from '@/stores/modules/tabs'
|
||||
import { useGlobalStore } from '@/stores/modules/global'
|
||||
import { useKeepAliveStore } from '@/stores/modules/keepAlive'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const tabStore = useTabsStore();
|
||||
const globalStore = useGlobalStore();
|
||||
const keepAliveStore = useKeepAliveStore();
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const tabStore = useTabsStore()
|
||||
const globalStore = useGlobalStore()
|
||||
const keepAliveStore = useKeepAliveStore()
|
||||
|
||||
// refresh current page
|
||||
const refreshCurrentPage: Function = inject("refresh") as Function;
|
||||
const refreshCurrentPage: Function = inject('refresh') as Function
|
||||
const refresh = () => {
|
||||
setTimeout(() => {
|
||||
keepAliveStore.removeKeepAliveName(route.name as string);
|
||||
refreshCurrentPage(false);
|
||||
nextTick(() => {
|
||||
keepAliveStore.addKeepAliveName(route.name as string);
|
||||
refreshCurrentPage(true);
|
||||
});
|
||||
}, 0);
|
||||
};
|
||||
setTimeout(() => {
|
||||
keepAliveStore.removeKeepAliveName(route.name as string)
|
||||
refreshCurrentPage(false)
|
||||
nextTick(() => {
|
||||
keepAliveStore.addKeepAliveName(route.name as string)
|
||||
refreshCurrentPage(true)
|
||||
})
|
||||
}, 0)
|
||||
}
|
||||
|
||||
// maximize current page
|
||||
const maximize = () => {
|
||||
globalStore.setGlobalState("maximize", true);
|
||||
};
|
||||
globalStore.setGlobalState('maximize', true)
|
||||
}
|
||||
|
||||
// Close Current
|
||||
const closeCurrentTab = () => {
|
||||
if (route.meta.isAffix) return;
|
||||
tabStore.removeTabs(route.fullPath);
|
||||
};
|
||||
if (route.meta.isAffix) return
|
||||
tabStore.removeTabs(route.fullPath)
|
||||
}
|
||||
|
||||
// Close All
|
||||
const closeAllTab = () => {
|
||||
tabStore.closeMultipleTab();
|
||||
router.push(HOME_URL);
|
||||
};
|
||||
tabStore.closeMultipleTab()
|
||||
router.push(HOME_URL)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "../index.scss";
|
||||
@use '../index.scss';
|
||||
</style>
|
||||
|
||||
@@ -1,121 +1,119 @@
|
||||
<template>
|
||||
<div class="tabs-box">
|
||||
<div class="tabs-menu">
|
||||
<el-tabs v-model="tabsMenuValue" type="card" @tab-click="tabClick" @tab-remove="tabRemove">
|
||||
<el-tab-pane
|
||||
v-for="item in tabsMenuList"
|
||||
:key="item.path"
|
||||
:label="item.title"
|
||||
:name="item.path"
|
||||
:closable="item.close"
|
||||
>
|
||||
<template #label>
|
||||
<el-icon v-show="item.icon && tabsIcon" class="tabs-icon">
|
||||
<component :is="item.icon"></component>
|
||||
</el-icon>
|
||||
{{ item.title }}
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<MoreButton />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Sortable from 'sortablejs'
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useGlobalStore } from '@/stores/modules/global'
|
||||
import { useTabsStore } from '@/stores/modules/tabs'
|
||||
import { useAuthStore } from '@/stores/modules/auth'
|
||||
import { TabsPaneContext, TabPaneName } from 'element-plus'
|
||||
import MoreButton from './components/MoreButton.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const tabStore = useTabsStore()
|
||||
const authStore = useAuthStore()
|
||||
const globalStore = useGlobalStore()
|
||||
|
||||
const tabsMenuValue = ref(route.fullPath)
|
||||
const tabsMenuList = computed(() => tabStore.tabsMenuList)
|
||||
const tabsIcon = computed(() => globalStore.tabsIcon)
|
||||
|
||||
onMounted(() => {
|
||||
tabsDrop()
|
||||
initTabs()
|
||||
})
|
||||
|
||||
// 监听路由的变化(防止浏览器后退/前进不变化 tabsMenuValue)
|
||||
watch(
|
||||
() => route.fullPath,
|
||||
() => {
|
||||
if (route.meta.isFull) return
|
||||
if (route.meta.hideTab) {
|
||||
tabsMenuValue.value = route.meta.parentPath as string
|
||||
} else {
|
||||
tabsMenuValue.value = route.fullPath
|
||||
const tabsParams = {
|
||||
icon: route.meta.icon as string,
|
||||
title: route.meta.title as string,
|
||||
path: route.fullPath,
|
||||
name: route.name as string,
|
||||
close: !route.meta.isAffix,
|
||||
isKeepAlive: route.meta.isKeepAlive as boolean
|
||||
}
|
||||
tabStore.addTabs(tabsParams)
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// 初始化需要固定的 tabs
|
||||
const initTabs = () => {
|
||||
authStore.flatMenuListGet.forEach(item => {
|
||||
if (item.meta.isAffix && !item.meta.isHide && !item.meta.isFull) {
|
||||
const tabsParams = {
|
||||
icon: item.meta.icon,
|
||||
title: item.meta.title,
|
||||
path: item.path,
|
||||
name: item.name,
|
||||
close: !item.meta.isAffix,
|
||||
isKeepAlive: item.meta.isKeepAlive,
|
||||
unshift: true
|
||||
}
|
||||
tabStore.addTabs(tabsParams)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// tabs 拖拽排序
|
||||
const tabsDrop = () => {
|
||||
Sortable.create(document.querySelector('.el-tabs__nav') as HTMLElement, {
|
||||
draggable: '.el-tabs__item',
|
||||
animation: 300,
|
||||
onEnd({ newIndex, oldIndex }) {
|
||||
const tabsList = [...tabStore.tabsMenuList]
|
||||
const currRow = tabsList.splice(oldIndex as number, 1)[0]
|
||||
tabsList.splice(newIndex as number, 0, currRow)
|
||||
tabStore.setTabs(tabsList)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Tab Click
|
||||
const tabClick = (tabItem: TabsPaneContext) => {
|
||||
const fullPath = tabItem.props.name as string
|
||||
router.push(fullPath)
|
||||
}
|
||||
|
||||
// Remove Tab
|
||||
const tabRemove = (fullPath: TabPaneName) => {
|
||||
|
||||
|
||||
tabStore.removeTabs(fullPath as string, fullPath == route.fullPath || '/machine/testScriptAdd' == route.fullPath)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import './index.scss';
|
||||
</style>
|
||||
<template>
|
||||
<div class="tabs-box">
|
||||
<div class="tabs-menu">
|
||||
<el-tabs v-model="tabsMenuValue" type="card" @tab-click="tabClick" @tab-remove="tabRemove">
|
||||
<el-tab-pane
|
||||
v-for="item in tabsMenuList"
|
||||
:key="item.path"
|
||||
:label="item.title"
|
||||
:name="item.path"
|
||||
:closable="item.close"
|
||||
>
|
||||
<template #label>
|
||||
<el-icon v-show="item.icon && tabsIcon" class="tabs-icon">
|
||||
<component :is="item.icon"></component>
|
||||
</el-icon>
|
||||
{{ item.title }}
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<MoreButton />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Sortable from 'sortablejs'
|
||||
import { computed, onMounted, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useGlobalStore } from '@/stores/modules/global'
|
||||
import { useTabsStore } from '@/stores/modules/tabs'
|
||||
import { useAuthStore } from '@/stores/modules/auth'
|
||||
import { TabPaneName, TabsPaneContext } from 'element-plus'
|
||||
import MoreButton from './components/MoreButton.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const tabStore = useTabsStore()
|
||||
const authStore = useAuthStore()
|
||||
const globalStore = useGlobalStore()
|
||||
|
||||
const tabsMenuValue = ref(route.fullPath)
|
||||
const tabsMenuList = computed(() => tabStore.tabsMenuList)
|
||||
const tabsIcon = computed(() => globalStore.tabsIcon)
|
||||
|
||||
onMounted(() => {
|
||||
tabsDrop()
|
||||
initTabs()
|
||||
})
|
||||
|
||||
// 监听路由的变化(防止浏览器后退/前进不变化 tabsMenuValue)
|
||||
watch(
|
||||
() => route.fullPath,
|
||||
() => {
|
||||
if (route.meta.isFull) return
|
||||
if (route.meta.hideTab) {
|
||||
tabsMenuValue.value = route.meta.parentPath as string
|
||||
} else {
|
||||
tabsMenuValue.value = route.fullPath
|
||||
const tabsParams = {
|
||||
icon: route.meta.icon as string,
|
||||
title: route.meta.title as string,
|
||||
path: route.fullPath,
|
||||
name: route.name as string,
|
||||
close: !route.meta.isAffix,
|
||||
isKeepAlive: route.meta.isKeepAlive as boolean
|
||||
}
|
||||
tabStore.addTabs(tabsParams)
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// 初始化需要固定的 tabs
|
||||
const initTabs = () => {
|
||||
authStore.flatMenuListGet.forEach(item => {
|
||||
if (item.meta.isAffix && !item.meta.isHide && !item.meta.isFull) {
|
||||
const tabsParams = {
|
||||
icon: item.meta.icon,
|
||||
title: item.meta.title,
|
||||
path: item.path,
|
||||
name: item.name,
|
||||
close: !item.meta.isAffix,
|
||||
isKeepAlive: item.meta.isKeepAlive,
|
||||
unshift: true
|
||||
}
|
||||
tabStore.addTabs(tabsParams)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// tabs 拖拽排序
|
||||
const tabsDrop = () => {
|
||||
Sortable.create(document.querySelector('.el-tabs__nav') as HTMLElement, {
|
||||
draggable: '.el-tabs__item',
|
||||
animation: 300,
|
||||
onEnd({ newIndex, oldIndex }) {
|
||||
const tabsList = [...tabStore.tabsMenuList]
|
||||
const currRow = tabsList.splice(oldIndex as number, 1)[0]
|
||||
tabsList.splice(newIndex as number, 0, currRow)
|
||||
tabStore.setTabs(tabsList)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Tab Click
|
||||
const tabClick = (tabItem: TabsPaneContext) => {
|
||||
const fullPath = tabItem.props.name as string
|
||||
router.push(fullPath)
|
||||
}
|
||||
|
||||
// Remove Tab
|
||||
const tabRemove = (fullPath: TabPaneName) => {
|
||||
tabStore.removeTabs(fullPath as string, fullPath == route.fullPath || '/machine/testScriptAdd' == route.fullPath)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use './index.scss';
|
||||
</style>
|
||||
|
||||
@@ -1,186 +1,198 @@
|
||||
<template>
|
||||
<el-drawer v-model="drawerVisible" title="布局设置" size="290px">
|
||||
<!-- 布局样式 -->
|
||||
<el-divider class="divider" content-position="center">
|
||||
<el-icon><Notification /></el-icon>
|
||||
布局样式
|
||||
</el-divider>
|
||||
<div class="layout-box">
|
||||
<el-tooltip effect="dark" content="纵向" placement="top" :show-after="200">
|
||||
<div :class="['layout-item layout-vertical', { 'is-active': layout == 'vertical' }]" @click="setLayout('vertical')">
|
||||
<div class="layout-dark"></div>
|
||||
<div class="layout-container">
|
||||
<div class="layout-light"></div>
|
||||
<div class="layout-content"></div>
|
||||
</div>
|
||||
<el-icon v-if="layout == 'vertical'">
|
||||
<CircleCheckFilled />
|
||||
</el-icon>
|
||||
<el-drawer v-model="drawerVisible" title="布局设置" size="290px">
|
||||
<!-- 布局样式 -->
|
||||
<el-divider class="divider" content-position="center">
|
||||
<el-icon><Notification /></el-icon>
|
||||
布局样式
|
||||
</el-divider>
|
||||
<div class="layout-box">
|
||||
<el-tooltip effect="dark" content="纵向" placement="top" :show-after="200">
|
||||
<div
|
||||
:class="['layout-item layout-vertical', { 'is-active': layout == 'vertical' }]"
|
||||
@click="setLayout('vertical')"
|
||||
>
|
||||
<div class="layout-dark"></div>
|
||||
<div class="layout-container">
|
||||
<div class="layout-light"></div>
|
||||
<div class="layout-content"></div>
|
||||
</div>
|
||||
<el-icon v-if="layout == 'vertical'">
|
||||
<CircleCheckFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="经典" placement="top" :show-after="200">
|
||||
<div
|
||||
:class="['layout-item layout-classic', { 'is-active': layout == 'classic' }]"
|
||||
@click="setLayout('classic')"
|
||||
>
|
||||
<div class="layout-dark"></div>
|
||||
<div class="layout-container">
|
||||
<div class="layout-light"></div>
|
||||
<div class="layout-content"></div>
|
||||
</div>
|
||||
<el-icon v-if="layout == 'classic'">
|
||||
<CircleCheckFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="横向" placement="top" :show-after="200">
|
||||
<div
|
||||
:class="['layout-item layout-transverse', { 'is-active': layout == 'transverse' }]"
|
||||
@click="setLayout('transverse')"
|
||||
>
|
||||
<div class="layout-dark"></div>
|
||||
<div class="layout-content"></div>
|
||||
<el-icon v-if="layout == 'transverse'">
|
||||
<CircleCheckFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="分栏" placement="top" :show-after="200">
|
||||
<div
|
||||
:class="['layout-item layout-columns', { 'is-active': layout == 'columns' }]"
|
||||
@click="setLayout('columns')"
|
||||
>
|
||||
<div class="layout-dark"></div>
|
||||
<div class="layout-light"></div>
|
||||
<div class="layout-content"></div>
|
||||
<el-icon v-if="layout == 'columns'">
|
||||
<CircleCheckFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="经典" placement="top" :show-after="200">
|
||||
<div :class="['layout-item layout-classic', { 'is-active': layout == 'classic' }]" @click="setLayout('classic')">
|
||||
<div class="layout-dark"></div>
|
||||
<div class="layout-container">
|
||||
<div class="layout-light"></div>
|
||||
<div class="layout-content"></div>
|
||||
</div>
|
||||
<el-icon v-if="layout == 'classic'">
|
||||
<CircleCheckFilled />
|
||||
</el-icon>
|
||||
<div class="theme-item">
|
||||
<span>
|
||||
侧边栏反转色
|
||||
<el-tooltip effect="dark" content="侧边栏颜色变为深色模式" placement="top">
|
||||
<el-icon><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-switch v-model="asideInverted" @change="setAsideTheme" />
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="横向" placement="top" :show-after="200">
|
||||
<div :class="['layout-item layout-transverse', { 'is-active': layout == 'transverse' }]" @click="setLayout('transverse')">
|
||||
<div class="layout-dark"></div>
|
||||
<div class="layout-content"></div>
|
||||
<el-icon v-if="layout == 'transverse'">
|
||||
<CircleCheckFilled />
|
||||
</el-icon>
|
||||
<div class="theme-item mb50">
|
||||
<span>
|
||||
头部反转色
|
||||
<el-tooltip effect="dark" content="头部颜色变为深色模式" placement="top">
|
||||
<el-icon><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-switch v-model="headerInverted" @change="setHeaderTheme" />
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="分栏" placement="top" :show-after="200">
|
||||
<div :class="['layout-item layout-columns', { 'is-active': layout == 'columns' }]" @click="setLayout('columns')">
|
||||
<div class="layout-dark"></div>
|
||||
<div class="layout-light"></div>
|
||||
<div class="layout-content"></div>
|
||||
<el-icon v-if="layout == 'columns'">
|
||||
<CircleCheckFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>
|
||||
侧边栏反转色
|
||||
<el-tooltip effect="dark" content="侧边栏颜色变为深色模式" placement="top">
|
||||
<el-icon><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-switch v-model="asideInverted" @change="setAsideTheme" />
|
||||
</div>
|
||||
<div class="theme-item mb50">
|
||||
<span>
|
||||
头部反转色
|
||||
<el-tooltip effect="dark" content="头部颜色变为深色模式" placement="top">
|
||||
<el-icon><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-switch v-model="headerInverted" @change="setHeaderTheme" />
|
||||
</div>
|
||||
|
||||
<!-- 全局主题 -->
|
||||
<el-divider class="divider" content-position="center">
|
||||
<el-icon><ColdDrink /></el-icon>
|
||||
全局主题
|
||||
</el-divider>
|
||||
<div class="theme-item">
|
||||
<span>主题颜色</span>
|
||||
<el-color-picker v-model="primary" :predefine="colorList" @change="changePrimary" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>暗黑模式</span>
|
||||
<SwitchDark />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>灰色模式</span>
|
||||
<el-switch v-model="isGrey" @change="changeGreyOrWeak('grey', !!$event)" />
|
||||
</div>
|
||||
<div class="theme-item mb40">
|
||||
<span>色弱模式</span>
|
||||
<el-switch v-model="isWeak" @change="changeGreyOrWeak('weak', !!$event)" />
|
||||
</div>
|
||||
<!-- 全局主题 -->
|
||||
<el-divider class="divider" content-position="center">
|
||||
<el-icon><ColdDrink /></el-icon>
|
||||
全局主题
|
||||
</el-divider>
|
||||
<div class="theme-item">
|
||||
<span>主题颜色</span>
|
||||
<el-color-picker v-model="primary" :predefine="colorList" @change="changePrimary" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>暗黑模式</span>
|
||||
<SwitchDark />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>灰色模式</span>
|
||||
<el-switch v-model="isGrey" @change="changeGreyOrWeak('grey', !!$event)" />
|
||||
</div>
|
||||
<div class="theme-item mb40">
|
||||
<span>色弱模式</span>
|
||||
<el-switch v-model="isWeak" @change="changeGreyOrWeak('weak', !!$event)" />
|
||||
</div>
|
||||
|
||||
<!-- 界面设置 -->
|
||||
<el-divider class="divider" content-position="center">
|
||||
<el-icon><Setting /></el-icon>
|
||||
界面设置
|
||||
</el-divider>
|
||||
<div class="theme-item">
|
||||
<span>菜单折叠</span>
|
||||
<el-switch v-model="isCollapse" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>菜单手风琴</span>
|
||||
<el-switch v-model="accordion" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>面包屑</span>
|
||||
<el-switch v-model="breadcrumb" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>面包屑图标</span>
|
||||
<el-switch v-model="breadcrumbIcon" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>标签栏</span>
|
||||
<el-switch v-model="tabs" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>标签栏图标</span>
|
||||
<el-switch v-model="tabsIcon" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>页脚</span>
|
||||
<el-switch v-model="footer" />
|
||||
</div>
|
||||
</el-drawer>
|
||||
<!-- 界面设置 -->
|
||||
<el-divider class="divider" content-position="center">
|
||||
<el-icon><Setting /></el-icon>
|
||||
界面设置
|
||||
</el-divider>
|
||||
<div class="theme-item">
|
||||
<span>菜单折叠</span>
|
||||
<el-switch v-model="isCollapse" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>菜单手风琴</span>
|
||||
<el-switch v-model="accordion" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>面包屑</span>
|
||||
<el-switch v-model="breadcrumb" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>面包屑图标</span>
|
||||
<el-switch v-model="breadcrumbIcon" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>标签栏</span>
|
||||
<el-switch v-model="tabs" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>标签栏图标</span>
|
||||
<el-switch v-model="tabsIcon" />
|
||||
</div>
|
||||
<div class="theme-item">
|
||||
<span>页脚</span>
|
||||
<el-switch v-model="footer" />
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useTheme } from "@/hooks/useTheme";
|
||||
import { useGlobalStore } from "@/stores/modules/global";
|
||||
import { LayoutType } from "@/stores/interface";
|
||||
import { DEFAULT_PRIMARY } from "@/config";
|
||||
import mittBus from "@/utils/mittBus";
|
||||
import SwitchDark from "@/components/SwitchDark/index.vue";
|
||||
import { ref } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useTheme } from '@/hooks/useTheme'
|
||||
import { useGlobalStore } from '@/stores/modules/global'
|
||||
import { LayoutType } from '@/stores/interface'
|
||||
import { DEFAULT_PRIMARY } from '@/config'
|
||||
import mittBus from '@/utils/mittBus'
|
||||
import SwitchDark from '@/components/SwitchDark/index.vue'
|
||||
|
||||
const { changePrimary, changeGreyOrWeak, setAsideTheme, setHeaderTheme } = useTheme();
|
||||
const { changePrimary, changeGreyOrWeak, setAsideTheme, setHeaderTheme } = useTheme()
|
||||
|
||||
const globalStore = useGlobalStore();
|
||||
const globalStore = useGlobalStore()
|
||||
const {
|
||||
layout,
|
||||
primary,
|
||||
isGrey,
|
||||
isWeak,
|
||||
asideInverted,
|
||||
headerInverted,
|
||||
isCollapse,
|
||||
accordion,
|
||||
breadcrumb,
|
||||
breadcrumbIcon,
|
||||
tabs,
|
||||
tabsIcon,
|
||||
footer
|
||||
} = storeToRefs(globalStore);
|
||||
layout,
|
||||
primary,
|
||||
isGrey,
|
||||
isWeak,
|
||||
asideInverted,
|
||||
headerInverted,
|
||||
isCollapse,
|
||||
accordion,
|
||||
breadcrumb,
|
||||
breadcrumbIcon,
|
||||
tabs,
|
||||
tabsIcon,
|
||||
footer
|
||||
} = storeToRefs(globalStore)
|
||||
|
||||
// 预定义主题颜色
|
||||
const colorList = [
|
||||
DEFAULT_PRIMARY,
|
||||
"#daa96e",
|
||||
"#0c819f",
|
||||
"#409eff",
|
||||
"#27ae60",
|
||||
"#ff5c93",
|
||||
"#e74c3c",
|
||||
"#fd726d",
|
||||
"#f39c12",
|
||||
"#9b59b6"
|
||||
];
|
||||
DEFAULT_PRIMARY,
|
||||
'#daa96e',
|
||||
'#0c819f',
|
||||
'#409eff',
|
||||
'#27ae60',
|
||||
'#ff5c93',
|
||||
'#e74c3c',
|
||||
'#fd726d',
|
||||
'#f39c12',
|
||||
'#9b59b6'
|
||||
]
|
||||
|
||||
// 设置布局方式
|
||||
const setLayout = (val: LayoutType) => {
|
||||
globalStore.setGlobalState("layout", val);
|
||||
setAsideTheme();
|
||||
};
|
||||
globalStore.setGlobalState('layout', val)
|
||||
setAsideTheme()
|
||||
}
|
||||
|
||||
// 打开主题设置
|
||||
const drawerVisible = ref(false);
|
||||
mittBus.on("openThemeDrawer", () => (drawerVisible.value = true));
|
||||
const drawerVisible = ref(false)
|
||||
mittBus.on('openThemeDrawer', () => (drawerVisible.value = true))
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./index.scss";
|
||||
@use './index.scss';
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user