| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- <template>
- <div class="app-shell">
- <ModuleRail :active-module="activeModule" @select="onModuleSelect" />
- <ContextNav
- :title="contextTitle"
- :items="contextItems"
- :collapsed="contextCollapsed"
- @toggle="contextCollapsed = !contextCollapsed"
- />
- <div class="app-shell__main">
- <SystemStatusBar
- :period-name="periodName"
- :phase="phase"
- :unread-count="0"
- />
- <main class="app-shell__content">
- <router-view />
- </main>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, computed, watch } from 'vue'
- import { useRoute, useRouter } from 'vue-router'
- import { useWorkspaceStore } from '@/stores/workspace'
- import ModuleRail from './ModuleRail.vue'
- import ContextNav from './ContextNav.vue'
- import SystemStatusBar from './SystemStatusBar.vue'
- import {
- HomeFilled, Aim, DataAnalysis, Setting,
- Monitor, List, Share, TrendCharts,
- DocumentChecked, ChatDotRound, Warning, Clock,
- Calendar, OfficeBuilding, Notebook, Grid, Tickets
- } from '@element-plus/icons-vue'
- const route = useRoute()
- const router = useRouter()
- const workspace = useWorkspaceStore()
- const activeModule = ref('workspace')
- const contextCollapsed = ref(false)
- const moduleContexts = {
- workspace: {
- title: '工作台',
- items: [
- { to: '/workspace', label: '当前周期', icon: Monitor }
- ]
- },
- okr: {
- title: '目标与对齐',
- items: [
- { to: '/okr/my', label: '我的 OKR', icon: Aim },
- { to: '/okr/team', label: '团队 OKR', icon: List },
- { to: '/okr/alignment', label: 'OKR 对齐', icon: Share },
- { to: '/okr/execution', label: '执行进度', icon: TrendCharts }
- ]
- },
- performance: {
- title: '绩效评审',
- items: [
- { to: '/scores/my', label: '我的绩效', icon: DocumentChecked },
- { to: '/scores/review', label: '待我评审', icon: DataAnalysis },
- { to: '/feedback', label: '绩效沟通', icon: ChatDotRound },
- { to: '/scores/appeal', label: '绩效申诉', icon: Warning },
- { to: '/scores/history', label: '历史绩效', icon: Clock }
- ]
- },
- admin: {
- title: '系统管理',
- items: [
- { to: '/period', label: '考核周期', icon: Calendar },
- { to: '/org', label: '组织架构', icon: OfficeBuilding },
- { to: '/period/templates', label: '绩效模板', icon: Notebook },
- { to: '/dimensions', label: '考核维度', icon: Grid },
- { to: '/logs', label: '操作日志', icon: Tickets }
- ]
- }
- }
- const contextTitle = computed(() => moduleContexts[activeModule.value]?.title || '')
- const contextItems = computed(() => moduleContexts[activeModule.value]?.items || [])
- const periodName = computed(() => workspace.currentPeriod?.name || '')
- const phase = computed(() => workspace.currentPhase || '')
- function onModuleSelect(key) {
- activeModule.value = key
- const first = moduleContexts[key]?.items[0]
- if (first) router.push(first.to)
- }
- // Sync active module from route
- watch(() => route.path, (path) => {
- for (const [mod, ctx] of Object.entries(moduleContexts)) {
- if (ctx.items.some(i => path.startsWith(i.to))) {
- activeModule.value = mod
- return
- }
- }
- }, { immediate: true })
- </script>
- <style scoped>
- .app-shell {
- display: flex;
- min-height: 100vh;
- background: var(--workspace-bg, #f5f8fa);
- }
- .app-shell__main {
- flex: 1;
- min-width: 0;
- display: flex;
- flex-direction: column;
- }
- .app-shell__content {
- flex: 1;
- overflow-y: auto;
- padding: var(--spacing-lg, 16px);
- }
- </style>
|