企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
歌手与歌曲关系是一对多,编辑关系只要在有外键的歌曲的页面进行操作。而歌单与歌曲的关系不同与此,为优化用户的体验,不在歌曲的页面实现,应当在一个新的组件中实现。再结合歌曲的数据分析,可以已歌手作为歌曲的分类信息。最后页面设计的实现可以基于el-tree-fransfer (一个基于 VUE 和 element-ui 的树形穿梭框组件)。效果如图所示: ![image-20210416174733569](https://img.kancloud.cn/c6/0b/c60b423e7434d96fd9972fcf6f4f8c6d_1211x775.png) ## 5.3.1 服务端 (1)基于前台需求封装对象。 1)EL穿梭框树对象父节点,关键代码如下: ```java public class ElNode0Vo implements Serializable { /** * 节点Id */ private String id; /** * 父节点ID */ private Long pid = 0L; /** * 节点文本 */ private String label = ""; /** * 节点是否关闭 */ private Boolean disabled = false; /** * 子节点 */ private List<ElNodeVo> children; } ``` 2)EL穿梭框树对象子节点 ```java public class ElNodeVo implements Serializable { /** * 节点Id */ private String id; /** * 父节点ID */ private String pid; /** * 节点文本 */ private String label = ""; /** * 节点是否关闭 */ private Boolean disabled = false; /** * 子节点 */ private List<ElNodeVo> children; } ``` (2)根据查询到的歌曲查询数据封装为EL穿梭框树对象: ```java private List<ElNode0Vo> toVoList(List<Song> songList) { if (CollectionUtils.isEmpty(songList)) { return null; } ArrayList<ElNode0Vo> elNodeVos = new ArrayList<>(); Map<Long, List<Song>> collect = songList.stream().collect(Collectors.groupingBy(Song::getSingerId)); collect.forEach( (singerId, songs) -> { String pid = "singer" + singerId; ElNode0Vo elNode0Vo = new ElNode0Vo(); elNode0Vo.setId(pid); elNode0Vo.setLabel(iSingerService.getById(singerId).getName()); elNode0Vo.setChildren(songs.stream().map( song -> { ElNodeVo nodeVo = new ElNodeVo(); nodeVo.setId(String.valueOf(song.getId())); nodeVo.setLabel(song.getName()); nodeVo.setPid(pid); return nodeVo; } ).collect(Collectors.toList())); elNodeVos.add(elNode0Vo); } ); return elNodeVos; } ``` (3)根据前端传来的EL穿梭框树对象将数据保存到数据库; ```java List<ElNode0Vo> toData = in.getToData(); if (CollUtil.isNotEmpty(toData)) { ArrayList<ListSongMap> listSongMaps = new ArrayList<>(); toData.forEach( singer -> { List<ElNodeVo> children = singer.getChildren(); children.forEach( song -> { ListSongMap songMap = new ListSongMap(); songMap.setSongId(Long.valueOf(song.getId())); songMap.setSongListId(songListId); listSongMaps.add(songMap); } ); } ); return this.saveBatch(listSongMaps); } ``` ## 5.3.2 后台设计 (1)将编辑页面封装为弹出框 ```vue <el-dialog :title="name" :visible.sync="dialogVisible" width="60%" :before-close="handleClose"> <tree-transfer :title="title" :from_data='fromData' :button_text="button_text" :to_data='toData' :defaultProps="{label:'label'}" @addBtn='add' @removeBtn='remove' :mode='mode' height='540px' filter> </tree-transfer> <span slot="footer" class="dialog-footer"> <el-button @click="resetData">重置</el-button> <el-button type="primary" @click="onsubmit">提交 </el-button> </span> </el-dialog> ```