当前位置:   article > 正文

基于springboot+vue(thymeleaf)+mysql下的自创音乐网站平台--CrushMusic(开发日志十三)_themleaf中音频下载和预览

themleaf中音频下载和预览

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

成果展示:

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

 

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

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

 

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

 

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

原理解释:

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

四个键html代码:

  1. <div class="td-hover">
  2. <a><i class="bi bi-play-circle"></i></a>
  3. <a><i class="bi bi-plus"></i></a>
  4. <a th:href="@{${song.getSong_mp3Url()}}" th:download="${song.getSong_name()}+'.mp3'"><i class="bi bi-download"></i></a>
  5. <a th:onclick="|addSongInSheet(${songStat.index+1})|" style="position: relative;"><i class="bi bi-plus-circle"></i>
  6. <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;">
  7. <table>
  8. <tr th:each="sheet:${mySheetList}">
  9. <td>
  10. <a th:href="@{/sheet/addSongInSheet2(songlist_sheetId=${sheet.getSheet_id()},songlist_songId=${song.getSong_id()})}" th:text="${sheet.getSheet_name()}"></a>
  11. </td>
  12. </tr>
  13. </table>
  14. </div>
  15. </a>
  16. </div>

js代码:

  1. function addSongInSheet(index) {
  2. var div = document.getElementById("addSongInSheet"+index);
  3. if(div.style.display == "none"){
  4. div.style.display = "block";
  5. }else if(div.style.display == "block"){
  6. div.style.display = "none";
  7. }
  8. }

css代码:

  1. .td-hover{
  2. display: none;
  3. }
  4. .tr-hover tr:nth-child(odd):hover .td-hover{
  5. display: block;
  6. }
  7. .tr-hover tr:nth-child(even):hover .td-hover{
  8. display: block;
  9. }

后端代码:

  1. /**
  2. * 前台将歌曲与歌单建立映射关系
  3. * @param songlist_sheetId 歌单ID
  4. * @param songlist_songId 歌曲ID
  5. * @return
  6. */
  7. @GetMapping(path = "addSongInSheet2")
  8. public String addSongInSheet2(@Param("songlist_sheetId")Integer songlist_sheetId,@Param("songlist_songId")Integer songlist_songId,HttpServletRequest req) {
  9. HttpSession session = req.getSession();
  10. User user = (User) session.getAttribute("LoginUser");
  11. if(!sheetService.addSheetAndSong(songlist_sheetId,songlist_songId)){
  12. System.out.println("添加歌曲歌单关联失败");
  13. }
  14. return "redirect:myMusic?sheet_userId="+user.getUser_id()+"&sheet_id="+songlist_sheetId;
  15. }
  16. /**
  17. * 前台将歌单与歌曲解除映射关系
  18. * @param songlist_sheetId 歌单ID
  19. * @param songlist_songId 歌曲ID
  20. * @return 页面地址
  21. */
  22. @GetMapping(path = "delSongInSheet2")
  23. public String delSongInSheet2(@Param("songlist_sheetId")Integer songlist_sheetId,@Param("songlist_songId")Integer songlist_songId,HttpServletRequest req) {
  24. HttpSession session = req.getSession();
  25. User user = (User) session.getAttribute("LoginUser");
  26. if(!sheetService.delSheetAndSong(songlist_sheetId,songlist_songId)){
  27. System.out.println("删除歌曲歌单关联失败");
  28. }
  29. return "redirect:myMusic?sheet_userId="+user.getUser_id()+"&sheet_id="+songlist_sheetId;
  30. }

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

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org"
  3. xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
  4. xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
  5. <head>
  6. <title>评论</title>
  7. <div th:replace="~{reception/common/common::cjbar}"/>
  8. <script type="text/javascript" src="/js/onload.js"></script>
  9. </head>
  10. <body id="top">
  11. <div th:replace="~{reception/common/common::topbar}"/>
  12. <div th:replace="~{reception/common/common::topbar2}"/>
  13. <div class="middle-width">
  14. <div style="width: 100%;padding-left: 50px;padding-right: 50px;">
  15. <div style="height: 50px;"></div>
  16. <form method="post" th:action="@{/comment/addComment(comment_targetId=${comment_targetId},comment_type=${comment_type})}">
  17. <textarea style="resize: none;" name="comment_text" cols="155" rows="5" placeholder="发表评论:"></textarea><br>
  18. <input type="submit" class="btn btn-primary btn-color btn-size" value="发表">
  19. </form>
  20. <p style="font-size: 25px;font-family: '黑体'" th:text="'精彩评论('+${commentList.size()}+')'"></p>
  21. <div th:each="comment:${commentList}" style="border-top: 1px rgb(211,211,211) solid;">
  22. <table style="margin-top: 20px;margin-bottom: 20px;">
  23. <tr>
  24. <td style="width: 5%;" rowspan="2"><img style="width: 50px;height: 50px;border-radius: 50%;" th:src="${comment.getComment_userImg()}"></td>
  25. <td style="width: 95%;color: rgb(211,211,211);" th:text="${comment.getComment_nickName()}"></td>
  26. </tr>
  27. <tr>
  28. <td style="color: rgb(211,211,211);" th:text="${comment.getComment_time()}"></td>
  29. </tr>
  30. <tr>
  31. <td></td>
  32. <td th:text="${comment.getComment_text()}"></td>
  33. </tr>
  34. </table>
  35. </div>
  36. </div>
  37. </div>
  38. <div style="position: fixed;bottom: 10px;right: 10px;">
  39. <a href="#top" target="_self"><img width="60px;" height="60px;" src="/images/background/top.jpg"></a>
  40. </div>
  41. </body>
  42. <script>
  43. </script>
  44. </html>

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

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

  1. <select id="findCommentBySheetId2" resultType="com.jhb.crash_music.pojo.Comment2">
  2. select
  3. comment_id,
  4. comment_text,
  5. comment_userId,
  6. comment_time,
  7. comment_type,
  8. comment_targetId,
  9. u.user_nickname AS comment_nickName,
  10. u.user_imgUrl AS comment_userImg
  11. from
  12. comment_table AS c
  13. LEFT JOIN user_table AS u ON c.comment_userId = u.user_id
  14. where
  15. comment_type=1 and comment_targetId=#{comment_targetId}
  16. </select>
  17. <select id="findCommentByAlbumId2" resultType="com.jhb.crash_music.pojo.Comment2">
  18. select
  19. comment_id,
  20. comment_text,
  21. comment_userId,
  22. comment_time,
  23. comment_type,
  24. comment_targetId,
  25. u.user_nickname AS comment_nickName,
  26. u.user_imgUrl AS comment_userImg
  27. from
  28. comment_table AS c
  29. LEFT JOIN user_table AS u ON c.comment_userId = u.user_id
  30. where
  31. comment_type=2 and comment_targetId=#{comment_targetId}
  32. </select>
  33. <select id="findCommentBySongId2" resultType="com.jhb.crash_music.pojo.Comment2">
  34. select
  35. comment_id,
  36. comment_text,
  37. comment_userId,
  38. comment_time,
  39. comment_type,
  40. comment_targetId,
  41. u.user_nickname AS comment_nickName,
  42. u.user_imgUrl AS comment_userImg
  43. from
  44. comment_table AS c
  45. LEFT JOIN user_table AS u ON c.comment_userId = u.user_id
  46. where
  47. comment_type=3 and comment_targetId=#{comment_targetId}
  48. </select>

