本次添加了鼠标移动到歌曲列表时相应位置出现播放键、添加进播放列表键、下载键、添加到歌单键,还实现了简单的评论功能,由于主要功能不是评论,所以没有写回复功能,后面也可以添加这个功能,毕竟博客系统写过。

成果展示:

先展示鼠标指到歌曲列表时出现四个键:

这里我们的鼠标指向的是第一个,因为这个截图原因所以没有出现鼠标,可以看到我们歌曲列表出现了四个键,其中第一个是播放和第二个添加播放列表我们还没实现,所以先展示第三个按钮,点击下载 :

可以看到我们直接进行了下载,这个实现原理简单,之后进行讲解,再来展示点击添加进歌单,只能添加进自己创建的歌单,我们此用户只有一个自创歌单-周氏中国风,所以只会出现一个选择:

由于是在同一歌单下,所以添加就不展示了,是可以成功的,接下来展示评论模块,我们评论在设计表的时候就已经将评论目标分为了三个部分,分别为1、歌单 2、专辑 3、歌曲,其中前两个已经实现,第三个是要与播放页面一起放的,所以暂时先不写,先展示某个歌单的评论,我们就点击当前歌单评论进行查看:

之所以没设置返回键,是因为我新开了一个窗口进行评论,想回去直接点击导航栏就行,这点是参考酷狗音乐设计的,也可以自己发表评论,我这里已经提前发表了评论就不进行展示,专辑评论也是同一个界面,只是对应的类型ID不同,搜索出的结果会不相同,都是相同原理就不展示了。

原理解释:

四个键是根据tr的hover属性进行display:none与display:block进行切换的,默认display为none,当鼠标指向tr时触发hover,同时设置display为block,点击+号也是通过触发display切换,关键代码:

四个键html代码:

<div class="td-hover"><a><i class="bi bi-play-circle"></i></a><a><i class="bi bi-plus"></i></a><a th:href="@{${song.getSong_mp3Url()}}" th:download="${song.getSong_name()}+'.mp3'"><i class="bi bi-download"></i></a><a th:onclick="|addSongInSheet(${songStat.index+1})|" style="position: relative;"><i class="bi bi-plus-circle"></i><div th:id="addSongInSheet+${songStat.index+1}" style="width:120px;height: 200px;font-size:10px;position:absolute;top:-50px;left:20px;background-color: rgb(235,235,235);padding: 5px;border-radius: 3%;border: 1px rgb(211,211,211) solid;display: none;overflow-x: scroll;"><table><tr th:each="sheet:${mySheetList}"><td><a th:href="@{/sheet/addSongInSheet2(songlist_sheetId=${sheet.getSheet_id()},songlist_songId=${song.getSong_id()})}" th:text="${sheet.getSheet_name()}"></a></td></tr></table></div></a>
</div>

js代码:

function addSongInSheet(index) {var div = document.getElementById("addSongInSheet"+index);if(div.style.display == "none"){div.style.display = "block";}else if(div.style.display == "block"){div.style.display = "none";}}

css代码:

.td-hover{display: none;
}
.tr-hover tr:nth-child(odd):hover .td-hover{display: block;
}
.tr-hover tr:nth-child(even):hover .td-hover{display: block;
}

后端代码:

/*** 前台将歌曲与歌单建立映射关系* @param songlist_sheetId 歌单ID* @param songlist_songId 歌曲ID* @return*/@GetMapping(path = "addSongInSheet2")public String addSongInSheet2(@Param("songlist_sheetId")Integer songlist_sheetId,@Param("songlist_songId")Integer songlist_songId,HttpServletRequest req) {HttpSession session = req.getSession();User user = (User) session.getAttribute("LoginUser");if(!sheetService.addSheetAndSong(songlist_sheetId,songlist_songId)){System.out.println("添加歌曲歌单关联失败");}return "redirect:myMusic?sheet_userId="+user.getUser_id()+"&sheet_id="+songlist_sheetId;}/*** 前台将歌单与歌曲解除映射关系* @param songlist_sheetId 歌单ID* @param songlist_songId 歌曲ID* @return 页面地址*/@GetMapping(path = "delSongInSheet2")public String delSongInSheet2(@Param("songlist_sheetId")Integer songlist_sheetId,@Param("songlist_songId")Integer songlist_songId,HttpServletRequest req) {HttpSession session = req.getSession();User user = (User) session.getAttribute("LoginUser");if(!sheetService.delSheetAndSong(songlist_sheetId,songlist_songId)){System.out.println("删除歌曲歌单关联失败");}return "redirect:myMusic?sheet_userId="+user.getUser_id()+"&sheet_id="+songlist_sheetId;}

