Forráskód Böngészése

add:增加歌曲上传列表展示init v1

lvzhiqiang 1 éve
szülő
commit
ff621ad5a0

+ 6 - 0
pom.xml

@@ -183,6 +183,12 @@
             <artifactId>poi-ooxml</artifactId>
             <version>3.17</version>
         </dependency>
+        <!--mp3agic-->
+        <dependency>
+            <groupId>com.mpatric</groupId>
+            <artifactId>mp3agic</artifactId>
+            <version>0.9.1</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 81 - 0
src/main/java/top/lvzhiqiang/controller/MusicInfoController.java

@@ -0,0 +1,81 @@
+package top.lvzhiqiang.controller;
+
+import com.alibaba.fastjson.JSON;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import top.lvzhiqiang.dto.MusicInfoQuery;
+import top.lvzhiqiang.dto.R;
+import top.lvzhiqiang.exception.ParameterException;
+import top.lvzhiqiang.service.MusicInfoService;
+import top.lvzhiqiang.util.StringUtils;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+
+/**
+ * 音乐信息 Controller
+ *
+ * @author lvzhiqiang
+ * 2024/9/25 10:47
+ */
+@RestController
+@RequestMapping("/musicInfo")
+public class MusicInfoController {
+
+    @Resource
+    private MusicInfoService musicInfoService;
+
+    /**
+     * 音乐列表分页
+     *
+     * @param musicInfoQuery
+     * @return com.github.pagehelper.PageInfo<top.lvzhiqiang.entity.FileMusicCollection>
+     * @author lvzhiqiang
+     * 2024/9/25 10:47
+     */
+    @PostMapping("/getMusicInfoPage")
+    public Object getMusicInfoPage(@RequestBody MusicInfoQuery musicInfoQuery) {
+        return musicInfoService.getMusicInfoPage(JSON.parseObject(JSON.toJSONString(musicInfoQuery), HashMap.class));
+    }
+
+    /**
+     * 上传音乐
+     *
+     * @author lvzhiqiang
+     * 2024/9/25 10:47
+     */
+    @RequestMapping("/insertOrUpdateMusic")
+    @ResponseBody
+    public R insertOrUpdateMusic(@RequestParam("file") MultipartFile file, String remark, String categoryId, String id, String title,
+                                 String singer, String issuingDate, String collectionDate, String qualityType) {
+        if (StringUtils.isEmpty(id) && StringUtils.isEmpty(title)) {
+            throw new ParameterException("title为空!");
+        }
+
+        if (StringUtils.isEmpty(categoryId)) {
+            throw new ParameterException("categoryId为空!");
+        }
+
+        if (StringUtils.isEmpty(qualityType)) {
+            qualityType = "low";
+        }
+
+        return musicInfoService.insertOrUpdateImg(file, remark, categoryId, id, title, singer, issuingDate, collectionDate, qualityType);
+    }
+
+    @RequestMapping("/deleteMusics/{musicId}")
+    @ResponseBody
+    public R deleteMusics(@PathVariable Long musicId) {
+        if (musicId == null) {
+            throw new ParameterException("musicId为空!");
+        }
+
+        return musicInfoService.deleteMusics(musicId);
+    }
+
+
+    public static void main(String[] args) {
+        String s = "https://image.baidu.com/search/down?thumburl=https://baidu.com&url=https://tvax3.sinaimg.cn/large/006BNqYCly1ht929ixe8mj309s0dojsb.jpg";
+        System.out.println(s.length());
+    }
+}

+ 49 - 0
src/main/java/top/lvzhiqiang/dto/MusicInfoQuery.java

@@ -0,0 +1,49 @@
+package top.lvzhiqiang.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class MusicInfoQuery implements Serializable {
+
+    /**
+     * 关键词
+     */
+    private String keyword;
+
+    /**
+     * 类别
+     */
+    private String genres;
+
+    /**
+     * 演员
+     */
+    private String cast;
+
+    /**
+     * 排序{desc|asc}
+     */
+    private String order;
+
+    /**
+     * 排序字段
+     */
+    private String orderField;
+
+    /**
+     * 页号
+     */
+    private Integer pageNo;
+
+    /**
+     * 页大小
+     */
+    private Integer pageSize;
+
+    /**
+     * 大类型{骑兵,步兵,流出,待处理}
+     */
+    private String bigType;
+}

+ 2 - 0
src/main/java/top/lvzhiqiang/entity/CoinApiConfig.java

@@ -81,4 +81,6 @@ public class CoinApiConfig implements Serializable {
 
     private List<String> trackCategoryList;
     private List<JSONObject> otherAttrList;
+
+    private List<JSONObject> musicCategoryList;
 }

