完成标签维护功能
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package com.adc.da.report.constant;
|
||||
|
||||
/**
|
||||
* @author Caihaohan
|
||||
*/
|
||||
public class TreeLabelConstants {
|
||||
|
||||
public static final Integer DELETED = 1;
|
||||
|
||||
public static final Integer UNDELETE = 0;
|
||||
|
||||
public static final String ROOT_TAG_PARENT_ID = "0";
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
package com.adc.da.report.controller;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.adc.da.report.eo.TreeLabelEntity;
|
||||
import com.adc.da.report.service.ITreeLabelService;
|
||||
import com.adc.da.report.vo.TreeLabelVo;
|
||||
import com.adc.da.util.http.ResponseMessage;
|
||||
import com.adc.da.util.http.Result;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.subject.ExecutionException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Caihaohan
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@Api(tags = "树型标签管理")
|
||||
@RequestMapping("/${restPath}/tree-label")
|
||||
public class TreeLabelManagerController {
|
||||
|
||||
@Resource
|
||||
private ITreeLabelService iTreeLabelService;
|
||||
|
||||
|
||||
/**
|
||||
* 新增或编辑标签
|
||||
*
|
||||
* @param treeLabelVo
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation("新增或编辑标签")
|
||||
@PostMapping("/add")
|
||||
public ResponseMessage add(@Valid @RequestBody TreeLabelVo treeLabelVo) {
|
||||
TreeLabelEntity treeLabelEntity = Convert.convert(TreeLabelEntity.class, treeLabelVo);
|
||||
iTreeLabelService.saveOrUpdateTag(treeLabelEntity);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 标签列表
|
||||
*
|
||||
* @return
|
||||
* @throws ExecutionException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@ApiOperation("标签列表")
|
||||
@GetMapping("/list")
|
||||
public ResponseMessage list(@RequestParam(value = "like", required = false) String like
|
||||
) throws ExecutionException, InterruptedException {
|
||||
List<TreeLabelVo> rootLabel = iTreeLabelService.getTreeLabellist(like);
|
||||
return Result.success(rootLabel);
|
||||
}
|
||||
|
||||
@ApiOperation("标签删除|单个")
|
||||
@PostMapping("/delete/{id}")
|
||||
public ResponseMessage delete(@PathVariable("id") String id) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
String status = "0";
|
||||
boolean isDelete = iTreeLabelService.deleteById(id);
|
||||
if (!isDelete) {
|
||||
status = "1";
|
||||
}
|
||||
map.put("status", status);
|
||||
return Result.success(map);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.adc.da.report.dao.mysql;
|
||||
|
||||
import com.adc.da.report.eo.TreeLabelEntity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author ThinkBook
|
||||
* @description 针对表【ts_tree_label】的数据库操作Mapper
|
||||
* @createDate 2023-04-18 10:18:44
|
||||
* @Entity com.adc.da.report.eo.TreeLabelEntity
|
||||
*/
|
||||
public interface TreeLabelDao extends BaseMapper<TreeLabelEntity> {
|
||||
|
||||
/**
|
||||
* 获取当前层级标签中最大的orderNum
|
||||
* @param parentId
|
||||
* @return
|
||||
*/
|
||||
int getMaxNum(String parentId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.adc.da.report.eo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Caihaohan
|
||||
* @TableName ts_tree_label
|
||||
*/
|
||||
@TableName(value ="ts_tree_label")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TreeLabelEntity implements Serializable {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableId(value = "id",type = IdType.INPUT)
|
||||
private String id;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private String parentId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private String createDate;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Integer orderNum;
|
||||
|
||||
/**
|
||||
* 0代表未删除,1代表已删除
|
||||
*/
|
||||
private Integer delFlag;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.adc.da.report.service;
|
||||
|
||||
import com.adc.da.report.eo.TreeLabelEntity;
|
||||
import com.adc.da.report.vo.TreeLabelVo;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ThinkBook
|
||||
* @description 针对表【ts_tree_label】的数据库操作Service
|
||||
* @createDate 2023-04-18 10:18:44
|
||||
*/
|
||||
public interface ITreeLabelService extends IService<TreeLabelEntity> {
|
||||
|
||||
/**
|
||||
* 返回树形结构
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<TreeLabelVo> getTreeLabellist(String like);
|
||||
|
||||
|
||||
/**
|
||||
* 插入或更新标签
|
||||
* @param treeLabelEntity
|
||||
*/
|
||||
void saveOrUpdateTag(TreeLabelEntity treeLabelEntity);
|
||||
|
||||
/**
|
||||
* 自动维护顺序的删除标签方法
|
||||
*/
|
||||
boolean deleteByIdAutoOrder(String id);
|
||||
|
||||
/**
|
||||
* 删除标签
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
boolean deleteById(String id);
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
package com.adc.da.report.service.impl;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.adc.da.report.constant.TreeLabelConstants;
|
||||
import com.adc.da.report.vo.TreeLabelVo;
|
||||
import com.adc.da.util.exception.AdcDaBaseException;
|
||||
import com.adc.da.util.utils.StringUtils;
|
||||
import com.adc.da.util.utils.UUID;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.adc.da.report.eo.TreeLabelEntity;
|
||||
import com.adc.da.report.service.ITreeLabelService;
|
||||
import com.adc.da.report.dao.mysql.TreeLabelDao;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author ThinkBook
|
||||
* @description 针对表【ts_tree_label】的数据库操作Service实现
|
||||
* @createDate 2023-04-18 10:18:44
|
||||
*/
|
||||
@Service
|
||||
public class ITreeLabelServiceImpl extends ServiceImpl<TreeLabelDao, TreeLabelEntity>
|
||||
implements ITreeLabelService {
|
||||
|
||||
@Resource
|
||||
private TreeLabelDao treeLabelDao;
|
||||
|
||||
|
||||
@Override
|
||||
public List<TreeLabelVo> getTreeLabellist(String like) {
|
||||
//查询所有未删除的标签
|
||||
LambdaQueryWrapper<TreeLabelEntity> treeLabelEntityWrapper = new LambdaQueryWrapper<>();
|
||||
treeLabelEntityWrapper.eq(TreeLabelEntity::getDelFlag, TreeLabelConstants.UNDELETE);
|
||||
List<TreeLabelEntity> treeLabelEntities = treeLabelDao.selectList(treeLabelEntityWrapper);
|
||||
//找出根节点
|
||||
TreeLabelEntity rootTag = treeLabelEntities.stream().
|
||||
filter(treeLabelEntity ->
|
||||
TreeLabelConstants.ROOT_TAG_PARENT_ID.equals(treeLabelEntity.getParentId()))
|
||||
.collect(Collectors.toList()).get(0);
|
||||
List<TreeLabelVo> treeLabelVos = Convert.toList(TreeLabelVo.class, treeLabelEntities);
|
||||
|
||||
//分组排序
|
||||
Map<String, List<TreeLabelVo>> groupedLabelVos = treeLabelVos.stream()
|
||||
.collect(Collectors.groupingBy(TreeLabelVo::getParentId));
|
||||
//排序
|
||||
Map<String, List<TreeLabelVo>> sortedGroupedLabelVos = groupedLabelVos.entrySet().stream()
|
||||
.map(entry -> {
|
||||
List<TreeLabelVo> sortedList = entry.getValue();
|
||||
sortedList.sort(Comparator.comparing(TreeLabelVo::getOrderNum));
|
||||
return new AbstractMap.SimpleEntry<>(entry.getKey(), sortedList);
|
||||
})
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
//合并
|
||||
List<TreeLabelVo> labelVoList = sortedGroupedLabelVos.values().stream()
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//组装成树形结构
|
||||
List<TreeLabelVo> tree = createTree(rootTag.getParentId(), labelVoList);
|
||||
//模糊查询
|
||||
if (StringUtils.isNoneBlank(like)) {
|
||||
TreeLabelVo treeLabelVo = filterByName(tree.get(0), like);
|
||||
if (Objects.nonNull(treeLabelVo)) {
|
||||
return Collections.singletonList(treeLabelVo);
|
||||
}
|
||||
return Collections.singletonList(Convert.convert(TreeLabelVo.class, rootTag));
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveOrUpdateTag(TreeLabelEntity entity) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
//不能和根节点的父ID相同
|
||||
if (TreeLabelConstants.ROOT_TAG_PARENT_ID.equals(entity.getParentId())) {
|
||||
throw new AdcDaBaseException("不能和根节点的上级标签相同");
|
||||
}
|
||||
int count = treeLabelDao.selectCount(new QueryWrapper<TreeLabelEntity>()
|
||||
.eq("id", entity.getParentId()));
|
||||
if (count == 0) {
|
||||
throw new AdcDaBaseException("上级标签不存在");
|
||||
}
|
||||
|
||||
//新增标签
|
||||
if (StringUtils.isEmpty(entity.getId())) {
|
||||
entity.setId(UUID.randomUUID10());
|
||||
entity.setCreateDate(format.format(new Date()));
|
||||
treeLabelDao.insert(entity);
|
||||
} else {
|
||||
//编辑标签
|
||||
treeLabelDao.updateById(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteByIdAutoOrder(String id) {
|
||||
TreeLabelEntity labelEntity = treeLabelDao.selectById(id);
|
||||
String parentId = labelEntity.getParentId();
|
||||
int currentNum = labelEntity.getOrderNum();
|
||||
int maxNum = treeLabelDao.getMaxNum(parentId);
|
||||
//删除标签
|
||||
treeLabelDao.delete(new QueryWrapper<TreeLabelEntity>().eq("id", id));
|
||||
//如果删除的不是最后一个标签,需要移动前面的标签
|
||||
if (currentNum != maxNum) {
|
||||
LambdaQueryWrapper<TreeLabelEntity> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.gt(TreeLabelEntity::getOrderNum, currentNum)
|
||||
.le(TreeLabelEntity::getOrderNum, maxNum)
|
||||
.eq(TreeLabelEntity::getParentId, parentId);
|
||||
List<TreeLabelEntity> labelList = treeLabelDao.selectList(wrapper);
|
||||
for (TreeLabelEntity entity : labelList) {
|
||||
entity.setOrderNum(entity.getOrderNum() - 1);
|
||||
treeLabelDao.updateById(entity);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteById(String id) {
|
||||
int i = treeLabelDao.deleteById(id);
|
||||
return i != 0;
|
||||
}
|
||||
|
||||
private List<TreeLabelVo> createTree(String rootParentId, List<TreeLabelVo> treeLabelVos) {
|
||||
List<TreeLabelVo> tree = new ArrayList<>();
|
||||
for (TreeLabelVo label : treeLabelVos) {
|
||||
if (label.getParentId().equals(rootParentId)) {
|
||||
label.setChildLabel(createTree(label.getId(), treeLabelVos));
|
||||
tree.add(label);
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
public static TreeLabelVo filterByName(TreeLabelVo root, String name) {
|
||||
TreeLabelVo newRoot = new TreeLabelVo();
|
||||
newRoot.setId(root.getId());
|
||||
newRoot.setName(root.getName());
|
||||
newRoot.setParentId(root.getParentId());
|
||||
newRoot.setOrderNum(root.getOrderNum());
|
||||
List<TreeLabelVo> childLabel = new ArrayList<>();
|
||||
if (root.getChildLabel() != null) {
|
||||
for (TreeLabelVo child : root.getChildLabel()) {
|
||||
TreeLabelVo newChild = filterByName(child, name);
|
||||
if (newChild != null) {
|
||||
childLabel.add(newChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
newRoot.setChildLabel(childLabel.isEmpty() ? null : childLabel);
|
||||
return root.getName().contains(name) || !childLabel.isEmpty() ? newRoot : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.adc.da.report.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ThinkBook
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class TreeLabelVo {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 标签名称
|
||||
*/
|
||||
@NotBlank(message = "名称不能为空")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 父id
|
||||
*/
|
||||
private String parentId;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Integer orderNum;
|
||||
|
||||
/**
|
||||
* 子标签
|
||||
*/
|
||||
private List<TreeLabelVo> childLabel;
|
||||
|
||||
public TreeLabelVo(String parentId) {
|
||||
this.parentId = parentId;
|
||||
this.childLabel = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.adc.da.report.dao.mysql.TreeLabelDao">
|
||||
|
||||
<resultMap id="BaseResultMap" type="com.adc.da.report.eo.TreeLabelEntity">
|
||||
<id property="id" column="id" jdbcType="VARCHAR"/>
|
||||
<result property="name" column="name" jdbcType="VARCHAR"/>
|
||||
<result property="parentid" column="parentId" jdbcType="VARCHAR"/>
|
||||
<result property="createdate" column="createDate" jdbcType="TIMESTAMP"/>
|
||||
<result property="ordernum" column="orderNum" jdbcType="INTEGER"/>
|
||||
<result property="delFlag" column="del_flag" jdbcType="TINYINT"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="getMaxNum" parameterType="string" resultType="int">
|
||||
select max(t.orderNum)
|
||||
from TS_TREE_LABEL t
|
||||
where parentid = #{parentId}
|
||||
</select>
|
||||
</mapper>
|
||||
Binary file not shown.
Reference in New Issue
Block a user