然后是评论模块,先展示HTML代码:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"xmlns:sec="http://www.thymeleaf.org/extras/spring-security"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head><title>评论</title><div th:replace="~{reception/common/common::cjbar}"/><script type="text/javascript" src="/js/onload.js"></script>
</head><body id="top">
<div th:replace="~{reception/common/common::topbar}"/>
<div th:replace="~{reception/common/common::topbar2}"/>
<div class="middle-width"><div style="width: 100%;padding-left: 50px;padding-right: 50px;"><div style="height: 50px;"></div><form method="post" th:action="@{/comment/addComment(comment_targetId=${comment_targetId},comment_type=${comment_type})}"><textarea style="resize: none;" name="comment_text" cols="155" rows="5" placeholder="发表评论:"></textarea><br><input type="submit" class="btn btn-primary btn-color btn-size" value="发表"></form><p style="font-size: 25px;font-family: '黑体'" th:text="'精彩评论('+${commentList.size()}+')'"></p><div th:each="comment:${commentList}" style="border-top: 1px rgb(211,211,211) solid;"><table style="margin-top: 20px;margin-bottom: 20px;"><tr><td style="width: 5%;" rowspan="2"><img style="width: 50px;height: 50px;border-radius: 50%;" th:src="${comment.getComment_userImg()}"></td><td style="width: 95%;color: rgb(211,211,211);" th:text="${comment.getComment_nickName()}"></td></tr><tr><td style="color: rgb(211,211,211);" th:text="${comment.getComment_time()}"></td></tr><tr><td></td><td th:text="${comment.getComment_text()}"></td></tr></table></div></div>
</div>
<div style="position: fixed;bottom: 10px;right: 10px;"><a href="#top" target="_self"><img width="60px;" height="60px;" src="/images/background/top.jpg"></a>
</div>
</body>
<script></script>
</html>

解释:此HTML分为输入框和评论列表,评论列表里有用户的头像、用户的昵称、用户发表评论的日期、用户的评论内容,但我们的评论表只包含了用户的ID与评论内容类型等,不包括用户表的其他内容,因为有了前面的经验,第一时间就想到了左连接关联表,这样就能通过评论用户ID查出用户的昵称与头像:

SQL语句如下,因为有三个不同的类型,所以分为了三类:

    <select id="findCommentBySheetId2" resultType="com.jhb.crash_music.pojo.Comment2">selectcomment_id,comment_text,comment_userId,comment_time,comment_type,comment_targetId,u.user_nickname AS comment_nickName,u.user_imgUrl AS comment_userImgfromcomment_table AS cLEFT JOIN user_table AS u ON c.comment_userId = u.user_idwherecomment_type=1 and comment_targetId=#{comment_targetId}</select><select id="findCommentByAlbumId2" resultType="com.jhb.crash_music.pojo.Comment2">selectcomment_id,comment_text,comment_userId,comment_time,comment_type,comment_targetId,u.user_nickname AS comment_nickName,u.user_imgUrl AS comment_userImgfromcomment_table AS cLEFT JOIN user_table AS u ON c.comment_userId = u.user_idwherecomment_type=2 and comment_targetId=#{comment_targetId}</select><select id="findCommentBySongId2" resultType="com.jhb.crash_music.pojo.Comment2">selectcomment_id,comment_text,comment_userId,comment_time,comment_type,comment_targetId,u.user_nickname AS comment_nickName,u.user_imgUrl AS comment_userImgfromcomment_table AS cLEFT JOIN user_table AS u ON c.comment_userId = u.user_idwherecomment_type=3 and comment_targetId=#{comment_targetId}</select>

