音乐管理系统 SpringBoot + vue

文章目录

  • 1、简要介绍
  • 2、数据库设计
  • 3、解决的问题
    • 1、图片和音频的上传和存储
    • 2、分页功能
  • 4、数据返回


也算是进行了半个学期,跟着老师讲的进行

后端使用SpringBoot 前端 vue + layui
jdk 18

项目地址:gitee


1、简要介绍

  只有管理端,但是对用户端的判断功能在数据库中已经体现,

  实现了mp3音频文件和图片文件的上传,原理是存储在静态资源中,数据库中存的也是路径而已

以下为部分截图,整体风格亦是如此

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、数据库设计


CREATE TABLE `role`  (`id` int NOT NULL AUTO_INCREMENT COMMENT '角色id',`role_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '角色名称',`role_status` int NULL DEFAULT NULL COMMENT '角色状态  0 不可用  1 可用',`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,`update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,`dis` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`rule` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;CREATE TABLE `singer`  (`id` int UNSIGNED NOT NULL AUTO_INCREMENT,`name` varchar(45) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,`sex` tinyint NULL DEFAULT NULL,`pic` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,`birth` datetime NULL DEFAULT NULL,`location` varchar(45) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,`introduction` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 44 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = DYNAMIC;CREATE TABLE `song`  (`id` int UNSIGNED NOT NULL AUTO_INCREMENT,`singer_id` int UNSIGNED NOT NULL,`name` varchar(45) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,`introduction` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '发行时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`pic` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,`lyric` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL,`url` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 124 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = DYNAMIC;CREATE TABLE `sys_user`  (`id` int NOT NULL AUTO_INCREMENT,`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名',`nick_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '昵称',`gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '性别',`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码  密文存储 ',`phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '手机号码',`status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '1 可用   0 禁用',`image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '服务器路径',`created_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建者',`role_uid` int NULL DEFAULT NULL COMMENT '角色  严格遵循外键约束,但在表设计时候,不使用约束语句',`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

3、解决的问题

1、图片和音频的上传和存储

  首先肯定是要有一个对于存储文件的配置,然后,在前端发送的时候,注意使用
post + headers: { 'content-type': 'multipart/form-data' } 的格式,

package com.whd.system.controller;import com.github.pagehelper.util.StringUtil;
import com.whd.system.common.AxiosResult;
import com.whd.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.UUID;@RestController
@RequestMapping("/fileup")
public class FileUpController {public static final String UPLOAD_PATH = "F:\\javaweb\\study\\spingBootMaven\\src\\main\\resources\\upload\\";@PostMapping("/image")public AxiosResult<String> upload(@RequestParam(value = "name") String name,  MultipartFile photo, HttpServletRequest request) throws IOException {if(name==null || name.equals("")){return AxiosResult.error("参数错误");}String extension = StringUtils.getFilenameExtension(photo.getOriginalFilename());String fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + extension;String curDateStr = LocalDate.now().toString();File file = new File(UPLOAD_PATH+name+"\\"+ curDateStr);if (!file.exists()) {file.mkdirs();}photo.transferTo(new File(UPLOAD_PATH +name+ "\\" + curDateStr + "/" + fileName));return AxiosResult.success(name+ "\\" + curDateStr + "/" + fileName);}@PostMapping("/video")public AxiosResult<String> uploadViedo(@RequestParam(value = "name") String name,  MultipartFile video, HttpServletRequest request) throws IOException {name+="\\viedo";if(!video.getContentType().equals("audio/mpeg")) {return AxiosResult.error("只允许上传mp3格式的音频文件");}String extension = StringUtils.getFilenameExtension(video.getOriginalFilename());String fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + extension;String curDateStr = LocalDate.now().toString();System.out.println(UPLOAD_PATH+name+"\\"+ curDateStr);File file = new File(UPLOAD_PATH+name+"\\"+ curDateStr);if (!file.exists()) {file.mkdirs();}video.transferTo(new File(UPLOAD_PATH +name+ "\\" + curDateStr + "/" + fileName));return AxiosResult.success(name+ "\\" + curDateStr + "/" + fileName);}}

2、分页功能

  通过自定义的一个组件(当然不是我写的),在后端进行判断处理,其实没有想到那么复杂

组件如下:

<script>
Vue.component('zpagenav', {template: `<nav class="zpagenav">` +`<ul class="page-ul">` +`<li v-bind:key="index" v-for="(item,index) in pageList" v-bind:class ="item.class" @click.stop="setPage(item)" v-html="item.html">` +`</li>` +`</ul>` +`<span class="total">共 {{total}} 条</span>` +`</nav>`,props: {prevHtml: String,nextHtml: String,page: Number,total: Number,pageSize: Number,maxPage: Number},computed: {pageList: function() {var _this = this,pageList = [];let pageCount = Math.ceil(_this.total / _this.pageSize);let page = _this.page;let prevHtml = _this.prevHtml ? _this.prevHtml : '&lt;';let nextHtml = _this.nextHtml ? _this.nextHtml : '&gt;';let maxPage = _this.maxPage ? _this.maxPage : 9;let hasPrev = page > 1;let hasNext = page < pageCount;//上一页pageList.push({class: hasPrev ? '' : 'disabled',page: hasPrev ? page - 1 : page,html: prevHtml});//首页pageList.push({class: page == 1 ? 'active' : '',page: 1,html: 1});var p0 = Math.floor(maxPage / 2);var p1 = 1 + 2 + p0; //首页+省略至少2个页码+中间页面数的一半var start, end;if(page >= p1) {start = page - p0;//前置省略号pageList.push({class: 'dot',page: page,html: '...'});} else {start = 2;}var p2 = page + p0;if(p2 < pageCount) {end = p2;} else {end = pageCount - 1;}//页码列表for(let i = start; i <= end; i++) {pageList.push({class: page == i ? 'active' : '',page: i,html: i});}if(end < pageCount - 1) {//后置省略号pageList.push({class: 'dot',page: page,html: '...'});}//尾页if(pageCount > 1) {pageList.push({class: page == pageCount ? 'active' : '',page: pageCount,html: pageCount});}//下一页pageList.push({class: hasNext ? '' : 'disabled',page: hasNext ? page + 1 : page,html: nextHtml});return pageList;}},methods: {setPage: function(item) {if(item.class == '') {this.$emit('pagehandler', item.page);}}}
});</script><style>
.zpagenav {text-align: center;-webkit-user-select: none;
}.zpagenav {font-family: arial;color: #48576a;
}.zpagenav ul {display: inline-block;margin: 20px 20px;padding: 0;
}.zpagenav ul li {display: inline-block;margin: 0;padding: 0 4px;border: 1px solid #d1dbe5;border-right: 0;background: #fff;font-size: 13px;min-width: 28px;height: 28px;line-height: 28px;cursor: pointer;box-sizing: border-box;text-align: center;
}.zpagenav ul li:last-child {border-right: 1px solid #d1dbe5;
}.zpagenav ul li:hover {color: #20a0ff;
}.zpagenav ul li.active {border-color: #20a0ff;background-color: #20a0ff;color: #fff;cursor: default;
}.zpagenav ul li.active:hover {color: #fff;
}.zpagenav ul li.disabled {cursor: not-allowed;color: #e4e4e4;
}.zpagenav ul li.dot {cursor: default;
}</style>

使用的时候,注意引入该文件,和该文件的样式文件,然后,将这一坨复制到分页的地方

      <div class="page"><div class="wrap"><zpagenav v-bind:page="page" v-bind:page-size="pageSize" v-bind:total="total" v-bind:max-page="maxPage"v-on:pagehandler="pageHandler"></zpagenav></div></div>

注意,在vue 的 data 中加上 page: 1, pageSize: 10, total: 0, maxPage: 5,这三个属性,
然后,就是后端处理返回数据了,正常查询结果,通过 PageHelper PageInfo进行分页处理

处理逻辑如下例子:

 @PostMapping("/select/selectAllPage")public AxiosResult<PageResult<SongVo>> getAllSongByPage(@RequestBody PageVO pageVO){Integer page = pageVO.getPage();Integer size = pageVO.getSize();// 开始分页PageHelper.startPage(page, size);List<SongVo> songs=songMapper.getSongList();songs.forEach(song -> {song.setPic(PIC_URL + song.getPic());song.setUrl(PIC_URL + song.getUrl());});PageInfo<SongVo> pageInfo = new PageInfo<>(songs);//将数据封装在自己写的PageResultPageResult<SongVo> pageResult = new PageResult<>();pageResult.setPage(pageInfo.getPageNum());pageResult.setTotalPage(pageInfo.getPages());pageResult.setList(pageInfo.getList());pageResult.setTotal(pageInfo.getTotal());pageResult.setPageSize(pageInfo.getPageSize());return AxiosResult.success(pageResult);}

对于AxiosResult也是自己写的一个实体类, 用于返回信息和状态码, 具体代码可查看项目中的代码:
对于PageResult 类

@Data
public class PageResult<T> {private int page;private int pageSize;private long total;private List<T> list;private int totalPage;
}

PageVO 类

@Data
public class PageVO {private Integer page=1;//用户查询的第几页private Integer size=10;//每页展示的数量
}

4、数据返回

  通过SpringBoot返回的数据类型,会自动转为json格式,但是上面所提到的AxiosResult也不是必须的,但是这样子看起来更方便,该类可以作为模板重复使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/29933.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ORA-12560: TNS:协议适配器错误

项目场景&#xff1a; 由于最近一直没有连接oracle&#xff0c;然后之前windows也是正常可以启动oracle&#xff0c;正常连接。无论是SQL Developer还是SQL PLUS命令&#xff0c;都能正常连接和操作。 问题描述 这两天刚好用SQL Developer工具连接&#xff0c;然后报错&#…

土木工程好发的期刊有哪些?

土木工程作为一门涉及建筑、桥梁、道路、铁路、隧道、水利工程等多个领域的学科&#xff0c;其研究成果和应用广泛影响着社会基础设施的发展和建设。对于土木工程领域的研究人员来说&#xff0c;选择合适的期刊发表论文&#xff0c;不仅可以增加学术影响力&#xff0c;还可以为…

[C#] opencvsharp对Mat数据进行序列化或者反序列化以及格式化输出

【简要介绍】 在OpenCVSharp中&#xff0c;FileStorage类用于将数据&#xff08;包括OpenCV的Mat类型数据&#xff09;序列化为XML或YAML格式的文件&#xff0c;以及从这些文件中反序列化数据。以下是关于FileStorage类用法的详细说明&#xff1a; 写入数据&#xff08;序列化…

华纳云:美国云服务器主要的资源回收和释放机制

美国云服务器的资源回收和释放机制通常涉及几个关键方面&#xff0c;包括自动化、按需分配、资源回收策略以及相关的管理工具和服务。这些机制确保云资源的高效利用&#xff0c;降低成本并提高性能。以下是一些主要的资源回收和释放机制&#xff1a; 1. 按需分配和计费 弹性计算…

React-Redux

什么是Redux&#xff1f; Redux是React最常用的集中状态管理工具&#xff0c;类似于Vue中的Pinia&#xff08;Vuex&#xff09;&#xff0c;可以独立于框架运行 作用&#xff1a;通过集中管理的方式管理应用的状态 例子&#xff1a;不和任何框架绑定&#xff0c;不使用任何构…

图像处理与视觉感知复习--形态学图像处理

文章目录 计算图像膨胀和腐蚀计算开操作和闭操作击中或击不中变化 计算图像膨胀和腐蚀 定义&#xff1a; A c A^c Ac 表示集合A的补集几何的反射 有集合A中所有元素相对于原点的反射元素组成的集合称为集合A的反射&#xff0c;几位 A ^ \hat{A} A^ A ^ { w ∣ w − a , a …

SpringTask-Timer实现定时任务

1、Timer 实现定时任务 1.1、JDK1.3 开始推出定时任务实现工具。 1.2、API 执行代码 public static void main(String[] args) throws ParseException {Timer timer new Timer();String str"2024-06-10 23:24:00";Date date new SimpleDateFormat("yyyy-MM…

Pikachu靶场--文件包含

参考借鉴 Pikachu靶场之文件包含漏洞详解_pikachu文件包含-CSDN博客 文件包含&#xff08;CTF教程&#xff0c;Web安全渗透入门&#xff09;__bilibili File Inclusion(local) 查找废弃隐藏文件 随机选一个然后提交查询 URL中出现filenamefile2.php filename是file2.php&…

爱死了,4款逆天IOS App推荐!

河马喝水提醒 「河马喝水提醒」是一款生活小助手应用&#xff0c;旨在帮助用户建立并维持定时喝水的良好习惯。该应用不仅是一个提醒闹钟&#xff0c;更是健康生活的贴心伙伴。它每天定时推送提醒&#xff0c;帮助用户在繁忙的日常中不忘补充水分。此外&#xff0c;该应用还提供…

移植案例与原理 - build lite配置目录全梳理

命令行工具hb(HarmonyOS|OpenHarmony Build 编译构建系统的缩写)都很熟悉了。这是一个基于gn和ninja的构建系统&#xff0c;以支持OpenHarmony组件化开发为目标&#xff0c;提供以下基本功能&#xff1a; 支持按组件拼装产品并编译。 独立构建芯片解决方案厂商源码。 独立构建…

什么是FOUC(无样式内容闪烁)?你如何来避免FOUC?

FOUC&#xff08;Flash of Unstyled Content&#xff0c;无样式内容闪烁&#xff09;是指在网页加载过程中&#xff0c;用户可能会短暂地看到未应用样式的原始 HTML 内容&#xff0c;随后样式表加载完成后&#xff0c;页面才会以正确的样式重新渲染。这种现象会影响用户体验&am…

wpf textbox 有焦点 导致后台更新 前台不跟着改变

这个问题可能是由于 WPF 的数据绑定机制导致的。当 TextBox 有焦点时,它会独立于数据绑定进行更新,这可能会导致前台界面不能及时反映后台数据的变化。 1.使用 UpdateSourceTrigger 属性: 在数据绑定时,将 UpdateSourceTrigger 属性设置为 PropertyChanged。这样当 TextBox 的…

vue中的自定义指令

第1部分&#xff1a;引言 在Vue.js中&#xff0c;自定义指令提供了一种非常灵活的方式来扩展Vue的功能。它们允许开发者直接对DOM进行操作&#xff0c;响应数据变化&#xff0c;甚至与其他组件或库集成。 第2部分&#xff1a;Vue自定义指令概述 2.1 什么是Vue自定义指令 Vu…

ROM和RAM的区别

ROM&#xff08;Read-Only Memory&#xff0c;只读存储器&#xff09;和RAM&#xff08;Random-Access Memory&#xff0c;随机存取存储器&#xff09;是计算机系统中两种不同类型的内存&#xff0c;它们在功能、存储内容和使用方式上有着明显的区别&#xff0c;但同时也存在一…

新人学习笔记之(数据类型(小数))

一、小数的数据类型分为&#xff1a;float、double #include<stdio.h>int main() {// 1. 定义float、double、long double数据类型的变量// float 单精度小数&#xff08;精确度小数后6位&#xff09;windows占4个字节&#xff08;38位&#xff09;float a 3.14F; // f…

Linux操作系统学习:day03

内容来自&#xff1a;Linux介绍 视频推荐&#xff1a;[Linux基础入门教程-linux命令-vim-gcc/g -动态库/静态库 -makefile-gdb调试]( 目录 day0317、创建删除目录创建目录删除目录 18、文件的拷贝19、mv 命令20、查看文件内容的相关命令21、给文件创建软连接或硬链接 day03 …

环境搭建---单机k8s

配置基础环境 关闭防火墙 [rootVM-20-14-centos ~]# systemctl stop firewalld && systemctl disable firewalld关闭selinux [rootVM-20-14-centos ~]# setenforce 0 && sed -i "s/SELINUXenforcing/SELINUXdisabled/g" /etc/selinux/config禁止s…

[Qt的学习日常]--常用控件3

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、显示类控…

Spark入门(一篇就够了)

文章目录 引言1. Spark 基础1.1 Spark 为何物1.2 Spark VS Hadoop1.3 Spark 优势及特点1.3.1 优秀的数据模型和丰富计算抽象1.3.2 完善的生态圈-fullstack1.3.3 spark的特点 1.4 Spark 运行模式 2. Spark Core2.1 RDD详解2.1.1 RDD概念2.1.2 RDD属性2.1.3 RDD API2.1.3.1 RDD 的…

轻松掌握文本处理技巧:自定义提取指定行范围,高效批量处理文本数据,轻松提升工作效率!

在信息爆炸的时代&#xff0c;文本数据已经成为我们生活和工作中不可或缺的一部分。然而&#xff0c;面对海量的文本数据&#xff0c;如何高效、准确地提取所需信息&#xff0c;成为了许多人面临的挑战。今天&#xff0c;我们向您推荐一种全新的文本处理技巧&#xff0c;让您轻…