1、后端编写

1.1 Service服务层编写

  1. package com.gmw.musicserver.service;
  2. import com.gmw.musicserver.entity.Singer;
  3. import com.baomidou.mybatisplus.extension.service.IService;
  4. import java.util.List;
  5. /**
  6. * <p>
  7. * 歌手表 服务类
  8. * </p>
  9. *
  10. * @author 未进化的程序猿
  11. * @since 2022-01-26
  12. */
  13. public interface SingerService extends IService<Singer> {
  14. /**
  15. *增加
  16. */
  17. public boolean insertSinger(Singer singer);
  18. /**
  19. *修改
  20. */
  21. public boolean updateSinger(Singer singer);
  22. /**
  23. * 删除
  24. */
  25. public boolean deleteSinger(Integer id);
  26. /**
  27. * 根据主键查询整个对象
  28. */
  29. public Singer selectByPrimaryKey(Integer id);
  30. /**
  31. * 查询所有歌手
  32. */
  33. public List<Singer> allSinger();
  34. /**
  35. * 根据歌手名字模糊查询列表
  36. */
  37. public List<Singer> singerOfName(String name);
  38. /**
  39. * 根据性别查询
  40. */
  41. public List<Singer> singerOfSex(Integer sex);
  42. }
  1. package com.gmw.musicserver.service.impl;
  2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  3. import com.gmw.musicserver.entity.Singer;
  4. import com.gmw.musicserver.mapper.SingerMapper;
  5. import com.gmw.musicserver.service.SingerService;
  6. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  7. import org.springframework.stereotype.Service;
  8. import java.util.List;
  9. /**
  10. * <p>
  11. * 歌手表 服务实现类
  12. * </p>
  13. *
  14. * @author 未进化的程序猿
  15. * @since 2022-01-26
  16. */
  17. @Service
  18. public class SingerServiceImpl extends ServiceImpl<SingerMapper, Singer> implements SingerService {
  19. /**
  20. * 添加歌手
  21. * @param singer
  22. * @return
  23. */
  24. @Override
  25. public boolean insertSinger(Singer singer) {
  26. int insert = this.baseMapper.insert(singer);
  27. return insert > 0;
  28. }
  29. /**
  30. * 更新歌手
  31. * @param singer
  32. * @return
  33. */
  34. @Override
  35. public boolean updateSinger(Singer singer) {
  36. return this.baseMapper.updateById(singer) > 0;
  37. }
  38. /**
  39. * 删除歌手
  40. * @param id
  41. * @return
  42. */
  43. @Override
  44. public boolean deleteSinger(Integer id) {
  45. return this.baseMapper.deleteById(id) > 0;
  46. }
  47. /**
  48. * 根据主键ID查询歌手
  49. * @param id
  50. * @return
  51. */
  52. @Override
  53. public Singer selectByPrimaryKey(Integer id) {
  54. return this.baseMapper.selectById(id);
  55. }
  56. /**
  57. * 查询所有的歌手
  58. * @return
  59. */
  60. @Override
  61. public List<Singer> allSinger() {
  62. return this.baseMapper.selectList(null);
  63. }
  64. /**
  65. * 根据歌手的名称,模糊查询所有歌手
  66. * @param name
  67. * @return
  68. */
  69. @Override
  70. public List<Singer> singerOfName(String name) {
  71. QueryWrapper<Singer> queryWrapper = new QueryWrapper<>();
  72. queryWrapper.like("name",name);
  73. return this.baseMapper.selectList(queryWrapper);
  74. }
  75. /**
  76. * 根据性别查询所有的歌手
  77. * @param sex
  78. * @return
  79. */
  80. @Override
  81. public List<Singer> singerOfSex(Integer sex) {
  82. QueryWrapper<Singer> queryWrapper = new QueryWrapper<>();
  83. queryWrapper.eq("sex",sex);
  84. return this.baseMapper.selectList(queryWrapper);
  85. }
  86. }

