mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2024-11-25 09:41:49 +08:00
feat: 复制歌词
This commit is contained in:
parent
481ba6bce3
commit
9d807d1d63
|
@ -244,6 +244,8 @@ export default {
|
||||||
minePlaylists: 'My Playlists',
|
minePlaylists: 'My Playlists',
|
||||||
likedPlaylists: 'Liked Playlists',
|
likedPlaylists: 'Liked Playlists',
|
||||||
cardiacMode: 'Cardiac Mode',
|
cardiacMode: 'Cardiac Mode',
|
||||||
|
copyLyric: 'Copy Lyric',
|
||||||
|
copyLyricWithTranslation: 'Copy Lyric With Translation',
|
||||||
},
|
},
|
||||||
toast: {
|
toast: {
|
||||||
savedToPlaylist: 'Saved to playlist',
|
savedToPlaylist: 'Saved to playlist',
|
||||||
|
|
|
@ -230,6 +230,8 @@ export default {
|
||||||
minePlaylists: 'My Playlists',
|
minePlaylists: 'My Playlists',
|
||||||
likedPlaylists: 'Liked Playlists',
|
likedPlaylists: 'Liked Playlists',
|
||||||
cardiacMode: 'Cardiac Mode',
|
cardiacMode: 'Cardiac Mode',
|
||||||
|
copyLyric: 'Copy Lyric',
|
||||||
|
copyLyricWithTranslation: 'Copy Lyric With Translation',
|
||||||
},
|
},
|
||||||
toast: {
|
toast: {
|
||||||
savedToMyLikedSongs: 'Beğendiğim Müziklere Kaydet',
|
savedToMyLikedSongs: 'Beğendiğim Müziklere Kaydet',
|
||||||
|
|
|
@ -243,6 +243,8 @@ export default {
|
||||||
minePlaylists: '创建的歌单',
|
minePlaylists: '创建的歌单',
|
||||||
likedPlaylists: '收藏的歌单',
|
likedPlaylists: '收藏的歌单',
|
||||||
cardiacMode: '心动模式',
|
cardiacMode: '心动模式',
|
||||||
|
copyLyric: '复制歌词',
|
||||||
|
copyLyricWithTranslation: '复制歌词(含翻译)',
|
||||||
},
|
},
|
||||||
toast: {
|
toast: {
|
||||||
savedToPlaylist: '已添加到歌单',
|
savedToPlaylist: '已添加到歌单',
|
||||||
|
|
|
@ -240,6 +240,8 @@ export default {
|
||||||
minePlaylists: '我建立的歌單',
|
minePlaylists: '我建立的歌單',
|
||||||
likedPlaylists: '收藏的歌單',
|
likedPlaylists: '收藏的歌單',
|
||||||
cardiacMode: '心動模式',
|
cardiacMode: '心動模式',
|
||||||
|
copyLyric: '複製歌詞',
|
||||||
|
copyLyricWithTranslation: '複製歌詞(含翻譯)',
|
||||||
},
|
},
|
||||||
toast: {
|
toast: {
|
||||||
savedToPlaylist: '已新增至歌單',
|
savedToPlaylist: '已新增至歌單',
|
||||||
|
|
|
@ -84,3 +84,30 @@ function trimContent(content) {
|
||||||
let t = content.trim();
|
let t = content.trim();
|
||||||
return t.length < 1 ? content : t;
|
return t.length < 1 ? content : t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} lyric
|
||||||
|
*/
|
||||||
|
export async function copyLyric(lyric) {
|
||||||
|
const textToCopy = lyric;
|
||||||
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(textToCopy);
|
||||||
|
} catch (err) {
|
||||||
|
alert('复制失败,请手动复制!');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const tempInput = document.createElement('textarea');
|
||||||
|
tempInput.value = textToCopy;
|
||||||
|
tempInput.style.position = 'absolute';
|
||||||
|
tempInput.style.left = '-9999px';
|
||||||
|
document.body.appendChild(tempInput);
|
||||||
|
tempInput.select();
|
||||||
|
try {
|
||||||
|
document.execCommand('copy');
|
||||||
|
} catch (err) {
|
||||||
|
alert('复制失败,请手动复制!');
|
||||||
|
}
|
||||||
|
document.body.removeChild(tempInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -248,7 +248,11 @@
|
||||||
@dblclick="clickLyricLine(line.time, true)"
|
@dblclick="clickLyricLine(line.time, true)"
|
||||||
>
|
>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<span v-if="line.contents[0]">{{ line.contents[0] }}</span>
|
<span
|
||||||
|
v-if="line.contents[0]"
|
||||||
|
@click.right="openLyricMenu($event, line, 0)"
|
||||||
|
>{{ line.contents[0] }}</span
|
||||||
|
>
|
||||||
<br />
|
<br />
|
||||||
<span
|
<span
|
||||||
v-if="
|
v-if="
|
||||||
|
@ -256,10 +260,26 @@
|
||||||
$store.state.settings.showLyricsTranslation
|
$store.state.settings.showLyricsTranslation
|
||||||
"
|
"
|
||||||
class="translation"
|
class="translation"
|
||||||
|
@click.right="openLyricMenu($event, line, 1)"
|
||||||
>{{ line.contents[1] }}</span
|
>{{ line.contents[1] }}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ContextMenu v-if="!noLyric" ref="lyricMenu">
|
||||||
|
<div class="item" @click="copyLyric(false)">{{
|
||||||
|
$t('contextMenu.copyLyric')
|
||||||
|
}}</div>
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
rightClickLyric &&
|
||||||
|
rightClickLyric.contents[1] &&
|
||||||
|
$store.state.settings.showLyricsTranslation
|
||||||
|
"
|
||||||
|
class="item"
|
||||||
|
@click="copyLyric(true)"
|
||||||
|
>{{ $t('contextMenu.copyLyricWithTranslation') }}</div
|
||||||
|
>
|
||||||
|
</ContextMenu>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
|
@ -284,9 +304,10 @@
|
||||||
|
|
||||||
import { mapState, mapMutations, mapActions } from 'vuex';
|
import { mapState, mapMutations, mapActions } from 'vuex';
|
||||||
import VueSlider from 'vue-slider-component';
|
import VueSlider from 'vue-slider-component';
|
||||||
|
import ContextMenu from '@/components/ContextMenu.vue';
|
||||||
import { formatTrackTime } from '@/utils/common';
|
import { formatTrackTime } from '@/utils/common';
|
||||||
import { getLyric } from '@/api/track';
|
import { getLyric } from '@/api/track';
|
||||||
import { lyricParser } from '@/utils/lyrics';
|
import { lyricParser, copyLyric } from '@/utils/lyrics';
|
||||||
import ButtonIcon from '@/components/ButtonIcon.vue';
|
import ButtonIcon from '@/components/ButtonIcon.vue';
|
||||||
import * as Vibrant from 'node-vibrant/dist/vibrant.worker.min.js';
|
import * as Vibrant from 'node-vibrant/dist/vibrant.worker.min.js';
|
||||||
import Color from 'color';
|
import Color from 'color';
|
||||||
|
@ -299,6 +320,7 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
VueSlider,
|
VueSlider,
|
||||||
ButtonIcon,
|
ButtonIcon,
|
||||||
|
ContextMenu,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -312,6 +334,7 @@ export default {
|
||||||
background: '',
|
background: '',
|
||||||
date: this.formatTime(new Date()),
|
date: this.formatTime(new Date()),
|
||||||
isFullscreen: !!document.fullscreenElement,
|
isFullscreen: !!document.fullscreenElement,
|
||||||
|
rightClickLyric: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -587,6 +610,21 @@ export default {
|
||||||
this.player.play();
|
this.player.play();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
openLyricMenu(e, lyric, idx) {
|
||||||
|
this.rightClickLyric = { ...lyric, idx };
|
||||||
|
this.$refs.lyricMenu.openMenu(e);
|
||||||
|
e.preventDefault();
|
||||||
|
},
|
||||||
|
copyLyric(withTranslation) {
|
||||||
|
if (this.rightClickLyric) {
|
||||||
|
const idx = this.rightClickLyric.idx;
|
||||||
|
if (!withTranslation) {
|
||||||
|
copyLyric(this.rightClickLyric.contents[idx]);
|
||||||
|
} else {
|
||||||
|
copyLyric(this.rightClickLyric.contents.join(' '));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
setLyricsInterval() {
|
setLyricsInterval() {
|
||||||
this.lyricsInterval = setInterval(() => {
|
this.lyricsInterval = setInterval(() => {
|
||||||
const progress = this.player.seek(null, false) ?? 0;
|
const progress = this.player.seek(null, false) ?? 0;
|
||||||
|
@ -926,6 +964,7 @@ export default {
|
||||||
transform-origin: center left;
|
transform-origin: center left;
|
||||||
transform: scale(0.95);
|
transform: scale(0.95);
|
||||||
transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
opacity: 0.28;
|
opacity: 0.28;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user