后端语句:

  1. /**
  2. * 评论列表查询
  3. * @param comment_type 评论类型
  4. * @param comment_targetId 评论目标ID
  5. * @return 页面地址
  6. */
  7. @GetMapping(path = "commentList")
  8. public String commentList(@Param("comment_type")Integer comment_type,@Param("comment_targetId")Integer comment_targetId,Model model){
  9. List<Comment2> commentList = new ArrayList<>();
  10. if(comment_type==1){
  11. commentList = commentService.findCommentBySheetId2(comment_targetId);
  12. }else if(comment_type==2){
  13. commentList = commentService.findCommentByAlbumId2(comment_targetId);
  14. }else {
  15. commentList = commentService.findCommentBySongId2(comment_targetId);
  16. }
  17. model.addAttribute("comment_type",comment_type);
  18. model.addAttribute("commentList",commentList);
  19. model.addAttribute("comment_targetId",comment_targetId);
  20. return "reception/index/comment";
  21. }
  22. /**
  23. * 用户添加评论
  24. * @param comment_targetId 评论目标ID
  25. * @param comment_type 评论类型
  26. * @param comment_text 评论正文
  27. * @return 页面地址
  28. */
  29. @PostMapping(path = "addComment")
  30. public String addComment(@Param("comment_targetId")Integer comment_targetId, @Param("comment_type")Integer comment_type,@Param("comment_text")String comment_text, HttpServletRequest req){
  31. HttpSession session = req.getSession();
  32. User user = (User)session.getAttribute("LoginUser");
  33. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  34. String comment_time = sdf.format(new Date());
  35. Comment comment = new Comment(comment_text,user.getUser_id(),comment_time,comment_type,comment_targetId);
  36. if(!commentService.addComment(comment)){
  37. System.out.println("用户发表评论失败");
  38. }
  39. return "redirect:commentList?comment_type="+comment_type+"&comment_targetId="+comment_targetId;
  40. }
  41. /**
  42. * 删除用户自己的评论
  43. * @param comment_id 评论ID
  44. * @param comment_targetId 评论目标ID
  45. * @param comment_type 评论类型
  46. * @return 页面地址
  47. */
  48. @GetMapping(path = "delComment")
  49. public String delComment(@Param("comment_id")Integer comment_id,@Param("comment_targetId")Integer comment_targetId, @Param("comment_type")Integer comment_type){
  50. if(!commentService.delComment(comment_id)){
  51. System.out.println("用户删除评论失败");
  52. }
  53. return "redirect:commentList?comment_type="+comment_type+"&comment_targetId="+comment_targetId;
  54. }

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/218470
推荐阅读
相关标签
  

闽ICP备14008679号