音乐管理系统 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;然后报错&#…

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

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

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; 支持按组件拼装产品并编译。 独立构建芯片解决方案厂商源码。 独立构建…

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;让您轻…

科普童话投稿

《科普童话》杂志是由国家新闻出版总署批准、黑龙江省教育厅主管、黑龙江省语言文字报刊社主办的正规期刊。《科普童话》以培养科学素养与创新探索精神为办刊宗旨&#xff0c;以科学与艺术统一为编辑方针&#xff0c;以科学教育、教育科学作为自己的出发点&#xff0c;致力于对…

基于Java + Swing + MySQL的学生选课及成绩管理系统(Java课程设计)

目录 开发工具系统结构功能展示登录与注册界面&#xff08;通用&#xff09;主界面&#xff08;通用&#xff09;学生信息查询界面&#xff08;学生用户&#xff09;学生信息管理界面&#xff08;教师用户 管理员用户&#xff09;学生选课界面&#xff08;学生用户&#xff09;…

OpenAI新开放了这些好用的API功能(附AI学习指南)

OpenAI近期召开了开发者大会&#xff0c;同时也发布和开放了一些新的功能特性&#xff0c;比如新版本GPT-4 Turbo&#xff0c;支持128k上下文&#xff0c;知识截止更新到2023年4月&#xff0c;视觉能力、DALLE3&#xff0c;文字转语音TTS等等全都对API开放&#xff0c;GPTs商店…

反馈型振荡器

目录 反馈型振荡器分类 基本工作原理 启动过程 “心脏”LC振荡 起振条件 平衡条件 稳定条件 互感耦合振荡器 电感三端LC振荡器 电容三端LC振荡器 串联改进电容三端式振荡器 并联改进电容三端式振荡器 相位平衡条件的判断准则 反馈型振荡器分类 基本工作原理 启动过…

华为---RIP路由协议的汇总

8.3 RIP路由协议的汇总 8.3.1 原理概述 当网络中路由器的路由条目非常多时&#xff0c;可以通过路由汇总(又称路由汇聚或路由聚合)来减少路由条目数&#xff0c;加快路由收敛时间和增强网络稳定性。路由汇总的原理是&#xff0c;同一个自然网段内的不同子网的路由在向外(其他…

第十二章:会话控制

会话控制 文章目录 会话控制一、介绍二、cookie2.1 cookie 是什么2.2 cookie 的特点2.3 cookie 的运行流程2.4 浏览器操作 cookie2.5 cookie 的代码操作&#xff08;1&#xff09;设置 cookie&#xff08;2&#xff09;读取 cookie&#xff08;3&#xff09;删除 cookie 三、se…

【1】、var、let、const 三者的区别

主要围绕一下五个方面 变量提升暂时性死区块级作用域重复声明修改声明的变量 1、变量的提升 【var】可以在声明前使用&#xff0c;即输出为undefined 【let】和【const】未声明不可使用&#xff0c;否则会报错 2、暂时性死区定义&#xff1a;在代码块内&#xff0c;如果引用…