1.2 Controller控制层编写

  1. package com.gmw.musicserver.controller;
  2. import com.gmw.musicserver.commonutils.R;
  3. import com.gmw.musicserver.entity.Singer;
  4. import com.gmw.musicserver.service.SingerService;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.web.bind.annotation.*;
  9. import org.springframework.web.multipart.MultipartFile;
  10. import javax.servlet.http.HttpServletRequest;
  11. import java.io.File;
  12. import java.io.IOException;
  13. import java.text.DateFormat;
  14. import java.text.ParseException;
  15. import java.text.SimpleDateFormat;
  16. import java.util.Date;
  17. import java.util.List;
  18. /**
  19. * <p>
  20. * 歌手表 前端控制器
  21. * 歌手管理
  22. * </p>
  23. *
  24. * @author 未进化的程序猿
  25. * @since 2022-01-26
  26. */
  27. @RestController
  28. @RequestMapping("/musicserver/singer")
  29. public class SingerController {
  30. public static final Logger logger = LoggerFactory.getLogger(SingerController.class);
  31. @Autowired
  32. public SingerService singerService;
  33. /**
  34. * 添加歌手
  35. */
  36. @PostMapping(value = "/addSinger")
  37. public R addSinger(HttpServletRequest request){
  38. String name = request.getParameter("name").trim(); //姓名
  39. String sex = request.getParameter("sex").trim(); //性别
  40. String pic = request.getParameter("pic").trim(); //头像
  41. String birth = request.getParameter("birth").trim(); //生日
  42. String location = request.getParameter("location").trim();//地区
  43. String introduction = request.getParameter("introduction").trim();//简介
  44. //把生日转换成Date格式
  45. DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
  46. Date birthDate = new Date();
  47. try {
  48. birthDate = dateFormat.parse(birth);
  49. } catch (ParseException e) {
  50. e.printStackTrace();
  51. }
  52. //保存到歌手的对象中
  53. Singer singer = new Singer();
  54. singer.setName(name);
  55. singer.setSex(Integer.parseInt(sex));
  56. singer.setBirth(birthDate);
  57. singer.setLocation(location);
  58. singer.setIntroduction(introduction);
  59. singer.setPic("/img/singerPic/hhh.jpg");
  60. logger.info("歌手对象: {}",singer);
  61. boolean flag = this.singerService.insertSinger(singer);
  62. if(flag){
  63. return R.ok().message("添加歌手成功!!");
  64. }
  65. return R.error().message("添加歌手失败!!");
  66. }
  67. /**
  68. * 修改歌手
  69. */
  70. @PostMapping(value = "/updateSinger")
  71. public R updateSinger(HttpServletRequest request){
  72. String id = request.getParameter("id").trim(); //主键
  73. String name = request.getParameter("name").trim(); //姓名
  74. String sex = request.getParameter("sex").trim(); //性别
  75. String birth = request.getParameter("birth").trim(); //生日
  76. String location = request.getParameter("location").trim();//地区
  77. String introduction = request.getParameter("introduction").trim();//简介
  78. //把生日转换成Date格式
  79. DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
  80. Date birthDate = new Date();
  81. try {
  82. birthDate = dateFormat.parse(birth);
  83. } catch (ParseException e) {
  84. e.printStackTrace();
  85. }
  86. //保存到歌手的对象中
  87. Singer singer = new Singer();
  88. singer.setId(Integer.parseInt(id));
  89. singer.setName(name);
  90. singer.setSex(Integer.parseInt(sex));
  91. singer.setBirth(birthDate);
  92. singer.setLocation(location);
  93. singer.setIntroduction(introduction);
  94. logger.info("歌手对象: {}",singer);
  95. boolean flag = this.singerService.updateSinger(singer);
  96. if(flag){
  97. return R.ok().message("修改歌手成功!!");
  98. }
  99. return R.error().message("修改歌手失败!!");
  100. }
  101. /**
  102. * 删除歌手
  103. */
  104. @GetMapping(value = "/deleteSinger")
  105. public R deleteSinger(HttpServletRequest request){
  106. Integer id = Integer.parseInt(request.getParameter("id"));
  107. //删除歌手之前,也需要删除歌手的图片
  108. //通过ID主键查询歌手对象
  109. Singer singer = this.singerService.selectByPrimaryKey(id);
  110. //获取歌手图片
  111. String singerPic = singer.getPic();
  112. logger.info("歌手图片: {}",singerPic);
  113. //获取歌手保存的文件目录
  114. String singerPath = System.getProperty("user.dir") + singerPic;
  115. logger.info("获取歌手保存的文件目录: {}",singerPath);
  116. File file = new File(singerPath);
  117. if(file.isFile()){
  118. //判断如果是文件的话,就删除文件
  119. boolean isDelete = file.delete();
  120. logger.info("是否删除成功: {}",isDelete);
  121. if(!isDelete){
  122. return R.error().message("删除歌手失败!!");
  123. }
  124. }
  125. boolean flag = this.singerService.deleteSinger(id);
  126. if(flag){
  127. return R.ok().message("删除歌手成功!!");
  128. }
  129. return R.error().message("删除歌手失败!!");
  130. }
  131. /**
  132. * 根据主键查询整个对象
  133. */
  134. @GetMapping(value = "/selectByPrimaryKey")
  135. public R selectByPrimaryKey(HttpServletRequest request){
  136. Integer id = Integer.parseInt(request.getParameter("id"));
  137. Singer singer = this.singerService.selectByPrimaryKey(id);
  138. return R.ok().data("singer",singer);
  139. }
  140. /**
  141. * 查询所有歌手
  142. */
  143. @GetMapping(value = "/allSinger")
  144. public R allSinger(){
  145. List<Singer> singerList = this.singerService.allSinger();
  146. logger.info("查询所有歌手: {}",singerList);
  147. return R.ok().data("list",singerList);
  148. }
  149. /**
  150. * 根据歌手名字模糊查询列表
  151. */
  152. @GetMapping(value = "/singerOfName")
  153. public R singerOfName(HttpServletRequest request){
  154. String name = request.getParameter("name");
  155. logger.info("歌手名称: {}",name);
  156. List<Singer> singerList = this.singerService.singerOfName(name);
  157. return R.ok().data("list",singerList);
  158. }
  159. /**
  160. * 根据性别查询
  161. */
  162. @GetMapping(value = "/singerOfSex")
  163. public R singerOfSex(HttpServletRequest request){
  164. Integer sex = Integer.parseInt(request.getParameter("sex"));
  165. List<Singer> singerList = this.singerService.singerOfSex(sex);
  166. return R.ok().data("list",singerList);
  167. }
  168. /**
  169. * 更新歌手图片
  170. */
  171. @PostMapping(value = "/updateSingerPic")
  172. public R updateSingerPic(@RequestParam("file")MultipartFile file,@RequestParam("id") Integer id){
  173. logger.info("歌手ID: {}",id);
  174. //判断上传的图片是否为空
  175. if(file.isEmpty()){
  176. logger.info("上传图片失败");
  177. return R.error().message("上传图片失败!!");
  178. }
  179. //文件名=当前时间到毫秒+原来的文件名
  180. String fileName = System.currentTimeMillis() + file.getOriginalFilename();
  181. logger.info("文件名: {}",fileName);
  182. //上传文件保存路径
  183. String filePath = System.getProperty("user.dir")
  184. + System.getProperty("file.separator") + "img"
  185. + System.getProperty("file.separator") + "singerPic";
  186. logger.info("上传文件保存路径: {}" ,filePath);
  187. //如果文件路径不存在,新增该路径
  188. File file1 = new File(filePath);
  189. if (!file1.exists()){
  190. file1.mkdir();
  191. }
  192. //实际的文件地址
  193. String fileDest = filePath + System.getProperty("file.separator") + fileName;
  194. logger.info("实际文件地址: {}",fileDest);
  195. File dest = new File(fileDest);
  196. //存储到数据库里的相对文件地址
  197. String storeAvatorPath = "/img/singerPic/" + fileName;
  198. logger.info("存储到数据库里的相对文件地址: {}",storeAvatorPath);
  199. try {
  200. //上传
  201. file.transferTo(dest);
  202. //上传成功后,根据ID,修改歌手图片
  203. Singer singer = new Singer();
  204. singer.setId(id); //歌手ID
  205. singer.setPic(storeAvatorPath); //歌手图片
  206. boolean flag = this.singerService.updateSinger(singer);
  207. if (flag){
  208. return R.ok().message("图片上传成功!!");
  209. }else {
  210. return R.error().message("图片上传失败!!");
  211. }
  212. } catch (IOException e) {
  213. logger.info("文件上传失败: {}",e.getMessage());
  214. return R.error().message("图片上传失败!!" + e.getMessage());
  215. }
  216. }
  217. }

