任务大厅导出数据增加任务明细和积分明细列

- 新增'积分明细'列:显示每种任务类型的积分(如:全新场景: 21.0分; 部分调整: 1.0分)
- 新增'任务明细'列:显示每种任务类型的数量(如:全新场景 x7; 部分调整 x1)
- 支持多个子任务组,按组号显示(如:第1组: xxx; 第2组: xxx)
This commit is contained in:
Your Name 2026-01-24 11:53:18 +08:00
parent 7d9ef13125
commit 27ed077290
2 changed files with 154 additions and 6 deletions

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.designhub.entity.*;
import com.designhub.mapper.*;
import com.designhub.util.ExcelExportUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -26,6 +27,7 @@ import java.util.Map;
public class ExportService {
private final TaskMapper taskMapper;
private final TaskItemMapper taskItemMapper;
private final UserMapper userMapper;
private final DepartmentMapper departmentMapper;
private final DesignerService designerService;
@ -34,6 +36,7 @@ public class ExportService {
private final CategoryMapper categoryMapper;
private final PlatformMapper platformMapper;
private final org.springframework.jdbc.core.JdbcTemplate jdbcTemplate;
private final ObjectMapper objectMapper;
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@ -87,6 +90,20 @@ public class ExportService {
Map<Long, String> userMap = loadUserMap();
Map<Long, String> deptMap = loadDeptMap();
// 预加载所有相关任务的子任务明细
List<Long> taskIds = tasks.stream().map(Task::getId).toList();
Map<Long, List<TaskItem>> taskItemsMap = new HashMap<>();
if (!taskIds.isEmpty()) {
List<TaskItem> allItems = taskItemMapper.selectList(
new LambdaQueryWrapper<TaskItem>()
.in(TaskItem::getTaskId, taskIds)
.orderBy(true, true, TaskItem::getGroupNo)
);
for (TaskItem item : allItems) {
taskItemsMap.computeIfAbsent(item.getTaskId(), k -> new ArrayList<>()).add(item);
}
}
// 转换为导出数据
List<TaskHallExportVO> exportList = new ArrayList<>();
for (Task task : tasks) {
@ -113,23 +130,82 @@ public class ExportService {
vo.setIsPipeline(task.getIsPipeline() != null && task.getIsPipeline() == 1 ? "是" : "否");
vo.setCreateTime(task.getCreateTime() != null ? task.getCreateTime().format(DATE_FORMATTER) : "");
vo.setDeadline(task.getDeadline() != null ? task.getDeadline().format(DATE_FORMATTER) : "");
// 🔥 添加任务明细和积分明细
List<TaskItem> items = taskItemsMap.get(task.getId());
if (items != null && !items.isEmpty()) {
StringBuilder taskDetails = new StringBuilder();
StringBuilder scoreDetails = new StringBuilder();
for (int i = 0; i < items.size(); i++) {
TaskItem item = items.get(i);
if (i > 0) {
taskDetails.append("\n");
scoreDetails.append("\n");
}
// 解析typeDetails JSON
if (item.getTypeDetails() != null && !item.getTypeDetails().isEmpty()) {
try {
@SuppressWarnings("unchecked")
List<Map<String, Object>> typeDetails = objectMapper.readValue(item.getTypeDetails(), List.class);
StringBuilder itemDetail = new StringBuilder();
StringBuilder itemScore = new StringBuilder();
for (int j = 0; j < typeDetails.size(); j++) {
Map<String, Object> detail = typeDetails.get(j);
String typeName = String.valueOf(detail.get("typeName"));
Object qtyObj = detail.get("quantity");
Object scoreObj = detail.get("totalScore");
int qty = qtyObj instanceof Number ? ((Number) qtyObj).intValue() : 1;
String score = scoreObj != null ? String.valueOf(scoreObj) : "0";
if (j > 0) {
itemDetail.append("; ");
itemScore.append("; ");
}
itemDetail.append(typeName).append(" x").append(qty);
itemScore.append(typeName).append(": ").append(score).append("分");
}
// 如果有多个子任务组,添加组号前缀
if (items.size() > 1) {
taskDetails.append("第").append(item.getGroupNo()).append("组: ");
scoreDetails.append("第").append(item.getGroupNo()).append("组: ");
}
taskDetails.append(itemDetail);
scoreDetails.append(itemScore);
} catch (Exception e) {
log.warn("解析任务明细失败: taskId={}, itemId={}, error={}",
task.getId(), item.getId(), e.getMessage());
}
}
}
vo.setTaskDetails(taskDetails.toString());
vo.setScoreDetails(scoreDetails.toString());
} else {
vo.setTaskDetails("");
vo.setScoreDetails("");
}
exportList.add(vo);
}
// 定义表头
String[] headers = {
"任务编号", "任务标题", "任务类型", "需求类型", "品牌", "类目", "平台",
"SPU信息", "任务积分", "预估工时(小时)", "数量", "发布人", "发布部门",
"接收人", "接收部门", "状态", "发布类型", "是否紧急", "是否流水线",
"创建时间", "截止时间"
"SPU信息", "任务积分", "积分明细", "任务明细", "预估工时(小时)", "数量",
"发布人", "发布部门", "接收人", "接收部门", "状态", "发布类型",
"是否紧急", "是否流水线", "创建时间", "截止时间"
};
// 定义字段名
String[] fieldNames = {
"taskNo", "title", "taskType", "demandType", "brand", "category", "platform",
"spuInfo", "score", "estimatedHours", "quantity", "publisher", "publisherDept",
"receiver", "receiverDept", "status", "releaseType", "isUrgent", "isPipeline",
"createTime", "deadline"
"spuInfo", "score", "scoreDetails", "taskDetails", "estimatedHours", "quantity",
"publisher", "publisherDept", "receiver", "receiverDept", "status", "releaseType",
"isUrgent", "isPipeline", "createTime", "deadline"
};
// 生成文件名
@ -255,6 +331,8 @@ public class ExportService {
private String platform;
private String spuInfo;
private String score;
private String scoreDetails; // 积分明细
private String taskDetails; // 任务明细
private String estimatedHours;
private Integer quantity;
private String publisher;

View File

@ -0,0 +1,70 @@
# 系统更新通知
**更新日期**:2026年1月20日 - 1月24日
---
## 新功能
### 任务节点查询(1月24日)
- 新增任务节点查询功能,点击顶部导航栏的搜索图标即可使用
- 支持通过任务编号或任务标题查询任务当前进度
- 可查看完整的任务流程时间线和相关人员信息
### 任务搜索增强(1月22日)
- 扩展任务搜索功能,支持搜索任务卡片的所有信息(品牌、平台、SPU、发起人等)
### 数据分析增强(1月21日-23日)
- 一级需求部门排名统计现在显示所有部门(包括没有发起任务的)
- 一级需求部门排名表格增加一级部门和二级部门名称列
- 新增用户维度的数据分析功能
- 新增任务明细类型分析(一级、二级、三级分类统计)
### 任务大厅权限扩展(1月21日)
- 一级需求部门和需求部门成员现在可以查看任务大厅所有任务卡片
---
## 功能优化
### 一级需求任务流程
- 一级需求部门发起任务现在必须上传预览图
- 任务卡片和子任务卡片现在显示一级需求人和需求部门发起人信息
- 优化一级需求任务的发起人显示,现在显示明细完善人作为发起人
- 一级需求发起人现在可以收到任务各节点的进度通知(审核通过、驳回、接单、进度更新、完成等)
- 明细完善人现在可以撤回和编辑草稿状态的任务
- 支持审核时选择子部门成员完善任务明细
- 支持一级需求部门任务跨部门分配成员
### 界面优化
- 任务卡片需求人名字过长时显示省略号,鼠标悬停显示完整信息
- 优化全局滚动条样式
- 子任务状态 pending_approval 现在显示为中文"待审核"
- 审核通过的任务正确显示"待接单"或"进行中"状态
### 流水线任务通知
- 流水线任务(如建模+美工)如果预先指定了第二节点的设计师,当第一节点完成后会自动通知该设计师
- 子任务组审核通过后的通知现在显示完整的任务明细积分
### 积分池
- 子部门现在可以共享上级部门的积分池(当子部门积分为0且未单独充值时)
- 二级部门支持独立配置积分池
### 导出功能
- 修复导出功能报错问题
- 导出数据现在正确显示需求类型(新品/优化等)
---
## 问题修复
- 修复任务类型分析数据未正确聚合到上级分类的问题
- 修复子任务状态在某些情况下未正确更新的问题
- 修复预先指定设计师的子任务在审核时未自动识别的问题
- 修复数据分析页面用户需求排名的积分统计错误
- 修复进度检查错误扣分问题(排除流水线任务的主任务)
- 修复接单部门驳回任务时的退回逻辑(没有负责人时退回给发起人)
---
如有问题请联系管理员。