feat: add business line permissions and Wayne namespace mapping

This commit is contained in:
mac
2026-07-17 15:02:18 +08:00
parent e1d755b2df
commit d264924d1e
23 changed files with 1343 additions and 81 deletions
+79 -64
View File
@@ -1,8 +1,9 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { businessLineApi, type BusinessLine as ApiBusinessLine } from '@/api/businessLine'
export interface BusinessLine {
id: string
id: number
name: string
ou: string
role: string
@@ -10,63 +11,19 @@ export interface BusinessLine {
iconBg: string
iconColor: string
authorized: boolean
permission?: 0 | 1
created_at?: string
updated_at?: string
}
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,
},
]
const COLORS = [
['#1A1430', '#C9A6FF'],
['#0E1C2C', '#8EC8FF'],
['#241B0A', '#FFC97A'],
['#1A2A1A', '#A6FFB0'],
['#2A1A2A', '#FFB0E0'],
] as const
function loadSavedBL(): BusinessLine | null {
try {
@@ -78,30 +35,88 @@ function loadSavedBL(): BusinessLine | null {
return null
}
export const useBusinessLineStore = defineStore('businessLine', () => {
const businessLines = ref<BusinessLine[]>(MOCK_BUSINESS_LINES)
const currentBL = ref<BusinessLine | null>(loadSavedBL())
// 默认选中第一个已授权的业务线
if (!currentBL.value) {
currentBL.value = businessLines.value.find((bl) => bl.authorized) || null
function saveBL(bl: BusinessLine | null) {
if (!bl) {
localStorage.removeItem(STORAGE_KEY)
return
}
localStorage.setItem(STORAGE_KEY, JSON.stringify(bl))
}
function initials(name: string) {
const compact = name.replace(/\s+/g, '')
return compact.slice(0, 2).toUpperCase() || 'BL'
}
function mapBusinessLine(item: ApiBusinessLine, index: number): BusinessLine {
const [iconBg, iconColor] = COLORS[index % COLORS.length]
return {
id: item.id,
name: item.name,
ou: `ou=${item.name}`,
role: item.permission === 0 ? '管理员' : '普通用户',
iconText: initials(item.name),
iconBg,
iconColor,
authorized: true,
permission: item.permission,
created_at: item.created_at,
updated_at: item.updated_at,
}
}
export const useBusinessLineStore = defineStore('businessLine', () => {
const businessLines = ref<BusinessLine[]>([])
const currentBL = ref<BusinessLine | null>(loadSavedBL())
const loading = ref(false)
const items = computed(() => businessLines.value)
const current = computed(() => currentBL.value)
const isCurrentAdmin = computed(() => currentBL.value?.permission === 0)
const authorizedBLs = computed(() =>
businessLines.value.filter((bl) => bl.authorized),
)
function switchBL(id: string) {
async function loadMine() {
loading.value = true
try {
const rows = await businessLineApi.listMine()
const mapped = rows.map(mapBusinessLine)
businessLines.value = mapped
const savedID = currentBL.value?.id
const next = mapped.find((bl) => bl.id === savedID) || mapped[0] || null
currentBL.value = next
saveBL(next)
} finally {
loading.value = false
}
}
function switchBL(id: number) {
const bl = businessLines.value.find((b) => b.id === id)
if (!bl || !bl.authorized) return
currentBL.value = bl
localStorage.setItem(STORAGE_KEY, JSON.stringify(bl))
saveBL(bl)
}
function clear() {
businessLines.value = []
currentBL.value = null
saveBL(null)
}
return {
businessLines,
items,
currentBL,
current,
loading,
isCurrentAdmin,
authorizedBLs,
loadMine,
switchBL,
clear,
}
})