1.3 定位头像的地址

因为当客户端浏览器访问http://127.0.0.1:8888/img/singerPic/hhh.jpg的时候,会找不到这个静态资源,所以需要我们手动的去映射;

image.png

创建一个配置类,实现WebMvcConfig接口

  1. package com.gmw.musicserver.config;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
  4. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  5. /**
  6. * 歌手图片映射配置-定位歌手头像地址
  7. */
  8. @Configuration
  9. public class SingerPicConfig implements WebMvcConfigurer {
  10. @Override
  11. public void addResourceHandlers(ResourceHandlerRegistry registry) {
  12. registry.addResourceHandler("/img/singerPic/**")
  13. .addResourceLocations(
  14. "file:" + System.getProperty("user.dir") + System.getProperty("file.separator")
  15. + "img" + System.getProperty("file.separator")
  16. + "singerPic" + System.getProperty("file.separator")
  17. );
  18. }
  19. }

1.4 更新歌手的图片

  1. /**
  2. * 更新歌手图片
  3. */
  4. @PostMapping(value = "/updateSingerPic")
  5. public R updateSingerPic(@RequestParam("file")MultipartFile file,@RequestParam("id") Integer id){
  6. logger.info("歌手ID: {}",id);
  7. //判断上传的图片是否为空
  8. if(file.isEmpty()){
  9. logger.info("上传图片失败");
  10. return R.error().message("上传图片失败!!");
  11. }
  12. //文件名=当前时间到毫秒+原来的文件名
  13. String fileName = System.currentTimeMillis() + file.getOriginalFilename();
  14. logger.info("文件名: {}",fileName);
  15. //上传文件保存路径
  16. String filePath = System.getProperty("user.dir")
  17. + System.getProperty("file.separator") + "img"
  18. + System.getProperty("file.separator") + "singerPic";
  19. logger.info("上传文件保存路径: {}" ,filePath);
  20. //如果文件路径不存在,新增该路径
  21. File file1 = new File(filePath);
  22. if (!file1.exists()){
  23. file1.mkdir();
  24. }
  25. //实际的文件地址
  26. String fileDest = filePath + System.getProperty("file.separator") + fileName;
  27. logger.info("实际文件地址: {}",fileDest);
  28. File dest = new File(fileDest);
  29. //存储到数据库里的相对文件地址
  30. String storeAvatorPath = "/img/singerPic/" + fileName;
  31. logger.info("存储到数据库里的相对文件地址: {}",storeAvatorPath);
  32. try {
  33. //上传
  34. file.transferTo(dest);
  35. //上传成功后,根据ID,修改歌手图片
  36. Singer singer = new Singer();
  37. singer.setId(id); //歌手ID
  38. singer.setPic(storeAvatorPath); //歌手图片
  39. boolean flag = this.singerService.updateSinger(singer);
  40. if (flag){
  41. return R.ok().message("图片上传成功!!");
  42. }else {
  43. return R.error().message("图片上传失败!!");
  44. }
  45. } catch (IOException e) {
  46. logger.info("文件上传失败: {}",e.getMessage());
  47. return R.error().message("图片上传失败!!" + e.getMessage());
  48. }
  49. }

2、前端编写

image.png