+ 80 - 0
src/main/java/top/lvzhiqiang/entity/FileMusicCollection.java

@@ -0,0 +1,80 @@
+package top.lvzhiqiang.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 文件-音乐表
+ *
+ * @author lvzhiqiang
+ * 2024/9/25 10:47
+ */
+@Data
+public class FileMusicCollection implements Serializable {
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 标题
+     */
+    private String title;
+
+    /**
+     * 歌手
+     */
+    private String singer;
+
+    /**
+     * 发行日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private LocalDate issuingDate;
+
+    /**
+     * 时长
+     */
+    private String duration;
+
+    /**
+     * 大小
+     */
+    private String size;
+
+    /**
+     * 路径
+     */
+    private String highQualityUrl;
+    private String lowQualityUrl;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 收藏日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private LocalDate collectionDate;
+
+    /**
+     * 删除标志{1:正常,2:已删除}
+     */
+    private Integer deleteFlag;
+
+    /**
+     * 最后修改时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime modifyTime;
+
+    private String categoryName;
+    private String categoryId;
+}

+ 3 - 0
src/main/java/top/lvzhiqiang/mapper/CoinApiConfigMapper.java

@@ -80,4 +80,7 @@ public interface CoinApiConfigMapper {
 
     @Select("select id,category_name categoryName from file_image_category where delete_flag = 1")
     List<JSONObject> findFileImageCategoryList();
+
+    @Select("select id,category_name categoryName from file_music_collection_category where delete_flag = 1")
+    List<JSONObject> findFileMusicCategoryList();
 }

+ 44 - 0
src/main/java/top/lvzhiqiang/mapper/MusicInfoMapper.java

@@ -0,0 +1,44 @@
+package top.lvzhiqiang.mapper;
+
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import top.lvzhiqiang.entity.FileMusicCollection;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 音乐信息Mapper
+ *
+ * @author lvzhiqiang
+ * 2024/9/25 10:47
+ */
+public interface MusicInfoMapper {
+
+    @Insert("INSERT INTO file_music_collection(title, category_id, singer, issuing_date, duration, size, high_quality_url, low_quality_url, remark, collection_date, modify_time) " +
+            "VALUES (#{title}, #{categoryId}, #{singer}, #{issuingDate}, #{duration}, #{size}, #{highQualityUrl}, #{lowQualityUrl}, #{remark}, #{collectionDate}, now())")
+    void insertFileMusic(FileMusicCollection fileMusicCollection);
+
+    @Select("select * from file_music_collection where id = #{id}")
+    FileMusicCollection findFileMusicCollectionById(Long id);
+
+    @Update("update file_music_collection set title=#{title},category_id=#{categoryId},singer=#{singer},issuing_date=#{issuingDate},duration=#{duration},size=#{size}," +
+            "high_quality_url=#{highQualityUrl},low_quality_url=#{lowQualityUrl},remark=#{remark},collection_date=#{collectionDate},modify_time=now() where id=#{id}")
+    void updateFileMusicCollection(FileMusicCollection fileMusicCollection);
+
+    @Select({"<script>" +
+            "select a.* from file_music_collection a WHERE a.delete_flag = 1" +
+            "<if test=\"keyword != null and keyword != ''\">" +
+            "   and (a.title like concat('%',#{keyword},'%') or a.remark like concat('%',#{keyword},'%') or a.singer like concat('%',#{keyword},'%'))" +
+            "</if>" +
+            "<if test=\"categoryField != null and categoryField != ''\">" +
+            "   and a.category_id like concat('%',#{categoryField},'%') " +
+            "</if>" +
+            " order by ${sortField} ${sort}" +
+            "</script>"})
+    List<FileMusicCollection> findMusicCollectionList(Map<String, Object> params);
+
+    @Select("delete from file_music_collection where id = #{id}")
+    void deleteFileMusicCollectionById(Long musicId);
+}

+ 25 - 0
src/main/java/top/lvzhiqiang/service/MusicInfoService.java

@@ -0,0 +1,25 @@
+package top.lvzhiqiang.service;
+
+import org.springframework.web.multipart.MultipartFile;
+import top.lvzhiqiang.dto.R;
+
+import java.util.Map;
+
+/**
+ * 音乐信息Service
+ *
+ * @author lvzhiqiang
+ * 2024/9/25 10:47
+ */
+public interface MusicInfoService {
+    /**
+     * 条件查询
+     *
+     * @return
+     */
+    Object getMusicInfoPage(Map<String, Object> params);
+
+    R insertOrUpdateImg(MultipartFile file, String remark, String categoryId, String id, String title, String singer, String issuingDate, String collectionDate, String qualityType);
+
+    R deleteMusics(Long musicId);
+}

+ 2 - 0
src/main/java/top/lvzhiqiang/service/impl/CoinApiConfigServiceImpl.java

@@ -61,6 +61,8 @@ public class CoinApiConfigServiceImpl implements CoinApiConfigService {
                 coinApiConfig.setTrackCategoryList(coinApiConfigMapper.findTrackCategoryList());
             } else if (coinApiConfig.getNameEn().equals("image")) {
                 coinApiConfig.setOtherAttrList(coinApiConfigMapper.findFileImageCategoryList());
+            } else if (coinApiConfig.getNameEn().equals("music")) {
+                coinApiConfig.setMusicCategoryList(coinApiConfigMapper.findFileMusicCategoryList());
             }
         }
 

