2026-05-21 21:42:23 +08:00
|
|
|
|
import type { Component } from 'vue';
|
|
|
|
|
|
import { markRaw, shallowRef } from 'vue';
|
|
|
|
|
|
|
|
|
|
|
|
export type WorkbenchModuleKey =
|
2026-05-23 14:22:58 +08:00
|
|
|
|
// 保留:现有 key 沿用(避免影响线上用户布局存储)
|
|
|
|
|
|
| 'myTodo' // A1 · 我的待办
|
|
|
|
|
|
| 'myRequirement' // B9 · 我的需求
|
|
|
|
|
|
| 'myProject' // B7 · 我参与的项目
|
|
|
|
|
|
| 'shortcut' // E19 · 快捷入口
|
|
|
|
|
|
| 'projectHealth' // C15 · 产品 / 项目健康度
|
|
|
|
|
|
| 'favorite' // E21 · 我的收藏 / 关注
|
|
|
|
|
|
// 重构(key 沿用,组件内容重写)
|
|
|
|
|
|
| 'myTask' // A2 · 我的今日(原"我的任务")
|
|
|
|
|
|
| 'teamTodo' // C11 · 团队任务看板(原"团队待办汇总")
|
|
|
|
|
|
// 新增 16 个(蓝图 2026-05-22)
|
|
|
|
|
|
| 'myTicket' // A3 · 我负责的工单(工单待开发,先 mock)
|
|
|
|
|
|
| 'mentions' // A4 · @我的提及
|
|
|
|
|
|
| 'approval' // A5 · 待审批(管理者)
|
|
|
|
|
|
| 'worklogReminder' // A6 · 工时填报提醒(动作型)
|
|
|
|
|
|
| 'myExecution' // B8 · 我负责的执行
|
|
|
|
|
|
| 'personalItem' // B10 · 我的个人事项
|
|
|
|
|
|
| 'projectSnapshot' // F23 · 项目深度快照(对象快照 / pin)
|
|
|
|
|
|
| 'productSnapshot' // F24 · 产品深度快照(对象快照 / pin)
|
|
|
|
|
|
| 'teamWorklog' // C12 · 团队工时分布(管理者)
|
|
|
|
|
|
| 'teamLoad' // C13 · 团队负载(管理者)
|
|
|
|
|
|
| 'riskAlert' // C14 · 风险预警(管理者)
|
|
|
|
|
|
| 'myWeekWorklog' // D16 · 我的本周工时
|
|
|
|
|
|
| 'myCompletionRate' // D17 · 我的完成率
|
|
|
|
|
|
| 'ticketSla' // D18 · 工单 SLA 总览(管理者 + 工单待开发)
|
|
|
|
|
|
| 'recentVisit' // E20 · 最近访问
|
|
|
|
|
|
| 'noticeNotification'; // E22 · 公告 + 通知摘要
|
2026-05-21 21:42:23 +08:00
|
|
|
|
|
2026-05-23 14:22:58 +08:00
|
|
|
|
// 扩展:action(动作型 widget)、snapshot(对象快照型 widget,需 pin 一个对象)
|
|
|
|
|
|
export type WorkbenchModuleCategory = 'personal' | 'manager' | 'tool' | 'action' | 'snapshot';
|
2026-05-21 21:42:23 +08:00
|
|
|
|
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 });
|
|
|
|
|
|
|
|
|
|
|
|
const registry: WorkbenchModuleMeta[] = [
|
2026-05-23 14:22:58 +08:00
|
|
|
|
// === 保留 6 个:默认布局沿用原配置,用户线上布局 0 影响 ===
|
2026-05-21 21:42:23 +08:00
|
|
|
|
{
|
|
|
|
|
|
key: 'myTodo',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '我的待办',
|
|
|
|
|
|
icon: 'mdi:clipboard-text-clock-outline',
|
|
|
|
|
|
category: 'personal',
|
|
|
|
|
|
defaultVisible: true,
|
|
|
|
|
|
defaultColumn: 'left',
|
2026-05-23 14:22:58 +08:00
|
|
|
|
defaultOrder: 1
|
2026-05-21 21:42:23 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'myTask',
|
|
|
|
|
|
component: placeholder,
|
2026-05-23 14:22:58 +08:00
|
|
|
|
displayName: '我的今日',
|
|
|
|
|
|
icon: 'mdi:calendar-check-outline',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
category: 'personal',
|
|
|
|
|
|
defaultVisible: true,
|
|
|
|
|
|
defaultColumn: 'left',
|
2026-05-23 14:22:58 +08:00
|
|
|
|
defaultOrder: 2
|
2026-05-21 21:42:23 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'myRequirement',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '我的需求',
|
|
|
|
|
|
icon: 'mdi:file-document-multiple-outline',
|
|
|
|
|
|
category: 'personal',
|
|
|
|
|
|
defaultVisible: true,
|
|
|
|
|
|
defaultColumn: 'left',
|
2026-05-23 14:22:58 +08:00
|
|
|
|
defaultOrder: 3
|
2026-05-21 21:42:23 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'myProject',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '我参与的项目',
|
|
|
|
|
|
icon: 'mdi:briefcase-outline',
|
|
|
|
|
|
category: 'personal',
|
|
|
|
|
|
defaultVisible: true,
|
|
|
|
|
|
defaultColumn: 'right',
|
|
|
|
|
|
defaultOrder: 1
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-05-23 14:22:58 +08:00
|
|
|
|
key: 'shortcut',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
component: placeholder,
|
2026-05-23 14:22:58 +08:00
|
|
|
|
displayName: '快捷入口',
|
|
|
|
|
|
icon: 'mdi:rocket-launch-outline',
|
|
|
|
|
|
category: 'tool',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
defaultVisible: true,
|
|
|
|
|
|
defaultColumn: 'right',
|
|
|
|
|
|
defaultOrder: 2
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-05-23 14:22:58 +08:00
|
|
|
|
key: 'projectHealth',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
component: placeholder,
|
2026-05-23 14:22:58 +08:00
|
|
|
|
displayName: '产品 / 项目健康度',
|
|
|
|
|
|
icon: 'mdi:heart-pulse',
|
|
|
|
|
|
category: 'manager',
|
|
|
|
|
|
defaultVisible: false,
|
2026-05-21 21:42:23 +08:00
|
|
|
|
defaultColumn: 'right',
|
2026-05-23 14:22:58 +08:00
|
|
|
|
defaultOrder: 10
|
2026-05-21 21:42:23 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'teamTodo',
|
|
|
|
|
|
component: placeholder,
|
2026-05-23 14:22:58 +08:00
|
|
|
|
displayName: '团队任务看板',
|
|
|
|
|
|
icon: 'mdi:view-column-outline',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
category: 'manager',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'right',
|
2026-05-23 14:22:58 +08:00
|
|
|
|
defaultOrder: 11
|
2026-05-21 21:42:23 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-05-23 14:22:58 +08:00
|
|
|
|
key: 'favorite',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
component: placeholder,
|
2026-05-23 14:22:58 +08:00
|
|
|
|
displayName: '我的收藏 / 关注',
|
|
|
|
|
|
icon: 'mdi:star-outline',
|
|
|
|
|
|
category: 'tool',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'right',
|
|
|
|
|
|
defaultOrder: 30
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// === 新增 16 个:默认全部 hidden,进 widget 库待用户挑(避免一上来挤爆工作台) ===
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'myTicket',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '我负责的工单',
|
|
|
|
|
|
icon: 'mdi:ticket-confirmation-outline',
|
|
|
|
|
|
category: 'personal',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'left',
|
|
|
|
|
|
defaultOrder: 20
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'mentions',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '@我的提及',
|
|
|
|
|
|
icon: 'mdi:at',
|
|
|
|
|
|
category: 'personal',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'left',
|
|
|
|
|
|
defaultOrder: 21
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'approval',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '待审批',
|
|
|
|
|
|
icon: 'mdi:checkbox-multiple-marked-outline',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
category: 'manager',
|
|
|
|
|
|
defaultVisible: false,
|
2026-05-23 14:22:58 +08:00
|
|
|
|
defaultColumn: 'left',
|
|
|
|
|
|
defaultOrder: 22
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'worklogReminder',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '工时填报提醒',
|
|
|
|
|
|
icon: 'mdi:timer-sand',
|
|
|
|
|
|
category: 'action',
|
|
|
|
|
|
defaultVisible: false,
|
2026-05-21 21:42:23 +08:00
|
|
|
|
defaultColumn: 'right',
|
2026-05-23 14:22:58 +08:00
|
|
|
|
defaultOrder: 20
|
2026-05-21 21:42:23 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-05-23 14:22:58 +08:00
|
|
|
|
key: 'myExecution',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
component: placeholder,
|
2026-05-23 14:22:58 +08:00
|
|
|
|
displayName: '我负责的执行',
|
|
|
|
|
|
icon: 'mdi:flag-checkered',
|
|
|
|
|
|
category: 'personal',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'left',
|
|
|
|
|
|
defaultOrder: 23
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'personalItem',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '我的个人事项',
|
|
|
|
|
|
icon: 'mdi:format-list-checks',
|
|
|
|
|
|
category: 'personal',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'left',
|
|
|
|
|
|
defaultOrder: 24
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'projectSnapshot',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '项目深度快照',
|
|
|
|
|
|
icon: 'mdi:image-area',
|
|
|
|
|
|
category: 'snapshot',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'left',
|
|
|
|
|
|
defaultOrder: 40
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'productSnapshot',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '产品深度快照',
|
|
|
|
|
|
icon: 'mdi:image-area-close',
|
|
|
|
|
|
category: 'snapshot',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'left',
|
|
|
|
|
|
defaultOrder: 41
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'teamWorklog',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '团队工时分布',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
icon: 'mdi:chart-bar',
|
|
|
|
|
|
category: 'manager',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'right',
|
2026-05-23 14:22:58 +08:00
|
|
|
|
defaultOrder: 12
|
2026-05-21 21:42:23 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-05-23 14:22:58 +08:00
|
|
|
|
key: 'teamLoad',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
component: placeholder,
|
2026-05-23 14:22:58 +08:00
|
|
|
|
displayName: '团队负载',
|
|
|
|
|
|
icon: 'mdi:scale-balance',
|
|
|
|
|
|
category: 'manager',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'right',
|
|
|
|
|
|
defaultOrder: 13
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'riskAlert',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '风险预警',
|
|
|
|
|
|
icon: 'mdi:alert-octagon-outline',
|
|
|
|
|
|
category: 'manager',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'right',
|
|
|
|
|
|
defaultOrder: 14
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'myWeekWorklog',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '我的本周工时',
|
|
|
|
|
|
icon: 'mdi:chart-line',
|
|
|
|
|
|
category: 'personal',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'left',
|
|
|
|
|
|
defaultOrder: 25
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'myCompletionRate',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '我的完成率',
|
|
|
|
|
|
icon: 'mdi:chart-donut',
|
|
|
|
|
|
category: 'personal',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'left',
|
|
|
|
|
|
defaultOrder: 26
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'ticketSla',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '工单 SLA 总览',
|
|
|
|
|
|
icon: 'mdi:timer-alert-outline',
|
|
|
|
|
|
category: 'manager',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'right',
|
|
|
|
|
|
defaultOrder: 15
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'recentVisit',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '最近访问',
|
|
|
|
|
|
icon: 'mdi:history',
|
|
|
|
|
|
category: 'tool',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'right',
|
|
|
|
|
|
defaultOrder: 31
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'noticeNotification',
|
|
|
|
|
|
component: placeholder,
|
|
|
|
|
|
displayName: '公告 + 通知',
|
|
|
|
|
|
icon: 'mdi:bullhorn-outline',
|
2026-05-21 21:42:23 +08:00
|
|
|
|
category: 'tool',
|
|
|
|
|
|
defaultVisible: false,
|
|
|
|
|
|
defaultColumn: 'right',
|
2026-05-23 14:22:58 +08:00
|
|
|
|
defaultOrder: 32
|
2026-05-21 21:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
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 };
|
|
|
|
|
|
}
|