代码如下:

  1. <template>
  2. <div class="table">
  3. <div class="container">
  4. <div class="handle-box">
  5. <el-button type="primary" size="mini" @click="delAll">批量删除</el-button>
  6. <el-input v-model="select_word" size="mini" placeholder="请输入歌手名" class="handle-input"></el-input>
  7. <el-button type="primary" size="mini" @click="centerDialogVisible = true">添加歌手</el-button>
  8. </div>
  9. </div>
  10. <el-table size="mini" ref="multipleTable" border style="width:100%" height="680px" :data="data" @selection-change="handleSelectionChange">
  11. <el-table-column type="selection" width="40"></el-table-column>
  12. <el-table-column label="歌手图片" width="110" align="center">
  13. <template slot-scope="scope">
  14. <div class="singer-img">
  15. <img :src="getUrl(scope.row.pic)" style="width:100%"/>
  16. </div>
  17. <el-upload :action="uploadUrl(scope.row.id)" :before-upload="beforeAvatorUpload"
  18. :on-success="handleAvatorSuccess">
  19. <el-button size="mini">更新图片</el-button>
  20. </el-upload>
  21. </template>
  22. </el-table-column>
  23. <el-table-column prop="name" label="歌手" width="120" align="center"></el-table-column>
  24. <el-table-column label="性别" width="50" align="center">
  25. <template slot-scope="scope">
  26. {{changeSex(scope.row.sex)}}
  27. </template>
  28. </el-table-column>
  29. <el-table-column label="生日" width="120" align="center">
  30. <template slot-scope="scope">
  31. {{attachBirth(scope.row.birth)}}
  32. </template>
  33. </el-table-column>
  34. <el-table-column prop="location" label="地区" width="100" align="center"></el-table-column>
  35. <el-table-column label="简介">
  36. <template slot-scope="scope">
  37. <p style="height:100px;overflow:scroll">{{scope.row.introduction}}</p>
  38. </template>
  39. </el-table-column>
  40. <el-table-column label="歌曲管理" width="110" align="center">
  41. <template slot-scope="scope">
  42. <el-button size="mini" @click="songEdit(scope.row.id,scope.row.name)">歌曲管理</el-button>
  43. </template>
  44. </el-table-column>
  45. <el-table-column label="操作" width="150" align="center">
  46. <template slot-scope="scope">
  47. <el-button size="mini" @click="handleEdit(scope.row)">编辑</el-button>
  48. <el-button size="mini" type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
  49. </template>
  50. </el-table-column>
  51. </el-table>
  52. <div class="pagination">
  53. <el-pagination
  54. background
  55. layout = "total,prev,pager,next"
  56. :current-page="currentPage"
  57. :page-size="pageSize"
  58. :total="tableData.length"
  59. @current-change="handleCurrentChange"
  60. >
  61. </el-pagination>
  62. </div>
  63. <el-dialog title="添加歌手" :visible.sync="centerDialogVisible" width="400px" center>
  64. <el-form :model="registerForm" ref="registerForm" label-width="80px">
  65. <el-form-item prop="name" label="歌手名" size="mini">
  66. <el-input v-model="registerForm.name" placeholder="歌手名"></el-input>
  67. </el-form-item>
  68. <el-form-item label="性别" size="mini">
  69. <el-radio-group v-model="registerForm.sex">
  70. <el-radio :label="0"></el-radio>
  71. <el-radio :label="1"></el-radio>
  72. <el-radio :label="2">组合</el-radio>
  73. <el-radio :label="3">不明</el-radio>
  74. </el-radio-group>
  75. </el-form-item>
  76. <el-form-item prop="birth" label="生日" size="mini">
  77. <el-date-picker type="date" placeholder="选择日期" v-model="registerForm.birth" style="width:100%"></el-date-picker>
  78. </el-form-item>
  79. <el-form-item prop="location" label="地区" size="mini">
  80. <el-input v-model="registerForm.location" placeholder="地区"></el-input>
  81. </el-form-item>
  82. <el-form-item prop="introduction" label="简介" size="mini">
  83. <el-input v-model="registerForm.introduction" placeholder="简介" type="textarea"></el-input>
  84. </el-form-item>
  85. </el-form>
  86. <span slot="footer">
  87. <el-button size="mini" @click="centerDialogVisible = false">取消</el-button>
  88. <el-button size="mini" @click="addSinger">确定</el-button>
  89. </span>
  90. </el-dialog>
  91. <el-dialog title="修改歌手" :visible.sync="editVisible" width="400px" center>
  92. <el-form :model="form" ref="form" label-width="80px">
  93. <el-form-item prop="name" label="歌手名" size="mini">
  94. <el-input v-model="form.name" placeholder="歌手名"></el-input>
  95. </el-form-item>
  96. <el-form-item label="性别" size="mini">
  97. <el-radio-group v-model="form.sex">
  98. <el-radio :label="0"></el-radio>
  99. <el-radio :label="1"></el-radio>
  100. <el-radio :label="2">组合</el-radio>
  101. <el-radio :label="3">不明</el-radio>
  102. </el-radio-group>
  103. </el-form-item>
  104. <el-form-item label="生日" size="mini">
  105. <el-date-picker type="date" placeholder="选择日期" v-model="form.birth" style="width:100%"></el-date-picker>
  106. </el-form-item>
  107. <el-form-item prop="location" label="地区" size="mini">
  108. <el-input v-model="form.location" placeholder="地区"></el-input>
  109. </el-form-item>
  110. <el-form-item prop="introduction" label="简介" size="mini">
  111. <el-input v-model="form.introduction" placeholder="简介" type="textarea"></el-input>
  112. </el-form-item>
  113. </el-form>
  114. <span slot="footer">
  115. <el-button size="mini" @click="editVisible = false">取消</el-button>
  116. <el-button size="mini" @click="editSave">确定</el-button>
  117. </span>
  118. </el-dialog>
  119. <el-dialog title="删除歌手" :visible.sync="delVisible" width="300px" center>
  120. <div align="center">删除不可恢复,是否确定删除?</div>
  121. <span slot="footer">
  122. <el-button size="mini" @click="delVisible = false">取消</el-button>
  123. <el-button size="mini" @click="deleteRow">确定</el-button>
  124. </span>
  125. </el-dialog>
  126. </div>
  127. </template>
  128. <script>
  129. import {setSinger, getAllSinger,updateSinger,delSinger} from '../api/singer/index';
  130. import { mixin } from '../mixins/index';
  131. export default {
  132. mixins: [mixin],
  133. data(){
  134. return{
  135. centerDialogVisible: false, //添加弹窗是否显示
  136. editVisible: false, //编辑弹窗是否显示
  137. delVisible: false, //删除弹窗是否显示
  138. registerForm:{ //添加框
  139. name: '',
  140. sex: '',
  141. birth: '',
  142. location: '',
  143. introduction: ''
  144. },
  145. form:{ //编辑框
  146. id: '',
  147. name: '',
  148. sex: '',
  149. birth: '',
  150. location: '',
  151. introduction: ''
  152. },
  153. tableData: [],
  154. tempData: [],
  155. select_word: '',
  156. pageSize: 5, //分页每页大小
  157. currentPage: 1, //当前页
  158. idx: -1, //当前选择项
  159. multipleSelection: [] //哪些项已经打勾
  160. }
  161. },
  162. computed:{
  163. //计算当前搜索结果表里的数据
  164. data(){
  165. return this.tableData.slice((this.currentPage - 1) * this.pageSize,this.currentPage * this.pageSize)
  166. }
  167. },
  168. watch:{
  169. //搜索框里面的内容发生变化的时候,搜索结果table列表的内容跟着它的内容发生变化
  170. select_word: function(){
  171. if(this.select_word == ''){
  172. this.tableData = this.tempData;
  173. }else{
  174. this.tableData = [];
  175. for(let item of this.tempData){
  176. if(item.name.includes(this.select_word)){
  177. this.tableData.push(item);
  178. }
  179. }
  180. }
  181. }
  182. },
  183. created(){
  184. this.getData();
  185. },
  186. methods:{
  187. //获取当前页
  188. handleCurrentChange(val){
  189. this.currentPage = val;
  190. },
  191. //查询所有歌手
  192. getData(){
  193. this.tempData = [];
  194. this.tableData = [];
  195. getAllSinger().then(res => {
  196. this.tempData = res.data.list;
  197. this.tableData = res.data.list;
  198. })
  199. },
  200. //添加歌手
  201. addSinger(){
  202. let d = this.registerForm.birth;
  203. let datetime = d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate();
  204. let params = new URLSearchParams();
  205. params.append('name',this.registerForm.name);
  206. params.append('sex',this.registerForm.sex);
  207. params.append('pic','/img/singerPic/hhh.jpg');
  208. params.append('birth',datetime);
  209. params.append('location',this.registerForm.location);
  210. params.append('introduction',this.registerForm.introduction);
  211. setSinger(params)
  212. .then(res => {
  213. if(res.code == 20000){
  214. this.getData();
  215. this.notify("添加成功","success");
  216. }else{
  217. this.notify("添加失败","error");
  218. }
  219. })
  220. .catch(err => {
  221. console.log(err);
  222. });
  223. this.centerDialogVisible = false;
  224. },
  225. //弹出编辑页面
  226. handleEdit(row){
  227. this.editVisible = true;
  228. this.form = {
  229. id: row.id,
  230. name: row.name,
  231. sex: row.sex,
  232. birth: row.birth,
  233. location: row.location,
  234. introduction: row.introduction
  235. }
  236. },
  237. //保存编辑页面修改的数据
  238. editSave(){
  239. let d = new Date(this.form.birth);
  240. let datetime = d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate();
  241. let params = new URLSearchParams();
  242. params.append('id',this.form.id);
  243. params.append('name',this.form.name);
  244. params.append('sex',this.form.sex);
  245. params.append('birth',datetime);
  246. params.append('location',this.form.location);
  247. params.append('introduction',this.form.introduction);
  248. updateSinger(params)
  249. .then(res => {
  250. if(res.code == 20000){
  251. this.getData();
  252. this.notify("修改成功","success");
  253. }else{
  254. this.notify("修改失败","error");
  255. }
  256. })
  257. .catch(err => {
  258. console.log(err);
  259. });
  260. this.editVisible = false;
  261. },
  262. //更新图片
  263. uploadUrl(id){
  264. return `${this.$store.state.HOST}/musicserver/singer/updateSingerPic?id=${id}`
  265. },
  266. //删除一名歌手
  267. deleteRow(){
  268. delSinger(this.idx)
  269. .then(res => {
  270. if(res){
  271. this.getData();
  272. this.notify("删除成功","success");
  273. }else{
  274. this.notify("删除失败","error");
  275. }
  276. })
  277. .catch(err => {
  278. console.log(err);
  279. });
  280. this.delVisible = false;
  281. },
  282. //转向歌曲管理页面
  283. songEdit(id,name){
  284. this.$router.push({path:`/Song`,query:{id,name}});
  285. }
  286. }
  287. }
  288. </script>
  289. <style scoped>
  290. .handle-box{
  291. margin-bottom: 20px;
  292. }
  293. .singer-img{
  294. width: 100%;
  295. height: 80px;
  296. border-radius: 5px;
  297. margin-bottom: 5px;
  298. overflow: hidden;
  299. }
  300. .handle-input{
  301. width: 300px;
  302. display: inline-block;
  303. }
  304. .pagination{
  305. display: flex;
  306. justify-content: center;
  307. }
  308. </style>

