material_manage_system/frontend/src/App.vue

102 lines
3.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div id="app">
<template v-if="authStore.isLoggedIn">
<AppHeader />
<div class="app-container">
<AppSidebar :active-menu="currentRoute" @menu-select="handleMenuSelect" />
<main class="app-main">
<!-- 公司尚未确定时用屏障占位,不挂载业务页面,避免组件 onMounted 发出缺少组织头的请求 -->
<div v-if="organizationBarrier" class="organization-barrier">
<el-empty v-if="organizationStore.loadError" description="公司信息加载失败,请重试">
<el-button type="primary" :loading="retrying" @click="retryInitialize">
重新加载
</el-button>
</el-empty>
<el-empty v-else description="请先选择要操作的公司" />
</div>
<router-view v-else :key="viewKey" />
</main>
</div>
</template>
<template v-else-if="!route.meta.requiresAuth">
<router-view />
</template>
</div>
</template>
<script setup>
import { computed, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useAuthStore } from './stores/auth'
import { useOrganizationStore } from './stores/organization'
import AppHeader from './components/layout/AppHeader.vue'
import AppSidebar from './components/layout/AppSidebar.vue'
const route = useRoute()
const router = useRouter()
const authStore = useAuthStore()
const organizationStore = useOrganizationStore()
// 加载失败后用户手动重试;重试本身不应被误认为公司切换,故用独立标记。
const retrying = ref(false)
const currentRoute = computed(() => route.path)
// 组织级页面在公司未确定时不挂载:由 AppHeader 的切换器引导用户先选公司。
const organizationBarrier = computed(
() => route.meta.organizationScoped === true && organizationStore.currentOrganizationId == null
)
// 组织级页面用“公司 ID + 上下文版本”作为挂载 key:切换公司即重新挂载,旧页面状态随之清空。
// 全局的用户、组织、角色管理页不作为公司数据页,key 固定、不随公司变化。
const viewKey = computed(() => {
if (route.meta.organizationScoped !== true) return 'global'
return `organization-${organizationStore.currentOrganizationId}-${organizationStore.contextVersion}`
})
function handleMenuSelect(path) {
router.push(path)
}
// 手动重试公司初始化:成功后 currentOrganizationId 变为非空,屏障自动撤下;
// 仍失败时保持“加载失败”提示,等待用户再次重试。
async function retryInitialize() {
retrying.value = true
try {
await organizationStore.initialize()
} catch {
// 错误已由 axios 拦截器提示,且 store 已置 loadError,这里不再重复弹提示。
} finally {
retrying.value = false
}
}
</script>
<style>
#app {
height: 100vh;
display: flex;
flex-direction: column;
}
.app-container {
display: flex;
flex: 1;
overflow: hidden;
}
.app-sidebar {
width: 200px;
flex-shrink: 0;
}
.app-main {
flex: 1;
padding: 20px;
overflow-y: auto;
}
.organization-barrier {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
</style>