feat: 一级需求任务卡片显示一级需求人和需求部门发起人

1. 后端 fillTaskRelatedInfo 填充明细完善人姓名 (detailCompleterName)
2. 前端任务卡片统一显示:
   - 一级需求人(橙色):一级需求部门的原始发起人 + 部门名称
   - 需求部门发起人(绿色):明细完善人
   - 发布人:非一级需求任务时显示
3. 需求部门负责人和成员可以看到一级需求任务(明细完善人在本部门的)
4. 后端增加 getMyDetailCompleterTasks 接口查询明细完善人任务
This commit is contained in:
Your Name 2026-01-22 14:15:56 +08:00
parent cb5ad8955c
commit 93da7aca22
4 changed files with 283 additions and 65 deletions

View File

@ -68,11 +68,12 @@ public class TaskController {
@Parameter(description = "发布者部门ID列表(逗号分隔)") @RequestParam(required = false) String publisherDeptIds,
@Parameter(description = "接收部门ID") @RequestParam(required = false) Long receiverDeptId,
@Parameter(description = "排除的状态列表(逗号分隔,如 draft,completed,cancelled)") @RequestParam(required = false) String excludeStatuses,
@Parameter(description = "包含明细完善人所属部门ID列表(逗号分隔,用于查询一级需求任务)") @RequestParam(required = false) String includeDetailCompleterDeptIds,
@Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer page,
@Parameter(description = "每页数量") @RequestParam(defaultValue = "20") Integer pageSize) {
log.info("查询任务列表: status={}, taskTypeId={}, publisherDeptId={}, publisherDeptIds={}, receiverDeptId={}, excludeStatuses={}, page={}, pageSize={}",
status, taskTypeId, publisherDeptId, publisherDeptIds, receiverDeptId, excludeStatuses, page, pageSize);
log.info("查询任务列表: status={}, taskTypeId={}, publisherDeptId={}, publisherDeptIds={}, receiverDeptId={}, excludeStatuses={}, includeDetailCompleterDeptIds={}, page={}, pageSize={}",
status, taskTypeId, publisherDeptId, publisherDeptIds, receiverDeptId, excludeStatuses, includeDetailCompleterDeptIds, page, pageSize);
// 处理多个发布者部门ID
List<Long> publisherDeptIdList = null;
@ -93,7 +94,17 @@ public class TaskController {
.collect(Collectors.toList());
}
IPage<Task> taskPage = taskService.getTaskList(page, pageSize, status, taskTypeId, publisherDeptId, publisherDeptIdList, receiverDeptId, excludeStatusList);
// 处理明细完善人部门ID列表
List<Long> detailCompleterDeptIdList = null;
if (includeDetailCompleterDeptIds != null && !includeDetailCompleterDeptIds.isEmpty()) {
detailCompleterDeptIdList = Arrays.stream(includeDetailCompleterDeptIds.split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.map(Long::parseLong)
.collect(Collectors.toList());
}
IPage<Task> taskPage = taskService.getTaskList(page, pageSize, status, taskTypeId, publisherDeptId, publisherDeptIdList, receiverDeptId, excludeStatusList, detailCompleterDeptIdList);
return Result.success(taskPage);
}
@ -284,7 +295,7 @@ public class TaskController {
@Operation(summary = "我的任务", description = "获取当前用户的任务列表")
@GetMapping("/my")
public Result<IPage<Task>> getMyTasks(
@RequestParam(required = false) String role, // publisher 或 receiver
@RequestParam(required = false) String role, // publisher、receiver 或 detail_completer
@RequestParam(required = false) String status,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "20") Integer pageSize,
@ -299,6 +310,9 @@ public class TaskController {
IPage<Task> taskPage;
if ("publisher".equals(role)) {
taskPage = taskService.getMyPublishedTasks(page, pageSize, userId, status);
} else if ("detail_completer".equals(role)) {
// 查询用户作为明细完善人的一级需求任务
taskPage = taskService.getMyDetailCompleterTasks(page, pageSize, userId, status);
} else {
taskPage = taskService.getMyReceivedTasks(page, pageSize, userId, status);
}

View File

@ -17,6 +17,7 @@ import com.designhub.mapper.BrandMapper;
import com.designhub.mapper.CategoryMapper;
import com.designhub.mapper.PlatformMapper;
import com.designhub.mapper.DemandTypeMapper;
import com.designhub.mapper.UserMapper;
import com.designhub.vo.DashboardStatsVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -64,6 +65,7 @@ public class TaskService {
private final com.designhub.mapper.DepartmentMapper departmentMapper;
private final com.designhub.util.WorkHoursCalculator workHoursCalculator;
private final com.designhub.mapper.DelayPenaltyRecordMapper delayPenaltyRecordMapper;
private final UserMapper userMapper;
@org.springframework.beans.factory.annotation.Autowired
@org.springframework.context.annotation.Lazy
@ -784,7 +786,7 @@ public class TaskService {
* 获取任务列表
*/
public IPage<Task> getTaskList(Integer page, Integer pageSize, String status, Long taskTypeId, Long publisherDeptId, List<Long> publisherDeptIds, Long receiverDeptId) {
return getTaskList(page, pageSize, status, taskTypeId, publisherDeptId, publisherDeptIds, receiverDeptId, null);
return getTaskList(page, pageSize, status, taskTypeId, publisherDeptId, publisherDeptIds, receiverDeptId, null, null);
}
/**
@ -792,6 +794,15 @@ public class TaskService {
* @param excludeStatuses 要排除的状态列表(如 draft,completed,cancelled)
*/
public IPage<Task> getTaskList(Integer page, Integer pageSize, String status, Long taskTypeId, Long publisherDeptId, List<Long> publisherDeptIds, Long receiverDeptId, List<String> excludeStatuses) {
return getTaskList(page, pageSize, status, taskTypeId, publisherDeptId, publisherDeptIds, receiverDeptId, excludeStatuses, null);
}
/**
* 获取任务列表(支持排除指定状态 + 包含一级需求任务的明细完善人所属部门)
* @param excludeStatuses 要排除的状态列表(如 draft,completed,cancelled)
* @param includeDetailCompleterDeptIds 包含明细完善人所属部门ID列表(用于需求部门负责人查看一级需求任务)
*/
public IPage<Task> getTaskList(Integer page, Integer pageSize, String status, Long taskTypeId, Long publisherDeptId, List<Long> publisherDeptIds, Long receiverDeptId, List<String> excludeStatuses, List<Long> includeDetailCompleterDeptIds) {
Page<Task> pageParam = new Page<>(page, pageSize);
LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();
@ -813,11 +824,63 @@ public class TaskService {
// 根据发布者部门筛选(部门负责人视角切换时使用)
// 优先使用 publisherDeptIds(多个部门ID列表)
if (publisherDeptIds != null && !publisherDeptIds.isEmpty()) {
wrapper.in(Task::getPublisherDeptId, publisherDeptIds);
log.info("按多个发布者部门筛选: publisherDeptIds={}", publisherDeptIds);
} else if (publisherDeptId != null) {
wrapper.eq(Task::getPublisherDeptId, publisherDeptId);
// 🔥 如果同时有 includeDetailCompleterDeptIds,需要用 OR 条件组合
if (includeDetailCompleterDeptIds != null && !includeDetailCompleterDeptIds.isEmpty()) {
// 需要查询:(发布者部门在 publisherDeptIds 中) OR (一级需求任务且明细完善人在指定部门中)
// 获取指定部门的所有用户ID
List<Long> detailCompleterUserIds = userMapper.selectList(
new LambdaQueryWrapper<User>()
.in(User::getDeptId, includeDetailCompleterDeptIds)
.eq(User::getStatus, 1)
.eq(User::getDeleted, 0)
).stream().map(User::getId).collect(java.util.stream.Collectors.toList());
log.info("查询一级需求任务,明细完善人部门IDs: {}, 对应用户IDs: {}", includeDetailCompleterDeptIds, detailCompleterUserIds);
if (publisherDeptIds != null && !publisherDeptIds.isEmpty()) {
// 组合条件:(publisherDeptId IN publisherDeptIds) OR (isPrimaryTask=1 AND detailCompleterId IN userIds)
wrapper.and(w -> w
.in(Task::getPublisherDeptId, publisherDeptIds)
.or(orWrapper -> {
orWrapper.eq(Task::getIsPrimaryTask, 1);
if (!detailCompleterUserIds.isEmpty()) {
orWrapper.in(Task::getDetailCompleterId, detailCompleterUserIds);
} else {
// 如果没有用户,添加一个不可能匹配的条件
orWrapper.eq(Task::getDetailCompleterId, -1);
}
})
);
log.info("组合查询: publisherDeptIds={} OR (isPrimaryTask=1 AND detailCompleterId IN {})", publisherDeptIds, detailCompleterUserIds);
} else if (publisherDeptId != null) {
wrapper.and(w -> w
.eq(Task::getPublisherDeptId, publisherDeptId)
.or(orWrapper -> {
orWrapper.eq(Task::getIsPrimaryTask, 1);
if (!detailCompleterUserIds.isEmpty()) {
orWrapper.in(Task::getDetailCompleterId, detailCompleterUserIds);
} else {
orWrapper.eq(Task::getDetailCompleterId, -1);
}
})
);
} else {
// 只查询一级需求任务
wrapper.eq(Task::getIsPrimaryTask, 1);
if (!detailCompleterUserIds.isEmpty()) {
wrapper.in(Task::getDetailCompleterId, detailCompleterUserIds);
} else {
wrapper.eq(Task::getDetailCompleterId, -1);
}
}
} else {
// 原有逻辑:只按发布者部门筛选
if (publisherDeptIds != null && !publisherDeptIds.isEmpty()) {
wrapper.in(Task::getPublisherDeptId, publisherDeptIds);
log.info("按多个发布者部门筛选: publisherDeptIds={}", publisherDeptIds);
} else if (publisherDeptId != null) {
wrapper.eq(Task::getPublisherDeptId, publisherDeptId);
}
}
// 根据接收部门筛选(部门负责人视角切换时使用,支持部门ID列表)
@ -1237,6 +1300,38 @@ public class TaskService {
return taskPage;
}
/**
* 获取我作为明细完善人的一级需求任务
* 需求部门成员完善任务明细后,可以在"进行中任务"看到这些任务
*/
public IPage<Task> getMyDetailCompleterTasks(Integer page, Integer pageSize, Long userId, String status) {
Page<Task> pageParam = new Page<>(page, pageSize);
LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();
// 查询条件:一级需求任务 且 明细完善人是当前用户
wrapper.eq(Task::getIsPrimaryTask, 1)
.eq(Task::getDetailCompleterId, userId)
.eq(Task::getDeleted, 0);
// 根据状态筛选
if (StringUtils.hasText(status)) {
wrapper.eq(Task::getStatus, status);
}
// 按更新时间倒序
wrapper.orderByDesc(Task::getUpdateTime);
IPage<Task> taskPage = taskMapper.selectPage(pageParam, wrapper);
// 填充关联信息和子任务统计
for (Task task : taskPage.getRecords()) {
fillTaskRelatedInfo(task);
fillSubTaskStats(task);
}
return taskPage;
}
/**
* 填充流水线任务的子任务统计信息
*/
@ -1445,6 +1540,14 @@ public class TaskService {
}
}
// 填充明细完善人名称(需求部门成员)
if (task.getDetailCompleterId() != null) {
User detailCompleter = userService.getUserById(task.getDetailCompleterId());
if (detailCompleter != null) {
task.setDetailCompleterName(detailCompleter.getRealName() != null ? detailCompleter.getRealName() : detailCompleter.getUsername());
}
}
// 填充子任务统计信息
fillSubTaskStats(task);
}

View File

@ -176,7 +176,7 @@ export interface TaskHallParams {
}
export interface MyTasksParams {
role?: 'publisher' | 'receiver'
role?: 'publisher' | 'receiver' | 'detail_completer'
status?: string
page?: number
pageSize?: number

View File

@ -221,13 +221,19 @@
</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }} ({{ task.primaryPublisherDeptName || '一级部门' }})</span>
</div>
<!-- 发布人:如果是一级需求任务且发布人和一级需求人不同,显示为"需求部门发布人" -->
<div class="detail-item">
<!-- 明细完善人(一级需求任务且有明细完善人) -->
<div v-if="task.isPrimaryTask === 1 && task.detailCompleterName" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#52c41a" />
</span>
<span style="color: #52c41a;">需求部门发起人: {{ task.detailCompleterName }}</span>
</div>
<!-- 发布人:非一级需求任务或一级需求任务无明细完善人时显示 -->
<div v-if="!(task.isPrimaryTask === 1 && task.detailCompleterName)" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#31f08b" />
</span>
<span v-if="task.isPrimaryTask === 1 && task.primaryPublisherId !== task.publisherId">需求部门发布人: {{ task.publisherName || '未知' }}</span>
<span v-else>发布人: {{ task.publisherName || '未知' }}</span>
<span>发布人: {{ task.publisherName || '未知' }}</span>
</div>
<div v-if="task.attachmentUrl" class="detail-item detail-item-attachment">
<span class="icon">
@ -424,15 +430,21 @@
<span class="icon">
<Icon name="user" size="sm" color="#faad14" />
</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }}</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }} ({{ task.primaryPublisherDeptName || '一级部门' }})</span>
</div>
<!-- 发起人/需求部门发布人 -->
<div class="detail-item">
<!-- 明细完善人(一级需求任务且有明细完善人) -->
<div v-if="task.isPrimaryTask === 1 && task.detailCompleterName" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#52c41a" />
</span>
<span style="color: #52c41a;">需求部门发起人: {{ task.detailCompleterName }}</span>
</div>
<!-- 发起人:非一级需求任务或一级需求任务无明细完善人时显示 -->
<div v-if="!(task.isPrimaryTask === 1 && task.detailCompleterName)" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#31f08b" />
</span>
<span v-if="task.isPrimaryTask === 1 && task.primaryPublisherId !== task.publisherId">需求部门发布人: {{ task.publisherName || '--' }}</span>
<span v-else>发起人: {{ task.publisherName || '--' }}</span>
<span>发起人: {{ task.publisherName || '--' }}</span>
</div>
<div v-if="task._itemType !== 'taskGroup'" class="detail-item">
<span class="icon">
@ -516,14 +528,21 @@
<span class="icon">
<Icon name="user" size="sm" color="#faad14" />
</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }}</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }} ({{ task.primaryPublisherDeptName || '一级部门' }})</span>
</div>
<div v-if="task.publisherName" class="detail-item">
<!-- 明细完善人(一级需求任务且有明细完善人) -->
<div v-if="task.isPrimaryTask === 1 && task.detailCompleterName" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#52c41a" />
</span>
<span style="color: #52c41a;">需求部门发起人: {{ task.detailCompleterName }}</span>
</div>
<!-- 发布人:非一级需求任务或一级需求任务无明细完善人时显示 -->
<div v-if="task.publisherName && !(task.isPrimaryTask === 1 && task.detailCompleterName)" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#31f08b" />
</span>
<span v-if="task.isPrimaryTask === 1 && task.primaryPublisherId !== task.publisherId">需求部门发布人: {{ task.publisherName }}</span>
<span v-else>发布人: {{ task.publisherName }}</span>
<span>发布人: {{ task.publisherName }}</span>
</div>
</div>
@ -806,14 +825,21 @@
<span class="icon">
<Icon name="user" size="sm" color="#faad14" />
</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }}</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }} ({{ task.primaryPublisherDeptName || '一级部门' }})</span>
</div>
<div v-if="task.publisherName" class="detail-item">
<!-- 明细完善人(一级需求任务且有明细完善人) -->
<div v-if="task.isPrimaryTask === 1 && task.detailCompleterName" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#52c41a" />
</span>
<span style="color: #52c41a;">需求部门发起人: {{ task.detailCompleterName }}</span>
</div>
<!-- 发布人:非一级需求任务或一级需求任务无明细完善人时显示 -->
<div v-if="task.publisherName && !(task.isPrimaryTask === 1 && task.detailCompleterName)" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#31f08b" />
</span>
<span v-if="task.isPrimaryTask === 1 && task.primaryPublisherId !== task.publisherId">需求部门发布人: {{ task.publisherName }}</span>
<span v-else>发布人: {{ task.publisherName }}</span>
<span>发布人: {{ task.publisherName }}</span>
</div>
</div>
@ -1024,15 +1050,21 @@
<span class="icon">
<Icon name="user" size="sm" color="#faad14" />
</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }}</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }} ({{ task.primaryPublisherDeptName || '一级部门' }})</span>
</div>
<!-- 发起人/需求部门发布人 -->
<div class="detail-item">
<!-- 明细完善人(一级需求任务且有明细完善人) -->
<div v-if="task.isPrimaryTask === 1 && task.detailCompleterName" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#52c41a" />
</span>
<span style="color: #52c41a;">需求部门发起人: {{ task.detailCompleterName }}</span>
</div>
<!-- 发起人:非一级需求任务或一级需求任务无明细完善人时显示 -->
<div v-if="!(task.isPrimaryTask === 1 && task.detailCompleterName)" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#31f08b" />
</span>
<span v-if="task.isPrimaryTask === 1 && task.primaryPublisherId !== task.publisherId">需求部门发布人: {{ task.publisherName || '--' }}</span>
<span v-else>发起人: {{ task.publisherName || '--' }}</span>
<span>发起人: {{ task.publisherName || '--' }}</span>
</div>
<div class="detail-item">
<span class="icon">
@ -1121,14 +1153,21 @@
<span class="icon">
<Icon name="user" size="sm" color="#faad14" />
</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }}</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }} ({{ task.primaryPublisherDeptName || '一级部门' }})</span>
</div>
<div v-if="task.publisherName" class="detail-item">
<!-- 明细完善人(一级需求任务且有明细完善人) -->
<div v-if="task.isPrimaryTask === 1 && task.detailCompleterName" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#52c41a" />
</span>
<span style="color: #52c41a;">需求部门发起人: {{ task.detailCompleterName }}</span>
</div>
<!-- 发布人:非一级需求任务或一级需求任务无明细完善人时显示 -->
<div v-if="task.publisherName && !(task.isPrimaryTask === 1 && task.detailCompleterName)" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#31f08b" />
</span>
<span v-if="task.isPrimaryTask === 1 && task.primaryPublisherId !== task.publisherId">需求部门发布人: {{ task.publisherName }}</span>
<span v-else>发布人: {{ task.publisherName }}</span>
<span>发布人: {{ task.publisherName }}</span>
</div>
</div>
@ -1442,14 +1481,21 @@
<span class="icon">
<Icon name="user" size="sm" color="#faad14" />
</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }}</span>
<span style="color: #faad14;">一级需求人: {{ task.primaryPublisherName }} ({{ task.primaryPublisherDeptName || '一级部门' }})</span>
</div>
<div v-if="task.publisherName" class="detail-item">
<!-- 明细完善人(一级需求任务且有明细完善人) -->
<div v-if="task.isPrimaryTask === 1 && task.detailCompleterName" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#52c41a" />
</span>
<span style="color: #52c41a;">需求部门发起人: {{ task.detailCompleterName }}</span>
</div>
<!-- 发布人:非一级需求任务或一级需求任务无明细完善人时显示 -->
<div v-if="task.publisherName && !(task.isPrimaryTask === 1 && task.detailCompleterName)" class="detail-item">
<span class="icon">
<Icon name="user" size="sm" color="#31f08b" />
</span>
<span v-if="task.isPrimaryTask === 1 && task.primaryPublisherId !== task.publisherId">需求部门发布人: {{ task.publisherName }}</span>
<span v-else>发布人: {{ task.publisherName }}</span>
<span>发布人: {{ task.publisherName }}</span>
</div>
</div>
@ -4593,13 +4639,14 @@ const loadInProgressTasks = async (newFilters?: any) => {
console.log('主任务处理后,allTasks长度:', allTasks.length, 'totalCount:', totalCount)
}
} else {
// 需求部门视角:看该部门发起的任务(通过 deptId 参数)
// 需求部门视角:看该部门发起的任务(通过 deptId 参数)+ 一级需求任务(明细完善人在该部门)
console.log('需求部门视角切换,查询部门ID:', currentDeptView.value)
// 需求部门负责人:使用 excludeStatuses 排除草稿和已完成的任务
const { status, ...paramsWithoutStatus } = params
const taskResponse = await taskApi.getTasks({
...paramsWithoutStatus,
publisherDeptId: currentDeptView.value, // 按发布者部门过滤
includeDetailCompleterDeptIds: String(currentDeptView.value), // 🔥 同时包含一级需求任务(明细完善人在该部门)
excludeStatuses: 'draft,completed,cancelled' // 🔥 后端排除指定状态
})
if (taskResponse.data && taskResponse.data.records) {
@ -4626,7 +4673,7 @@ const loadInProgressTasks = async (newFilters?: any) => {
totalCount += itemResponse.data.total || 0
}
} else {
// 需求部门负责人:看自己管理的所有需求部门发起的任务
// 需求部门负责人:看自己管理的所有需求部门发起的任务 + 一级需求任务(指定本部门成员为明细完善人的)
// 获取用户管理的所有需求部门ID(包括自己所属的部门)
const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}')
const demandDeptIds: number[] = []
@ -4652,10 +4699,12 @@ const loadInProgressTasks = async (newFilters?: any) => {
console.log('需求部门负责人查询的部门ID列表:', demandDeptIds)
// 需求部门负责人:查询所有处理中的任务(排除 draft、completed、cancelled)
// 🔥 同时查询一级需求任务(指定本部门成员为明细完善人的)
const { status: _, ...paramsWithoutStatus } = params
const taskResponse = await taskApi.getTasks({
...paramsWithoutStatus,
publisherDeptIds: demandDeptIds.join(','), // 按多个发布者部门过滤
includeDetailCompleterDeptIds: demandDeptIds.join(','), // 🔥 同时包含一级需求任务(明细完善人在本部门)
excludeStatuses: 'draft,completed,cancelled' // 🔥 后端排除指定状态
})
if (taskResponse.data && taskResponse.data.records) {
@ -4693,15 +4742,25 @@ const loadInProgressTasks = async (newFilters?: any) => {
totalCount += itemResponse.data.total || 0
}
} else if (currentDeptType === 'demand') {
// 需求部门普通用户:看自己发起的任务中有子任务在进行中的
const taskResponse = await taskApi.getMyTasks({
role: 'publisher',
page: inProgressPagination.page,
pageSize: inProgressPagination.pageSize,
keyword: inProgressFilters.keyword
})
if (taskResponse.code === 200 && taskResponse.data && taskResponse.data.records) {
const tasksWithInProgress = taskResponse.data.records.filter((task: any) => {
// 需求部门普通用户:看自己发起的任务 + 自己作为明细完善人的一级需求任务
const [publisherResponse, detailCompleterResponse] = await Promise.all([
taskApi.getMyTasks({
role: 'publisher',
page: inProgressPagination.page,
pageSize: inProgressPagination.pageSize,
keyword: inProgressFilters.keyword
}),
// 🔥 查询自己作为明细完善人的一级需求任务
taskApi.getMyTasks({
role: 'detail_completer',
page: 1,
pageSize: 100 // 获取所有
})
])
// 处理我发起的任务
if (publisherResponse.code === 200 && publisherResponse.data && publisherResponse.data.records) {
const tasksWithInProgress = publisherResponse.data.records.filter((task: any) => {
if (task.isPipeline === 1) {
return (task.subTaskInProgress || 0) > 0 || task.status === 'in_progress'
}
@ -4711,8 +4770,29 @@ const loadInProgressTasks = async (newFilters?: any) => {
...task,
isSubTask: false
}))
totalCount = allTasks.length
}
// 🔥 处理我作为明细完善人的一级需求任务(排除已完成和草稿状态)
if (detailCompleterResponse.code === 200 && detailCompleterResponse.data && detailCompleterResponse.data.records) {
const detailCompleterTasks = detailCompleterResponse.data.records.filter((task: any) => {
// 排除草稿和已完成状态
return task.status !== 'draft' && task.status !== 'completed' && task.status !== 'cancelled'
}).map((task: any) => ({
...task,
isSubTask: false
}))
// 合并并去重(避免同一任务重复显示)
const existingTaskIds = new Set(allTasks.map((t: any) => t.id))
detailCompleterTasks.forEach((task: any) => {
if (!existingTaskIds.has(task.id)) {
allTasks.push(task)
}
})
console.log('需求部门成员 - 发起的任务:', publisherResponse.data.records.length, '明细完善人任务:', detailCompleterTasks.length, '合并后:', allTasks.length)
}
totalCount = allTasks.length
} else {
// 接单部门用户(设计师):看子任务卡片 + 直接分配给自己的普通任务
const [itemResponse, taskResponse] = await Promise.all([
@ -6072,25 +6152,46 @@ const loadAllTabCounts = async () => {
} else {
// 未切换视角或普通用户:根据部门类型查询
if (currentDeptType === 'demand' || currentDeptType === 'primary_demand') {
// 需求部门/一级需求部门用户:查询自己发起的任务中有子任务在进行中的
// 需求部门/一级需求部门用户:查询自己发起的任务 + 自己作为明细完善人的一级需求任务
promises.push(
taskApi.getMyTasks({
role: 'publisher',
page: 1,
pageSize: 100 // 获取所有任务然后过滤
}).then(res => {
if (res.data && res.data.records) {
// 过滤出有进行中子任务的任务
const inProgressTasks = res.data.records.filter((task: any) => {
Promise.all([
taskApi.getMyTasks({
role: 'publisher',
page: 1,
pageSize: 100 // 获取所有任务然后过滤
}),
// 🔥 同时查询明细完善人任务
taskApi.getMyTasks({
role: 'detail_completer',
page: 1,
pageSize: 100
})
]).then(([publisherRes, detailCompleterRes]) => {
let count = 0
const countedTaskIds = new Set<number>()
// 统计我发起的进行中任务
if (publisherRes.data && publisherRes.data.records) {
const inProgressTasks = publisherRes.data.records.filter((task: any) => {
if (task.isPipeline === 1) {
return (task.subTaskInProgress || 0) > 0 || task.status === 'in_progress'
}
return task.status === 'in_progress'
})
inProgressTotal.value = inProgressTasks.length
} else {
inProgressTotal.value = 0
inProgressTasks.forEach((task: any) => countedTaskIds.add(task.id))
count += inProgressTasks.length
}
// 🔥 统计我作为明细完善人的进行中任务(去重)
if (detailCompleterRes.data && detailCompleterRes.data.records) {
const detailCompleterInProgress = detailCompleterRes.data.records.filter((task: any) => {
// 排除草稿和已完成状态,且不重复计算
return task.status !== 'draft' && task.status !== 'completed' && task.status !== 'cancelled' && !countedTaskIds.has(task.id)
})
count += detailCompleterInProgress.length
}
inProgressTotal.value = count
}).catch(() => {
inProgressTotal.value = 0
})