2.1 添加歌手

image.png

  1. <el-button type="primary" size="mini" @click="centerDialogVisible = true">添加歌手</el-button>
  1. <el-dialog title="添加歌手" :visible.sync="centerDialogVisible" width="400px" center>
  2. <el-form :model="registerForm" ref="registerForm" label-width="80px">
  3. <el-form-item prop="name" label="歌手名" size="mini">
  4. <el-input v-model="registerForm.name" placeholder="歌手名"></el-input>
  5. </el-form-item>
  6. <el-form-item label="性别" size="mini">
  7. <el-radio-group v-model="registerForm.sex">
  8. <el-radio :label="0"></el-radio>
  9. <el-radio :label="1"></el-radio>
  10. <el-radio :label="2">组合</el-radio>
  11. <el-radio :label="3">不明</el-radio>
  12. </el-radio-group>
  13. </el-form-item>
  14. <el-form-item prop="birth" label="生日" size="mini">
  15. <el-date-picker type="date" placeholder="选择日期" v-model="registerForm.birth" style="width:100%"></el-date-picker>
  16. </el-form-item>
  17. <el-form-item prop="location" label="地区" size="mini">
  18. <el-input v-model="registerForm.location" placeholder="地区"></el-input>
  19. </el-form-item>
  20. <el-form-item prop="introduction" label="简介" size="mini">
  21. <el-input v-model="registerForm.introduction" placeholder="简介" type="textarea"></el-input>
  22. </el-form-item>
  23. </el-form>
  24. <span slot="footer">
  25. <el-button size="mini" @click="centerDialogVisible = false">取消</el-button>
  26. <el-button size="mini" @click="addSinger">确定</el-button>
  27. </span>
  28. </el-dialog>

