import { ref, computed, shallowRef, type Component } from 'vue';
/**
* 布局选项描述
*/
export interface LayoutOption {
id: string;
label: string;
icon: string; // emoji 或 SVG 标识
description?: string;
component: Component;
}
const STORAGE_KEY = 'cube-layout';
// 模块级响应式状态(全局单例)
const registeredLayouts = ref<LayoutOption[]>([]);
const currentLayoutId = ref<string>('');
/**
* 注册一个布局
* 通常在 main.ts / initApp 回调中调用
* 第一个注册的布局自动成为默认布局
*/
export function registerLayout(option: LayoutOption): void {
if (registeredLayouts.value.some((l) => l.id === option.id)) return;
registeredLayouts.value.push(option);
// 第一次注册时,从 localStorage 恢复或设为第一个
if (!currentLayoutId.value) {
const stored = localStorage.getItem(STORAGE_KEY);
const valid = stored && registeredLayouts.value.some((l) => l.id === stored);
currentLayoutId.value = valid ? stored! : option.id;
}
}
/**
* 布局组合式函数
* 在 Topnav / RootLayout 等组件中使用
*/
export function useLayout() {
const currentLayout = computed<LayoutOption | undefined>(() =>
registeredLayouts.value.find((l) => l.id === currentLayoutId.value),
);
const currentComponent = computed<Component | undefined>(() => currentLayout.value?.component);
function setLayout(id: string): void {
if (!registeredLayouts.value.some((l) => l.id === id)) return;
currentLayoutId.value = id;
localStorage.setItem(STORAGE_KEY, id);
}
return {
layouts: registeredLayouts,
currentLayoutId,
currentLayout,
currentComponent,
setLayout,
};
}
|