Files
cn-rdms-web/src/views/workbench/homepage.ts

528 lines
16 KiB
TypeScript
Raw Normal View History

import dayjs from 'dayjs';
export type WorkbenchTrend = 'up' | 'down' | 'flat';
refactor(workbench): 重构待办面板功能提升用户体验 - 替换原有时间桶过滤为分类标签页和截止时间筛选器 - 添加优先级排序功能,支持任务类别内按优先级排序 - 重构待办数据结构,新增创建时间和优先级字段 - 移除高优先级标记,统一使用优先级枚举值 - 添加个人事项创建对话框和相关操作功能 - 更新模拟数据以匹配新的数据结构和功能需求 - 优化列表排序逻辑,按创建时间升序排列,无截止时间排最后 - 为各类别待办项添加逾期状态标识和计数统计 - 实现分页加载,每页显示5条待办记录 - 更新样式类名以匹配新的逾期判断逻辑 refactor(project): 优化项目执行模块提升性能和可维护性 - 移除执行项点击切换功能相关的事件和方法 - 删除不再使用的select-execution事件发射器 - 移除执行标签的悬停效果和鼠标指针样式 - 重构任务表格视图,将日期格式化函数名称标准化 - 在跨执行模式下也显示进度列,统一界面布局 - 更新最近更新列宽度并调整日期格式显示 - 将默认页面大小从10增加到20以提高加载效率 feat(list): 统一日期格式化功能简化代码维护 - 将日期时间格式化函数重命名为更准确的date格式化 - 在产品列表和项目列表中统一使用新的日期格式化函数 - 移除秒数显示,仅保留年月日格式提高可读性 refactor(todo): 重构待办事项数据模型和过滤逻辑 - 重新定义待办事项分类类型,移除mention添加personal - 新增主标签、截止时间筛选器和优先级类型定义 - 添加创建时间字段用于排序和显示 - 实现基于分类、截止时间和优先级的过滤函数 - 创建优先级权重映射用于排序算法 - 更新待办项构建函数以支持新的排序逻辑 - 修改逾期判断逻辑以适应新的数据结构 - 移除原有的高优先级字段,统一使用优先级枚举 - 添加优先级排序功能支持升序降序切换 - 重构排序算法,优先按创建时间,其次按截止时间排序 refactor(task): 清理任务模块中已废弃的功能 - 移除通过ID选择执行项的相关函数和事件处理器 - 删除任务卡片和表格中的执行项点击切换功能 - 更新任务工作区组件以移除废弃的事件监听 - 调整任务表格视图中进度条的样式和状态显示 refactor(components): 项目列表中添加进度条可视化组件 - 引入Element Plus进度条组件用于项目进度展示 - 在项目列表中添加进度列并实现进度条渲染 - 配置进度条样式包括内嵌文字、成功状态和边框圆角 - 调整进度列宽度以适应进度条显示需求 refactor(widgets): 整理工作台模块配置和清理冗余组件 - 从工作台模块注册中移除已废弃的myTicket组件 - 更新模块注释说明,明确myTicket已废弃的原因 - 删除不再使用的workbench-my-ticket.vue组件文件 - 更新模块总数注释从16个调整为15个
2026-05-25 14:30:44 +08:00
export type WorkbenchTodoCategory = 'task' | 'ticket' | 'personal' | 'review';
refactor(workbench): 重构待办面板功能提升用户体验 - 替换原有时间桶过滤为分类标签页和截止时间筛选器 - 添加优先级排序功能,支持任务类别内按优先级排序 - 重构待办数据结构,新增创建时间和优先级字段 - 移除高优先级标记,统一使用优先级枚举值 - 添加个人事项创建对话框和相关操作功能 - 更新模拟数据以匹配新的数据结构和功能需求 - 优化列表排序逻辑,按创建时间升序排列,无截止时间排最后 - 为各类别待办项添加逾期状态标识和计数统计 - 实现分页加载,每页显示5条待办记录 - 更新样式类名以匹配新的逾期判断逻辑 refactor(project): 优化项目执行模块提升性能和可维护性 - 移除执行项点击切换功能相关的事件和方法 - 删除不再使用的select-execution事件发射器 - 移除执行标签的悬停效果和鼠标指针样式 - 重构任务表格视图,将日期格式化函数名称标准化 - 在跨执行模式下也显示进度列,统一界面布局 - 更新最近更新列宽度并调整日期格式显示 - 将默认页面大小从10增加到20以提高加载效率 feat(list): 统一日期格式化功能简化代码维护 - 将日期时间格式化函数重命名为更准确的date格式化 - 在产品列表和项目列表中统一使用新的日期格式化函数 - 移除秒数显示,仅保留年月日格式提高可读性 refactor(todo): 重构待办事项数据模型和过滤逻辑 - 重新定义待办事项分类类型,移除mention添加personal - 新增主标签、截止时间筛选器和优先级类型定义 - 添加创建时间字段用于排序和显示 - 实现基于分类、截止时间和优先级的过滤函数 - 创建优先级权重映射用于排序算法 - 更新待办项构建函数以支持新的排序逻辑 - 修改逾期判断逻辑以适应新的数据结构 - 移除原有的高优先级字段,统一使用优先级枚举 - 添加优先级排序功能支持升序降序切换 - 重构排序算法,优先按创建时间,其次按截止时间排序 refactor(task): 清理任务模块中已废弃的功能 - 移除通过ID选择执行项的相关函数和事件处理器 - 删除任务卡片和表格中的执行项点击切换功能 - 更新任务工作区组件以移除废弃的事件监听 - 调整任务表格视图中进度条的样式和状态显示 refactor(components): 项目列表中添加进度条可视化组件 - 引入Element Plus进度条组件用于项目进度展示 - 在项目列表中添加进度列并实现进度条渲染 - 配置进度条样式包括内嵌文字、成功状态和边框圆角 - 调整进度列宽度以适应进度条显示需求 refactor(widgets): 整理工作台模块配置和清理冗余组件 - 从工作台模块注册中移除已废弃的myTicket组件 - 更新模块注释说明,明确myTicket已废弃的原因 - 删除不再使用的workbench-my-ticket.vue组件文件 - 更新模块总数注释从16个调整为15个
2026-05-25 14:30:44 +08:00
export type WorkbenchTodoMainTab = 'all' | WorkbenchTodoCategory;
export type WorkbenchTodoDeadlineFilter = 'overdue' | 'today' | 'week' | null;
export type WorkbenchTodoPriority = 'high' | 'mid' | 'low';
export type WorkbenchProjectStatus = 'active' | 'preview' | 'paused';
export interface WorkbenchBannerSummarySource {
/** 今日待办数 */
todoCount: number;
/** 即将到期数(今日/明日内截止) */
upcomingCount: number;
/** 本周已完成 */
weekDone: number;
/** 本周总量 */
weekTotal: number;
/** 本周进行中 */
weekInProgress: number;
/** 本周逾期 */
weekOverdue: number;
}
export interface WorkbenchBannerSummary {
todoCount: number;
upcomingCount: number;
weekDone: number;
weekTotal: number;
weekInProgress: number;
weekOverdue: number;
/** 完成率0-100 整数) */
weekCompletionRate: number;
}
export interface WorkbenchKpiSource {
/** 待办 */
todo: {
count: number;
diffFromYesterday: number;
};
/** 我负责的任务 */
task: {
count: number;
diffFromYesterday: number;
};
/** 我参与的项目 */
project: {
count: number;
activeCount: number;
};
/** 我负责的需求 */
requirement: {
count: number;
pendingReview: number;
};
}
export interface WorkbenchKpiCard {
key: 'todo' | 'task' | 'project' | 'requirement';
label: string;
value: number;
trend: WorkbenchTrend;
trendText: string;
hint: string;
icon: string;
tone: 'sky' | 'emerald' | 'amber' | 'rose';
}
export interface WorkbenchTodoItemSource {
id: string;
category: WorkbenchTodoCategory;
title: string;
refactor(workbench): 重构待办面板功能提升用户体验 - 替换原有时间桶过滤为分类标签页和截止时间筛选器 - 添加优先级排序功能,支持任务类别内按优先级排序 - 重构待办数据结构,新增创建时间和优先级字段 - 移除高优先级标记,统一使用优先级枚举值 - 添加个人事项创建对话框和相关操作功能 - 更新模拟数据以匹配新的数据结构和功能需求 - 优化列表排序逻辑,按创建时间升序排列,无截止时间排最后 - 为各类别待办项添加逾期状态标识和计数统计 - 实现分页加载,每页显示5条待办记录 - 更新样式类名以匹配新的逾期判断逻辑 refactor(project): 优化项目执行模块提升性能和可维护性 - 移除执行项点击切换功能相关的事件和方法 - 删除不再使用的select-execution事件发射器 - 移除执行标签的悬停效果和鼠标指针样式 - 重构任务表格视图,将日期格式化函数名称标准化 - 在跨执行模式下也显示进度列,统一界面布局 - 更新最近更新列宽度并调整日期格式显示 - 将默认页面大小从10增加到20以提高加载效率 feat(list): 统一日期格式化功能简化代码维护 - 将日期时间格式化函数重命名为更准确的date格式化 - 在产品列表和项目列表中统一使用新的日期格式化函数 - 移除秒数显示,仅保留年月日格式提高可读性 refactor(todo): 重构待办事项数据模型和过滤逻辑 - 重新定义待办事项分类类型,移除mention添加personal - 新增主标签、截止时间筛选器和优先级类型定义 - 添加创建时间字段用于排序和显示 - 实现基于分类、截止时间和优先级的过滤函数 - 创建优先级权重映射用于排序算法 - 更新待办项构建函数以支持新的排序逻辑 - 修改逾期判断逻辑以适应新的数据结构 - 移除原有的高优先级字段,统一使用优先级枚举 - 添加优先级排序功能支持升序降序切换 - 重构排序算法,优先按创建时间,其次按截止时间排序 refactor(task): 清理任务模块中已废弃的功能 - 移除通过ID选择执行项的相关函数和事件处理器 - 删除任务卡片和表格中的执行项点击切换功能 - 更新任务工作区组件以移除废弃的事件监听 - 调整任务表格视图中进度条的样式和状态显示 refactor(components): 项目列表中添加进度条可视化组件 - 引入Element Plus进度条组件用于项目进度展示 - 在项目列表中添加进度列并实现进度条渲染 - 配置进度条样式包括内嵌文字、成功状态和边框圆角 - 调整进度列宽度以适应进度条显示需求 refactor(widgets): 整理工作台模块配置和清理冗余组件 - 从工作台模块注册中移除已废弃的myTicket组件 - 更新模块注释说明,明确myTicket已废弃的原因 - 删除不再使用的workbench-my-ticket.vue组件文件 - 更新模块总数注释从16个调整为15个
2026-05-25 14:30:44 +08:00
/** 创建时间ISO 字符串。列表默认按这个升序 */
createdTime: string;
/** 截止时间ISO 字符串 */
deadline: string | null;
/** 来源(提交人/项目名/工单号) */
source: string;
refactor(workbench): 重构待办面板功能提升用户体验 - 替换原有时间桶过滤为分类标签页和截止时间筛选器 - 添加优先级排序功能,支持任务类别内按优先级排序 - 重构待办数据结构,新增创建时间和优先级字段 - 移除高优先级标记,统一使用优先级枚举值 - 添加个人事项创建对话框和相关操作功能 - 更新模拟数据以匹配新的数据结构和功能需求 - 优化列表排序逻辑,按创建时间升序排列,无截止时间排最后 - 为各类别待办项添加逾期状态标识和计数统计 - 实现分页加载,每页显示5条待办记录 - 更新样式类名以匹配新的逾期判断逻辑 refactor(project): 优化项目执行模块提升性能和可维护性 - 移除执行项点击切换功能相关的事件和方法 - 删除不再使用的select-execution事件发射器 - 移除执行标签的悬停效果和鼠标指针样式 - 重构任务表格视图,将日期格式化函数名称标准化 - 在跨执行模式下也显示进度列,统一界面布局 - 更新最近更新列宽度并调整日期格式显示 - 将默认页面大小从10增加到20以提高加载效率 feat(list): 统一日期格式化功能简化代码维护 - 将日期时间格式化函数重命名为更准确的date格式化 - 在产品列表和项目列表中统一使用新的日期格式化函数 - 移除秒数显示,仅保留年月日格式提高可读性 refactor(todo): 重构待办事项数据模型和过滤逻辑 - 重新定义待办事项分类类型,移除mention添加personal - 新增主标签、截止时间筛选器和优先级类型定义 - 添加创建时间字段用于排序和显示 - 实现基于分类、截止时间和优先级的过滤函数 - 创建优先级权重映射用于排序算法 - 更新待办项构建函数以支持新的排序逻辑 - 修改逾期判断逻辑以适应新的数据结构 - 移除原有的高优先级字段,统一使用优先级枚举 - 添加优先级排序功能支持升序降序切换 - 重构排序算法,优先按创建时间,其次按截止时间排序 refactor(task): 清理任务模块中已废弃的功能 - 移除通过ID选择执行项的相关函数和事件处理器 - 删除任务卡片和表格中的执行项点击切换功能 - 更新任务工作区组件以移除废弃的事件监听 - 调整任务表格视图中进度条的样式和状态显示 refactor(components): 项目列表中添加进度条可视化组件 - 引入Element Plus进度条组件用于项目进度展示 - 在项目列表中添加进度列并实现进度条渲染 - 配置进度条样式包括内嵌文字、成功状态和边框圆角 - 调整进度列宽度以适应进度条显示需求 refactor(widgets): 整理工作台模块配置和清理冗余组件 - 从工作台模块注册中移除已废弃的myTicket组件 - 更新模块注释说明,明确myTicket已废弃的原因 - 删除不再使用的workbench-my-ticket.vue组件文件 - 更新模块总数注释从16个调整为15个
2026-05-25 14:30:44 +08:00
/** 优先级,用于前端排序与高亮 */
priority?: WorkbenchTodoPriority;
/** 是否逾期 */
overdue?: boolean;
/** 跳转路由 key可选未配则不跳转 */
routeKey?: string;
}
export interface WorkbenchTodoItem extends Omit<WorkbenchTodoItemSource, 'deadline'> {
deadlineLabel: string;
/** 相对截止天数:负数表示已逾期 */
remainingDays: number | null;
categoryLabel: string;
categoryTone: 'sky' | 'emerald' | 'amber' | 'rose' | 'violet';
}
export interface WorkbenchActivityItemSource {
id: string;
actor: string;
action: string;
/** 目标对象(需求/任务/工单/项目名等) */
target: string;
/** 目标对象的种类,用于颜色 */
targetKind: 'requirement' | 'task' | 'ticket' | 'project' | 'product';
/** 时间ISO */
time: string;
/** 是否 @ 了当前用户 */
mentioned?: boolean;
}
export interface WorkbenchActivityItem extends Omit<WorkbenchActivityItemSource, 'time'> {
timeLabel: string;
relativeLabel: string;
tone: 'sky' | 'emerald' | 'amber' | 'rose' | 'violet';
}
export interface WorkbenchProjectItemSource {
id: string;
name: string;
code: string;
status: WorkbenchProjectStatus;
/** 我的角色 */
myRole: string;
/** 进度百分比 0-100 */
progress: number;
/** 我负责的任务数 */
myTaskCount: number;
/** 我负责的待处理任务数 */
myPendingTaskCount: number;
/** 最近活动时间ISO */
lastActiveTime: string;
}
export interface WorkbenchProjectItem extends Omit<WorkbenchProjectItemSource, 'lastActiveTime'> {
statusLabel: string;
statusTone: 'sky' | 'emerald' | 'amber';
progress: number;
lastActiveLabel: string;
}
const todoCategoryMeta: Record<
WorkbenchTodoCategory,
{ label: string; tone: WorkbenchTodoItem['categoryTone']; icon: string }
> = {
task: { label: '任务', tone: 'emerald', icon: 'mdi:checkbox-marked-circle-outline' },
ticket: { label: '工单', tone: 'amber', icon: 'mdi:ticket-confirmation-outline' },
refactor(workbench): 重构待办面板功能提升用户体验 - 替换原有时间桶过滤为分类标签页和截止时间筛选器 - 添加优先级排序功能,支持任务类别内按优先级排序 - 重构待办数据结构,新增创建时间和优先级字段 - 移除高优先级标记,统一使用优先级枚举值 - 添加个人事项创建对话框和相关操作功能 - 更新模拟数据以匹配新的数据结构和功能需求 - 优化列表排序逻辑,按创建时间升序排列,无截止时间排最后 - 为各类别待办项添加逾期状态标识和计数统计 - 实现分页加载,每页显示5条待办记录 - 更新样式类名以匹配新的逾期判断逻辑 refactor(project): 优化项目执行模块提升性能和可维护性 - 移除执行项点击切换功能相关的事件和方法 - 删除不再使用的select-execution事件发射器 - 移除执行标签的悬停效果和鼠标指针样式 - 重构任务表格视图,将日期格式化函数名称标准化 - 在跨执行模式下也显示进度列,统一界面布局 - 更新最近更新列宽度并调整日期格式显示 - 将默认页面大小从10增加到20以提高加载效率 feat(list): 统一日期格式化功能简化代码维护 - 将日期时间格式化函数重命名为更准确的date格式化 - 在产品列表和项目列表中统一使用新的日期格式化函数 - 移除秒数显示,仅保留年月日格式提高可读性 refactor(todo): 重构待办事项数据模型和过滤逻辑 - 重新定义待办事项分类类型,移除mention添加personal - 新增主标签、截止时间筛选器和优先级类型定义 - 添加创建时间字段用于排序和显示 - 实现基于分类、截止时间和优先级的过滤函数 - 创建优先级权重映射用于排序算法 - 更新待办项构建函数以支持新的排序逻辑 - 修改逾期判断逻辑以适应新的数据结构 - 移除原有的高优先级字段,统一使用优先级枚举 - 添加优先级排序功能支持升序降序切换 - 重构排序算法,优先按创建时间,其次按截止时间排序 refactor(task): 清理任务模块中已废弃的功能 - 移除通过ID选择执行项的相关函数和事件处理器 - 删除任务卡片和表格中的执行项点击切换功能 - 更新任务工作区组件以移除废弃的事件监听 - 调整任务表格视图中进度条的样式和状态显示 refactor(components): 项目列表中添加进度条可视化组件 - 引入Element Plus进度条组件用于项目进度展示 - 在项目列表中添加进度列并实现进度条渲染 - 配置进度条样式包括内嵌文字、成功状态和边框圆角 - 调整进度列宽度以适应进度条显示需求 refactor(widgets): 整理工作台模块配置和清理冗余组件 - 从工作台模块注册中移除已废弃的myTicket组件 - 更新模块注释说明,明确myTicket已废弃的原因 - 删除不再使用的workbench-my-ticket.vue组件文件 - 更新模块总数注释从16个调整为15个
2026-05-25 14:30:44 +08:00
personal: { label: '个人事项', tone: 'violet', icon: 'mdi:notebook-edit-outline' },
review: { label: '待评审', tone: 'sky', icon: 'mdi:file-search-outline' }
};
const todoPriorityWeight: Record<WorkbenchTodoPriority, number> = {
high: 0,
mid: 1,
low: 2
};
const activityToneMap: Record<WorkbenchActivityItemSource['targetKind'], WorkbenchActivityItem['tone']> = {
requirement: 'sky',
task: 'emerald',
ticket: 'amber',
project: 'violet',
product: 'rose'
};
const projectStatusMeta: Record<WorkbenchProjectStatus, { label: string; tone: WorkbenchProjectItem['statusTone'] }> = {
active: { label: '进行中', tone: 'emerald' },
preview: { label: '试运行', tone: 'sky' },
paused: { label: '已暂停', tone: 'amber' }
};
function clampPercent(value: number) {
if (!Number.isFinite(value)) return 0;
return Math.min(100, Math.max(0, Math.round(value)));
}
function formatRelative(value: string) {
const target = dayjs(value);
if (!target.isValid()) return '--';
const now = dayjs();
const diffMinutes = now.diff(target, 'minute');
if (diffMinutes < 1) return '刚刚';
if (diffMinutes < 60) return `${diffMinutes} 分钟前`;
const diffHours = now.diff(target, 'hour');
if (diffHours < 24) return `${diffHours} 小时前`;
const diffDays = now.diff(target, 'day');
if (diffDays < 7) return `${diffDays} 天前`;
return target.format('MM-DD HH:mm');
}
function formatDeadline(value: string | null) {
if (!value) return '不限';
const target = dayjs(value);
if (!target.isValid()) return '不限';
const now = dayjs().startOf('day');
const start = target.startOf('day');
const days = start.diff(now, 'day');
if (days === 0) return `今日 ${target.format('HH:mm')}`;
if (days === 1) return `明日 ${target.format('HH:mm')}`;
if (days === -1) return `昨日 ${target.format('HH:mm')}`;
if (days > 0 && days <= 7) return `${days} 天后 ${target.format('MM-DD')}`;
if (days < 0) return `逾期 ${Math.abs(days)}`;
return target.format('YYYY-MM-DD');
}
function getRemainingDays(value: string | null) {
if (!value) return null;
const target = dayjs(value);
if (!target.isValid()) return null;
return target.startOf('day').diff(dayjs().startOf('day'), 'day');
}
export function buildWorkbenchBannerSummary(source: WorkbenchBannerSummarySource): WorkbenchBannerSummary {
const total = Math.max(0, source.weekTotal);
const done = Math.max(0, source.weekDone);
const rate = total === 0 ? 0 : clampPercent((done / total) * 100);
return {
todoCount: Math.max(0, source.todoCount),
upcomingCount: Math.max(0, source.upcomingCount),
weekDone: done,
weekTotal: total,
weekInProgress: Math.max(0, source.weekInProgress),
weekOverdue: Math.max(0, source.weekOverdue),
weekCompletionRate: rate
};
}
export function buildWorkbenchKpiCards(source: WorkbenchKpiSource): WorkbenchKpiCard[] {
function diffTrend(diff: number): { trend: WorkbenchTrend; text: string } {
if (diff > 0) return { trend: 'up', text: `较昨日 +${diff}` };
if (diff < 0) return { trend: 'down', text: `较昨日 ${diff}` };
return { trend: 'flat', text: '与昨日持平' };
}
const todoTrend = diffTrend(source.todo.diffFromYesterday);
const taskTrend = diffTrend(source.task.diffFromYesterday);
return [
{
key: 'todo',
label: '我的待办',
value: source.todo.count,
trend: todoTrend.trend,
trendText: todoTrend.text,
hint: '需要我处理的评审、任务、工单与 @ 提醒合计',
icon: 'mdi:clipboard-text-clock-outline',
tone: 'sky'
},
{
key: 'task',
label: '我负责的任务',
value: source.task.count,
trend: taskTrend.trend,
trendText: taskTrend.text,
hint: '当前由我负责的进行中任务',
icon: 'mdi:checkbox-marked-circle-outline',
tone: 'emerald'
},
{
key: 'project',
label: '我参与的项目',
value: source.project.count,
trend: 'flat',
trendText: `进行中 ${source.project.activeCount}`,
hint: '我作为成员参与的项目总数',
icon: 'mdi:briefcase-outline',
tone: 'amber'
},
{
key: 'requirement',
label: '我负责的需求',
value: source.requirement.count,
trend: 'flat',
trendText: `待评审 ${source.requirement.pendingReview}`,
hint: '由我担任产品经理或负责人的需求',
icon: 'mdi:file-document-multiple-outline',
tone: 'rose'
}
];
}
export function buildWorkbenchTodoItems(source: readonly WorkbenchTodoItemSource[]): WorkbenchTodoItem[] {
return [...source]
.sort((left, right) => {
refactor(workbench): 重构待办面板功能提升用户体验 - 替换原有时间桶过滤为分类标签页和截止时间筛选器 - 添加优先级排序功能,支持任务类别内按优先级排序 - 重构待办数据结构,新增创建时间和优先级字段 - 移除高优先级标记,统一使用优先级枚举值 - 添加个人事项创建对话框和相关操作功能 - 更新模拟数据以匹配新的数据结构和功能需求 - 优化列表排序逻辑,按创建时间升序排列,无截止时间排最后 - 为各类别待办项添加逾期状态标识和计数统计 - 实现分页加载,每页显示5条待办记录 - 更新样式类名以匹配新的逾期判断逻辑 refactor(project): 优化项目执行模块提升性能和可维护性 - 移除执行项点击切换功能相关的事件和方法 - 删除不再使用的select-execution事件发射器 - 移除执行标签的悬停效果和鼠标指针样式 - 重构任务表格视图,将日期格式化函数名称标准化 - 在跨执行模式下也显示进度列,统一界面布局 - 更新最近更新列宽度并调整日期格式显示 - 将默认页面大小从10增加到20以提高加载效率 feat(list): 统一日期格式化功能简化代码维护 - 将日期时间格式化函数重命名为更准确的date格式化 - 在产品列表和项目列表中统一使用新的日期格式化函数 - 移除秒数显示,仅保留年月日格式提高可读性 refactor(todo): 重构待办事项数据模型和过滤逻辑 - 重新定义待办事项分类类型,移除mention添加personal - 新增主标签、截止时间筛选器和优先级类型定义 - 添加创建时间字段用于排序和显示 - 实现基于分类、截止时间和优先级的过滤函数 - 创建优先级权重映射用于排序算法 - 更新待办项构建函数以支持新的排序逻辑 - 修改逾期判断逻辑以适应新的数据结构 - 移除原有的高优先级字段,统一使用优先级枚举 - 添加优先级排序功能支持升序降序切换 - 重构排序算法,优先按创建时间,其次按截止时间排序 refactor(task): 清理任务模块中已废弃的功能 - 移除通过ID选择执行项的相关函数和事件处理器 - 删除任务卡片和表格中的执行项点击切换功能 - 更新任务工作区组件以移除废弃的事件监听 - 调整任务表格视图中进度条的样式和状态显示 refactor(components): 项目列表中添加进度条可视化组件 - 引入Element Plus进度条组件用于项目进度展示 - 在项目列表中添加进度列并实现进度条渲染 - 配置进度条样式包括内嵌文字、成功状态和边框圆角 - 调整进度列宽度以适应进度条显示需求 refactor(widgets): 整理工作台模块配置和清理冗余组件 - 从工作台模块注册中移除已废弃的myTicket组件 - 更新模块注释说明,明确myTicket已废弃的原因 - 删除不再使用的workbench-my-ticket.vue组件文件 - 更新模块总数注释从16个调整为15个
2026-05-25 14:30:44 +08:00
const leftCreated = dayjs(left.createdTime).valueOf();
const rightCreated = dayjs(right.createdTime).valueOf();
if (leftCreated !== rightCreated) return leftCreated - rightCreated;
const leftDeadline = left.deadline ? dayjs(left.deadline).valueOf() : Number.POSITIVE_INFINITY;
const rightDeadline = right.deadline ? dayjs(right.deadline).valueOf() : Number.POSITIVE_INFINITY;
return leftDeadline - rightDeadline;
})
.map(item => {
const meta = todoCategoryMeta[item.category];
return {
...item,
deadlineLabel: formatDeadline(item.deadline),
remainingDays: getRemainingDays(item.deadline),
categoryLabel: meta.label,
categoryTone: meta.tone
} satisfies WorkbenchTodoItem;
});
}
refactor(workbench): 重构待办面板功能提升用户体验 - 替换原有时间桶过滤为分类标签页和截止时间筛选器 - 添加优先级排序功能,支持任务类别内按优先级排序 - 重构待办数据结构,新增创建时间和优先级字段 - 移除高优先级标记,统一使用优先级枚举值 - 添加个人事项创建对话框和相关操作功能 - 更新模拟数据以匹配新的数据结构和功能需求 - 优化列表排序逻辑,按创建时间升序排列,无截止时间排最后 - 为各类别待办项添加逾期状态标识和计数统计 - 实现分页加载,每页显示5条待办记录 - 更新样式类名以匹配新的逾期判断逻辑 refactor(project): 优化项目执行模块提升性能和可维护性 - 移除执行项点击切换功能相关的事件和方法 - 删除不再使用的select-execution事件发射器 - 移除执行标签的悬停效果和鼠标指针样式 - 重构任务表格视图,将日期格式化函数名称标准化 - 在跨执行模式下也显示进度列,统一界面布局 - 更新最近更新列宽度并调整日期格式显示 - 将默认页面大小从10增加到20以提高加载效率 feat(list): 统一日期格式化功能简化代码维护 - 将日期时间格式化函数重命名为更准确的date格式化 - 在产品列表和项目列表中统一使用新的日期格式化函数 - 移除秒数显示,仅保留年月日格式提高可读性 refactor(todo): 重构待办事项数据模型和过滤逻辑 - 重新定义待办事项分类类型,移除mention添加personal - 新增主标签、截止时间筛选器和优先级类型定义 - 添加创建时间字段用于排序和显示 - 实现基于分类、截止时间和优先级的过滤函数 - 创建优先级权重映射用于排序算法 - 更新待办项构建函数以支持新的排序逻辑 - 修改逾期判断逻辑以适应新的数据结构 - 移除原有的高优先级字段,统一使用优先级枚举 - 添加优先级排序功能支持升序降序切换 - 重构排序算法,优先按创建时间,其次按截止时间排序 refactor(task): 清理任务模块中已废弃的功能 - 移除通过ID选择执行项的相关函数和事件处理器 - 删除任务卡片和表格中的执行项点击切换功能 - 更新任务工作区组件以移除废弃的事件监听 - 调整任务表格视图中进度条的样式和状态显示 refactor(components): 项目列表中添加进度条可视化组件 - 引入Element Plus进度条组件用于项目进度展示 - 在项目列表中添加进度列并实现进度条渲染 - 配置进度条样式包括内嵌文字、成功状态和边框圆角 - 调整进度列宽度以适应进度条显示需求 refactor(widgets): 整理工作台模块配置和清理冗余组件 - 从工作台模块注册中移除已废弃的myTicket组件 - 更新模块注释说明,明确myTicket已废弃的原因 - 删除不再使用的workbench-my-ticket.vue组件文件 - 更新模块总数注释从16个调整为15个
2026-05-25 14:30:44 +08:00
export function filterWorkbenchTodoItemsByCategory(items: readonly WorkbenchTodoItem[], tab: WorkbenchTodoMainTab) {
if (tab === 'all') return [...items];
return items.filter(item => item.category === tab);
}
export function filterWorkbenchTodoItemsByDeadline(
items: readonly WorkbenchTodoItem[],
filter: WorkbenchTodoDeadlineFilter
) {
if (!filter) return [...items];
if (filter === 'overdue') return items.filter(item => isOverdue(item));
if (filter === 'today') return items.filter(item => item.remainingDays === 0);
// filter === 'week':含今日,含逾期一起暴露给用户处理
return items.filter(item => item.remainingDays !== null && item.remainingDays <= 7);
}
export function isWorkbenchTodoOverdue(item: WorkbenchTodoItem) {
return isOverdue(item);
}
function isOverdue(item: WorkbenchTodoItem) {
if (item.overdue) return true;
return item.remainingDays !== null && item.remainingDays < 0;
}
export function sortWorkbenchTodoItemsByPriority(
items: readonly WorkbenchTodoItem[],
direction: 'asc' | 'desc' = 'desc'
) {
const factor = direction === 'desc' ? 1 : -1;
return [...items].sort((left, right) => {
const leftWeight = todoPriorityWeight[left.priority ?? 'low'];
const rightWeight = todoPriorityWeight[right.priority ?? 'low'];
if (leftWeight !== rightWeight) return (leftWeight - rightWeight) * factor;
return dayjs(left.createdTime).valueOf() - dayjs(right.createdTime).valueOf();
});
}
export function buildWorkbenchActivityItems(source: readonly WorkbenchActivityItemSource[]): WorkbenchActivityItem[] {
return [...source]
.filter(item => dayjs(item.time).isValid())
.sort((left, right) => dayjs(right.time).valueOf() - dayjs(left.time).valueOf())
.map(item => ({
...item,
timeLabel: dayjs(item.time).format('YYYY-MM-DD HH:mm'),
relativeLabel: formatRelative(item.time),
tone: activityToneMap[item.targetKind]
}));
}
export function buildWorkbenchProjectItems(source: readonly WorkbenchProjectItemSource[]): WorkbenchProjectItem[] {
return source.map(item => {
const meta = projectStatusMeta[item.status];
return {
...item,
statusLabel: meta.label,
statusTone: meta.tone,
progress: clampPercent(item.progress),
lastActiveLabel: formatRelative(item.lastActiveTime)
} satisfies WorkbenchProjectItem;
});
}
export function getGreeting(hour: number = dayjs().hour()) {
if (hour < 6) return '凌晨好';
if (hour < 11) return '早上好';
if (hour < 13) return '中午好';
if (hour < 18) return '下午好';
if (hour < 22) return '晚上好';
return '夜深了';
}
export function getTodayLabel() {
const today = dayjs();
const weekdayMap = ['日', '一', '二', '三', '四', '五', '六'];
return `今天 ${today.format('YYYY-MM-DD')} 星期${weekdayMap[today.day()]}`;
}
export type WorkbenchMyTaskBucket = 'today' | 'week' | 'overdue' | 'all';
export interface WorkbenchMyTaskItemSource {
id: string;
title: string;
statusCode: string;
statusLabel: string;
executionName: string;
projectName: string;
priority: 'high' | 'mid' | 'low';
deadline: string | null;
}
export interface WorkbenchMyTaskItem extends Omit<WorkbenchMyTaskItemSource, 'deadline'> {
deadlineLabel: string;
remainingDays: number | null;
overdue: boolean;
}
export function buildWorkbenchMyTaskItems(source: readonly WorkbenchMyTaskItemSource[]): WorkbenchMyTaskItem[] {
return [...source]
.sort((a, b) => {
const av = a.deadline ? dayjs(a.deadline).valueOf() : Number.POSITIVE_INFINITY;
const bv = b.deadline ? dayjs(b.deadline).valueOf() : Number.POSITIVE_INFINITY;
return av - bv;
})
.map(item => {
const remaining = getRemainingDays(item.deadline);
return {
...item,
deadlineLabel: formatDeadline(item.deadline),
remainingDays: remaining,
overdue: remaining !== null && remaining < 0
} satisfies WorkbenchMyTaskItem;
});
}
export function filterWorkbenchMyTaskItems(items: readonly WorkbenchMyTaskItem[], bucket: WorkbenchMyTaskBucket) {
if (bucket === 'all') return [...items];
if (bucket === 'overdue') return items.filter(i => i.overdue);
if (bucket === 'today') return items.filter(i => i.remainingDays === 0);
return items.filter(i => i.remainingDays !== null && i.remainingDays >= 0 && i.remainingDays <= 7);
}
export interface WorkbenchMyRequirementGroupSource {
statusCode: string;
statusLabel: string;
count: number;
tone: 'sky' | 'amber' | 'emerald' | 'rose';
}
export type WorkbenchMyRequirementGroup = WorkbenchMyRequirementGroupSource;
export function buildWorkbenchMyRequirementGroups(
source: readonly WorkbenchMyRequirementGroupSource[]
): WorkbenchMyRequirementGroup[] {
return [...source];
}
export interface WorkbenchTeamTodoRowSource {
projectId: string;
projectName: string;
memberId: string;
memberName: string;
inProgress: number;
overdue: number;
weekDone: number;
}
export type WorkbenchTeamTodoRow = WorkbenchTeamTodoRowSource;
export function buildWorkbenchTeamTodoRows(source: readonly WorkbenchTeamTodoRowSource[]): WorkbenchTeamTodoRow[] {
return [...source].sort((a, b) => b.overdue - a.overdue);
}
export type WorkbenchHealthLevel = 'green' | 'yellow' | 'red';
export interface WorkbenchProjectHealthCardSource {
projectId: string;
projectName: string;
code: string;
health: WorkbenchHealthLevel;
riskCount: number;
overdueTasks: number;
backlogRequirements: number;
}
export interface WorkbenchProjectHealthCard extends WorkbenchProjectHealthCardSource {
healthLabel: string;
}
export function buildWorkbenchProjectHealthCards(
source: readonly WorkbenchProjectHealthCardSource[]
): WorkbenchProjectHealthCard[] {
const labelMap: Record<WorkbenchHealthLevel, string> = { green: '健康', yellow: '关注', red: '风险' };
return source.map(s => ({ ...s, healthLabel: labelMap[s.health] }));
}
export interface WorkbenchProgressBarSource {
projectId: string;
projectName: string;
/** 完成率 0-100 */
weekCompletionRate: number;
}
export type WorkbenchProgressBar = WorkbenchProgressBarSource;
export function buildWorkbenchProgressBars(source: readonly WorkbenchProgressBarSource[]): WorkbenchProgressBar[] {
return source.map(s => ({ ...s, weekCompletionRate: Math.min(100, Math.max(0, Math.round(s.weekCompletionRate))) }));
}
export type WorkbenchFavoriteKind = 'product' | 'project' | 'requirement' | 'task';
export interface WorkbenchFavoriteItemSource {
id: string;
kind: WorkbenchFavoriteKind;
title: string;
source: string;
}
export interface WorkbenchFavoriteItem extends WorkbenchFavoriteItemSource {
kindLabel: string;
kindTone: 'sky' | 'emerald' | 'amber' | 'rose';
}
export function buildWorkbenchFavoriteItems(source: readonly WorkbenchFavoriteItemSource[]): WorkbenchFavoriteItem[] {
const meta: Record<WorkbenchFavoriteKind, { label: string; tone: 'sky' | 'emerald' | 'amber' | 'rose' }> = {
product: { label: '产品', tone: 'sky' },
project: { label: '项目', tone: 'emerald' },
requirement: { label: '需求', tone: 'amber' },
task: { label: '任务', tone: 'rose' }
};
return source.map(s => ({ ...s, kindLabel: meta[s.kind].label, kindTone: meta[s.kind].tone }));
}