+ 27 - 0
src/main/java/top/lvzhiqiang/service/impl/CoinServiceImpl.java

@@ -28,6 +28,7 @@ import top.lvzhiqiang.entity.*;
 import top.lvzhiqiang.exception.BusinessException;
 import top.lvzhiqiang.mapper.CoinApiConfigMapper;
 import top.lvzhiqiang.mapper.CoinMapper;
+import top.lvzhiqiang.mapper.MusicInfoMapper;
 import top.lvzhiqiang.mapper.PictureInfoMapper;
 import top.lvzhiqiang.service.CoinService;
 import top.lvzhiqiang.util.*;
@@ -111,6 +112,8 @@ public class CoinServiceImpl implements CoinService {
 
     @Resource
     private PictureInfoMapper pictureInfoMapper;
+    @Resource
+    private MusicInfoMapper musicInfoMapper;
 
     @Resource
     private RedissonClient redissonClient;
@@ -1583,11 +1586,21 @@ public class CoinServiceImpl implements CoinService {
             result = response.getJSONArray("data");
 
             renderMainSearch4CurrentPlan(result, params.getInteger("chaRateSort"));
+        } else if (params.getString("nameEn").equals("music")) {
+            PageHelper.startPage(params.getInteger("pageNo"), params.getInteger("pageSize"), true);
+            List<FileMusicCollection> fileMusicCollectionList = musicInfoMapper.findMusicCollectionList(params.toJavaObject(Map.class));
+
+            PageInfo<FileMusicCollection> musicCollectionPageInfo = new PageInfo<>(fileMusicCollectionList);
+
+            renderMainSearch4Music(fileMusicCollectionList);
+            return musicCollectionPageInfo;
         }
 
         return result;
     }
 