image.png

:visible.sync=”centerDialogVisible” 表示当centerDialogVisible属性为true时才会弹出文本框,false隐藏文本框

定义属性变量
image.png
编写请求后端接口方法
image.png

  1. import {get,post} from '../http'
  2. //查询歌手
  3. export const getAllSinger =() => get(`musicserver/singer/allSinger`);
  4. //添加歌手
  5. export const setSinger = (params) => post(`musicserver/singer/addSinger`,params);
  6. //编辑歌手
  7. export const updateSinger = (params) => post(`musicserver/singer/updateSinger`,params);
  8. //删除歌手
  9. export const delSinger = (id) => get(`musicserver/singer/deleteSinger?id=${id}`);

image.png
编写添加歌手的方法
image.png

  1. //添加歌手
  2. addSinger(){
  3. let d = this.registerForm.birth;
  4. let datetime = d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate();
  5. let params = new URLSearchParams();
  6. params.append('name',this.registerForm.name);
  7. params.append('sex',this.registerForm.sex);
  8. params.append('pic','/img/singerPic/hhh.jpg');
  9. params.append('birth',datetime);
  10. params.append('location',this.registerForm.location);
  11. params.append('introduction',this.registerForm.introduction);
  12. setSinger(params)
  13. .then(res => {
  14. if(res.code == 20000){
  15. this.getData();
  16. this.notify("添加成功","success");
  17. }else{
  18. this.notify("添加失败","error");
  19. }
  20. })
  21. .catch(err => {
  22. console.log(err);
  23. });
  24. //添加歌手成功后,将弹出文本框隐藏
  25. this.centerDialogVisible = false;
  26. },

2.2 查询歌手

image.png

  1. <el-table size="mini" ref="multipleTable" border style="width:100%" height="680px" :data="data" @selection-change="handleSelectionChange">
  2. <el-table-column type="selection" width="40"></el-table-column>
  3. <el-table-column label="歌手图片" width="110" align="center">
  4. <template slot-scope="scope">
  5. <div class="singer-img">
  6. <img :src="getUrl(scope.row.pic)" style="width:100%"/>
  7. </div>
  8. <el-upload :action="uploadUrl(scope.row.id)" :before-upload="beforeAvatorUpload"
  9. :on-success="handleAvatorSuccess">
  10. <el-button size="mini">更新图片</el-button>
  11. </el-upload>
  12. </template>
  13. </el-table-column>
  14. <el-table-column prop="name" label="歌手" width="120" align="center"></el-table-column>
  15. <el-table-column label="性别" width="50" align="center">
  16. <template slot-scope="scope">
  17. {{changeSex(scope.row.sex)}}
  18. </template>
  19. </el-table-column>
  20. <el-table-column label="生日" width="120" align="center">
  21. <template slot-scope="scope">
  22. {{attachBirth(scope.row.birth)}}
  23. </template>
  24. </el-table-column>
  25. <el-table-column prop="location" label="地区" width="100" align="center"></el-table-column>
  26. <el-table-column label="简介">
  27. <template slot-scope="scope">
  28. <p style="height:100px;overflow:scroll">{{scope.row.introduction}}</p>
  29. </template>
  30. </el-table-column>
  31. <el-table-column label="歌曲管理" width="110" align="center">
  32. <template slot-scope="scope">
  33. <el-button size="mini" @click="songEdit(scope.row.id,scope.row.name)">歌曲管理</el-button>
  34. </template>
  35. </el-table-column>
  36. <el-table-column label="操作" width="150" align="center">
  37. <template slot-scope="scope">
  38. <el-button size="mini" @click="handleEdit(scope.row)">编辑</el-button>
  39. <el-button size="mini" type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
  40. </template>
  41. </el-table-column>
  42. </el-table>

处理性别的方法
image.png

  1. //获取性别中文
  2. changeSex(value){
  3. if(value == 0){
  4. return '女';
  5. }
  6. if(value == 1){
  7. return '男';
  8. }
  9. if(value == 2){
  10. return '组合';
  11. }
  12. if(value == 3){
  13. return '不明';
  14. }
  15. return value;
  16. },

