一、场景图示:
二、业务拆分和编程思路
这里业务主要分为两大部分,一个左边树形结构,另一个是根据左边树形结构展示右侧列表。
左边树形结构:全国是最大的主干,主干下面有主节点,每一个主节点下面分为子节点。
表的设计如下:
这里只需要关注parent_id,主节点的id=子节点的parent_id;
树形结构代码展示:两种方式,一种是一次性加载,另一种是通过主干的id(子节点的父id),查当前节点下的子节点。
一次性加载树形结构:
/*entity*/
@ApiModel(value = "区域架构表")
@Table(name = "sys_sellarea")
@Data
@Accessors(chain = true)
public class SysSellarea extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 销售区域编码
*/
@Column(name = "sellarea_code")
@ApiModelProperty(value = "销售区域编码")
private String sellareaCode;
/**
* 销售区域名称
*/
@Column(name = "sellarea_name")
@ApiModelProperty(value = "销售区域名称")
private String sellareaName;
/**
* 上级ID
*/
@Column(name = "parent_id")
@ApiModelProperty(value = "上级ID")
private String parentId;
@Transient//表示额外新增的属性。是否选中
private boolean hasChecked;
@Transient//表示额外新增的属性。是否有子节点
private boolean hasChildren;
@Transient
private List<SysSellarea> children = new LinkedList<SysSellarea>();
@JsonIgnore
public static List<SysSellarea> sortList(Map<String, SysSellarea> map) {
List<SysSellarea> SysSellareaTree = new ArrayList<>();
map.forEach((id, obj) -> {
if (map.containsKey(obj.getParentId())) {
map.get(obj.getParentId()).getChildren().add(obj);
} else {
SysSellareaTree.add(obj);
}
});
return SysSellareaTree;
}
}
/*controller,这里copy代码时注意修改代码继承关系并加上autowired*/
@Api(tags = "销售区域")
@RestController
@RequestMapping("sysSellarea")
public class SysSellareaController extends BaseSystemController<SysSellareaService,SysSellarea> {
@ApiOperation(value = "查找所有区域")
@GetMapping("/getSysSellarea")
public Result getSysSellarea() {
return ResultGenerator.genSuccessResult(service.getSysSellarea());
}
}
/*service*/
public interface SysSellareaService extends BaseService<SysSellarea> {
List<SysSellarea> getSysSellarea();
}
/*serviceimpl*/
@Service
@Transactional
public class SysSellareaServiceImpl extends BaseServiceImpl<SysSellareaDao, SysSellarea> implements SysSellareaService {
/**
* @return
*/
@Override
public List<SysSellarea> getSysSellarea() {
List<SysSellarea> sysSellareas = null;
try {
Map<String, SysSellarea> sysSellarea = dao.getSysSellarea();
sysSellareas = SysSellarea.sortList(sysSellarea);
} catch (Exception e) {
e.printStackTrace();
}
return sysSellareas;
}
//dao
@Repository
public interface SysSellareaDao extends TKMapper<SysSellarea> {
@MapKey("id")
Map<String, SysSellarea> getSysSellarea();
}
//xml
<select id="getSysSellarea" resultType="com.security.common.entity.system.SysSellarea">
SELECT
<include refid="Sellarea_param"/>,
EXISTS (SELECT id FROM sys_sellarea WHERE parent_id = ssa.id AND del_flag = 0) AS hasChildren
FROM sys_sellarea ssa WHERE ssa.del_flag = 0;
</select>
右侧列表展示,在笔者的业务中。右侧其实也是一个树形结构,但是这里只做列表展示。
表设计:
代码展示及分析:
@RestController
@RequestMapping("/sysChannelInfo")
public class SysChannelInfoController{
@GetMapping("/getChannelInfo")
public Result getChannelInfo(String sellAreaId,
String channelName,
Integer page,
Integer size
) {
return service.getChannel(sellAreaId, channelName, page, size);
}
}
根据当前区域id查下面的所有主节点,再通过主节点id的list带进去查主节点list下的渠道列表
@Service("SysChannelInfoService")
public class SysChannelInfoServiceImpl {
@Override
public Result getChannel(String sellAreaId, String channelName, Integer page, Integer size) {
//查询当前销售区域所有父节点id
List<String> parentList = getParentList(sellAreaId);
//当前节点也存进去
parentList.add(sellAreaId);
page = page == null ? 1 : page;
size = size == null ? 10 : size;
PageHelper.startPage(page, size);
List<SysChannelInfo> list = dao.getChannel(parentList, channelName);
return ResultGenerator.genSuccessResult(RestRes.table(new PageInfo(list)));
}
private List<String> getParentList(String sellAreaId) {
List<SysSellarea> sellareas = sellareaDao.select((SysSellarea) new SysSellarea().setDelFlag(0));
//根据当前节点id查当前对象并获取到当前对象的父id。
SysSellarea sellArea = sellareaService.selectById(sellAreaId);
List<String> parentList = new ArrayList<>();
return findParent(sellareas, sellArea.getParentId(), parentList);
}
private List<String> findParent(List<SysSellarea> sellareas, String parentId, List<String> parentList) {
for (SysSellarea sellArea : sellareas) {
if (parentId.equals(sellArea.getId())) {
parentList.add(sellArea.getId());
//递归获取所有节点的父id并存进list,带到xml中查list下的渠道列表
findParent(sellareas, sellArea.getParentId(), parentList);
}
}
return parentList;
}
}
@Repository
public interface SysChannelInfoDao{
List<SysChannelInfo> getChannel(@Param("sellAreaList") List<String> parentList,
@Param("channelName")String channelName);
}
<!--渠道分页-->
<select id="getChannel" resultType="com.security.common.entity.system.SysChannelInfo">
select
sci.id, sci.channel_name, sci.seq, sci.level, sci.path, sci.status
from sys_channel_info sci
join sys_channel_sellarea scs on sci.id=scs.channel_id
where sci.del_flag=0
and
<if test="sellAreaList !=null and sellAreaList.size>0">
scs.sellarea_id in
<foreach collection="sellAreaList" item="sellAreaId" index="index" open="(" close=")" separator=",">
#{sellAreaId}
</foreach>
</if>
<if test="channelName !=null and channelName!=''">
and sci.channel_name like concat('%',#{channelName},'%')
</if>
</select>