feat: 优化指派设计师功能,改用Select下拉框并显示工作量和预计完成时间

问题修复:
✅ 修复指派设计师按钮点击无效的问题
✅ 将Radio组改为Select下拉框,体验更好

功能优化:

1. 后端增强 (UserService.java)
   ✅ 新增返回设计师最早预计完成时间 (earliestDeadline)
   ✅ 查询该设计师进行中任务的最早deadline
   ✅ 便于负责人评估设计师工作量

2. 前端界面优化 (TaskHall.vue)
   ✅ 将RadioGroup改为Select下拉框
   ✅ 下拉框尺寸改为large,更易操作
   ✅ 显示设计师姓名
   ✅ 显示进行中任务数量
   ✅ 显示预计最早完成时间(相对时间)
   ✅ 根据工作量显示不同颜色:
      - 0个任务:绿色 "空闲"
      - 1-3个:绿色 "进行中: X个"
      - 4-5个:橙色 "进行中: X个"
      - 6+个:红色 "进行中: X个"

3. 时间显示格式
   ✅ 相对时间显示(例如:2天8小时后)
   ✅ 24小时内显示小时数
   ✅ 已逾期显示为"已逾期"

4. 下拉框选项样式
   ✅ 双栏布局:左侧姓名,右侧工作信息
   ✅ 工作量和完成时间用 | 分隔
   ✅ 信息一目了然

使用示例:
- 选择"指定设计师接单"
- 点击下拉框
- 看到:张三 | 进行中: 2个 | 最早完成: 1天5小时后
- 方便评估后选择最合适的设计师
This commit is contained in:
Your Name 2026-01-03 12:27:52 +08:00
parent 7e970fa614
commit c3454123db
3 changed files with 77 additions and 25 deletions

View File

@ -1256,6 +1256,23 @@ public class UserService {
}
}
// 获取最早预计完成时间(查询该设计师进行中任务的最早deadline)
if (taskMapper != null && inProgressCount > 0) {
// 查询普通任务的最早deadline
LambdaQueryWrapper<com.designhub.entity.Task> taskQuery = new LambdaQueryWrapper<>();
taskQuery.eq(com.designhub.entity.Task::getReceiverId, user.getId())
.eq(com.designhub.entity.Task::getStatus, "in_progress")
.eq(com.designhub.entity.Task::getDeleted, 0)
.isNotNull(com.designhub.entity.Task::getDeadline)
.orderByAsc(com.designhub.entity.Task::getDeadline)
.last("LIMIT 1");
com.designhub.entity.Task earliestTask = taskMapper.selectOne(taskQuery);
if (earliestTask != null && earliestTask.getDeadline() != null) {
designerInfo.put("earliestDeadline", earliestTask.getDeadline());
}
}
result.add(designerInfo);
}

View File

@ -150,6 +150,7 @@ export interface DesignerWithWorkload {
deptId?: number;
deptName?: string;
inProgressCount: number; // 进行中的任务数量
earliestDeadline?: string; // 最早预计完成时间
}
/**

View File

@ -2753,33 +2753,67 @@ const showAssignDesignerModal = async (task: Task) => {
color: '#262626'
}
}, '选择设计师'),
h(RadioGroup, {
h(Select, {
value: selectedDesignerId,
onChange: (e: any) => {
selectedDesignerId = e.target.value
placeholder: '请选择要指派的设计师',
style: { width: '100%' },
size: 'large',
onChange: (val: number) => {
selectedDesignerId = val
},
style: { width: '100%' }
}, designers.map(designer =>
h(Radio, {
value: designer.id,
style: {
display: 'flex',
alignItems: 'center',
marginBottom: '10px',
padding: '12px',
border: '1px solid #e8e8e8',
borderRadius: '6px',
background: selectedDesignerId === designer.id ? '#e6f7ff' : 'white',
transition: 'all 0.3s'
}
}, [
h('span', { style: { flex: 1, fontSize: '14px', fontWeight: 500 } }, designer.realName),
h(Tag, {
color: designer.inProgressCount > 5 ? 'error' :
designer.inProgressCount > 3 ? 'warning' : 'success'
}, `进行中: ${designer.inProgressCount}`)
])
))
options: designers.map(designer => {
const formatDeadline = (deadline: string) => {
if (!deadline) return ''
try {
const date = new Date(deadline)
const now = new Date()
const diff = date.getTime() - now.getTime()
const days = Math.floor(diff / (1000 * 60 * 60 * 24))
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
if (diff < 0) return '已逾期'
if (days === 0) return `${hours}小时后`
return `${days}天${hours}小时后`
} catch {
return ''
}
}
const workloadColor = designer.inProgressCount > 5 ? '#ff4d4f' :
designer.inProgressCount > 3 ? '#faad14' : '#52c41a'
const workloadText = designer.inProgressCount === 0 ? '空闲' :
`进行中: ${designer.inProgressCount}个`
const deadlineText = designer.earliestDeadline ?
` | 最早完成: ${formatDeadline(designer.earliestDeadline)}` : ''
return {
value: designer.id,
label: h('div', {
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '4px 0'
}
}, [
h('span', {
style: {
fontSize: '14px',
fontWeight: 500,
flex: 1
}
}, designer.realName),
h('span', {
style: {
fontSize: '12px',
color: workloadColor,
marginLeft: '12px'
}
}, `${workloadText}${deadlineText}`)
])
}
})
})
])
])