处理日期的方法
image.png

  1. //获取生日
  2. attachBirth(val){
  3. return String(val).substr(0,10);
  4. },

编写请求后端查询接口
image.png
定义临时变量,接收后端传过来的值
image.png
查询所有歌手
image.png

2.3 定位头像的地址

image.png
在mixins.js工具类中,编写访问歌手图片的方法
image.png

  1. export const mixin = {
  2. methods:{
  3. //提示信息
  4. notify(title,type){
  5. this.$notify({
  6. title: title,
  7. type: type
  8. })
  9. },
  10. //根据相对地址获取绝对地址
  11. getUrl(url){
  12. return `${this.$store.state.HOST}/${url}`
  13. },
  14. //获取性别中文
  15. changeSex(value){
  16. if(value == 0){
  17. return '女';
  18. }
  19. if(value == 1){
  20. return '男';
  21. }
  22. if(value == 2){
  23. return '组合';
  24. }
  25. if(value == 3){
  26. return '不明';
  27. }
  28. return value;
  29. },
  30. //获取生日
  31. attachBirth(val){
  32. return String(val).substr(0,10);
  33. },
  34. //上传图片之前的校验
  35. beforeAvatorUpload(file){
  36. const isJPG = (file.type === 'image/jpeg')||(file.type === 'image/png');
  37. if(!isJPG){
  38. this.$message.error('上传头像图片只能是jpg或png格式');
  39. return false;
  40. }
  41. const isLt2M = (file.size / 1024 /1024) < 2;
  42. if(!isLt2M){
  43. this.$message.error('上传头像图片大小不能超过2MB');
  44. return false;
  45. }
  46. return true;
  47. },
  48. //上传图片成功之后要做的工作
  49. handleAvatorSuccess(res){
  50. let _this = this;
  51. if(res.code == 20000){
  52. _this.getData();
  53. _this.$notify({
  54. title: '上传成功',
  55. type: 'success'
  56. });
  57. }else{
  58. _this.$notify({
  59. title: '上传失败',
  60. type: 'error'
  61. });
  62. }
  63. },
  64. //弹出删除窗口
  65. handleDelete(id){
  66. this.idx = id;
  67. this.delVisible = true;
  68. },
  69. //把已经选择的项赋值给multipleSelection
  70. handleSelectionChange(val){
  71. this.multipleSelection = val;
  72. },
  73. //批量删除已经选择的项
  74. delAll(){
  75. for(let item of this.multipleSelection){
  76. this.handleDelete(item.id);
  77. this.deleteRow();
  78. }
  79. this.multipleSelection = [];
  80. }
  81. }
  82. }

image.png
编写全局共享属性Vuex.Store
image.png

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. Vue.use(Vuex)
  4. const store = new Vuex.Store({
  5. state:{
  6. HOST: 'http://127.0.0.1:8888'
  7. }
  8. })
  9. export default store

访问通过,this.$store.state.HOST,就能访问到全局共享的属性值

2.4 更新歌手图片

image.png
image.png

  1. <el-upload :action="uploadUrl(scope.row.id)" :before-upload="beforeAvatorUpload"
  2. :on-success="handleAvatorSuccess">
  3. <el-button size="mini">更新图片</el-button>
  4. </el-upload>

:action=”uploadUrl(scope.row.id)” 表示要访问的后台地址,并携带歌手的id,通过id修改歌手图像
image.png

  1. //更新图片
  2. uploadUrl(id){
  3. return `${this.$store.state.HOST}/musicserver/singer/updateSingerPic?id=${id}`
  4. },

:before-upload=”beforeAvatorUpload” 表示文件上传之前,进行哪些操作,比如:上传的文件类型、大小都可以做限制;

  1. //上传图片之前的校验
  2. beforeAvatorUpload(file){
  3. const isJPG = (file.type === 'image/jpeg')||(file.type === 'image/png');
  4. if(!isJPG){
  5. this.$message.error('上传头像图片只能是jpg或png格式');
  6. return false;
  7. }
  8. const isLt2M = (file.size / 1024 /1024) < 2;
  9. if(!isLt2M){
  10. this.$message.error('上传头像图片大小不能超过2MB');
  11. return false;
  12. }
  13. return true;
  14. },

:on-success=”handleAvatorSuccess” 表示上传成功后需要进行哪些操作,比如:提示上传成功或者失败

  1. //上传图片成功之后要做的工作
  2. handleAvatorSuccess(res){
  3. let _this = this;
  4. if(res.code == 20000){
  5. _this.getData();
  6. _this.$notify({
  7. title: '上传成功',
  8. type: 'success'
  9. });
  10. }else{
  11. _this.$notify({
  12. title: '上传失败',
  13. type: 'error'
  14. });
  15. }
  16. },

2.5 根据歌手名搜索

image.png
image.png

核心:

根据watch监听,当输入歌名的文本框上的select_word属性值发生改变时,就会出发watch监听方法。先定义一个临时的变量tempDate[],当文本框为空时,将临时变量的值赋值给tableDate[],例如:tableDate = tempDate;
否则,清空tableDate = [],遍历临时变量的值,判断临时变量集合是否包含文本框的值select_word,包含的话,将满足条件的值,放到tableDate[]集合中去;

image.png
image.png

  1. watch:{
  2. //搜索框里面的内容发生变化的时候,搜索结果table列表的内容跟着它的内容发生变化
  3. select_word: function(){
  4. if(this.select_word == ''){
  5. this.tableData = this.tempData;
  6. }else{
  7. this.tableData = [];
  8. for(let item of this.tempData){
  9. if(item.name.includes(this.select_word)){
  10. this.tableData.push(item);
  11. }
  12. }
  13. }
  14. }
  15. },