后端语句:

    /*** 评论列表查询* @param comment_type 评论类型* @param comment_targetId 评论目标ID* @return 页面地址*/@GetMapping(path = "commentList")public String commentList(@Param("comment_type")Integer comment_type,@Param("comment_targetId")Integer comment_targetId,Model model){List<Comment2> commentList = new ArrayList<>();if(comment_type==1){commentList = commentService.findCommentBySheetId2(comment_targetId);}else if(comment_type==2){commentList = commentService.findCommentByAlbumId2(comment_targetId);}else {commentList = commentService.findCommentBySongId2(comment_targetId);}model.addAttribute("comment_type",comment_type);model.addAttribute("commentList",commentList);model.addAttribute("comment_targetId",comment_targetId);return "reception/index/comment";}/*** 用户添加评论* @param comment_targetId 评论目标ID* @param comment_type 评论类型* @param comment_text 评论正文* @return 页面地址*/@PostMapping(path = "addComment")public String addComment(@Param("comment_targetId")Integer comment_targetId, @Param("comment_type")Integer comment_type,@Param("comment_text")String comment_text, HttpServletRequest req){HttpSession session = req.getSession();User user = (User)session.getAttribute("LoginUser");SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String comment_time = sdf.format(new Date());Comment comment = new Comment(comment_text,user.getUser_id(),comment_time,comment_type,comment_targetId);if(!commentService.addComment(comment)){System.out.println("用户发表评论失败");}return "redirect:commentList?comment_type="+comment_type+"&comment_targetId="+comment_targetId;}/*** 删除用户自己的评论* @param comment_id 评论ID* @param comment_targetId 评论目标ID* @param comment_type 评论类型* @return 页面地址*/@GetMapping(path = "delComment")public String delComment(@Param("comment_id")Integer comment_id,@Param("comment_targetId")Integer comment_targetId, @Param("comment_type")Integer comment_type){if(!commentService.delComment(comment_id)){System.out.println("用户删除评论失败");}return "redirect:commentList?comment_type="+comment_type+"&comment_targetId="+comment_targetId;}

这样通过评论类型进行锁定,就不用分别写三个评论页面,一个足矣,之所以不直接在歌单或者专辑信息列表下展示评论列表,因为没有用AJAX,所以提交一个评论会重新加载整个界面的东西,AJAX之后会考虑加入,实现局部刷新时就可以把评论放在详情页面了,现在因为时间问题先这样写。

下一步,就真是进行播放功能的开发了,其他貌似都已经完成,最多就是在导航栏丰富点内容,比如加入搜索栏,以及一些信息图标等。

