148 lines
4.5 KiB
TypeScript
148 lines
4.5 KiB
TypeScript
import type { Component } from 'vue';
|
||
import { markRaw, shallowRef } from 'vue';
|
||
|
||
export type WorkbenchModuleKey =
|
||
// 保留:现有 key 沿用(避免影响线上用户布局存储)
|
||
| 'myTodo' // A1 · 我的待办
|
||
| 'myProject' // B7 · 我参与的项目
|
||
| 'shortcut' // E19 · 快捷入口
|
||
| 'projectHealth' // C15 · 产品 / 项目健康度
|
||
// 新增(蓝图 2026-05-22,原 A3 myTicket、A4 mentions、A5 approval、A6 worklogReminder、B10 personalItem、F23 projectSnapshot、C11 teamTodo、E21 favorite 已废弃,F23 已并入 B7 myProject "我负责的" tab)
|
||
| 'myExecution' // B8 · 我负责的执行
|
||
| 'productSnapshot' // F24 · 产品深度快照(对象快照 / 当前对象切换)
|
||
| 'teamLoad' // C13 · 团队负载(管理者)
|
||
| 'myWeekWorklog' // D16 · 工时(含「我的工时 / 团队工时」两 tab,原 C12 teamWorklog 已并入)
|
||
| 'noticeNotification'; // E22 · 公告 + 通知摘要
|
||
|
||
// 扩展:action(动作型 widget)、snapshot(对象快照型 widget,需指定一个对象)
|
||
export type WorkbenchModuleCategory = 'personal' | 'manager' | 'tool' | 'action' | 'snapshot';
|
||
export type WorkbenchColumnId = 'left' | 'right';
|
||
|
||
export interface WorkbenchModuleMeta {
|
||
key: WorkbenchModuleKey;
|
||
component: Component;
|
||
displayName: string;
|
||
icon: string;
|
||
category: WorkbenchModuleCategory;
|
||
defaultVisible: boolean;
|
||
defaultColumn: WorkbenchColumnId;
|
||
defaultOrder: number;
|
||
}
|
||
|
||
const placeholder = markRaw({ render: () => null });
|
||
|
||
// 默认布局(2026-05-27 调整,对应 WORKBENCH_LAYOUT_VERSION=3):
|
||
// left: myTodo(1) → myExecution(2)
|
||
// right: shortcut(1) → myProject(2) → myWeekWorklog(3) → teamLoad(4)
|
||
// hidden: projectHealth, noticeNotification, productSnapshot
|
||
// (noticeNotification 隐藏原因:公告搬到 banner、通知归全局头部铃铛)
|
||
const registry: WorkbenchModuleMeta[] = [
|
||
{
|
||
key: 'myTodo',
|
||
component: placeholder,
|
||
displayName: '我的待办',
|
||
icon: 'mdi:clipboard-text-clock-outline',
|
||
category: 'personal',
|
||
defaultVisible: true,
|
||
defaultColumn: 'left',
|
||
defaultOrder: 1
|
||
},
|
||
{
|
||
key: 'myExecution',
|
||
component: placeholder,
|
||
displayName: '我负责的执行',
|
||
icon: 'mdi:flag-checkered',
|
||
category: 'personal',
|
||
defaultVisible: true,
|
||
defaultColumn: 'left',
|
||
defaultOrder: 2
|
||
},
|
||
{
|
||
key: 'shortcut',
|
||
component: placeholder,
|
||
displayName: '快捷入口',
|
||
icon: 'mdi:rocket-launch-outline',
|
||
category: 'tool',
|
||
defaultVisible: true,
|
||
defaultColumn: 'right',
|
||
defaultOrder: 1
|
||
},
|
||
{
|
||
key: 'myProject',
|
||
component: placeholder,
|
||
displayName: '我的项目',
|
||
icon: 'mdi:briefcase-outline',
|
||
category: 'personal',
|
||
defaultVisible: true,
|
||
defaultColumn: 'right',
|
||
defaultOrder: 2
|
||
},
|
||
{
|
||
key: 'myWeekWorklog',
|
||
component: placeholder,
|
||
displayName: '工时',
|
||
icon: 'mdi:timer-outline',
|
||
category: 'personal',
|
||
defaultVisible: true,
|
||
defaultColumn: 'right',
|
||
defaultOrder: 3
|
||
},
|
||
{
|
||
key: 'teamLoad',
|
||
component: placeholder,
|
||
displayName: '团队负载',
|
||
icon: 'mdi:scale-balance',
|
||
category: 'manager',
|
||
defaultVisible: true,
|
||
defaultColumn: 'right',
|
||
defaultOrder: 4
|
||
},
|
||
// === 默认隐藏(用户可从 widget 库拖回) ===
|
||
{
|
||
key: 'projectHealth',
|
||
component: placeholder,
|
||
displayName: '产品 / 项目健康度',
|
||
icon: 'mdi:heart-pulse',
|
||
category: 'manager',
|
||
defaultVisible: false,
|
||
defaultColumn: 'right',
|
||
defaultOrder: 10
|
||
},
|
||
{
|
||
key: 'noticeNotification',
|
||
component: placeholder,
|
||
displayName: '公告 + 通知',
|
||
icon: 'mdi:bullhorn-outline',
|
||
category: 'tool',
|
||
defaultVisible: false,
|
||
defaultColumn: 'right',
|
||
defaultOrder: 11
|
||
},
|
||
{
|
||
key: 'productSnapshot',
|
||
component: placeholder,
|
||
displayName: '产品深度快照',
|
||
icon: 'mdi:image-area-close',
|
||
category: 'snapshot',
|
||
defaultVisible: false,
|
||
defaultColumn: 'left',
|
||
defaultOrder: 41
|
||
}
|
||
];
|
||
|
||
const registryRef = shallowRef(registry);
|
||
|
||
export function useWorkbenchModules() {
|
||
function getAllModules() {
|
||
return registryRef.value;
|
||
}
|
||
function getModuleMeta(key: WorkbenchModuleKey) {
|
||
return registryRef.value.find(m => m.key === key);
|
||
}
|
||
function registerModuleComponent(key: WorkbenchModuleKey, component: Component) {
|
||
const target = registryRef.value.find(m => m.key === key);
|
||
if (target) target.component = markRaw(component);
|
||
}
|
||
return { getAllModules, getModuleMeta, registerModuleComponent };
|
||
}
|