diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 6d63c3e..4380d44 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -11,6 +11,7 @@ declare module 'vue' { AppMain: typeof import('./src/components/Layout/AppMain.vue')['default'] AppSidebar: typeof import('./src/components/Layout/AppSidebar.vue')['default'] AuditLogTable: typeof import('./src/components/AuditLogTable.vue')['default'] + BusinessLineSwitcher: typeof import('./src/components/BusinessLineSwitcher.vue')['default'] ElButton: typeof import('element-plus/es')['ElButton'] ElIcon: typeof import('element-plus/es')['ElIcon'] ElInput: typeof import('element-plus/es')['ElInput'] diff --git a/frontend/src/components/BusinessLineSwitcher.vue b/frontend/src/components/BusinessLineSwitcher.vue new file mode 100644 index 0000000..c13e03e --- /dev/null +++ b/frontend/src/components/BusinessLineSwitcher.vue @@ -0,0 +1,230 @@ + + + + + diff --git a/frontend/src/components/Layout/AppHeader.vue b/frontend/src/components/Layout/AppHeader.vue index 3833271..41ca71d 100644 --- a/frontend/src/components/Layout/AppHeader.vue +++ b/frontend/src/components/Layout/AppHeader.vue @@ -5,6 +5,7 @@ xinfra 统一基础设施平台 ● 生产环境 +
@@ -36,6 +37,7 @@ import { useAuthStore } from '@/stores/auth' import { useTheme } from '@/composables/useTheme' import { useAuth } from '@/composables/useAuth' import { Moon, Sunny } from '@element-plus/icons-vue' +import BusinessLineSwitcher from '@/components/BusinessLineSwitcher.vue' const authStore = useAuthStore() const { logout } = useAuth() diff --git a/frontend/src/stores/businessLine.ts b/frontend/src/stores/businessLine.ts new file mode 100644 index 0000000..e7b69ab --- /dev/null +++ b/frontend/src/stores/businessLine.ts @@ -0,0 +1,107 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' + +export interface BusinessLine { + id: string + name: string + ou: string + role: string + iconText: string + iconBg: string + iconColor: string + authorized: boolean +} + +const STORAGE_KEY = 'xinfra-current-bl' + +// TODO: 替换为真实 API 调用 +const MOCK_BUSINESS_LINES: BusinessLine[] = [ + { + id: 'las', + name: 'LAS 业务线', + ou: 'ou=las', + role: 'SRE', + iconText: 'LA', + iconBg: '#1A1430', + iconColor: '#C9A6FF', + authorized: true, + }, + { + id: 'kodo', + name: 'Kodo 业务线', + ou: 'ou=kodo', + role: '研发', + iconText: 'KO', + iconBg: '#0E1C2C', + iconColor: '#8EC8FF', + authorized: true, + }, + { + id: 'lingxi', + name: '灵矽 业务线', + ou: 'ou=lingxi', + role: '未授权', + iconText: 'LX', + iconBg: '#241B0A', + iconColor: '#FFC97A', + authorized: false, + }, + { + id: 'ltoken', + name: 'LTOKEN 业务线', + ou: 'ou=ltoken', + role: '研发', + iconText: 'LT', + iconBg: '#1A2A1A', + iconColor: '#A6FFB0', + authorized: true, + }, + { + id: 'maas', + name: 'MAAS 业务线', + ou: 'ou=maas', + role: '未授权', + iconText: 'MA', + iconBg: '#2A1A2A', + iconColor: '#FFB0E0', + authorized: false, + }, +] + +function loadSavedBL(): BusinessLine | null { + try { + const saved = localStorage.getItem(STORAGE_KEY) + if (saved) return JSON.parse(saved) + } catch { + // ignore + } + return null +} + +export const useBusinessLineStore = defineStore('businessLine', () => { + const businessLines = ref(MOCK_BUSINESS_LINES) + const currentBL = ref(loadSavedBL()) + + // 默认选中第一个已授权的业务线 + if (!currentBL.value) { + currentBL.value = businessLines.value.find((bl) => bl.authorized) || null + } + + const authorizedBLs = computed(() => + businessLines.value.filter((bl) => bl.authorized), + ) + + function switchBL(id: string) { + const bl = businessLines.value.find((b) => b.id === id) + if (!bl || !bl.authorized) return + currentBL.value = bl + localStorage.setItem(STORAGE_KEY, JSON.stringify(bl)) + } + + return { + businessLines, + currentBL, + authorizedBLs, + switchBL, + } +})