You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
IESExtension/src/main/java/cn/teammodel/service/impl/EvaluationServiceImpl.java

218 lines
7.9 KiB

package cn.teammodel.service.impl;
import cn.hutool.core.lang.UUID;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.common.PK;
import cn.teammodel.config.exception.ServiceException;
import cn.teammodel.dao.EvaluationRepository;
import cn.teammodel.model.dto.DeleteNodeDto;
import cn.teammodel.model.dto.GetEvaluateTreeDto;
import cn.teammodel.model.dto.InsertNodeDto;
import cn.teammodel.model.dto.UpdateNodeDto;
import cn.teammodel.model.entity.appraise.Appraise;
import cn.teammodel.model.entity.appraise.AppraiseTreeNode;
import cn.teammodel.model.entity.User;
import cn.teammodel.security.utils.SecurityUtil;
import cn.teammodel.service.EvaluationService;
import com.azure.spring.data.cosmos.core.CosmosTemplate;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* @author winter
* @create 2023-11-20 17:47
*/
@Service
public class EvaluationServiceImpl implements EvaluationService {
@Resource
CosmosTemplate cosmosTemplate;
@Resource
private EvaluationRepository evaluationRepository;
/**
* evaluation : , <br/>
* token schoolId
*/
private Appraise findAppraise(String periodId) {
// 默认学区为 default
periodId = StringUtils.isEmpty(periodId) ? "default" : periodId;
User loginUser = SecurityUtil.getLoginUser();
String schoolId = loginUser.getSchoolId();
// 拿到要新增节点的原始数据
Appraise appraise = evaluationRepository.findAppraiseBySchoolIdAndPeriodIdAndCode(schoolId, periodId, PK.PK_APPRAISE);
if (appraise == null) {
throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "学校评价数据不存在");
}
return appraise;
}
@Override
public Appraise getTree(GetEvaluateTreeDto getEvaluateTreeDto) {
Appraise appraise = findAppraise(getEvaluateTreeDto.getPeriodId());
return this.buildTree(appraise);
}
@Override
public Appraise buildTree(Appraise appraise) {
if (appraise == null) {
return null;
}
List<AppraiseTreeNode> nodes = appraise.getNodes();
List<AppraiseTreeNode> parents = new ArrayList<>();
// pid 为 null 或者 "" 则为 parents
for (AppraiseTreeNode node : nodes) {
if (StringUtils.isBlank(node.getPid())) {
parents.add(node);
}
}
// 迭代构建孩子节点
for (AppraiseTreeNode parent : parents) {
buildChildren(parent, nodes);
}
appraise.setNodes(parents);
return appraise;
}
@Override
public void flattenTree(List<AppraiseTreeNode> trees, List<AppraiseTreeNode> nodes) {
// 递归结束条件
if (ObjectUtils.isEmpty(trees)) return;
// 这里的每个 tree 都是组装好的树,区别于单个节点
for (AppraiseTreeNode tree : trees) {
// 递归
flattenTree(tree.getChildren(), nodes);
// 回溯时删除 children,添加进列表
tree.setChildren(null);
nodes.add(tree);
}
}
@Override
public Appraise insertNode(InsertNodeDto insertNodeDto) {
Appraise appraise = findAppraise(insertNodeDto.getPeriodId());
User loginUser = SecurityUtil.getLoginUser();
List<AppraiseTreeNode> originNodes = appraise.getNodes();
// 拷贝数据到新节点
AppraiseTreeNode newNode = new AppraiseTreeNode();
BeanUtils.copyProperties(insertNodeDto, newNode);
String newNodePid = newNode.getPid();
// 根节点直接添加
if (StringUtils.isNotEmpty(newNodePid)) {
boolean invalid = originNodes.stream().noneMatch(item -> newNodePid.equals(item.getId()));
if (invalid) {
throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "父节点不存在");
}
}
// todo: 可不可以添加默认值 order ?
newNode.setId(UUID.randomUUID().toString());
newNode.setCreatorId(loginUser.getId());
newNode.setCreator(loginUser.getName());
newNode.setCreateTime(LocalDateTime.now());
originNodes.add(newNode);
return buildTree(evaluationRepository.save(appraise));
}
@Override
public Appraise updateNode(UpdateNodeDto updateNodeDto) {
String updateNodeId = updateNodeDto.getId();
Appraise appraise = findAppraise(updateNodeDto.getPeriodId());
List<AppraiseTreeNode> originNodes = appraise.getNodes();
// 每个节点都有 id, 直接校验是否合法
AppraiseTreeNode updateNode = originNodes.stream()
.filter(item -> updateNodeId.equals(item.getId()))
.findFirst()
.orElseThrow(() -> new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "更新节点不存在"));
// 更新字段,考虑直接 copy properties
updateNode.setName(updateNodeDto.getName());
updateNode.setLogo(updateNodeDto.getLogo());
updateNode.setOrder(updateNodeDto.getOrder());
updateNode.setPraise(updateNodeDto.isPraise());
// todo: 为新节点赋值必须参数 (id, creator), 可不可以添加默认值 order ?
return buildTree(evaluationRepository.save(appraise));
}
@Override
public Appraise deleteNode(DeleteNodeDto deleteNodeDto) {
// 删除指定节点,可能是(一级,二级,三级),设计一个通用的
Appraise appraise = findAppraise(deleteNodeDto.getPeriodId());
List<AppraiseTreeNode> nodes = appraise.getNodes();
List<AppraiseTreeNode> nodesToDelete = new ArrayList<>();
// 迭代器安全删除
for (AppraiseTreeNode node : nodes) {
if (node.getId().equals(deleteNodeDto.getId())) {
// 删除当前节点
nodesToDelete.add(node);
// 递归删除其孩子节点
this.collectNodesToDelete(node.getId(), nodes, nodesToDelete);
}
}
nodes.removeAll(nodesToDelete);
return buildTree(evaluationRepository.save(appraise));
}
/**
* id id ()
*/
private void collectNodesToDelete(String id, List<AppraiseTreeNode> nodes, List<AppraiseTreeNode> nodesToDelete) {
for (AppraiseTreeNode node : nodes) {
if (id.equals(node.getPid())) {
// 收集
nodesToDelete.add(node);
// 递归收集
collectNodesToDelete(node.getId(), nodes, nodesToDelete);
}
}
}
/**
* , (,)
*/
private void buildChildren(AppraiseTreeNode parent, List<AppraiseTreeNode> nodes) {
List<AppraiseTreeNode> children = getChildren(parent, nodes);
if (children.size() == 0) return;
parent.setChildren(children);
for (AppraiseTreeNode child : children) {
// 如果子节点还有孩子的话,就继续递归构建
if (getChildren(child, nodes).size() > 0) {
buildChildren(child, nodes);
}
}
}
/**
*
*/
private List<AppraiseTreeNode> getChildren(AppraiseTreeNode parent, List<AppraiseTreeNode> nodes) {
List<AppraiseTreeNode> children = new ArrayList<>();
for (AppraiseTreeNode node : nodes) {
if (StringUtils.isNotBlank(node.getPid()) && node.getPid().equals(parent.getId())) {
children.add(node);
}
}
return children;
}
}