yxk-20260729

改善提案
投票/打分页面逻辑优化
This commit is contained in:
ye1023
2026-07-29 10:39:00 +08:00
parent 0a04d98c72
commit 8751c8e86b
3 changed files with 78 additions and 8 deletions
@@ -225,6 +225,12 @@ public class ImprovementProposalController {
return handleBpmAction(() -> improvementProposalService.castInstituteVote(action, currentUser())); return handleBpmAction(() -> improvementProposalService.castInstituteVote(action, currentUser()));
} }
@PostMapping(value = "/bpm/submitInstituteVote")
@Operation(summary = "锁定所级评委投票并汇总结果")
public Result<String> submitInstituteVote(@RequestBody ImprovementProposalBpmActionDTO action) {
return handleBpmAction(() -> improvementProposalService.submitInstituteVote(action, currentUser()));
}
private LoginUser currentUser() { private LoginUser currentUser() {
return (LoginUser) SecurityUtils.getSubject().getPrincipal(); return (LoginUser) SecurityUtils.getSubject().getPrincipal();
} }
@@ -88,6 +88,9 @@ public interface IImprovementProposalService extends IService<ImprovementProposa
/** 记录当前所级评委的投票结果。 */ /** 记录当前所级评委的投票结果。 */
void castInstituteVote(ImprovementProposalBpmActionDTO action, LoginUser loginUser); void castInstituteVote(ImprovementProposalBpmActionDTO action, LoginUser loginUser);
/** 锁定当前所级评委的投票并在全员完成后汇总投票结果。 */
void submitInstituteVote(ImprovementProposalBpmActionDTO action, LoginUser loginUser);
/** /**
* 获取指定年度最新提案编号中的XXXX部分 * 获取指定年度最新提案编号中的XXXX部分
* *
@@ -250,6 +250,8 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
newScore.setScorerId(loginUser.getId()); newScore.setScorerId(loginUser.getId());
newScore.setScorerName(loginUser.getRealname()); newScore.setScorerName(loginUser.getRealname());
fillDeptScoreDraft(newScore, scoreAction, effectScore, totalScore); fillDeptScoreDraft(newScore, scoreAction, effectScore, totalScore);
// 草稿阶段记录最近保存时间,供评委在当前节点实时查看。
newScore.setScoreTime(new Date());
improvementDeptScoreMapper.insert(newScore); improvementDeptScoreMapper.insert(newScore);
} else { } else {
// 草稿保存只能更新 pending 记录,避免流程已提交后通过接口修改最终评分。 // 草稿保存只能更新 pending 记录,避免流程已提交后通过接口修改最终评分。
@@ -268,7 +270,7 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
.set(ImprovementDeptScore::getTotalScore, totalScore) .set(ImprovementDeptScore::getTotalScore, totalScore)
.set(ImprovementDeptScore::getScoreOpinion, scoreAction.getScoreOpinion()) .set(ImprovementDeptScore::getScoreOpinion, scoreAction.getScoreOpinion())
.set(ImprovementDeptScore::getScoreStatus, "pending") .set(ImprovementDeptScore::getScoreStatus, "pending")
.set(ImprovementDeptScore::getScoreTime, null)); .set(ImprovementDeptScore::getScoreTime, new Date()));
if (updated != 1) { if (updated != 1) {
throw new IllegalStateException("评分状态已变化,请刷新后重试"); throw new IllegalStateException("评分状态已变化,请刷新后重试");
} }
@@ -414,17 +416,37 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
throw new IllegalStateException("投票结果只能是同意或不同意"); throw new IllegalStateException("投票结果只能是同意或不同意");
} }
ImprovementProposal proposal = validateRunningTask(action, loginUser, TASK_INSTITUTE_VOTE); ImprovementProposal proposal = validateRunningTask(action, loginUser, TASK_INSTITUTE_VOTE);
ImprovementInstituteVote vote = improvementInstituteVoteMapper.selectByMainId(proposal.getId()).stream() ImprovementInstituteVote vote = findInstituteVote(proposal.getId(), loginUser.getId());
.filter(item -> loginUser.getId().equals(item.getVoterId()))
.findFirst()
.orElseThrow(() -> new IllegalStateException("当前用户不在所级评议投票名单中"));
if ("voted".equals(vote.getVoteStatus())) { if ("voted".equals(vote.getVoteStatus())) {
throw new IllegalStateException("您已完成投票,不能重复修改"); throw new IllegalStateException("投票已锁定,请重新提交流程办理");
} }
int updated = improvementInstituteVoteMapper.update(null, new LambdaUpdateWrapper<ImprovementInstituteVote>() int updated = improvementInstituteVoteMapper.update(null, new LambdaUpdateWrapper<ImprovementInstituteVote>()
.eq(ImprovementInstituteVote::getId, vote.getId()) .eq(ImprovementInstituteVote::getId, vote.getId())
.eq(ImprovementInstituteVote::getVoteStatus, "pending") .eq(ImprovementInstituteVote::getVoteStatus, "pending")
.set(ImprovementInstituteVote::getVoteResult, action.getVoteResult()) .set(ImprovementInstituteVote::getVoteResult, action.getVoteResult())
.set(ImprovementInstituteVote::getVoteTime, null)
.set(ImprovementInstituteVote::getProcessTaskId, action.getTaskId()));
if (updated != 1) {
throw new IllegalStateException("投票状态已变化,请刷新后重试");
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void submitInstituteVote(ImprovementProposalBpmActionDTO action, LoginUser loginUser) {
ImprovementProposal proposal = validateRunningTask(action, loginUser, TASK_INSTITUTE_VOTE);
ImprovementProposal lockedProposal = improvementProposalMapper.selectByIdForUpdate(proposal.getId());
if (lockedProposal == null || !action.getProcessInstanceId().equals(lockedProposal.getProcessInstanceId())) {
throw new IllegalStateException("提案流程状态已变化,请刷新后重试");
}
ImprovementInstituteVote vote = findInstituteVote(lockedProposal.getId(), loginUser.getId());
if (!"voted".equals(vote.getVoteStatus())) {
if (!"agree".equals(vote.getVoteResult()) && !"disagree".equals(vote.getVoteResult())) {
throw new IllegalStateException("请先选择投票通过或投票反对");
}
int updated = improvementInstituteVoteMapper.update(null, new LambdaUpdateWrapper<ImprovementInstituteVote>()
.eq(ImprovementInstituteVote::getId, vote.getId())
.eq(ImprovementInstituteVote::getVoteStatus, "pending")
.set(ImprovementInstituteVote::getVoteStatus, "voted") .set(ImprovementInstituteVote::getVoteStatus, "voted")
.set(ImprovementInstituteVote::getVoteTime, new Date()) .set(ImprovementInstituteVote::getVoteTime, new Date())
.set(ImprovementInstituteVote::getProcessTaskId, action.getTaskId())); .set(ImprovementInstituteVote::getProcessTaskId, action.getTaskId()));
@@ -432,6 +454,45 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
throw new IllegalStateException("投票状态已变化,请刷新后重试"); throw new IllegalStateException("投票状态已变化,请刷新后重试");
} }
} }
updateInstituteVoteSummaryIfComplete(lockedProposal, action.getProcessInstanceId());
}
private ImprovementInstituteVote findInstituteVote(String mainId, String voterId) {
return improvementInstituteVoteMapper.selectByMainId(mainId).stream()
.filter(item -> voterId.equals(item.getVoterId()))
.findFirst()
.orElseThrow(() -> new IllegalStateException("当前用户不在所级评议投票名单中"));
}
/**
* 所级评议以名单确定时写入的应投票人数为分母。赞成票满足 agree * 3 >= total * 2 即通过,避免小数取整歧义。
*/
private void updateInstituteVoteSummaryIfComplete(ImprovementProposal proposal, String processInstanceId) {
Integer totalVoters = proposal.getInstituteTotalVoters();
if (totalVoters == null || totalVoters <= 0) {
throw new IllegalStateException("所级评议应投票人数未初始化");
}
List<ImprovementInstituteVote> votes = improvementInstituteVoteMapper.selectByMainId(proposal.getId());
if (votes.size() != totalVoters) {
throw new IllegalStateException("所级评议投票名单与应投票人数不一致");
}
if (votes.stream().anyMatch(item -> !"voted".equals(item.getVoteStatus()))) {
return;
}
long agreeCount = votes.stream().filter(item -> "agree".equals(item.getVoteResult())).count();
long disagreeCount = votes.stream().filter(item -> "disagree".equals(item.getVoteResult())).count();
if (agreeCount + disagreeCount != totalVoters) {
throw new IllegalStateException("所级评议投票结果不完整");
}
String voteResult = agreeCount * 3 >= (long) totalVoters * 2 ? "passed" : "failed";
ImprovementProposal update = new ImprovementProposal();
update.setId(proposal.getId());
update.setInstituteAgreeCount((int) agreeCount);
update.setInstituteDisagreeCount((int) disagreeCount);
update.setInstituteVoteResult(voteResult);
improvementProposalMapper.updateById(update);
runtimeService.setVariable(processInstanceId, "institute_vote_result", voteResult);
}
/** /**
* 固定按角色编码读取名单,保存时再次查询以防前端伪造用户 ID 或角色配置已变更。 * 固定按角色编码读取名单,保存时再次查询以防前端伪造用户 ID 或角色配置已变更。