上一个章节,猿人君教会了你如何去设置广告牌,今天我们一起来学习,如何绑定前后台类目。
功能概览
在三级前台类目列表中,点击管理按钮,设置当前前台三级类目和后台类目的关系。通过勾选左侧后台类目的形式,将选中的三级类目内容放置到右侧的列表中,同时列表提供删除功能,点击保存按钮,完成前台类目和后台类目的关系绑定。
数据库设计
既然是绑定关系,那自然是需要关系表来持久这样的数据。至于为什么要建立这种关系,你可以查看之前的设计文章。
数据展示后端功能实现
在思考后端功能怎样实现时,我们可以先看看功能描述。点击管理后,来完成前后端类目关系设置的操作。你看,又是“设置”类的操作。对于这种操作,自然需要返回需要操作的数据,以及已经建立的关系数据了。
也就是说,我们的后端,需要至少两个数据接口——一个用于返回右侧的类目数据,一个返回已有的前后台类目关系。我们先在MallFnCategoryController中增加代码。
/**
* 返回用于选择的后台类目
* @param queryMallFnBgCategoryRel
* @return
*/
@RequestMapping("/findForSelect")
public Result<List<MallCategoryVo>> findForSelect(@RequestBody QueryMallFnBgCategoryRel queryMallFnBgCategoryRel){
QueryMallCategory queryMallCategory = new QueryMallCategory();
Result<List<MallCategoryVo>> dataResult= mallCategoryService.getMallCategoryVoList(queryMallCategory,null);
return dataResult;
}
/**
* 返回前台类目后台类目关系列表
* @param queryMallFnBgCategoryRel
* @return
*/
@RequestMapping("/findForSelectedTable")
public Result<List<MallFnBgCategoryRel>> findForSelectedTable(@RequestBody QueryMallFnBgCategoryRel queryMallFnBgCategoryRel){
Result<List<MallFnBgCategoryRel>> result= mallFnBgCategoryRelService.getMallFnBgCategoryRelsByQueryWithCateName(queryMallFnBgCategoryRel);
return result;
}
考虑到部分朋友对如何获取树结构数据不太熟悉,这里把service层的代码给到你。
/**
* 获取需要展示的类目
* @param queryMallCategory
* @param exculdeIdlist
* @return
*/
public Result<List<MallCategoryVo>> getMallCategoryVoList(QueryMallCategory queryMallCategory,List<Long> exculdeIdlist) {
Result<List<MallCategoryVo>> result = new Result<List<MallCategoryVo>>();
try {
List<MallCategory> dataList= mallCategoryDao.selectMallCategoryByQuery(queryMallCategory);
//删除需要屏蔽的对象
if(!CollectionUtils.isEmpty(exculdeIdlist)){
dataList.removeIf(a -> {
return exculdeIdlist.stream().anyMatch(b -> {
if (b!= null && b.equals(a.getCategoryId())) {
return true;
} else {
return false;
}
});
});
}
List<MallCategoryVo> voList= new ArrayList<MallCategoryVo>();
result.addDefaultModel(voList);
for(MallCategory category:dataList){
if(category.getLevel()==1){
MallCategoryVo vo = new MallCategoryVo();
vo.setCategoryId(category.getCategoryId());
vo.setCategoryName(category.getCategoryName());
vo.setLevel(category.getLevel());
voList.add(vo);
setChildren(dataList,vo);
}
}
} catch(Exception e) {
result.setSuccess(false);
}
return result;
}
/**
* 递归设置子节点
* @param dataList
* @param mallCategoryVo
*/
private void setChildren(List<MallCategory> dataList,MallCategoryVo mallCategoryVo){
for(MallCategory category:dataList){
if(mallCategoryVo.getCategoryId().equals(category.getParentId())){
MallCategoryVo child = new MallCategoryVo();
child.setCategoryId(category.getCategoryId());
child.setCategoryName(category.getCategoryName());
child.setLevel(category.getLevel());
mallCategoryVo.getChildren().add(child);
setChildren(dataList,child);
}
}
}
数据展示前端功能实现
后端的数据有了,那么接下来就是前端数据展示的实现了。像这样的前端界面,我们其实在类目属性绑定的功能中也遇到过。这里帮你复习下。
同样的,我们使用el-tree组件来展示后台类目数据。
使用el-table组件,实现动态表单的功能。
前端数据初始化
页面已经有了,我们一起来看看数据初始化的问题。
我们需要调用后端接口,初始化类目和动态表单的数据,以完成数据内容的填充。
后台类目数据选择
由于当前的前台类目,可能出现已经绑定的后台类目,那么在实现时,需要过滤已经设置过的数据。
updateKeyChildren(data, key1, key2) {
const checkedNodes = this.$refs.tree.getCheckedNodes()
if (checkedNodes != null && checkedNodes.length > 0) {
for (let i = 0; i < checkedNodes.length; i++) {
this.atteibute = {
id: undefined,
fnCategoryId: this.fnCategoryId,
categoryId: checkedNodes[i].categoryId,
categoryName: checkedNodes[i].categoryName,
fnCategoryName: this.fnCategoryName,
status: 1,
checked: true
}
const checkedNode = checkedNodes[i]
if (checkedNode.categoryId !== null && checkedNode.level === 3) {
let flag = true
for (let j = 0; j < this.tableList.length; j++) {
if (this.tableList[j].categoryId === checkedNode.categoryId) {
console.log(checkedNode)
flag = false
}
}
if (flag) {
if (checkedNode.checked) {
this.atteibute.mainCategory = 1
} else {
this.atteibute.mainCategory = 0
}
this.tableList.push(this.atteibute)
}
}
}
}
}
那有些内容,并不是想要的,需要删除怎么办啊?提供一个删除功能就好了。
handleDelete(index, row) {
this.tableList.splice(index, 1)
}
前端保存按钮功能实现
API的封装?你已经封装过很多次api了,这次你自己好好实现一把吧。
后端保存数据
增加一个后端数据接口,用于保存前后台类目的绑定关系就可以了。
/**
* 批量新增前后台类目关系
* @param mallFnBgCategoryRelList
* @return
*/
@RequestMapping("/addMallFnBgCategoryRelBatch")
public Result<List<MallFnBgCategoryRel>> addMallCategoryPropertyValueBatch(@RequestBody List<MallFnBgCategoryRel> mallFnBgCategoryRelList){
try{
return mallFnBgCategoryRelService.addMallFnBgCategoryRelBatch(mallFnBgCategoryRelList);
}catch(Exception e){
e.printStackTrace();
return new Result(false);
}
}
@Override
public Result<List<MallFnBgCategoryRel>> addMallFnBgCategoryRelBatch(List<MallFnBgCategoryRel> mallFnBgCategoryRelList) {
Result<List<MallFnBgCategoryRel>> result = new Result<List<MallFnBgCategoryRel>>();
try {
QueryMallFnBgCategoryRel query = new QueryMallFnBgCategoryRel();
query.setFnCategoryId(mallFnBgCategoryRelList.get(0).getFnCategoryId());
List<MallFnBgCategoryRel> dbList = mallFnBgCategoryRelDao.selectMallFnBgCategoryRelByQuery(query);
//有即新增无则删除
for(MallFnBgCategoryRel newRel:mallFnBgCategoryRelList){
if(null==newRel.getId()){
mallFnBgCategoryRelDao.insertMallFnBgCategoryRelModified(newRel);
continue;
}
for(MallFnBgCategoryRel dbRel:dbList){
if(newRel.getId().equals(dbRel.getId())){
mallFnBgCategoryRelDao.updateMallFnBgCategoryRelByIdModified(dbRel);
continue;
}
}
}
//删除列表中没有的记录
for(MallFnBgCategoryRel dbRel: dbList){
boolean flag=true;
for(MallFnBgCategoryRel newRel:mallFnBgCategoryRelList){
if(newRel.getId().equals(dbRel.getId())){
flag=false;
}
if(flag){
dbRel.setStatus(-1);
mallFnBgCategoryRelDao.updateMallFnBgCategoryRelByIdModified(dbRel);
}
}
}
result.addDefaultModel(mallFnBgCategoryRelList);
}catch(Exception e) {
result.setSuccess(false);
}
return result;
}