+
+
     private void renderMainSearch4CmcMap(List<CoinCmcMap> cmcMapList) {
         for (CoinCmcMap coinCmcMap : cmcMapList) {
             String platform = coinCmcMap.getPlatform();
@@ -1610,6 +1623,20 @@ public class CoinServiceImpl implements CoinService {
         }
     }
 
+    private void renderMainSearch4Music(List<FileMusicCollection> fileMusicCollectionList) {
+        List<JSONObject> fileMusicCategoryList = coinApiConfigMapper.findFileMusicCategoryList();
+        Map<String, String> fileMusicCategoryMap = fileMusicCategoryList.stream().collect(Collectors.toMap(e -> e.getString("id"), e -> e.getString("categoryName")));
+
+        String ftpBasePath = InitRunner.dicCodeMap.get("ftp_music_basepath").getCodeValue();
+        String ftpBaseUrl = InitRunner.dicCodeMap.get("ftp_baseurl").getCodeValue();
+        for (FileMusicCollection fileMusicCollection : fileMusicCollectionList) {
+            String categoryName = Arrays.stream(fileMusicCollection.getCategoryId().split(",")).map(original -> fileMusicCategoryMap.getOrDefault(original, original)).collect(Collectors.joining(","));
+            fileMusicCollection.setCategoryName(categoryName);
+            fileMusicCollection.setRemark("<span class=\"primary\" avid=\"" + fileMusicCollection.getId() + " \" >" + fileMusicCollection.getRemark() + " </span>");
+            fileMusicCollection.setLowQualityUrl(ftpBaseUrl + ftpBasePath + fileMusicCollection.getLowQualityUrl());
+        }
+    }
+
     private void renderMainSearch4Watchlist(List<CoinWatchlist> watchlistList) {
         BigDecimal bigDecimal10000 = new BigDecimal("10000");
 

+ 233 - 0
src/main/java/top/lvzhiqiang/service/impl/MusicInfoServiceImpl.java

@@ -0,0 +1,233 @@
+package top.lvzhiqiang.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.mpatric.mp3agic.InvalidDataException;
+import com.mpatric.mp3agic.Mp3File;
+import com.mpatric.mp3agic.UnsupportedTagException;
+import lombok.extern.slf4j.Slf4j;
+import org.jsoup.Connection;
+import org.jsoup.Jsoup;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+import top.lvzhiqiang.config.InitRunner;
+import top.lvzhiqiang.dto.R;
+import top.lvzhiqiang.entity.FileImage;
+import top.lvzhiqiang.entity.FileMusicCollection;
+import top.lvzhiqiang.enumeration.ResultCodeEnum;
+import top.lvzhiqiang.exception.BusinessException;
+import top.lvzhiqiang.mapper.MusicInfoMapper;
+import top.lvzhiqiang.service.MusicInfoService;
+import top.lvzhiqiang.util.DateUtils;
+import top.lvzhiqiang.util.FtpUtil;
+import top.lvzhiqiang.util.StringUtils;
+
+import javax.annotation.Resource;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.util.Map;
+
+/**
+ * 音乐信息ServiceImpl
+ *
+ * @author lvzhiqiang
+ * 2024/9/25 10:47
+ */
+@Service
+@Slf4j
+public class MusicInfoServiceImpl extends BaseServiceImpl<Object> implements MusicInfoService {
+
+    @Resource
+    private MusicInfoMapper musicInfoMapper;
+    @Value("${spring.profiles.active}")
+    private String env;
+
+    @Override
+    public Object getMusicInfoPage(Map<String, Object> params) {
+        return null;
+    }
+
+    @Override
+    public R insertOrUpdateImg(MultipartFile file, String remark, String categoryId, String id, String title, String singer, String issuingDate, String collectionDate, String qualityType) {
+        String imageUrl = "";
+        String imageSize = "";
+        String ftpBasePath = InitRunner.dicCodeMap.get("ftp_music_basepath").getCodeValue();
+        String ftpBaseUrl = InitRunner.dicCodeMap.get("ftp_baseurl").getCodeValue();
+        if (StringUtils.isEmpty(id)) {
+            FileMusicCollection fileMusicCollection = new FileMusicCollection();
+            String parentPath = StringUtils.isEmpty(issuingDate) ? String.valueOf(LocalDate.now().getYear()) : issuingDate.substring(0, 4);
+            try {
+                if (file != null && "low".equals(qualityType)) {
+                    // 1、给上传的图片生成新的文件名
+                    // 1.1获取原始文件名
+                    String oldName = file.getOriginalFilename();
+                    // 1.2使用FtpUtil工具类生成新的文件名,新文件名 = newName + 文件后缀
+                    String newName = FtpUtil.genImageName();
+                    newName = newName + oldName.substring(oldName.lastIndexOf("."));
+                    // 2、把图片上传到图片服务器
+                    // 2.1获取上传的io流
+                    InputStream input = file.getInputStream();
+
+                    // 2.2调用FtpUtil工具类进行上传
+                    boolean result = FtpUtil.uploadFile(ftpBasePath, parentPath, newName, input);
+
+                    if (result) {
+                        File tempFile = null;
+                        try {
+                            tempFile = File.createTempFile("tempMp3", ".mp3");
+                            file.transferTo(tempFile); // 将 MultipartFile 保存到临时文件
+                            Mp3File mp3 = new Mp3File(tempFile.getAbsolutePath());
+                            long durationInMillis = mp3.getLengthInMilliseconds(); // 时长(毫秒)
+                            // 转换为分:秒格式
+                            long seconds = durationInMillis / 1000; // 转换为秒
+                            long minutes = seconds / 60; // 分钟
+                            seconds = seconds % 60; // 剩余的秒数
+                            fileMusicCollection.setDuration(String.format("%02d:%02d", minutes, seconds));
+                        } catch (Exception e) {
+                            log.error("Mp3File process fail", e);
+                        } finally {
+                            // 删除临时文件
+                            if (tempFile != null && tempFile.exists()) {
+                                tempFile.delete();
+                            }
+                        }
+
+                        imageSize = BigDecimal.valueOf(file.getSize()).divide(new BigDecimal("1048576")).setScale(0, RoundingMode.UP).toPlainString().concat("MB");
+                        fileMusicCollection.setSize(imageSize);
+                        // 返回给前端图片访问路径
+                        imageUrl = parentPath + "/" + newName;
+                        fileMusicCollection.setLowQualityUrl(imageUrl);
+                    }
+                }
+
+                fileMusicCollection.setTitle(title);
+                fileMusicCollection.setCategoryId(categoryId);
+                fileMusicCollection.setSinger(singer);
+                fileMusicCollection.setIssuingDate(StringUtils.isEmpty(issuingDate) ? null : LocalDate.parse(issuingDate, DateUtils.dateFormatter));
+                fileMusicCollection.setRemark(remark);
+                fileMusicCollection.setCollectionDate(StringUtils.isEmpty(collectionDate) ? null : LocalDate.parse(collectionDate, DateUtils.dateFormatter));
+
+                musicInfoMapper.insertFileMusic(fileMusicCollection);
+            } catch (IOException e) {
+                log.error("insertOrUpdateMusic Exception,fileMusicCollection={}", fileMusicCollection, e);
+            }
+
+            JSONObject result = new JSONObject();
+            result.put("imageUrl", ftpBaseUrl + ftpBasePath + imageUrl);
+            result.put("imageSize", imageSize);
+
+            return R.ok().data(result);
+        } else {
+            FileMusicCollection fileMusicCollection = musicInfoMapper.findFileMusicCollectionById(Long.valueOf(id));
+            if (fileMusicCollection == null) {
+                throw new BusinessException(ResultCodeEnum.UNKNOWN_ERROR.getCode(), "ID 不存在!");
+            }
+
+            fileMusicCollection.setCategoryId(categoryId);
+            if (StringUtils.isNotEmpty(remark)) {
+                fileMusicCollection.setRemark(remark);
+            }
+            if (StringUtils.isNotEmpty(title)) {
+                fileMusicCollection.setTitle(title);
+            }
+            if (StringUtils.isNotEmpty(singer)) {
+                fileMusicCollection.setSinger(singer);
+            }
+            if (StringUtils.isNotEmpty(issuingDate)) {
+                fileMusicCollection.setIssuingDate(LocalDate.parse(issuingDate, DateUtils.dateFormatter));
+            }
+            if (StringUtils.isNotEmpty(collectionDate)) {
+                fileMusicCollection.setCollectionDate(LocalDate.parse(collectionDate, DateUtils.dateFormatter));
+            }
+
+            String parentPath = StringUtils.isEmpty(issuingDate) && fileMusicCollection.getIssuingDate() == null ? String.valueOf(LocalDate.now().getYear()) : issuingDate.substring(0, 4);
+            try {
+                if (file != null && "low".equals(qualityType)) {
+                    // 1、给上传的图片生成新的文件名
+                    // 1.1获取原始文件名
+                    String oldName = file.getOriginalFilename();
+                    // 1.2使用FtpUtil工具类生成新的文件名,新文件名 = newName + 文件后缀
+                    String newName = FtpUtil.genImageName();
+                    newName = newName + oldName.substring(oldName.lastIndexOf("."));
+                    // 2、把图片上传到图片服务器
+                    // 2.1获取上传的io流
+                    InputStream input = file.getInputStream();
+
+                    // 2.2调用FtpUtil工具类进行上传
+                    boolean result = FtpUtil.uploadFile(ftpBasePath, parentPath, newName, input);
+                    if (result) {
+                        FtpUtil.delFile(ftpBasePath + fileMusicCollection.getLowQualityUrl());
+
+                        File tempFile = null;
+                        try {
+                            tempFile = File.createTempFile("tempMp3", ".mp3");
+                            file.transferTo(tempFile); // 将 MultipartFile 保存到临时文件
+                            Mp3File mp3 = new Mp3File(tempFile.getAbsolutePath());
+                            long durationInMillis = mp3.getLengthInMilliseconds(); // 时长(毫秒)
+                            // 转换为分:秒格式
+                            long seconds = durationInMillis / 1000; // 转换为秒
+                            long minutes = seconds / 60; // 分钟
+                            seconds = seconds % 60; // 剩余的秒数
+                            fileMusicCollection.setDuration(String.format("%02d:%02d", minutes, seconds));
+                        } catch (Exception e) {
+                            log.error("Mp3File process fail", e);
+                        } finally {
+                            // 删除临时文件
+                            if (tempFile != null && tempFile.exists()) {
+                                tempFile.delete();
+                            }
+                        }
+
+                        imageSize = BigDecimal.valueOf(file.getSize()).divide(new BigDecimal("1048576")).setScale(2, RoundingMode.UP).toPlainString().concat("MB");
+                        fileMusicCollection.setSize(imageSize);
+                        // 返回给前端图片访问路径
+                        imageUrl = parentPath + "/" + newName;
+                        fileMusicCollection.setLowQualityUrl(imageUrl);
+                    } else {
+                        throw new BusinessException(ResultCodeEnum.UNKNOWN_ERROR.getCode(), "上传新文件失败!");
+                    }
+                }
+
+                musicInfoMapper.updateFileMusicCollection(fileMusicCollection);
+            } catch (Exception e) {
+                log.error("insertOrUpdateMusic Exception,fileMusicCollection={}", fileMusicCollection, e);
+                return R.error().message(e.getMessage());
+            }
+
+            return R.ok().data("success");
+        }
+    }
+
+    @Override
+    public R deleteMusics(Long musicId) {
+        FileMusicCollection fileMusicCollection = musicInfoMapper.findFileMusicCollectionById(musicId);
+        if (fileMusicCollection == null) {
+            throw new BusinessException(ResultCodeEnum.UNKNOWN_ERROR.getCode(), "ID 不存在!");
+        }
+
+        try {
+            String ftpBasePath = InitRunner.dicCodeMap.get("ftp_music_basepath").getCodeValue();
+            boolean flag = FtpUtil.delFile(ftpBasePath + fileMusicCollection.getLowQualityUrl());
+            if (flag) {
+                musicInfoMapper.deleteFileMusicCollectionById(musicId);
+                return R.ok();
+            } else {
+                return R.error().message("删除失败");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return R.error().message(e.getMessage());
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        String srcUrl = "https://image.baidu.com/search/down?thumburl=https://baidu.com&url=https://tva1.sinaimg.cn/mw690/007Y7SRMly1gmays3w173j30ol16fh8x.jpg";
+        Connection.Response response = Jsoup.connect(srcUrl).method(Connection.Method.GET).ignoreContentType(true).timeout(50 * 1000).execute();
+        byte[] imageBytes = response.bodyAsBytes();
+        System.out.println(imageBytes.length);
+    }
+}

+ 60 - 1
src/main/resources/static/coin.html

@@ -85,7 +85,7 @@
         white-space: nowrap;
     }
 
-    .quiet-loading, .uploadImgs-loading, .watchlist-loading {
+    .quiet-loading, .uploadImgs-loading, .uploadMusics-loading, .watchlist-loading {
         display: none;
         position: absolute;
         z-index: 999;
@@ -332,6 +332,28 @@
                 <option value="asc">asc</option>
             </select>
         </div>
+        <div id="apis-quiet-div-music" style="display: none;">
+            <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="prev">上一页</button>
+            <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="next">下一页</button>
+            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-music-pageNo" value="1">
+            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-music-pageSize" disabled="disabled" value="20">
+            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-music-pages" disabled="disabled" value="999999">
+            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-music-keyword" placeholder="关键词">
+            <select id="apis-quiet-div-music-categoryField" style="height: 24px;">
+                <option value="">--</option>
+            </select>
+            <select id="apis-quiet-div-music-sortField" style="height: 24px;">
+                <option value="a.modify_time">更新时间</option>
+                <option value="a.issuing_date">发型日期</option>
+                <option value="a.collection_date">收藏日期</option>
+                <option value="a.duration">时长</option>
+                <option value="a.size">大小</option>
+            </select>
+            <select id="apis-quiet-div-music-sort" style="height: 24px;">
+                <option value="desc">desc</option>
+                <option value="asc">asc</option>
+            </select>
+        </div>
         <div id="apis-quiet-div-cmcmap" style="display: none;">
             <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="prev">上一页</button>
             <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="next">下一页</button>
@@ -418,6 +440,10 @@
     </div>
     <div id="apis-quiet-content" style="display: none;">
         total:<span class="contentSPAN">0</span>
+        <audio controls style="display: none;">
+            <source src="" type="audio/mpeg">
+            您的浏览器不支持音频播放。
+        </audio>
         <table border="1" cellspacing="0">
             <div class="quiet-loading"><img src='cover/loading.gif'></div>
             <thead>
@@ -452,6 +478,39 @@
     </div>
     <div style="display: flex;">
         <div style="margin-right:20px;">
+            <div class="uploadMusics-loading"><img src='cover/loading.gif'></div>
+            <span class="font">InsertOrUpdateMusic</span>
+            <span id="uploadMusicsAlert" style="margin-left: 10px;font-size: 13px;"></span>
+            <form method="post" action="musicInfo/insertOrUpdateMusic" enctype="multipart/form-data" onsubmit="return false;" id="uploadMusics">
+                <span>Id</span>
+                <input type="text" name="id" placeholder="可为空" style="width: 50px;"/>
+                <span>标题</span>
+                <input type="text" name="title" placeholder="ID为空时不可为空"/>
+                <span>分类</span>
+                <select id="apis-quiet-div-uploadMusics-categoryField" style="height: 24px;" name="categoryId">
+                    <option value="">--</option>
+                </select>
+                <span>歌手</span>
+                <input type="text" name="singer" placeholder="可为空" style="width: 100px;"/>
+                <span>发行时间</span>
+                <input type="text" name="issuingDate" placeholder="可为空" style="width: 100px;"/>
+                <span>收藏日期</span>
+                <input type="text" name="collectionDate" placeholder="可为空" style="width: 100px;"/>
+                <span>备注</span>
+                <input type="text" name="remark" placeholder="可为空"/>
+                <select style="height: 24px;" name="qualityType">
+                    <option value="low">低品质</option>
+                    <option value="high">高品质</option>
+                </select>
+                <span>文件</span>
+                <input type="file" name="file" multiple/>
+                <input type="button" value="提交" onclick="uploadMusicsSubmit()">
+                <input type="reset" value="重置">
+            </form>
+        </div>
+    </div>
+    <div style="display: flex;">
+        <div style="margin-right:20px;">
             <div class="watchlist-loading"><img src='cover/loading.gif'></div>
             <span class="font">InsertOrUpdateWatchlist</span>
             <span id="insertOrUpdateWatchlistAlert" style="margin-left: 10px;font-size: 13px;"></span>

+ 101 - 4
src/main/resources/static/js/my-coin.js

@@ -157,19 +157,26 @@ function initOther4Select() {
                     }
 
                     // watchlist
-                    if (obj.nameEn === 'watchlist'){
+                    if (obj.nameEn === 'watchlist') {
                         var watchlistTrackCategoryStr = '';
                         $.each(obj.trackCategoryList, function (index2, obj2) {
                             watchlistTrackCategoryStr += '<option value="' + obj2 + '">' + obj2 + '</option>';
                         });
                         $("#apis-quiet-div-watchlist-trackCategoryField").append(watchlistTrackCategoryStr);
-                    }else if (obj.nameEn === 'image'){
+                    } else if (obj.nameEn === 'image') {
                         var uploadImageCategoryStr = '';
                         $.each(obj.otherAttrList, function (index2, obj2) {
                             uploadImageCategoryStr += '<option value="' + obj2.id + '">' + obj2.categoryName + '</option>';
                         });
                         $("#apis-quiet-div-uploadImgs-categoryField").append(uploadImageCategoryStr);
                         $("#apis-quiet-div-image-categoryField").append(uploadImageCategoryStr);
+                    } else if (obj.nameEn === 'music') {
+                        var uploadMusicCategoryStr = '';
+                        $.each(obj.musicCategoryList, function (index2, obj2) {
+                            uploadMusicCategoryStr += '<option value="' + obj2.id + '">' + obj2.categoryName + '</option>';
+                        });
+                        $("#apis-quiet-div-uploadMusics-categoryField").append(uploadMusicCategoryStr);
+                        $("#apis-quiet-div-music-categoryField").append(uploadMusicCategoryStr);
                     }
                 });
 
@@ -246,10 +253,18 @@ function handleSelectChange(objj) {
             $.each(returnEn, function (index, obj) {
                 theadStr += '<th returnEn="' + obj + '">' + returnCn[index] + '</th>';
             });
-            if (nameEn === 'watchlist' || nameEn === 'image') {
+            if (nameEn === 'watchlist' || nameEn === 'image' || nameEn === 'music') {
                 theadStr += '<th>操作</th>';
             }
 
+            if (nameEn === 'music') {
+                $("#apis-quiet-content > audio").css("display", "block");
+            } else {
+                $("#apis-quiet-content > audio").css("display", "none");
+                $("#apis-quiet-content > audio > source").attr("src", "");
+                $("#apis-quiet-content > audio")[0].load();
+            }
+
             $(obj).parent("div").next("div").find("span.contentSPAN").html('0');
             $(obj).parent("div").next("div").find("tr.contentTH").html(theadStr);
             $(obj).parent("div").next("div").find("tbody.contentTD").html('');
@@ -352,6 +367,13 @@ function mainSearch(url, nameEn, slideDiv, typetype, needCustomFlag) {
         jsonData.sortField = $("#apis-quiet-div-cmcmap-sortField").val();
         jsonData.sort = $("#apis-quiet-div-cmcmap-sort").val();
         jsonData.filterField = $("#apis-quiet-div-cmcmap-filterField").val();
+    } else if (nameEn === 'music') {
+        jsonData.pageNo = $("#apis-quiet-div-music-pageNo").val();
+        jsonData.pageSize = $("#apis-quiet-div-music-pageSize").val();
+        jsonData.keyword = $("#apis-quiet-div-music-keyword").val();
+        jsonData.sortField = $("#apis-quiet-div-music-sortField").val();
+        jsonData.sort = $("#apis-quiet-div-music-sort").val();
+        jsonData.categoryField = $("#apis-quiet-div-music-categoryField").val();
     }
 
     $.ajax({
@@ -368,7 +390,7 @@ function mainSearch(url, nameEn, slideDiv, typetype, needCustomFlag) {
                     return;
                 }
 
-                if (nameEn === 'orderHistoryProductType' || nameEn === 'traderList' || nameEn === 'watchlist' || nameEn === 'image' || nameEn === 'cmcmap') {
+                if (nameEn === 'orderHistoryProductType' || nameEn === 'traderList' || nameEn === 'watchlist' || nameEn === 'image' || nameEn === 'cmcmap' || nameEn === 'music') {
                     $("#apis-quiet-div-" + nameEn).find("input[id$=pages]").val(data.data.pages);
                     $('#' + slideDiv).find("span.contentSPAN").html(data.data.total);
                     data = data.data.list;
@@ -415,6 +437,11 @@ function mainSearch(url, nameEn, slideDiv, typetype, needCustomFlag) {
                         str += '<td style="padding: 0px 10px 0px 10px;">';
                         str += '<button class="apis-quiet-div-image-delete" operationType="delete" symbolName="' + dataDetail.id + '">删除</button>';
                         str += '</td>';
+                    } else if (nameEn === 'music') {
+                        str += '<td style="padding: 0px 10px 0px 10px;">';
+                        str += '<button class="apis-quiet-div-music-delete" operationType="delete" symbolName="' + dataDetail.id + '">删除</button>';
+                        str += '<button class="apis-quiet-div-music-play" operationType="play" symbolName="' + dataDetail.lowQualityUrl + '">播放</button>';
+                        str += '</td>';
                     }
 
                     str += '</tr>';
@@ -426,6 +453,9 @@ function mainSearch(url, nameEn, slideDiv, typetype, needCustomFlag) {
                     $(".watchlistpreview-top-close").unbind("click");
                 } else if (nameEn === 'image') {
                     $(".apis-quiet-div-image-delete").unbind("click");
+                } else if (nameEn === 'music') {
+                    $(".apis-quiet-div-music-delete").unbind("click");
+                    $(".apis-quiet-div-music-play").unbind("click");
                 }
 
                 $('#' + slideDiv).find(".contentTD").html(str);
@@ -599,6 +629,38 @@ function initContentEvent(nameEn) {
                 }
             });
         });
+    } else if (nameEn === 'music') {
+        $(".apis-quiet-div-music-delete").click(function () {
+            var symbol = $(this).attr("symbolName");
+            $.ajax({
+                url: "musicInfo/deleteMusics/" + symbol, //请求的url地址
+                type: "get", //请求方式
+                async: true, //请求是否异步,默认为异步,这也是ajax重要特性
+                success: function (data) {
+                    //请求成功时处理
+                    if (data != null && $.trim(data) != "" && data.success) {
+                        $(".apis-quiet-div-button2").click();
+                    } else {
+                        alert(data.message);
+                    }
+                },
+                beforeSend: function () {
+                    $(".quiet-loading").css("display", "block");
+                },
+                complete: function () {
+                    $(".quiet-loading").css("display", "none");
+                },
+                error: function (data) {
+                    //请求出错处理
+                    alert('error:' + data);
+                }
+            });
+        });
+        $(".apis-quiet-div-music-play").click(function () {
+            var symbol = $(this).attr("symbolName");
+            $("#apis-quiet-content > audio > source").attr("src", symbol);
+            $("#apis-quiet-content > audio")[0].load();
+        });
     }
 
     if (nameEn === 'orderHistoryProductType' || nameEn === 'traderList' || nameEn === 'watchlist' || nameEn === 'image' || nameEn === 'cmcmap') {
@@ -648,6 +710,41 @@ function uploadImgsSubmit(){
     });
 }
 
+function uploadMusicsSubmit(){
+    var fromData = new FormData($("#uploadMusics")[0]);
+    $.ajax({
+        url: "musicInfo/insertOrUpdateMusic", //请求的url地址
+        dataType: "json", //返回格式为json
+        data: fromData, //参数值
+        type: "post", //请求方式
+        processData: false,// 告诉jQuery不要去处理发送的数据
+        contentType: false,// 告诉jQuery不要去设置Content-Type请求头
+        async: true, //请求是否异步,默认为异步,这也是ajax重要特性
+        success: function (data) {
+            $(".uploadMusics-loading").css("display", "none");
+            //请求成功时处理
+            if (data != null && $.trim(data) != "" && data.success) {
+                $("#uploadMusicsAlert").html(JSON.stringify(data.data));
+                var quietSelectOption = $("#apis-quiet-select option:selected");
+                if ($(quietSelectOption).attr("nameen") === 'music') {
+                    $(".apis-quiet-div-button2").click();
+                }
+            } else {
+                $("#uploadMusicsAlert").html(data.message);
+            }
+        },
+        beforeSend: function () {
+            $(".uploadMusics-loading").css("display", "block");
+        },
+        complete: function () {
+        },
+        error: function (data) {
+            //请求出错处理
+            console.log("uploadMusics-submit error," + data);
+        }
+    });
+}
+
 function insertOrUpdateWatchlistSubmit(){
     var fromData = new FormData($("#insertOrUpdateWatchlist")[0]);
     $.ajax({