feat(projects): 工作台小组件设计

This commit is contained in:
2026-05-28 08:20:01 +08:00
parent 3988eaf910
commit 4ed4b537ad
54 changed files with 4726 additions and 2720 deletions

View File

@@ -1,5 +1,5 @@
import type { LayoutStorage } from './layout-storage';
import { WORKBENCH_LAYOUT_VERSION, type WorkbenchLayout } from './workbench-layout-types';
import type { WorkbenchLayout } from './workbench-layout-types';
const KEY_PREFIX = 'rdms-workbench-layout';
@@ -8,14 +8,14 @@ function buildKey(userId: string) {
}
export class LocalStorageAdapter implements LayoutStorage {
// 版本校验交给上层use-workbench-layout.load版本不匹配时上层需要拿到旧 settings 做迁移,
// 这里直接返回 raw 解析结果,只过滤掉无法解析的脏数据
// eslint-disable-next-line class-methods-use-this
async load(userId: string): Promise<WorkbenchLayout | null> {
try {
const raw = window.localStorage.getItem(buildKey(userId));
if (!raw) return null;
const parsed = JSON.parse(raw) as WorkbenchLayout;
if (parsed?.version !== WORKBENCH_LAYOUT_VERSION) return null;
return parsed;
return JSON.parse(raw) as WorkbenchLayout;
} catch {
return null;
}

View File

@@ -0,0 +1,34 @@
// 工作台跨 widget 共享的"项目色注册器"。
// 同一个 projectKey 在不同 widgetC12 团队工时分布、C13 团队负载、D16 我的本周工时…)
// 颜色保持一致,形成系统级"项目色码"。
//
// 分配策略:按首次访问顺序循环取 PROJECT_COLORSpersonal/other 固定色。
// 整页生命周期内稳定;新增项目自动追加。
// 项目色:纯分类色,不含红/橙系。告警语义留给等级色(红/橙/绿),避免视觉混淆。
const PROJECT_COLORS = ['#5B8FF9', '#5AD8A6', '#5D7092', '#F6BD16', '#6DC8EC', '#73D13D', '#36CFC9', '#36495D'];
// 个人事项独占紫色,与项目色明显区分
const PERSONAL_COLOR = '#9254DE';
const OTHER_COLOR = '#BFBFBF';
export type WorkbenchItemKind = 'project' | 'personal' | 'other';
const projectColorMap = new Map<string, string>();
export function getWorkbenchProjectColor(projectKey: string): string {
let color = projectColorMap.get(projectKey);
if (!color) {
color = PROJECT_COLORS[projectColorMap.size % PROJECT_COLORS.length];
projectColorMap.set(projectKey, color);
}
return color;
}
export function getWorkbenchItemColor(key: string, kind: WorkbenchItemKind): string {
if (kind === 'personal') return PERSONAL_COLOR;
if (kind === 'other') return OTHER_COLOR;
return getWorkbenchProjectColor(key);
}
export const WORKBENCH_PERSONAL_COLOR = PERSONAL_COLOR;
export const WORKBENCH_OTHER_COLOR = OTHER_COLOR;

View File

@@ -5,7 +5,7 @@ import { buildDefaultLayout } from './workbench-layout-default';
import type { LayoutStorage } from './layout-storage';
import { LocalStorageAdapter } from './layout-storage-local';
import { reconcileLayout } from './workbench-layout-reconcile';
import type { WorkbenchLayout } from './workbench-layout-types';
import { WORKBENCH_LAYOUT_VERSION, type WorkbenchLayout } from './workbench-layout-types';
export type WorkbenchMode = 'normal' | 'editing';
@@ -28,7 +28,16 @@ export function useWorkbenchLayout(options: UseWorkbenchLayoutOptions) {
async function load() {
const fromStorage = await storage.load(options.userId);
layout.value = reconcileLayout(fromStorage ?? buildDefaultLayout(getAllModules()), getAllModules());
if (fromStorage && fromStorage.version === WORKBENCH_LAYOUT_VERSION) {
layout.value = reconcileLayout(fromStorage, getAllModules());
return;
}
// 版本不匹配 / 无存储:走新默认布局;旧 settings 迁移过来,避免用户偏好(如 shortcut.menuKeys被 version bump 清空
const fresh = buildDefaultLayout(getAllModules());
if (fromStorage?.settings) {
fresh.settings = { ...fromStorage.settings };
}
layout.value = fresh;
}
const persist = useDebounceFn(async () => {

View File

@@ -4,32 +4,17 @@ import { markRaw, shallowRef } from 'vue';
export type WorkbenchModuleKey =
// 保留:现有 key 沿用(避免影响线上用户布局存储)
| 'myTodo' // A1 · 我的待办
| 'myRequirement' // B9 · 我的需求
| 'myProject' // B7 · 我参与的项目
| 'shortcut' // E19 · 快捷入口
| 'projectHealth' // C15 · 产品 / 项目健康度
| 'favorite' // E21 · 我的收藏 / 关注
// 重构key 沿用,组件内容重写)
| 'myTask' // A2 · 我的今日(原"我的任务"
| 'teamTodo' // C11 · 团队任务看板(原"团队待办汇总"
// 新增 15 个(蓝图 2026-05-22原 A3 myTicket 已废弃:与"我的待办 → 工单"重复且工单业务未上线)
| 'mentions' // A4 · @我的提及
| 'approval' // A5 · 待审批(管理者)
| 'worklogReminder' // A6 · 工时填报提醒(动作型)
// 新增(蓝图 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 · 我负责的执行
| 'personalItem' // B10 · 我的个人事项
| 'projectSnapshot' // F23 · 项目深度快照(对象快照 / pin
| 'productSnapshot' // F24 · 产品深度快照(对象快照 / pin
| 'teamWorklog' // C12 · 团队工时分布(管理者)
| 'productSnapshot' // F24 · 产品深度快照(对象快照 / 当前对象切换)
| 'teamLoad' // C13 · 团队负载(管理者)
| 'riskAlert' // C14 · 风险预警(管理者
| 'myWeekWorklog' // D16 · 我的本周工时
| 'myCompletionRate' // D17 · 我的完成率
| 'ticketSla' // D18 · 工单 SLA 总览(管理者 + 工单待开发)
| 'recentVisit' // E20 · 最近访问
| 'myWeekWorklog' // D16 · 工时(含「我的工时 / 团队工时」两 tab原 C12 teamWorklog 已并入
| 'noticeNotification'; // E22 · 公告 + 通知摘要
// 扩展action动作型 widget、snapshot对象快照型 widget pin 一个对象)
// 扩展action动作型 widget、snapshot对象快照型 widget指定一个对象)
export type WorkbenchModuleCategory = 'personal' | 'manager' | 'tool' | 'action' | 'snapshot';
export type WorkbenchColumnId = 'left' | 'right';
@@ -46,8 +31,12 @@ export interface WorkbenchModuleMeta {
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[] = [
// === 保留 6 个:默认布局沿用原配置,用户线上布局 0 影响 ===
{
key: 'myTodo',
component: placeholder,
@@ -59,35 +48,15 @@ const registry: WorkbenchModuleMeta[] = [
defaultOrder: 1
},
{
key: 'myTask',
key: 'myExecution',
component: placeholder,
displayName: '我的今日',
icon: 'mdi:calendar-check-outline',
displayName: '我负责的执行',
icon: 'mdi:flag-checkered',
category: 'personal',
defaultVisible: true,
defaultColumn: 'left',
defaultOrder: 2
},
{
key: 'myRequirement',
component: placeholder,
displayName: '我的需求',
icon: 'mdi:file-document-multiple-outline',
category: 'personal',
defaultVisible: true,
defaultColumn: 'left',
defaultOrder: 3
},
{
key: 'myProject',
component: placeholder,
displayName: '我参与的项目',
icon: 'mdi:briefcase-outline',
category: 'personal',
defaultVisible: true,
defaultColumn: 'right',
defaultOrder: 1
},
{
key: 'shortcut',
component: placeholder,
@@ -96,8 +65,39 @@ const registry: WorkbenchModuleMeta[] = [
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,
@@ -109,86 +109,14 @@ const registry: WorkbenchModuleMeta[] = [
defaultOrder: 10
},
{
key: 'teamTodo',
key: 'noticeNotification',
component: placeholder,
displayName: '团队任务看板',
icon: 'mdi:view-column-outline',
category: 'manager',
defaultVisible: false,
defaultColumn: 'right',
defaultOrder: 11
},
{
key: 'favorite',
component: placeholder,
displayName: '我的收藏 / 关注',
icon: 'mdi:star-outline',
displayName: '公告 + 通知',
icon: 'mdi:bullhorn-outline',
category: 'tool',
defaultVisible: false,
defaultColumn: 'right',
defaultOrder: 30
},
// === 新增 15 个:默认全部 hidden进 widget 库待用户挑(避免一上来挤爆工作台) ===
{
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',
category: 'manager',
defaultVisible: false,
defaultColumn: 'left',
defaultOrder: 22
},
{
key: 'worklogReminder',
component: placeholder,
displayName: '工时填报提醒',
icon: 'mdi:timer-sand',
category: 'action',
defaultVisible: false,
defaultColumn: 'right',
defaultOrder: 20
},
{
key: 'myExecution',
component: placeholder,
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
defaultOrder: 11
},
{
key: 'productSnapshot',
@@ -199,86 +127,6 @@ const registry: WorkbenchModuleMeta[] = [
defaultVisible: false,
defaultColumn: 'left',
defaultOrder: 41
},
{
key: 'teamWorklog',
component: placeholder,
displayName: '团队工时分布',
icon: 'mdi:chart-bar',
category: 'manager',
defaultVisible: false,
defaultColumn: 'right',
defaultOrder: 12
},
{
key: 'teamLoad',
component: placeholder,
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',
category: 'tool',
defaultVisible: false,
defaultColumn: 'right',
defaultOrder: 32
}
];

View File

@@ -1,6 +1,8 @@
import type { WorkbenchColumnId, WorkbenchModuleKey } from './use-workbench-modules';
export const WORKBENCH_LAYOUT_VERSION = 1;
// v3 (2026-05-27): myProject 移到右列、myExecution 顶替到 left 第 2 位、noticeNotification 默认隐藏(让位给 banner 公告 + 全局铃铛)。
// 版本不匹配时 LocalStorageAdapter.load 直接丢弃存量布局走新默认。
export const WORKBENCH_LAYOUT_VERSION = 3;
export interface WorkbenchShortcutSettings {
/** 用户在快捷入口里选了哪些菜单 key */