feat(music): 添加点赞功能并优化音乐解析
- 在 MusicPlayer 组件中添加点赞功能,使用 Check 和 Pointer 图标表示点赞状态 - 引入 toggleLikeMusic API 接口 - 优化歌词解析逻辑,提高代码可读性和性能 - 修改 UserLikeMusic 实体类,使用复合主键设计
This commit is contained in:
@@ -1,31 +1,28 @@
|
||||
package com.test.musichouduan.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
/**
|
||||
* 用户点赞音乐实体类
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "user_like_music", uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = {"userId", "musicId"})
|
||||
})
|
||||
public class UserLikeMusic {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Entity
|
||||
@Data
|
||||
@Table(name = "user_like_music")
|
||||
@IdClass(UserLikeMusic.class)
|
||||
public class UserLikeMusic implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Id
|
||||
@Column(name = "user_id")
|
||||
private Long userId;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Id
|
||||
@Column(name = "music_id")
|
||||
private Long musicId;
|
||||
|
||||
@CreationTimestamp
|
||||
@Column(nullable = false, updatable = false)
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
<el-tooltip :content="currentMusic.liked ? '取消点赞' : '点赞'" placement="top">
|
||||
<el-button circle @click="toggleLike">
|
||||
<el-icon>
|
||||
<component :is="currentMusic.liked ? 'Pointer' : 'Pointer'" />
|
||||
<component :is="currentMusic.liked ? 'Check' : 'Pointer'" />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
@@ -296,11 +296,11 @@ import { ref, computed, watch, nextTick } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { usePlayerStore } from '../stores/player'
|
||||
import { useUserStore } from '../stores/user'
|
||||
import { processMusicUrl, toggleCollectMusic, getMusicStatus } from '../api/music'
|
||||
import { processMusicUrl, toggleCollectMusic, getMusicStatus, toggleLikeMusic } from '../api/music'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {
|
||||
VideoPlay, VideoPause, Back, Right, List, Close, Delete,
|
||||
Mute, VideoCamera, Microphone, Star, StarFilled, ArrowDown, Pointer
|
||||
Mute, VideoCamera, Microphone, Star, StarFilled, ArrowDown, Pointer, Check
|
||||
} from '@element-plus/icons-vue'
|
||||
|
||||
const router = useRouter()
|
||||
@@ -380,26 +380,27 @@ const loopModeText = computed(() => {
|
||||
|
||||
// 解析歌词
|
||||
const parsedLyric = computed(() => {
|
||||
if (!currentMusic.value || !currentMusic.value.lyric) return []
|
||||
const lyric = currentMusic.value.lyric
|
||||
const lines = lyric.split('\n')
|
||||
const timeRegExp = /\[(\d{2}):(\d{2})\.(\d{2,3})\]/g
|
||||
const result = []
|
||||
if (!currentMusic.value || !currentMusic.value.lyric) return [];
|
||||
const lyric = currentMusic.value.lyric;
|
||||
const lines = lyric.split('\n');
|
||||
const result = [];
|
||||
const timeRegExp = /\[(\d{2}):(\d{2})\.(\d{2,3})\]/g;
|
||||
|
||||
for (const line of lines) {
|
||||
const timeMatches = [...line.matchAll(timeRegExp)]
|
||||
if (timeMatches.length > 0) {
|
||||
const match = timeMatches
|
||||
const min = parseInt(match)
|
||||
const sec = parseInt(match)
|
||||
const ms = parseInt(match)
|
||||
const time = min * 60 + sec + ms / 1000
|
||||
let text = line.replace(timeRegExp, '').trim()
|
||||
if (text) {
|
||||
result.push({ time, text })
|
||||
const text = line.replace(timeRegExp, '').trim();
|
||||
if (text) {
|
||||
timeRegExp.lastIndex = 0;
|
||||
let match;
|
||||
while ((match = timeRegExp.exec(line)) !== null) {
|
||||
const min = parseInt(match, 10);
|
||||
const sec = parseInt(match, 10);
|
||||
const ms = parseInt((match || '0').padEnd(3, '0'), 10);
|
||||
const time = min * 60 + sec + ms / 1000;
|
||||
result.push({ time, text });
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.sort((a, b) => a.time - b.time)
|
||||
return result.sort((a, b) => a.time - b.time);
|
||||
})
|
||||
|
||||
// 格式化时间
|
||||
|
||||
Reference in New Issue
Block a user