This commit is contained in:
2023-06-08 21:09:28 +08:00
parent d778ceab61
commit f8947d332a
158 changed files with 17210 additions and 259 deletions

View File

@@ -0,0 +1,15 @@
<template>
<div>
<a-layout-footer class="flex items-center justify-center h-10 footer text-center"
>成都测试管理平台</a-layout-footer
>
</div>
</template>
<script setup></script>
<style lang="less" scoped>
.footer {
color: var(--color-text-2);
}
</style>

View File

@@ -77,13 +77,13 @@
</a-space>
</a-doption>
<a-doption>
<a-space @click="$router.push({ name: 'Info' })">
<a-space @click="$router.push({ name: 'Usercenter' })">
<icon-user />
<span> 用户中心 </span>
</a-space>
</a-doption>
<a-doption>
<a-space @click="$router.push({ name: 'Setting' })">
<a-space @click="$router.push({ name: 'Usercenter' })">
<icon-settings />
<span> 用户设置 </span>
</a-space>

View File

@@ -13,78 +13,77 @@
</div>
</template>
<script lang="ts" setup>
import { ref, computed, watch, onUnmounted } from 'vue'
import type { RouteLocationNormalized } from 'vue-router'
import { listenerRouteChange, removeRouteListener } from '@/utils/route-listener'
import { useAppStore, useTabBarStore } from '@/store'
import tabItem from './tab-item.vue'
<script setup>
import { ref, computed, watch, onUnmounted } from "vue"
import { listenerRouteChange, removeRouteListener } from "@/utils/route-listener"
import { useAppStore, useTabBarStore } from "@/store"
import tabItem from "./tab-item.vue"
const appStore = useAppStore()
const tabBarStore = useTabBarStore()
const appStore = useAppStore()
const tabBarStore = useTabBarStore()
const affixRef = ref()
const tagList = computed(() => {
return tabBarStore.getTabList
})
const offsetTop = computed(() => {
return appStore.navbar ? 60 : 0
})
const affixRef = ref()
const tagList = computed(() => {
return tabBarStore.getTabList
})
const offsetTop = computed(() => {
return appStore.navbar ? 60 : 0
})
watch(
() => appStore.navbar,
() => {
affixRef.value.updatePosition()
}
)
listenerRouteChange((route) => {
if (!route.meta.noAffix && !tagList.value.some((tag) => tag.fullPath === route.fullPath)) {
tabBarStore.updateTabList(route)
}
}, true)
watch(
() => appStore.navbar,
() => {
affixRef.value.updatePosition()
}
)
listenerRouteChange((route) => {
if (!route.meta.noAffix && !tagList.value.some((tag) => tag.fullPath === route.fullPath)) {
tabBarStore.updateTabList(route)
}
}, true)
onUnmounted(() => {
removeRouteListener()
})
onUnmounted(() => {
removeRouteListener()
})
</script>
<style scoped lang="less">
.tab-bar-container {
position: relative;
.tab-bar-container {
position: relative;
background-color: var(--color-bg-2);
.tab-bar-box {
display: flex;
padding: 0 0 0 20px;
background-color: var(--color-bg-2);
.tab-bar-box {
display: flex;
padding: 0 0 0 20px;
background-color: var(--color-bg-2);
border-bottom: 1px solid var(--color-border);
.tab-bar-scroll {
height: 32px;
flex: 1;
overflow: hidden;
.tags-wrap {
padding: 4px 0;
height: 48px;
white-space: nowrap;
overflow-x: auto;
border-bottom: 1px solid var(--color-border);
.tab-bar-scroll {
height: 32px;
flex: 1;
overflow: hidden;
.tags-wrap {
padding: 4px 0;
height: 48px;
white-space: nowrap;
overflow-x: auto;
:deep(.arco-tag) {
display: inline-flex;
align-items: center;
margin-right: 6px;
cursor: pointer;
&:first-child {
.arco-tag-close-btn {
display: none;
}
:deep(.arco-tag) {
display: inline-flex;
align-items: center;
margin-right: 6px;
cursor: pointer;
&:first-child {
.arco-tag-close-btn {
display: none;
}
}
}
}
}
.tag-bar-operation {
width: 100px;
height: 32px;
}
}
.tag-bar-operation {
width: 100px;
height: 32px;
}
}
</style>

View File

@@ -0,0 +1,185 @@
<template>
<a-dropdown trigger="contextMenu" :popup-max-height="false" @select="actionSelect">
<span
class="arco-tag arco-tag-size-medium arco-tag-checked"
:class="{ 'link-activated': itemData.fullPath === $route.fullPath }"
@click="goto(itemData)"
>
<span class="tag-link"> {{ itemData.title }} </span>
<span
class="arco-icon-hover arco-tag-icon-hover arco-icon-hover-size-medium arco-tag-close-btn"
@click.stop="tagClose(itemData, index)"
>
<icon-close />
</span>
</span>
<template #content>
<a-doption :disabled="disabledReload" :value="Eaction.reload">
<icon-refresh />
<span>重新加载</span>
</a-doption>
<a-doption class="sperate-line" :disabled="disabledCurrent" :value="Eaction.current">
<icon-close />
<span>关闭当前标签页</span>
</a-doption>
<a-doption :disabled="disabledLeft" :value="Eaction.left">
<icon-to-left />
<span>关闭左侧标签页</span>
</a-doption>
<a-doption class="sperate-line" :disabled="disabledRight" :value="Eaction.right">
<icon-to-right />
<span>关闭右侧标签页</span>
</a-doption>
<a-doption :value="Eaction.others">
<icon-swap />
<span>关闭其它标签页</span>
</a-doption>
<a-doption :value="Eaction.all">
<icon-folder-delete />
<span>关闭全部标签页</span>
</a-doption>
</template>
</a-dropdown>
</template>
<script lang="ts" setup>
import { PropType, computed } from "vue"
import { useRouter, useRoute } from "vue-router"
import { useTabBarStore } from "@/store"
import { DEFAULT_ROUTE_NAME, REDIRECT_ROUTE_NAME } from "@/router/constants"
// eslint-disable-next-line no-shadow
enum Eaction {
reload = "reload",
current = "current",
left = "left",
right = "right",
others = "others",
all = "all"
}
const props = defineProps({
itemData: {
type: Object,
default() {
return []
}
},
index: {
type: Number,
default: 0
}
})
const router = useRouter()
const route = useRoute()
const tabBarStore = useTabBarStore()
const goto = (tag) => {
router.push({ ...tag })
}
const tagList = computed(() => {
return tabBarStore.getTabList
})
const disabledReload = computed(() => {
return props.itemData.fullPath !== route.fullPath
})
const disabledCurrent = computed(() => {
return props.index === 0
})
const disabledLeft = computed(() => {
return [0, 1].includes(props.index)
})
const disabledRight = computed(() => {
return props.index === tagList.value.length - 1
})
const tagClose = (tag, idx) => {
tabBarStore.deleteTag(idx, tag)
if (props.itemData.fullPath === route.fullPath) {
const latest = tagList.value[idx - 1] // 获取队列的前一个tab
router.push({ name: latest.name })
}
}
const findCurrentRouteIndex = () => {
return tagList.value.findIndex((el) => el.fullPath === route.fullPath)
}
const actionSelect = async (value: any) => {
const { itemData, index } = props
const copyTagList = [...tagList.value]
if (value === Eaction.current) {
tagClose(itemData, index)
} else if (value === Eaction.left) {
const currentRouteIdx = findCurrentRouteIndex()
copyTagList.splice(1, props.index - 1)
tabBarStore.freshTabList(copyTagList)
if (currentRouteIdx < index) {
router.push({ name: itemData.name })
}
} else if (value === Eaction.right) {
const currentRouteIdx = findCurrentRouteIndex()
copyTagList.splice(props.index + 1)
tabBarStore.freshTabList(copyTagList)
if (currentRouteIdx > index) {
router.push({ name: itemData.name })
}
} else if (value === Eaction.others) {
const filterList = tagList.value.filter((el, idx) => {
return idx === 0 || idx === props.index
})
tabBarStore.freshTabList(filterList)
router.push({ name: itemData.name })
} else if (value === Eaction.reload) {
tabBarStore.deleteCache(itemData)
await router.push({
name: REDIRECT_ROUTE_NAME,
params: {
path: route.fullPath
}
})
tabBarStore.addCache(itemData.name)
} else {
tabBarStore.resetTabList()
router.push({ name: DEFAULT_ROUTE_NAME })
}
}
</script>
<style scoped lang="less">
.tag-link {
color: var(--color-text-2);
text-decoration: none;
}
.link-activated {
color: rgb(var(--link-6));
.tag-link {
color: rgb(var(--link-6));
}
& + .arco-tag-close-btn {
color: rgb(var(--link-6));
}
}
:deep(.arco-dropdown-option-content) {
span {
margin-left: 10px;
}
}
.arco-dropdown-open {
.tag-link {
color: rgb(var(--danger-6));
}
.arco-tag-close-btn {
color: rgb(var(--danger-6));
}
}
.sperate-line {
border-bottom: 1px solid var(--color-neutral-3);
}
</style>