Browse Source

添加tabs页签

pull/1/head
wanggang 1 year ago
parent
commit
1efa20729e
  1. 3
      docs/demo/src/WTA/wwwroot/components/form/form-input.js
  2. 33
      docs/demo/src/WTA/wwwroot/layouts/index.js
  3. 171
      docs/demo/src/WTA/wwwroot/layouts/tabs.js
  4. 2
      docs/demo/src/WTA/wwwroot/router/index.js
  5. 10
      docs/demo/src/WTA/wwwroot/store/app.js
  6. 2
      docs/demo/src/WTA/wwwroot/styles/site.css

3
docs/demo/src/WTA/wwwroot/components/form/form-input.js

@ -83,9 +83,6 @@ export default {
return schema.input ?? schema.type;
};
/*end*/
// if (props.schema.url && !props.schema.options) {
// props.schema.options = (await post(props.schema.url)).map((o) => ({ label: o.name, value: o }));
// }
return {
model,
getDisabled,

33
docs/demo/src/WTA/wwwroot/layouts/index.js

@ -1,11 +1,14 @@
import html from "html";
import LayoutHeader from "./header.js";
import LayoutMenu from "./menu.js";
import LayoutTabs from "./tabs.js";
import LayoutFooter from "./footer.js";
import Icon from "../components/icon/index.js";
import { useAppStore } from "../store/index.js";
import { computed } from "vue";
export default {
components: { Icon, LayoutHeader, LayoutMenu, LayoutFooter },
components: { Icon, LayoutHeader, LayoutMenu, LayoutTabs, LayoutFooter },
template: html`<el-container>
<el-header><layout-header /></el-header>
<el-container>
@ -14,8 +17,22 @@ export default {
</el-aside>
<el-container class="backtop">
<el-scrollbar>
<layout-tabs />
<el-main>
<router-view :key="$route.fullPath"></router-view>
<router-view v-if="!isRefreshing" v-slot="{ Component, route }">
<component
:is="Component"
v-if="!appStore.isUseTabsRouter || !route.meta?.cached"
:key="$route.fullPath"
/>
<keep-alive>
<component
:is="Component"
v-if="appStore.isUseTabsRouter && route.meta?.cached"
:key="route.fullPath"
/>
</keep-alive>
</router-view>
</el-main>
<el-footer>
<layout-footer />
@ -25,4 +42,16 @@ export default {
</el-container>
</el-container>
</el-container>`,
setup() {
const appStore = useAppStore();
const isRefreshing = computed(() => appStore.isRefreshing);
const path = computed(() => useRoute().matched[0].path);
const items = computed(() => useRoute().matched[0].children);
return {
appStore,
isRefreshing,
path,
items,
};
},
};

171
docs/demo/src/WTA/wwwroot/layouts/tabs.js

@ -0,0 +1,171 @@
import html from "html";
import { ref, nextTick } from "vue";
import { useRoute, onBeforeRouteUpdate, useRouter } from "vue-router";
import Icon from "../components/icon/index.js";
import { useAppStore } from "../store/index.js";
import MenuItem from "./menu-item.js";
export default {
components: { Icon, MenuItem },
template: html`<el-tabs
v-model="model"
type="border-card"
class="router-tab"
@tab-remove="remove"
@tab-click="onClick"
>
<template v-for="(item, index) in appStore.routes" :key="item.fullPath">
<el-tab-pane v-model="item.fullPath" :name="item.fullPath" :closable="appStore.routes.length > 1">
<template #label>
<el-dropdown
:ref="(el) => setRef(index, el)"
class="h-full"
trigger="contextmenu"
@visible-change="showContextMenu(index, $event)"
>
<span class="inline-flex items-center">
<el-icon><icon v-if="item.meta.icon" :name="item.meta.icon" /></el-icon>
{{ item.meta?.title ?? item.fullPath }}
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="refresh(index)"><i-ep-refresh />刷新</el-dropdown-item>
<el-dropdown-item :disabled="index === 0" @click="removeLeft(index)">
<i-ep-back />关闭左侧
</el-dropdown-item>
<el-dropdown-item :disabled="index === appStore.routes.length - 1" @click="removeRight(index)">
<i-ep-right />关闭右侧
</el-dropdown-item>
<el-dropdown-item
:disabled="index === 0 && index === appStore.routes.length - 1"
@click="removeOthers(index)"
>
<i-ep-switch />
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-tab-pane>
</template>
</el-tabs>`,
styles: html`
<style>
.router-tab {
box-sizing: border-box;
height: 40px !important;
background-color: var(--el-fill-color-blank);
border-width: 0 !important;
}
.router-tab .el-tabs__item {
padding: 13px !important;
border-bottom-width: 0;
}
.router-tab .el-tabs__content {
display: none;
}
</style>
`,
setup() {
const appStore = useAppStore();
const itemRefs = ref([]);
const currentRoute = useRoute();
const router = useRouter();
const model = ref(currentRoute.fullPath);
onBeforeRouteUpdate((to) => {
model.value = to.fullPath;
});
const setRef = (index, el) => {
if (el) {
itemRefs.value[index] = el;
} else {
itemRefs.value.splice(index, 1);
}
};
const showContextMenu = (index, show) => {
if (show) {
itemRefs.value.forEach((item, i) => {
if (i !== index) {
item?.handleClose();
}
});
}
};
const refresh = (index) => {
const currentIndex = appStore.routes.findIndex((o) => o.fullPath === currentRoute.fullPath);
const route = appStore.routes[index];
if (index !== currentIndex) {
router.push({ path: route.fullPath });
}
appStore.isRefreshing = true;
nextTick(() => {
appStore.isRefreshing = false;
});
};
const remove = (name) => {
if (appStore.routes.length > 1) {
const index = appStore.routes.findIndex((o) => o.fullPath === name);
const currentIndex = appStore.routes.findIndex((o) => o.fullPath === currentRoute.fullPath);
appStore.routes.splice(index, 1);
if (index === currentIndex) {
if (appStore.routes[index]) {
router.push(appStore.routes[index]);
} else {
router.push(appStore.routes[index - 1]);
}
}
}
};
const removeLeft = (index) => {
const currentIndex = appStore.routes.findIndex((o) => o.fullPath === currentRoute.fullPath);
const route = appStore.routes[index];
appStore.routes.splice(0, index);
if (currentIndex < index) {
router.push(route);
}
};
const removeRight = (index) => {
const currentIndex = appStore.routes.findIndex((o) => o.fullPath === currentRoute.fullPath);
appStore.routes.splice(index + 1, appStore.routes.length - index);
if (currentIndex > index) {
router.push(appStore.routes[index]);
}
};
const removeOthers = (index) => {
removeRight(index);
removeLeft(index);
if (appStore.routes[0].fullPath !== currentRoute.fullPath) {
router.push(appStore.routes[0]);
}
};
const onClick = (context) => {
if (!context.active) {
router.push(context.props.name);
}
};
return {
model,
appStore,
itemRefs,
onBeforeRouteUpdate,
setRef,
showContextMenu,
refresh,
remove,
removeLeft,
removeRight,
removeOthers,
onClick,
};
},
};

2
docs/demo/src/WTA/wwwroot/router/index.js

@ -76,6 +76,8 @@ router.beforeEach(async (to, from, next) => {
router.afterEach((to) => {
try {
const appStore = useAppStore();
appStore.add(to);
if (to.meta.title) {
useTitle().value = `${to.meta.title}`;
}

10
docs/demo/src/WTA/wwwroot/store/app.js

@ -9,6 +9,8 @@ const useAppStore = defineStore("app", {
const state = {
settings: { ...settings },
isMenuCollapse: false,
isRefreshing: false,
routes: [],
};
const localSettings = JSON.parse(localStorage.getItem("settings") ?? "{}");
Object.assign(state.settings, localSettings);
@ -25,6 +27,14 @@ const useAppStore = defineStore("app", {
await refreshRouter();
}
},
add(route) {
if (!this.routes.find((o) => o.fullPath === route.fullPath)) {
this.routes.push(route);
} else {
const index = this.routes.findIndex((o) => o.fullPath === route.fullPath);
this.routes[index] = route;
}
},
},
});

2
docs/demo/src/WTA/wwwroot/styles/site.css

@ -50,7 +50,7 @@ a {
}
.el-main {
min-height: calc(100% - var(--header));
min-height: calc(100% - 100px);
overflow: auto;
}

Loading…
Cancel
Save