基于springboot+vue(thymeleaf)+mysql下的自创音乐网站平台--CrushMusic(开发日志十三)相关推荐

  1. 基于springboot+vue(thymeleaf)+mysql下的自创音乐网站平台--CrushMusic(开发日志十四)--audio控件重写音乐播放

    本次花了很大精力去完成了播放界面,虽然歌词同步这里没完成,但后续还是可以完善的,这次我重写了audio控件,让audio是自己想要的样式,先看成果图.  这个界面参考的是酷狗音乐网页版的布局,感觉自己 ...

  2. 基于springboot+vue(thymeleaf)+mysql下的自创音乐网站平台--CrushMusic(开发日志七)

    中间隔了有一段时间,因为去学了一些其他东西,加上还有课程,今天专门用了大半天来写前台界面与登录注册的UI设计,网上的模板我都不太想用,我就用框架来自己搭建前台,我参考了三大音乐网站的首页设计,基本都是 ...

  3. 十分钟写一个基于springboot+vue+redis+mysql的银行转账与用户后台管理系统,redis实现用户登录与缓存

    界面效果 用户管理界面 详情页面 编辑页面 删除功能 用户界面 查询余额 取出余额 存款 转账 后端包结构 bean包下代码 管理员类 package com.example.qqqundatabas ...

  4. 基于SpringBoot+Vue+Java+Mysql 的简历招聘系统【源码】

    文章目录 1.效果演示 2. 前言介绍 3.主要技术 4 **系统设计** 4.1 系统体系结构 4.2开发流程设计 4.3 数据库设计原则 4.4 数据表 5 **系统详细设计** 5.1管理员功能 ...

  5. 基于 SpringBoot + Vue 的智能停车场项目。

    一.开源项目简介 基于 SpringBoot + Vue 的智能停车场项目. 智能停车场管理平台!科学计费 多种计费方案灵活切换,商场.小区.停车场等场景均适用!无人值守 云端控制实现无岗亭模式下的车 ...

  6. 【毕业设计】基于springboot + vue微信小程序商城

    目录 前言 创新点/亮点✨ 毕设目录 一.视频展示 二.系统介绍 三.项目地址 四.运行环境 五.设计模块 ①前台 ②后台 六.系统功能模块结构图 七. 准备阶段 ①使用真实支付 ②使用模拟支付 八. ...

  7. 基于javaweb的电影院会员管理系统(java+springboot+vue+element-ui+mysql)

    基于javaweb的电影院会员管理系统(java+springboot+vue+element-ui+mysql) 运行环境 Java≥8.MySQL≥5.7.Node.js≥10 开发工具 后端:e ...

  8. 基于JAVA+SpringBoot+Vue+Mybatis+MYSQL的在线音乐网站

    项目介绍: 基于springboot+vue实现的音乐网站,系统采用前后端分离开发模式开发,分为三个工程文件,分别是springboot后台服务端工程,主要提供API接口:vue前端用户客户端工程,主 ...

  9. 计算机毕业设计基于springboot+vue+elementUI的网吧管理系统(源码+系统+mysql数据库+Lw文档)

    项目介绍 随着我国的经济发展,人们的生活水平也有了一定程度的提高,对网络的要求也越来越高,很多家庭都有了自己的电脑,但是很多时候大家在家里玩电脑的时候找不到那种玩耍的气氛和氛围,这个时候大家就都选择了 ...

最新文章

  1. Smart-linkmonitor-link配置注意事项
  2. lnmp shell安装脚本
  3. WordPress3.5安装出现的几个问题
  4. Stanford 研究领域
  5. ICCV2017 论文解读:基于图像检索的行人重识别 | PaperDaily #13
  6. 开放下载!《深入浅出玩转物联网平台》
  7. python异常(高级) Exception
  8. 【英语学习】【English L06】U08 News L5 They are expecting a baby!
  9. springboot线程池配置
  10. 罗定职业技术学院计算机考试二级,2018年罗定职业技术学院五年一贯制单独招生术科考试成绩.PDF...
  11. android生命周期_Android活动生命周期– 7个阶段和功能
  12. LINUX Telepresence编译详细过程记录
  13. 软件读写中文字符的文件出现乱码的解决办法
  14. react 移动端 实现video的自动播放
  15. 代码解释及MATLAB复现--灯哥四足机器人步态规划部分
  16. RTX 4080、RTX4070 Ti 相当于什么水平
  17. 简单的STM32蓝牙遥控小车完整项目及资料分享,超全
  18. 求解500万以内的亲和数
  19. OFD转PDF ~java实现
  20. python产品质量分析_Python数据分析实战之葡萄酒质量分析

热门文章

  1. 正则表达式 数字大于0(包含小数点)
  2. 并发中的Synchronized、Lock、Volite、Map、ThreadLocal
  3. C++ 静态库和动态库 详解
  4. 译文▍用Python做NLP:自然语言处理-介绍、入门与应用
  5. bios设置计算机用户密码,用BIOS设置当前计算机的管理员和用户的密码
  6. 苹果平板如何下载java_苹果正式放弃iTunes!如何将iPhone和iPad同步到Mac?
  7. console.read()的特殊用法及解决
  8. 全球速卖通开店入驻全指南
  9. 史上最全Java工程师面试题汇总,全会月薪至少3W
  10. HTML5制作机器人,使用CSS3制作机器人总动员的Eva