2.6 列表分页功能

image.png

  1. <div class="pagination">
  2. <el-pagination
  3. background
  4. layout = "total,prev,pager,next"
  5. :current-page="currentPage"
  6. :page-size="pageSize"
  7. :total="tableData.length"
  8. @current-change="handleCurrentChange"
  9. >
  10. </el-pagination>
  11. </div>

:current-page 表示当前页 :page-size 表示每页显示的条数 :total=”tableData.length” 表示总记录数 @current-change=”handleCurrentChange” 表示当选择某一页的时候,就会得到当前选中的页数

定义临时变量
image.png
通过计算属性,计算当前搜索结果表里的数据
image.png
在表格中设置:data属性值为,计算属性的data
image.png

2.7 修改歌手

image.png
image.png
弹出编辑页面

  1. <el-dialog title="修改歌手" :visible.sync="editVisible" width="400px" center>
  2. <el-form :model="form" ref="form" label-width="80px">
  3. <el-form-item prop="name" label="歌手名" size="mini">
  4. <el-input v-model="form.name" placeholder="歌手名"></el-input>
  5. </el-form-item>
  6. <el-form-item label="性别" size="mini">
  7. <el-radio-group v-model="form.sex">
  8. <el-radio :label="0"></el-radio>
  9. <el-radio :label="1"></el-radio>
  10. <el-radio :label="2">组合</el-radio>
  11. <el-radio :label="3">不明</el-radio>
  12. </el-radio-group>
  13. </el-form-item>
  14. <el-form-item label="生日" size="mini">
  15. <el-date-picker type="date" placeholder="选择日期" v-model="form.birth" style="width:100%"></el-date-picker>
  16. </el-form-item>
  17. <el-form-item prop="location" label="地区" size="mini">
  18. <el-input v-model="form.location" placeholder="地区"></el-input>
  19. </el-form-item>
  20. <el-form-item prop="introduction" label="简介" size="mini">
  21. <el-input v-model="form.introduction" placeholder="简介" type="textarea"></el-input>
  22. </el-form-item>
  23. </el-form>
  24. <span slot="footer">
  25. <el-button size="mini" @click="editVisible = false">取消</el-button>
  26. <el-button size="mini" @click="editSave">确定</el-button>
  27. </span>
  28. </el-dialog>

:visible.sync=”editVisible” 表示当editVisible属性为true时才会弹出文本框,false隐藏文本框

  1. //弹出编辑页面
  2. handleEdit(row){
  3. this.editVisible = true;
  4. this.form = {
  5. id: row.id,
  6. name: row.name,
  7. sex: row.sex,
  8. birth: row.birth,
  9. location: row.location,
  10. introduction: row.introduction
  11. }
  12. },

image.png
image.png
保存编辑页面修改的数据

  1. //保存编辑页面修改的数据
  2. editSave(){
  3. let d = new Date(this.form.birth);
  4. let datetime = d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate();
  5. let params = new URLSearchParams();
  6. params.append('id',this.form.id);
  7. params.append('name',this.form.name);
  8. params.append('sex',this.form.sex);
  9. params.append('birth',datetime);
  10. params.append('location',this.form.location);
  11. params.append('introduction',this.form.introduction);
  12. updateSinger(params)
  13. .then(res => {
  14. if(res.code == 20000){
  15. this.getData();
  16. this.notify("修改成功","success");
  17. }else{
  18. this.notify("修改失败","error");
  19. }
  20. })
  21. .catch(err => {
  22. console.log(err);
  23. });
  24. this.editVisible = false;
  25. },

2.8 删除歌手

image.png
image.png
定义临时变量
image.png
弹出删除窗口

  1. //弹出删除窗口
  2. handleDelete(id){
  3. this.idx = id;
  4. this.delVisible = true;
  5. },
  1. <el-dialog title="删除歌手" :visible.sync="delVisible" width="300px" center>
  2. <div align="center">删除不可恢复,是否确定删除?</div>
  3. <span slot="footer">
  4. <el-button size="mini" @click="delVisible = false">取消</el-button>
  5. <el-button size="mini" @click="deleteRow">确定</el-button>
  6. </span>
  7. </el-dialog>

image.png
删除一名歌手

  1. //删除一名歌手
  2. deleteRow(){
  3. delSinger(this.idx)
  4. .then(res => {
  5. if(res){
  6. this.getData();
  7. this.notify("删除成功","success");
  8. }else{
  9. this.notify("删除失败","error");
  10. }
  11. })
  12. .catch(err => {
  13. console.log(err);
  14. });
  15. this.delVisible = false;
  16. },

2.9 批量删除歌手

image.png
image.png

@selection-change=”handleSelectionChange” 表示可以得到选中的一组数据的集合

定义一个变量集合用来存储
image.png
把已经选择的项赋值给multipleSelection

  1. //把已经选择的项赋值给multipleSelection
  2. handleSelectionChange(val){
  3. this.multipleSelection = val;
  4. },

批量删除已经选择的项

  1. //批量删除已经选择的项
  2. delAll(){
  3. for(let item of this.multipleSelection){
  4. this.handleDelete(item.id);
  5. this.deleteRow();
  6. }
  7. this.multipleSelection = [];
  8. }

2.10 跳转到歌曲页面

image.png
image.png
image.png

  1. //转向歌曲管理页面
  2. songEdit(id,name){
  3. this.$router.push({path:`/Song`,query:{id,name}});
  4. }