成功将设计师组长板块的紧急事件和待办任务功能复用到客服工作台,实现数据统一管理和展示一致性。
新增接口 (dashboard.ts):
// 从问题板块映射的待办任务(复用组长端结构)
interface TodoTaskFromIssue {
id: string;
title: string;
description?: string;
priority: IssuePriority; // 'low' | 'medium' | 'high' | 'critical' | 'urgent'
type: IssueType; // 'bug' | 'task' | 'feedback' | 'risk' | 'feature'
status: IssueStatus; // 'open' | 'in_progress' | 'resolved' | 'closed'
projectId: string;
projectName: string;
relatedSpace?: string;
relatedStage?: string;
assigneeName?: string;
creatorName?: string;
createdAt: Date;
updatedAt: Date;
dueDate?: Date;
tags?: string[];
}
新增 Signals:
// 从问题板块加载的待办任务列表(复用组长端)
todoTasksFromIssues = signal<TodoTaskFromIssue[]>([]);
loadingTodoTasks = signal(false);
todoTaskError = signal('');
loadTodoTasksFromIssues)功能描述:
ProjectIssue 表查询所有待处理和处理中的问题查询逻辑:
// 查询条件
issueQuery.containedIn('status', ['open', 'in_progress']);
issueQuery.include(['project', 'assignee', 'creator', 'relatedSpace']);
issueQuery.descending('priority');
issueQuery.descending('createdAt');
issueQuery.limit(100);
优先级排序:
const priorityOrder: Record<IssuePriority, number> = {
urgent: 0, // 紧急
critical: 0, // 紧急
high: 1, // 高
medium: 2, // 中
low: 3 // 低
};
syncUrgentTasksFromTodos)筛选规则:
urgent 或 critical 或 high 的任务自动显示在"紧急事件"区域Task 格式以兼容现有 UI转换逻辑:
const urgentIssues = tasks.filter(task =>
task.priority === 'urgent' ||
task.priority === 'critical' ||
task.priority === 'high'
);
优先级配置:
getPriorityConfig(priority: IssuePriority): { label, icon, color, order }
- urgent/critical: 🔴 紧急 (#dc2626)
- high: 🟠 高 (#ea580c)
- medium: 🟡 中 (#ca8a04)
- low: ⚪ 低 (#9ca3af)
类型标签:
getIssueTypeLabel(type: IssueType): string
- bug: 缺陷
- feature: 需求
- task: 任务
- feedback: 反馈
- risk: 风险
状态标签:
getIssueStatusLabel(status: IssueStatus): string
- open: 待处理
- in_progress: 处理中
- resolved: 已解决
- closed: 已关闭
特点:
dashboard.html)完整复用组长端设计:
<section class="todo-section-customer-service">
<!-- 标题和刷新按钮 -->
<div class="section-header">
<h2>
待办任务
<span class="task-count">({{ todoTasksFromIssues().length }})</span>
</h2>
<button class="btn-refresh" (click)="refreshTodoTasks()">
<svg [class.rotating]="loadingTodoTasks()">...</svg>
</button>
</div>
<!-- 加载/错误/空状态 -->
<div class="loading-state">...</div>
<div class="error-state">...</div>
<div class="empty-state">...</div>
<!-- 待办任务列表 -->
<div class="todo-list-compact">
<div class="todo-item-compact" (click)="navigateToIssue(task)">
<!-- 优先级指示条 -->
<div class="priority-indicator" [attr.data-priority]="task.priority"></div>
<!-- 任务内容 -->
<div class="task-content">
<div class="task-header">
<span class="task-title">{{ task.title }}</span>
<div class="task-badges">
<span class="badge badge-priority">🔴 紧急</span>
<span class="badge badge-type">缺陷</span>
</div>
</div>
<div class="task-meta">
<span>📋 {{ task.projectName }}</span>
<span>🔄 {{ task.relatedStage }}</span>
<span>👤 {{ task.assigneeName }}</span>
</div>
<div class="task-footer">
<span>{{ formatDateTime(task.createdAt) }}</span>
<span class="due-date">⏰ {{ task.dueDate | date }}</span>
</div>
</div>
</div>
</div>
</section>
dashboard.scss)完整复用组长端样式:
核心类名:
.todo-section-customer-service - 主容器.todo-list-compact - 任务列表.todo-item-compact - 单个任务卡片.priority-indicator - 左侧优先级色条.task-content - 任务内容区.task-badges - 标签徽章优先级色条:
.priority-indicator {
width: 4px;
&[data-priority="urgent"],
&[data-priority="critical"] {
background: linear-gradient(180deg, #dc2626 0%, #991b1b 100%); // 红色
}
&[data-priority="high"] {
background: linear-gradient(180deg, #f97316 0%, #ea580c 100%); // 橙色
}
&[data-priority="medium"] {
background: linear-gradient(180deg, #eab308 0%, #ca8a04 100%); // 黄色
}
&[data-priority="low"] {
background: linear-gradient(180deg, #d1d5db 0%, #9ca3af 100%); // 灰色
}
}
交互效果:
.todo-item-compact {
cursor: pointer;
transition: all 0.2s;
&:hover {
background: #f9fafb;
border-color: #d1d5db;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
transform: translateY(-1px);
}
}
加载动画:
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
svg.rotating {
animation: rotate 1s linear infinite;
}
初始化 (ngOnInit)
↓
loadDashboardData()
↓
loadTodoTasksFromIssues() ← 查询 ProjectIssue 表
↓
转换数据格式 → TodoTaskFromIssue[]
↓
按优先级排序
↓
syncUrgentTasksFromTodos() ← 筛选紧急任务
↓
更新 todoTasksFromIssues signal
更新 urgentTasks signal
↓
UI 自动刷新
ProjectIssue 表
↓
查询 status = ['open', 'in_progress']
↓
├─→ 全部任务 → 待办任务区域 (todoTasksFromIssues)
│ └─ 点击跳转 → navigateToIssue()
│
└─→ 高优先级筛选 → 紧急事件区域 (urgentTasks)
priority = ['urgent', 'critical', 'high']
└─ 标记完成 → markTaskAsCompleted()
手动刷新:
refreshTodoTasks() {
loadTodoTasksFromIssues()
↓
重新查询数据库
↓
更新两个区域
}
自动同步:
优先级视觉表现:
状态反馈:
鼠标悬停:
紧凑设计:
严格类型定义:
// IssueType 只有 5 种类型
type IssueType = 'bug' | 'task' | 'feedback' | 'risk' | 'feature';
// IssueStatus 只有 4 种状态
type IssueStatus = 'open' | 'in_progress' | 'resolved' | 'closed';
// IssuePriority 有 5 个级别
type IssuePriority = 'low' | 'medium' | 'high' | 'critical' | 'urgent';
避免重复定义:
getIssueTypeLabel 实现查询优化:
include 预加载关联数据渲染优化:
track 优化列表渲染1. 重复函数定义:
error TS2393: Duplicate function implementation.
getIssueTypeLabel(type?: IssueType | string) // 旧实现(已删除)
getIssueTypeLabel(type: IssueType) // 新实现(保留)
2. 类型不匹配:
error TS2353: 'improvement' does not exist in type 'Record<IssueType, string>'
// 修复:移除不存在的类型 'improvement', 'question', 'documentation', 'other'
error TS2353: 'pending' does not exist in type 'Record<IssueStatus, string>'
// 修复:使用正确的状态 'open' 而不是 'pending'
状态值统一:
['open', 'in_progress']待处理, 处理中'pending' 改为 'open'单一数据源:
快速定位问题:
减少重复工作:
代码复用:
加载过程:
🔍 [客服-待办任务] 开始加载待办任务...
📊 [客服-待办任务] 找到 X 个问题
✅ [客服-待办任务] 加载完成: X 个任务
🔥 [客服-紧急事件] 筛选出 X 个紧急任务
错误处理:
❌ [客服-待办任务] 加载失败: [错误信息]
手动刷新:
🔄 [客服-待办任务] 手动刷新...
成功实现客服板块与组长板块的紧急事件和待办任务功能复用:
客服人员现在可以: