From 571388f41459d527e15f64beac35e6d87123bf77 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 5 Jan 2026 11:21:16 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 修复部门负责人看不到任务关联信息(品牌、类目、平台) - TaskService.getTaskById增加fillTaskRelatedInfo方法填充所有关联信息 2. 修复调整任务类型数量时积分同步显示 - 审核弹窗添加预估积分实时计算和显示 3. 修复流水线任务拆分后母任务不再显示在任务大厅 - TaskMapper添加is_pipeline=0条件 4. 修复驳回任务显示'草稿'问题 - 驳回时保存rejectReason到数据库 - 前端正确判断并显示'已驳回'状态 5. 修复重新编辑被驳回任务时数据丢失问题 - loadTaskForEdit完善所有字段加载 - 显示驳回原因提示用户修改 - 添加remark字段到formData 6. 修复进行中任务卡片缺少'指定'标签显示 --- .../java/com/designhub/mapper/TaskMapper.java | 2 +- .../service/TaskApprovalService.java | 2 + .../com/designhub/service/TaskService.java | 74 +++++++++++++++++++ frontend/src/views/CreateTask.vue | 39 +++++++--- frontend/src/views/TaskHall.vue | 38 +++++++++- 5 files changed, 143 insertions(+), 12 deletions(-) diff --git a/backend/src/main/java/com/designhub/mapper/TaskMapper.java b/backend/src/main/java/com/designhub/mapper/TaskMapper.java index 7a9e874..66895c2 100644 --- a/backend/src/main/java/com/designhub/mapper/TaskMapper.java +++ b/backend/src/main/java/com/designhub/mapper/TaskMapper.java @@ -36,7 +36,7 @@ public interface TaskMapper extends BaseMapper { "LEFT JOIN category c ON t.category_id = c.id " + "LEFT JOIN platform p ON t.platform_id = p.id " + "LEFT JOIN sys_user approver ON t.current_approver_id = approver.id " + - "WHERE t.status = 'pending' AND t.release_type = 'recruitment' AND t.approval_status = 'approved' AND t.deleted = 0" + + "WHERE t.status = 'pending' AND t.release_type = 'recruitment' AND t.approval_status = 'approved' AND t.deleted = 0 AND (t.is_pipeline = 0 OR t.is_pipeline IS NULL)" + " AND t.task_type_id = #{taskTypeId}" + " AND t.demand_type_id = #{demandTypeId}" + " AND t.brand_id = #{brandId}" + diff --git a/backend/src/main/java/com/designhub/service/TaskApprovalService.java b/backend/src/main/java/com/designhub/service/TaskApprovalService.java index 4c66fbc..6bd5bae 100644 --- a/backend/src/main/java/com/designhub/service/TaskApprovalService.java +++ b/backend/src/main/java/com/designhub/service/TaskApprovalService.java @@ -170,6 +170,7 @@ public class TaskApprovalService { task.setApprovalStatus("rejected_by_demand"); task.setStatus("draft"); + task.setRejectReason(reason); // 保存驳回原因 task.setCurrentApproverId(null); task.setCurrentApproverRole(null); taskMapper.updateById(task); @@ -461,6 +462,7 @@ public class TaskApprovalService { task.setApprovalStatus("rejected_by_receiving"); task.setStatus("draft"); + task.setRejectReason(reason); // 保存驳回原因 task.setCurrentApproverId(demandDept.getLeaderId()); task.setCurrentApproverRole("demand_leader"); taskMapper.updateById(task); diff --git a/backend/src/main/java/com/designhub/service/TaskService.java b/backend/src/main/java/com/designhub/service/TaskService.java index c68c6c4..eb0c4ef 100644 --- a/backend/src/main/java/com/designhub/service/TaskService.java +++ b/backend/src/main/java/com/designhub/service/TaskService.java @@ -12,6 +12,9 @@ import com.designhub.exception.BusinessException; import com.designhub.mapper.TaskAuditLogMapper; import com.designhub.mapper.TaskAssignLogMapper; import com.designhub.mapper.TaskMapper; +import com.designhub.mapper.BrandMapper; +import com.designhub.mapper.CategoryMapper; +import com.designhub.mapper.PlatformMapper; import com.designhub.vo.DashboardStatsVO; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -40,6 +43,9 @@ public class TaskService { private final TaskMapper taskMapper; private final TaskAuditLogMapper taskAuditLogMapper; private final TaskAssignLogMapper taskAssignLogMapper; + private final BrandMapper brandMapper; + private final CategoryMapper categoryMapper; + private final PlatformMapper platformMapper; private final TeamScorePoolService teamScorePoolService; private final ConfigService configService; private final DelayPenaltyService delayPenaltyService; @@ -723,8 +729,76 @@ public class TaskService { if (task == null) { throw new BusinessException(ResultCode.TASK_NOT_EXIST); } + + // 填充关联信息 + fillTaskRelatedInfo(task); + return task; } + + /** + * 填充任务关联信息(品牌、类目、平台、发布人等) + */ + private void fillTaskRelatedInfo(Task task) { + // 填充品牌名称 + if (task.getBrandId() != null) { + Brand brand = brandMapper.selectById(task.getBrandId()); + if (brand != null) { + task.setBrandName(brand.getName()); + } + } + + // 填充类目名称 + if (task.getCategoryId() != null) { + Category category = categoryMapper.selectById(task.getCategoryId()); + if (category != null) { + task.setCategoryName(category.getName()); + } + } + + // 填充平台名称 + if (task.getPlatformId() != null) { + Platform platform = platformMapper.selectById(task.getPlatformId()); + if (platform != null) { + task.setPlatformName(platform.getName()); + } + } + + // 填充发布人名称 + if (task.getPublisherId() != null) { + User publisher = userService.getUserById(task.getPublisherId()); + if (publisher != null) { + task.setPublisherName(publisher.getRealName() != null ? publisher.getRealName() : publisher.getUsername()); + } + } + + // 填充发布人部门名称 + if (task.getPublisherDeptId() != null) { + Department dept = departmentService.getDepartmentById(task.getPublisherDeptId()); + if (dept != null) { + task.setPublisherDeptName(dept.getDeptName()); + } + } + + // 填充接收人名称 + if (task.getReceiverId() != null) { + User receiver = userService.getUserById(task.getReceiverId()); + if (receiver != null) { + task.setReceiverName(receiver.getRealName() != null ? receiver.getRealName() : receiver.getUsername()); + } + } + + // 填充当前审核人名称 + if (task.getCurrentApproverId() != null) { + User approver = userService.getUserById(task.getCurrentApproverId()); + if (approver != null) { + task.setCurrentApproverName(approver.getRealName() != null ? approver.getRealName() : approver.getUsername()); + } + } + + // 填充子任务统计信息 + fillSubTaskStats(task); + } /** * 更新任务 diff --git a/frontend/src/views/CreateTask.vue b/frontend/src/views/CreateTask.vue index 87ab6db..80b7b1f 100644 --- a/frontend/src/views/CreateTask.vue +++ b/frontend/src/views/CreateTask.vue @@ -467,6 +467,7 @@ const formData = reactive({ categoryId: undefined, spuInfo: '', attachmentUrl: '', + remark: '', // 备注信息 releaseType: 'default', // receiverId: undefined, // 已移除,改用子任务指定 isUrgent: false @@ -796,7 +797,7 @@ const handleSubmit = async () => { spuInfo: formData.spuInfo, taskSubType: formData.taskSubType, attachmentUrl: attachmentUrl, - remark: '', + remark: formData.remark || '', priority: formData.isUrgent ? 3 : 1, // 0-低 1-普通 2-高 3-紧急 releaseType: formData.releaseType, // 发布类型 receiverId: undefined // 主任务不设接收人,由子任务指定 @@ -1042,7 +1043,7 @@ const loadTaskForEdit = async (taskId: number) => { const task = response.data if (task) { - // 填充表单数据 + // 填充基本表单数据 formData.title = task.title || '' formData.taskSubType = task.taskSubType || '' formData.brandId = task.brandId @@ -1051,32 +1052,50 @@ const loadTaskForEdit = async (taskId: number) => { formData.spuInfo = task.spuInfo || '' formData.remark = task.remark || '' formData.releaseType = task.releaseType || 'recruitment' + formData.isUrgent = task.isUrgent === 1 || task.isUrgent === true - // 处理任务类型 + // 处理任务类型和数量 if (task.taskTypeIds) { const typeIds = task.taskTypeIds.split(',').map((id: string) => parseInt(id.trim())) + // 尝试获取每个类型对应的数量(如果有taskItems,从中获取) formData.taskTypes = typeIds.map((typeId: number, index: number) => ({ taskTypeId: typeId, quantity: index === 0 ? (task.quantity || 1) : 1, receiverId: task.receiverId })) + } else if (task.taskTypeId) { + // 兼容单任务类型 + formData.taskTypes = [{ + taskTypeId: task.taskTypeId, + quantity: task.quantity || 1, + receiverId: task.receiverId + }] } - // 处理附件 + // 处理附件 - 完整加载原有附件 if (task.attachmentUrl) { formData.attachmentUrl = task.attachmentUrl // 将附件URL转换为fileList格式 const urls = task.attachmentUrl.split(',').filter((u: string) => u.trim()) - fileList.value = urls.map((url: string, index: number) => ({ - uid: `existing-${index}`, - name: `附件${index + 1}`, - status: 'done', - url: url.trim() - })) + fileList.value = urls.map((url: string, index: number) => { + const fileName = url.split('/').pop() || `附件${index + 1}` + return { + uid: `existing-${index}`, + name: fileName, + status: 'done' as const, + url: url.trim() + } + }) } editMode.value = true editTaskId.value = taskId + + // 显示驳回原因提示(如果是被驳回的任务) + if (task.rejectReason) { + message.warning(`驳回原因:${task.rejectReason},请修改后重新提交`) + } + console.log('任务数据加载成功:', task) } } catch (error) { diff --git a/frontend/src/views/TaskHall.vue b/frontend/src/views/TaskHall.vue index 6ecb213..991619a 100644 --- a/frontend/src/views/TaskHall.vue +++ b/frontend/src/views/TaskHall.vue @@ -800,6 +800,10 @@ 子任务 + + + 指定 + 进行中 @@ -1894,6 +1898,19 @@ + + +
+
+ 预估总积分 + {{ approveEstimatedScore }} 分 +
+
+ + {{ getTaskTypeName(item.typeId) }}: {{ getTaskTypeUnitScore(item.typeId) }} × {{ item.quantity }} + +
+
@@ -2389,6 +2406,20 @@ const getTaskTypeName = (typeId: number) => { return type?.name || '未知类型' } +// 获取任务类型单位积分 +const getTaskTypeUnitScore = (typeId: number) => { + const type = demandTypes.value.find(t => t.id === typeId) + return type?.unitScore || 0 +} + +// 计算审核弹窗中的预估总积分 +const approveEstimatedScore = computed(() => { + return approveTaskTypes.value.reduce((total, item) => { + const unitScore = getTaskTypeUnitScore(item.typeId) + return total + (unitScore * item.quantity) + }, 0) +}) + // 格式化时间 const formatTime = (time: string | undefined) => { if (!time) return '--' @@ -3888,10 +3919,15 @@ const handleConfigUpdate = async (event: CustomEvent) => { // 获取任务状态文本(增强版,支持区分驳回和草稿) const getTaskStatusText = (status: string, task?: any) => { // 如果有task对象,检查approvalStatus来区分驳回和草稿 - if (task && status === 'draft') { + if (task) { + // 检查是否被驳回(无论status是draft还是rejected) if (task.approvalStatus === 'rejected_by_demand' || task.approvalStatus === 'rejected_by_receiving') { return '已驳回' } + // 检查status是否是rejected + if (status === 'rejected') { + return '已驳回' + } } const statusMap: Record = {