Files
cn-rdms-web/src/views/workbench/composables/use-workbench-modules.ts

129 lines
4.6 KiB
TypeScript
Raw Normal View History

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 已并入)
// 扩展action动作型 widget、snapshot对象快照型 widget需指定一个对象
export type WorkbenchModuleCategory = 'personal' | 'manager' | 'tool' | 'action' | 'snapshot';
export interface WorkbenchModuleMeta {
key: WorkbenchModuleKey;
component: Component;
displayName: string;
icon: string;
category: WorkbenchModuleCategory;
defaultVisible: boolean;
/** 默认网格位置与尺寸12 栅格。hidden 项的 x/y 仅作占位show 时动态找空位。 */
defaultGrid: { x: number; y: number; w: number; h: number; minW: number; minH: number };
}
const placeholder = markRaw({ render: () => null });
// 默认布局2026-06-01 固化用户实拍布局,对应 WORKBENCH_LAYOUT_VERSION=5
// 左列x=0 w=7myTodo(y=0 h=25) → myWeekWorklog(y=25 h=22)
// 右列x=7 w=5shortcut(y=0 h=11) → myProject(y=11 h=17) → myExecution(y=28 h=19)
// 底部满宽x=0 w=12teamLoad(y=47 h=16)
// hiddenx/y 为占位show 时动态落到网格底部projectHealth、productSnapshot
const registry: WorkbenchModuleMeta[] = [
{
key: 'myTodo',
component: placeholder,
displayName: '我的待办',
icon: 'mdi:clipboard-text-clock-outline',
category: 'personal',
defaultVisible: true,
// minH 24 ≈ 608px保证至少完整展示 5 条待办(头部 124 + 5×71 列表 + 余量)
defaultGrid: { x: 0, y: 0, w: 7, h: 25, minW: 5, minH: 24 }
},
{
key: 'myExecution',
component: placeholder,
displayName: '我负责的执行',
icon: 'mdi:flag-checkered',
category: 'personal',
defaultVisible: true,
defaultGrid: { x: 7, y: 28, w: 5, h: 19, minW: 4, minH: 15 }
},
{
key: 'shortcut',
component: placeholder,
displayName: '快捷入口',
icon: 'mdi:rocket-launch-outline',
category: 'tool',
defaultVisible: true,
defaultGrid: { x: 7, y: 0, w: 5, h: 11, minW: 3, minH: 10 }
},
{
key: 'myProject',
component: placeholder,
displayName: '我的项目',
icon: 'mdi:briefcase-outline',
category: 'personal',
defaultVisible: true,
defaultGrid: { x: 7, y: 11, w: 5, h: 17, minW: 5, minH: 17 }
},
{
key: 'myWeekWorklog',
component: placeholder,
displayName: '工时',
icon: 'mdi:timer-outline',
category: 'personal',
defaultVisible: true,
defaultGrid: { x: 0, y: 25, w: 7, h: 22, minW: 6, minH: 18 }
},
{
key: 'teamLoad',
component: placeholder,
displayName: '团队负载',
icon: 'mdi:scale-balance',
category: 'manager',
defaultVisible: true,
defaultGrid: { x: 0, y: 47, w: 12, h: 16, minW: 4, minH: 15 }
},
// === 默认隐藏(用户可从 widget 库拖回) ===
{
key: 'projectHealth',
component: placeholder,
displayName: '产品 / 项目健康度',
icon: 'mdi:heart-pulse',
category: 'manager',
defaultVisible: false,
defaultGrid: { x: 0, y: 0, w: 5, h: 12, minW: 4, minH: 9 }
},
{
key: 'productSnapshot',
component: placeholder,
displayName: '产品深度快照',
icon: 'mdi:image-area-close',
category: 'snapshot',
defaultVisible: false,
defaultGrid: { x: 0, y: 0, w: 6, h: 14, minW: 4, minH: 10 }
}
];
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 };
}