package cn.cslg.pas.service;
import cn.cslg.pas.domain.ProjectField;
import cn.cslg.pas.domain.ProjectFieldOption;
import cn.cslg.pas.domain.ProjectFieldTree;
import cn.cslg.pas.common.utils.Response;
import cn.cslg.pas.mapper.ProjectFieldTreeMapper;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
*
* 自定义字段树类型关联表 服务实现类
*
*
* @author 王岩
* @since 2021-12-17
*/
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class ProjectFieldTreeService extends ServiceImpl {
private final ProjectFieldPatentLinkService projectFieldPatentLinkService;
private final ProjectFieldService projectFieldService;
public Integer getTreeNodeIdByPathNameAndUpdateTreeData(List pathName, ProjectField projectField) {
List treeNode = new ArrayList<>();
for (int i = 0; i < pathName.size(); i++) {
ProjectFieldTree projectFieldTree = this.getProjectFieldTreeOptionByFieldIdAndNameAndLevel(projectField.getId(), (i == 0 ? 0 : treeNode.get(i - 1)), pathName.get(i), i + 1);
if (projectFieldTree == null) {
projectFieldTree = new ProjectFieldTree();
projectFieldTree.setFieldId(projectField.getId());
projectFieldTree.setName(pathName.get(i));
projectFieldTree.setLevel(i + 1);
projectFieldTree.insert();
}
treeNode.add(projectFieldTree.getId());
projectFieldTree.setTreeId(projectFieldTree.getId());
projectFieldTree.setOrder(projectFieldTree.getId());
projectFieldTree.setPath(StringUtils.join(treeNode, "/"));
if (treeNode.size() == 1) {
projectFieldTree.setParentId(0);
} else {
projectFieldTree.setParentId(treeNode.get(i - 1));
}
projectFieldTree.updateById();
}
if (treeNode.size() == 0) {
return 0;
}
return treeNode.get(treeNode.size() - 1);
}
public List getProjectFieldTreeOptionByFieldId(Integer fieldId) {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ProjectFieldTree::getFieldId, fieldId);
queryWrapper.orderByAsc(ProjectFieldTree::getOrder);
return this.list(queryWrapper);
}
public ProjectFieldTree getProjectFieldTreeNodeByFieldIdAndParentIdAndName(Integer fieldId, Integer parentId, String name) {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ProjectFieldTree::getFieldId, fieldId);
queryWrapper.eq(ProjectFieldTree::getParentId, parentId);
queryWrapper.eq(ProjectFieldTree::getName, name);
return this.getOne(queryWrapper);
}
public ProjectFieldTree getProjectFieldTreeOptionByFieldIdAndNameAndLevel(Integer fieldId, Integer parentId, String name, Integer level) {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ProjectFieldTree::getFieldId, fieldId);
queryWrapper.eq(ProjectFieldTree::getName, name);
queryWrapper.eq(ProjectFieldTree::getLevel, level);
queryWrapper.eq(ProjectFieldTree::getParentId, parentId);
return this.getOne(queryWrapper);
}
public ProjectFieldTree getProjectFieldTreeOptionByFieldIdAndNameAndLevel(Integer fieldId, String name, Integer level) {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ProjectFieldTree::getFieldId, fieldId);
queryWrapper.eq(ProjectFieldTree::getName, name);
queryWrapper.eq(ProjectFieldTree::getLevel, level);
return this.getOne(queryWrapper);
}
public List getProjectFieldTreeOptionByFieldIds(List fieldIds) {
if (fieldIds == null || fieldIds.size() == 0) {
return new ArrayList<>();
}
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(ProjectFieldTree::getFieldId, fieldIds);
queryWrapper.orderByAsc(ProjectFieldTree::getOrder);
return this.list(queryWrapper);
}
public List getProjectFieldTreeOptionByIds(List ids) {
if (ids == null || ids.size() == 0) {
return new ArrayList<>();
}
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(ProjectFieldTree::getId, ids);
queryWrapper.orderByAsc(ProjectFieldTree::getOrder);
return this.list(queryWrapper);
}
public List> getProjectFieldTreeNodeByFieldId(Integer fieldId) {
List dataList = this.getProjectFieldTreeOptionByFieldId(fieldId);
for (ProjectFieldTree tree : dataList) {
List tempList = dataList.stream().filter(item -> item.getParentId().equals(tree.getTreeId())).collect(Collectors.toList());
tempList.forEach(item -> item.setParentId(tree.getId()));
}
TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
treeNodeConfig.setWeightKey("order");
List> nodeList = CollUtil.newArrayList();
for (ProjectFieldTree data : dataList) {
nodeList.add(new TreeNode<>(data.getId(), data.getParentId(), data.getName(), data.getOrder()));
}
List> treeNodes = TreeUtil.build(nodeList, 0, treeNodeConfig, (treeNode, tree) -> {
ProjectFieldTree temp = dataList.stream().filter(item -> item.getId().equals(treeNode.getId())).findFirst().orElse(new ProjectFieldTree());
tree.setId(treeNode.getId());
tree.setParentId(treeNode.getParentId());
tree.setWeight(treeNode.getWeight());
tree.setName(treeNode.getName());
tree.putExtra("level", temp.getLevel());
tree.putExtra("path", temp.getPath());
tree.putExtra("fieldId", temp.getFieldId());
});
return treeNodes;
}
public Integer getFieldTreeNodeTotal(Integer fieldId) {
return (int) this.count(Wrappers.lambdaQuery().eq(ProjectFieldTree::getFieldId, fieldId));
}
public Integer getFieldTreeParentId(Integer id) {
ProjectFieldTree tree = this.getById(id);
if (tree != null) {
return tree.getTreeId();
}
return 0;
}
public Integer[] getFieldTreeNodePath(Integer id, Integer parentId) {
ProjectFieldTree parentNode = this.getById(parentId);
String[] nodePath = parentNode.getPath().split("/");
Integer[] nodeIds = new Integer[nodePath.length + 1];
for (int i = 0; i < nodeIds.length - 1; i++) {
nodeIds[i] = Integer.parseInt(nodePath[i]);
}
nodeIds[nodePath.length] = id;
return nodeIds;
}
@Transactional
public Integer add(ProjectFieldTree tree) {
// Integer total = this.getFieldTreeNodeTotal(tree.getFieldId());
tree.setOrder(-1);
tree.insert();
this.edit(tree);
return tree.getId();
}
@Transactional
public void edit(ProjectFieldTree tree) {
Integer[] path = tree.getParentId() == 0 ? new Integer[]{tree.getId()} : this.getFieldTreeNodePath(tree.getId(), tree.getParentId());
tree.setPath(StringUtils.join(path, "/"));
tree.setLevel(path.length);
tree.setParentId(this.getFieldTreeParentId(tree.getParentId()));
tree.setTreeId(tree.getId());
if (tree.getOrder() == -1) {
tree.setOrder(tree.getId());
}
tree.updateById();
}
@Transactional
public void addBatch(List optionList, Integer fieldId) {
this.saveOrUpdateOption(optionList, fieldId, 0);
this.updateNodePath(fieldId);
}
@Transactional
public void editBatch(List optionList, Integer fieldId) {
List tempList = this.getProjectFieldTreeOptionByFieldId(fieldId);
List nodeIds = this.getTreeNodeIds(optionList, new ArrayList<>());
List deleteIds = tempList.stream().map(ProjectFieldTree::getId).filter(id -> !nodeIds.contains(id)).collect(Collectors.toList());
this.deleteByIds(deleteIds);
this.saveOrUpdateOption(optionList, fieldId, 0);
this.updateNodePath(fieldId);
}
private List getTreeNodeIds(List optionList, List ids) {
for (ProjectFieldOption option : optionList) {
if (option.getId() != null) {
ids.add(option.getId());
}
if (option.getChildren() != null && option.getChildren().size() != 0) {
this.getTreeNodeIds(option.getChildren(), ids);
}
}
return ids;
}
private void saveOrUpdateOption(List optionList, Integer fieldId, Integer parentId) {
for (ProjectFieldOption option : optionList) {
option.setParentId(parentId);
option.setFieldId(fieldId);
Integer id = this.saveOption(option);
if (option.getChildren() != null && option.getChildren().size() != 0) {
this.saveOrUpdateOption(option.getChildren(), fieldId, id);
}
}
}
private Integer saveOption(ProjectFieldOption option) {
ProjectFieldTree tree = new ProjectFieldTree();
tree.setId(option.getId());
tree.setName(option.getName());
tree.setFieldId(option.getFieldId());
tree.setOrder(option.getOrder());
tree.setParentId(option.getParentId());
if (tree.getId() == null) {
tree.insert();
}
tree.setTreeId(tree.getId());
tree.updateById();
return tree.getId();
}
private void updateNodePath(Integer fieldId) {
List treeList = this.getProjectFieldTreeOptionByFieldId(fieldId);
treeList.forEach(tree -> {
Integer[] paths = this.findTreeNodePath(tree.getId());
tree.setLevel(paths.length);
tree.setPath(StringUtils.join(paths, "/"));
});
this.saveOrUpdateBatch(treeList);
}
public Integer[] findTreeNodePath(Integer id) {
List paths = new ArrayList<>();
List parentPath = this.findParentPath(id, paths);
Collections.reverse(parentPath);
return parentPath.toArray(new Integer[parentPath.size()]);
}
private List findParentPath(Integer id, List paths) {
paths.add(id);
ProjectFieldTree tree = this.getById(id);
if (tree.getParentId() != 0) {
findParentPath(tree.getParentId(), paths);
}
return paths;
}
public void deleteByFieldId(Integer fieldId) {
this.remove(Wrappers.lambdaQuery().eq(ProjectFieldTree::getFieldId, fieldId));
}
private List findTreeNodes(Integer id, List nodes) {
nodes.add(id);
List treeList = this.list(Wrappers.lambdaQuery().eq(ProjectFieldTree::getParentId, id));
if (treeList != null && treeList.size() != 0) {
treeList.forEach(item -> {
nodes.add(item.getId());
this.findTreeNodes(item.getId(), nodes);
});
}
return nodes;
}
@Transactional
public void delete(Integer id) {
List nodes = this.findTreeNodes(id, new ArrayList<>());
projectFieldPatentLinkService.deleteByOptionIds(nodes);
this.removeByIds(nodes);
}
@Transactional
public void deleteByIds(List ids) {
if (ids != null && ids.size() != 0) {
projectFieldPatentLinkService.deleteByOptionIds(ids);
this.removeByIds(ids);
}
}
@Transactional
public String updateByProjectFieldTreeNode(ProjectFieldOption projectFieldOption) {
ProjectFieldTree temp = this.getProjectFieldTreeNodeByFieldIdAndParentIdAndName(projectFieldOption.getFieldId(), projectFieldOption.getParentId(), projectFieldOption.getName());
if (temp != null && !temp.getId().equals(projectFieldOption.getId())) {
return Response.error("选项名称已存在");
}
ProjectFieldTree projectFieldTree = new ProjectFieldTree();
projectFieldTree.setId(projectFieldOption.getId());
projectFieldTree.setFieldId(projectFieldOption.getFieldId());
projectFieldTree.setOrder(projectFieldOption.getOrder());
projectFieldTree.setParentId(projectFieldOption.getParentId());
projectFieldTree.setName(projectFieldOption.getName());
projectFieldTree.insertOrUpdate();
this.edit(projectFieldTree);
return Response.success(projectFieldTree.getId());
}
}