Browse Source

监督端-查询统计

dev-v1.0.2
庄锐波 5 months ago
parent
commit
c23613fbf3
  1. 95
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeCpPlanServiceImpl.java
  2. 4
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_mine.vue

95
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeCpPlanServiceImpl.java

@ -35,6 +35,7 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.satoken.utils.LoginHelper;
@ -758,7 +759,7 @@ public class EfcodeCpPlanServiceImpl implements IEfcodeCpPlanService {
}
// 2. 获取最大联合单位数量
int maxUnionUnit = cpSettingService.getMaxUnionUnit();
int maxUnionUnit = cpSettingService.getMaxAutoMatchUnionUnit();
// 2.1 获取系统匹配预约周数范围
int systemMatchWeeks = cpSettingService.getSystemMatchWeeks();
@ -769,8 +770,8 @@ public class EfcodeCpPlanServiceImpl implements IEfcodeCpPlanService {
LambdaQueryWrapper<EfcodeCpPlan> lqw = Wrappers.lambdaQuery();
lqw.gt(EfcodeCpPlan::getPlanDate, now);
lqw.eq(EfcodeCpPlan::getSystemReserved, 0L);
lqw.eq(EfcodeCpPlan::getManualReserved, 0L);
lqw.eq(EfcodeCpPlan::getReserveStatus, 1L);
//lqw.eq(EfcodeCpPlan::getManualReserved, 0L);
lqw.in(EfcodeCpPlan::getReserveStatus, 1L, 4L, 5L);
lqw.eq(EfcodeCpPlan::getIsPublic, 1L);
lqw.eq(EfcodeCpPlan::getIsUnion, 1L);
lqw.eq(EfcodeCpPlan::getIsDelete, 0L);
@ -785,6 +786,33 @@ public class EfcodeCpPlanServiceImpl implements IEfcodeCpPlanService {
log.info("[CpPlan-V2] 共查询到{}条待匹配计划", pendingPlans.size());
// 预查询所有待匹配计划的手动联合记录,构建互斥关系映射(已手动联合的计划对不应再被放入同一系统组)
Set<String> pendingPlanIdSet = pendingPlans.stream()
.map(EfcodeCpPlan::getId)
.collect(Collectors.toSet());
List<EfcodeCpReserve> allManualReserves = efcodeCpReserveMapper.selectList(
Wrappers.<EfcodeCpReserve>lambdaQuery()
.in(EfcodeCpReserve::getPlanId, pendingPlanIdSet)
.eq(EfcodeCpReserve::getResFrom, 0L)
);
// 按planGroupId分组,找出同组内的计划(即已手动联合过的计划对)
Map<String, Set<String>> manualGroupToPlanIds = allManualReserves.stream()
.filter(r -> StringUtils.isNotBlank(r.getPlanGroupId()))
.collect(Collectors.groupingBy(
EfcodeCpReserve::getPlanGroupId,
Collectors.mapping(EfcodeCpReserve::getPlanId, Collectors.toSet())
));
// 构建每个计划的手动联合伙伴映射: planId -> 已与其手动联合过的其他planId集合
Map<String, Set<String>> manualUnionPeers = new HashMap<>();
for (Set<String> groupPlanIds : manualGroupToPlanIds.values()) {
if (groupPlanIds.size() < 2) continue;
for (String pid : groupPlanIds) {
manualUnionPeers.computeIfAbsent(pid, k -> new HashSet<>()).addAll(groupPlanIds);
}
}
manualUnionPeers.forEach((pid, peers) -> peers.remove(pid));
log.info("[CpPlan-V2] 存在手动联合互斥关系的计划数量: {}", manualUnionPeers.size());
// 存储将要保存的联合记录列表
List<EfcodeCpReserve> unionReserveList = new ArrayList<>();
@ -809,7 +837,10 @@ public class EfcodeCpPlanServiceImpl implements IEfcodeCpPlanService {
LocalDate weekEndDate = weekStartDate.plusWeeks(systemMatchWeeks).minusDays(1); // 扩展N周后的周日
log.info("[CpPlan-V2] 计划ID={}的时间范围是:{} ~ {}", plan.getId(), weekStartDate, weekEndDate);
// 6. 从待匹配计划中筛选:同企业 + 时间范围内 + 不是当前计划创建者发布的 + 未被处理过
// 6. 获取当前计划的手动联合伙伴(与当前计划已手动联合过的计划ID)
Set<String> currentPlanPeers = manualUnionPeers.getOrDefault(plan.getId(), Collections.emptySet());
// 7. 从待匹配计划中筛选:同企业 + 时间范围内 + 不是当前计划创建者发布的 + 未被处理过 + 未与当前计划手动联合过
List<EfcodeCpPlan> matchedPlans = pendingPlans.stream()
.filter(p -> {
// 排除自身
@ -828,19 +859,31 @@ public class EfcodeCpPlanServiceImpl implements IEfcodeCpPlanService {
if (plan.getCreateBy() != null && plan.getCreateBy().equals(p.getCreateBy())) {
return false;
}
// 排除与当前计划已手动联合过的计划
if (currentPlanPeers.contains(p.getId())) {
return false;
}
// 在时间范围内
LocalDate pDate = p.getPlanDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
return !pDate.isBefore(weekStartDate) && !pDate.isAfter(weekEndDate);
})
.collect(Collectors.toList());
log.info("[CpPlan-V2] 计划ID={}, 在时间范围内找到{}条非本人发布的同企业计划", plan.getId(), matchedPlans.size());
log.info("[CpPlan-V2] 计划ID={}, 在时间范围内找到{}条非本人发布的同企业候选计划", plan.getId(), matchedPlans.size());
// 7. 从matchedPlans中取出不超过 maxUnionUnit-1 条记录(当前计划本身占1个名额)
// 8. 从matchedPlans中选取计划,确保同组内不含已手动联合过的计划对
int limit = maxUnionUnit - 1;
List<EfcodeCpPlan> selectedPlans = matchedPlans.stream()
.limit(limit)
.collect(Collectors.toList());
List<EfcodeCpPlan> selectedPlans = new ArrayList<>();
for (EfcodeCpPlan candidate : matchedPlans) {
if (selectedPlans.size() >= limit) break;
// 检查候选计划与已选中计划之间是否存在手动联合互斥关系
Set<String> candidatePeers = manualUnionPeers.getOrDefault(candidate.getId(), Collections.emptySet());
boolean hasConflict = selectedPlans.stream()
.anyMatch(sp -> candidatePeers.contains(sp.getId()));
if (!hasConflict) {
selectedPlans.add(candidate);
}
}
log.info("[CpPlan-V2] 计划ID={}, 最终选取{}条计划参与联合(最大允许{}条)", plan.getId(), selectedPlans.size(), limit);
@ -917,6 +960,40 @@ public class EfcodeCpPlanServiceImpl implements IEfcodeCpPlanService {
return resultMap;
}
/**
* 获取指定计划之前通过手动匹配已联合过的其他计划ID集合
*
* @param planId 当前计划ID
* @return 已手动联合过的计划ID集合,无则返回空集合
*/
private Set<String> getManualUnionPlanIds(String planId) {
// 查询当前plan在efcode_cp_reserve中手动匹配(res_from=0)的记录
List<EfcodeCpReserve> manualReserves = efcodeCpReserveMapper.selectList(
Wrappers.<EfcodeCpReserve>lambdaQuery()
.eq(EfcodeCpReserve::getPlanId, planId)
.eq(EfcodeCpReserve::getResFrom, 0L)
);
if (manualReserves.isEmpty()) {
return Collections.emptySet();
}
Set<String> manualGroupIds = manualReserves.stream()
.map(EfcodeCpReserve::getPlanGroupId)
.filter(StringUtils::isNotBlank)
.collect(Collectors.toSet());
if (manualGroupIds.isEmpty()) {
return Collections.emptySet();
}
// 查询同组中其他计划的planId
List<EfcodeCpReserve> groupedReserves = efcodeCpReserveMapper.selectList(
Wrappers.<EfcodeCpReserve>lambdaQuery()
.in(EfcodeCpReserve::getPlanGroupId, manualGroupIds)
.ne(EfcodeCpReserve::getPlanId, planId)
);
return groupedReserves.stream()
.map(EfcodeCpReserve::getPlanId)
.collect(Collectors.toSet());
}
/**
* 计划自动匹配预约V2(定时任务调用)
* <p>扫描待预约状态的计划,按自然周分组匹配,超出最大联合数量时拆分多组</p>

4
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_mine.vue

@ -92,7 +92,7 @@
</div>
<!-- 展开的预约信息区域 -->
<div v-if="expandedId === item.id && item.reserves && item.reserves.length > 0" class="reserve-section">
<!-- <div v-if="expandedId === item.id && item.reserves && item.reserves.length > 0" class="reserve-section">
<div class="reserve-section-title">关联预约信息</div>
<div
v-for="(rv, ri) in item.reserves"
@ -131,7 +131,7 @@
</div>
<div v-if="expandedId === item.id && (!item.reserves || item.reserves.length === 0)" class="reserve-section">
<div class="reserve-empty">暂无关联预约记录</div>
</div>
</div>-->
<div v-if="item.editEnable !== 0 || item.deleteEnable !== 0" class="card-actions">
<div

Loading…
Cancel
Save