This commit is contained in:
zwgczx committed 2026-02-24 17:14:01 +08:00
1 parent 6ba08da229
commit f121aa233e
13 files changed
+2559 -128

No files matched your search

+83 -28
View File
@@ -1,50 +1,105 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import xmView from '@/components/views/xmInfo.vue'
import { computed, ref, watch, type Component } from 'vue'
import { ScrollArea } from '@/components/ui/scroll-area'
// 使用 sessionStorage 管理左侧分类切换状态
const activeCategory = ref(sessionStorage.getItem('project-active-cat') || 'info')
interface TypeLineCategory {
key: string
label: string
component: Component
}
const props = withDefaults(
defineProps<{
scene?: string
title?: string
categories: TypeLineCategory[]
storageKey?: string
defaultCategory?: string
}>(),
{
scene: 'default',
title: '配置',
storageKey: '',
defaultCategory: ''
}
)
const cacheKey = computed(() => props.storageKey || `type-line-active-cat-${props.scene}`)
const resolveInitialCategory = () => {
const defaultKey = props.defaultCategory || props.categories[0]?.key || ''
const savedKey = sessionStorage.getItem(cacheKey.value)
const validSavedKey = props.categories.some(item => item.key === savedKey)
return validSavedKey ? (savedKey as string) : defaultKey
}
const activeCategory = ref(resolveInitialCategory())
watch(
() => [props.categories, props.defaultCategory, cacheKey.value],
() => {
activeCategory.value = resolveInitialCategory()
},
{ deep: true }
)
const switchCategory = (cat: string) => {
activeCategory.value = cat
sessionStorage.setItem('project-active-cat', cat)
sessionStorage.setItem(cacheKey.value, cat)
}
const activeComponent = computed(() => {
const selected = props.categories.find(item => item.key === activeCategory.value)
return selected?.component || props.categories[0]?.component || null
})
</script>
<template>
<div class="flex h-full w-full bg-background">
<div class="w-1/5 border-r p-6 flex flex-col gap-8 relative">
<div class="font-bold text-lg mb-4 text-primary">项目配置</div>
<div class="font-bold text-lg mb-4 text-primary">{{ props.title }}</div>
<div class="flex flex-col gap-10 relative">
<div class="absolute left-[11px] top-2 bottom-2 w-[2px] bg-muted"></div>
<div class="relative flex items-center gap-4 cursor-pointer group" @click="switchCategory('info')">
<div :class="['z-10 w-6 h-6 rounded-full border-2 flex items-center justify-center transition-all',
activeCategory === 'info' ? 'bg-primary border-primary scale-110' : 'bg-background border-muted-foreground']">
<div v-if="activeCategory === 'info'" class="w-2 h-2 bg-background rounded-full"></div>
<div
v-for="item in props.categories"
:key="item.key"
class="relative flex items-center gap-4 cursor-pointer group"
@click="switchCategory(item.key)"
>
<div
:class="[
'z-10 w-6 h-6 rounded-full border-2 flex items-center justify-center transition-all',
activeCategory === item.key
? 'bg-primary border-primary scale-110'
: 'bg-background border-muted-foreground'
]"
>
<div v-if="activeCategory === item.key" class="w-2 h-2 bg-background rounded-full"></div>
</div>
<span :class="['text-sm transition-colors', activeCategory === 'info' ? 'font-bold text-primary' : 'text-muted-foreground group-hover:text-foreground']">
分类信息
</span>
</div>
<div class="relative flex items-center gap-4 cursor-pointer group" @click="switchCategory('contract')">
<div :class="['z-10 w-6 h-6 rounded-full border-2 flex items-center justify-center transition-all',
activeCategory === 'contract' ? 'bg-primary border-primary scale-110' : 'bg-background border-muted-foreground']">
<div v-if="activeCategory === 'contract'" class="w-2 h-2 bg-background rounded-full"></div>
</div>
<span :class="['text-sm transition-colors', activeCategory === 'contract' ? 'font-bold text-primary' : 'text-muted-foreground group-hover:text-foreground']">
合同段管理
<span
:class="[
'text-sm transition-colors',
activeCategory === item.key
? 'font-bold text-primary'
: 'text-muted-foreground group-hover:text-foreground'
]"
>
{{ item.label }}
</span>
</div>
</div>
</div>
<div class="w-4/5 p-8 overflow-auto">
<keep-alive>
<component :is="activeCategory === 'info' ? xmView : xmView" />
</keep-alive>
<div class="w-4/5 min-h-0">
<ScrollArea class="h-full w-full">
<div class="p-3">
<keep-alive>
<component :is="activeComponent" />
</keep-alive>
</div>
</ScrollArea>
</div>
</div>
</template>
</template>