mirror of
https://github.com/xhongc/music-tag-web.git
synced 2026-05-12 19:16:23 +08:00
feature:新增咪咕音乐标签源
This commit is contained in:
0
applications/music/__init__.py
Normal file
0
applications/music/__init__.py
Normal file
3
applications/music/admin.py
Normal file
3
applications/music/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
5
applications/music/apps.py
Normal file
5
applications/music/apps.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MusicConfig(AppConfig):
|
||||
name = 'music'
|
||||
33
applications/music/migrations/0001_initial.py
Normal file
33
applications/music/migrations/0001_initial.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 2.2.6 on 2023-04-03 10:26
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Music',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=255)),
|
||||
('artist', models.CharField(default='', max_length=255)),
|
||||
('album', models.CharField(default='', max_length=255)),
|
||||
('genre', models.CharField(default='', max_length=255)),
|
||||
('year', models.CharField(default='', max_length=255)),
|
||||
('lyrics', models.TextField(default='')),
|
||||
('comment', models.TextField(default='')),
|
||||
('fs_id', models.CharField(default='', max_length=255)),
|
||||
('path', models.CharField(default='', max_length=255)),
|
||||
('parent_path', models.CharField(default='', max_length=255)),
|
||||
('size', models.CharField(default='', max_length=255)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
),
|
||||
]
|
||||
18
applications/music/migrations/0002_auto_20230403_1042.py
Normal file
18
applications/music/migrations/0002_auto_20230403_1042.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.2.6 on 2023-04-03 10:42
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('music', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='music',
|
||||
name='path',
|
||||
field=models.TextField(default=''),
|
||||
),
|
||||
]
|
||||
0
applications/music/migrations/__init__.py
Normal file
0
applications/music/migrations/__init__.py
Normal file
21
applications/music/models.py
Normal file
21
applications/music/models.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Music(models.Model):
|
||||
title = models.CharField(max_length=255)
|
||||
artist = models.CharField(max_length=255, default="")
|
||||
album = models.CharField(max_length=255, default="")
|
||||
genre = models.CharField(max_length=255, default="")
|
||||
year = models.CharField(max_length=255, default="")
|
||||
lyrics = models.TextField(default="")
|
||||
comment = models.TextField(default="")
|
||||
fs_id = models.CharField(max_length=255, default="")
|
||||
path = models.TextField(default="")
|
||||
parent_path = models.CharField(max_length=255, default="")
|
||||
size = models.CharField(max_length=255, default="")
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
3
applications/music/tests.py
Normal file
3
applications/music/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
21
applications/music/utils.py
Normal file
21
applications/music/utils.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from django.db import transaction
|
||||
|
||||
from applications.music.models import Music
|
||||
|
||||
def create_music(filename):
|
||||
bulk_list = []
|
||||
with transaction.atomic():
|
||||
with open(f"/Users/macbookair/coding/demo/music/{filename}.txt", "r") as f:
|
||||
song_list = f.readlines()
|
||||
for song in song_list:
|
||||
category, fs_id, isdir, local_ctime, local_mtime, path, server_ctime, server_mtime, server_filename, size = song.split(
|
||||
"||")
|
||||
parent_path = path.split("/")[-2]
|
||||
bulk_list.append(Music(**{
|
||||
"title": server_filename,
|
||||
"fs_id": fs_id,
|
||||
"path": path,
|
||||
"parent_path": parent_path,
|
||||
"size": size
|
||||
}))
|
||||
Music.objects.bulk_create(bulk_list)
|
||||
3
applications/music/views.py
Normal file
3
applications/music/views.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -29,7 +29,9 @@ class UpdateId3Serializer(serializers.Serializer):
|
||||
|
||||
class FetchId3ByTitleSerializer(serializers.Serializer):
|
||||
title = serializers.CharField(required=True)
|
||||
resource = serializers.CharField(required=True)
|
||||
|
||||
|
||||
class FetchLlyricSerializer(serializers.Serializer):
|
||||
song_id = serializers.CharField(required=True)
|
||||
resource = serializers.CharField(required=True)
|
||||
|
||||
0
applications/task/services/__init__.py
Normal file
0
applications/task/services/__init__.py
Normal file
82
applications/task/services/music_resource.py
Normal file
82
applications/task/services/music_resource.py
Normal file
@@ -0,0 +1,82 @@
|
||||
import requests
|
||||
|
||||
from applications.task.utils import timestamp_to_dt
|
||||
from applications.utils.send import send
|
||||
|
||||
|
||||
class MusicResource:
|
||||
def __init__(self, info):
|
||||
self.resource = self.get_resource(info)
|
||||
|
||||
def get_resource(self, info):
|
||||
if info == "netease":
|
||||
return NetEaseMusicClient()
|
||||
elif info == "migu":
|
||||
return MiGuMusicClient()
|
||||
raise Exception("暂不支持该音乐平台")
|
||||
|
||||
def fetch_lyric(self, song_id):
|
||||
return self.resource.fetch_lyric(song_id)
|
||||
|
||||
def fetch_id3_by_title(self, title):
|
||||
return self.resource.fetch_id3_by_title(title)
|
||||
|
||||
|
||||
class NetEaseMusicClient:
|
||||
BASE_URL = "https://music.163.com/"
|
||||
|
||||
def fetch_lyric(self, song_id):
|
||||
data = send({"url": self.BASE_URL + "api/song/lyric?lv=-1&kv=-1&tv=-1",
|
||||
"params": {"id": song_id}}, "linuxapi").POST("")
|
||||
return data.json().get("lrc", {}).get("lyric")
|
||||
|
||||
def fetch_id3_by_title(self, title):
|
||||
data = send({'s': title, 'type': '1', 'limit': '10', 'offset': '0'}).POST("weapi/cloudsearch/get/web")
|
||||
songs = data.json().get("result", {}).get("songs", [])
|
||||
for song in songs:
|
||||
artists = song.get("ar", [])
|
||||
album = song.get("al", {})
|
||||
if artists:
|
||||
artist = artists[0].get("name", "")
|
||||
artist_id = artists[0].get("id", "")
|
||||
else:
|
||||
artist = ""
|
||||
artist_id = ""
|
||||
year = song.get("publishTime", 0)
|
||||
if year:
|
||||
year = timestamp_to_dt(year / 1000, "%Y")
|
||||
song["artist"] = artist
|
||||
song["artist_id"] = artist_id
|
||||
song["album"] = album.get("name", "")
|
||||
song["album_id"] = album.get("id", "")
|
||||
song["album_img"] = album.get("picUrl", {})
|
||||
song["year"] = year
|
||||
return songs
|
||||
|
||||
|
||||
class MiGuMusicClient:
|
||||
BASE_URL = "https://m.music.migu.cn/"
|
||||
header = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0',
|
||||
'Referer': 'https://m.music.migu.cn/'
|
||||
}
|
||||
|
||||
def fetch_lyric(self, song_id):
|
||||
url = f'https://music.migu.cn/v3/api/music/audioPlayer/getLyric?copyrightId={song_id}'
|
||||
res = requests.get(url, headers=self.header)
|
||||
return res.json()["lyric"]
|
||||
|
||||
def fetch_id3_by_title(self, title):
|
||||
url = self.BASE_URL + f"migu/remoting/scr_search_tag?rows=10&type=2&keyword={title}&pgc=1"
|
||||
res = requests.get(url, headers=self.header)
|
||||
songs = res.json()["musics"]
|
||||
for song in songs:
|
||||
song["id"] = song['copyrightId']
|
||||
song["name"] = song['songName']
|
||||
song["artist"] = song['singerName']
|
||||
song["artist_id"] = song['singerId']
|
||||
song["album"] = song['albumName']
|
||||
song["album_id"] = song['albumId']
|
||||
song["album_img"] = song['cover']
|
||||
song["year"] = ""
|
||||
return songs
|
||||
@@ -6,6 +6,7 @@ from rest_framework.decorators import action
|
||||
|
||||
from applications.task.serialziers import FileListSerializer, Id3Serializer, UpdateId3Serializer, \
|
||||
FetchId3ByTitleSerializer, FetchLlyricSerializer
|
||||
from applications.task.services.music_resource import MusicResource
|
||||
from applications.task.utils import timestamp_to_dt
|
||||
from applications.utils.send import send
|
||||
from component.drf.viewsets import GenericViewSet
|
||||
@@ -104,9 +105,7 @@ class TaskViewSets(GenericViewSet):
|
||||
validate_data = self.is_validated_data(request.data)
|
||||
song_id = validate_data["song_id"]
|
||||
try:
|
||||
data = send({"url": BASE_URL + "api/song/lyric?lv=-1&kv=-1&tv=-1",
|
||||
"params": {"id": song_id}}, "linuxapi").POST("")
|
||||
lyric = data.json().get("lrc", {}).get("lyric")
|
||||
lyric = MusicResource(resource).fetch_lyric(song_id)
|
||||
except Exception as e:
|
||||
lyric = f"未找到歌词 {e}"
|
||||
return self.success_response(data=lyric)
|
||||
@@ -114,30 +113,8 @@ class TaskViewSets(GenericViewSet):
|
||||
@action(methods=['POST'], detail=False)
|
||||
def fetch_id3_by_title(self, request, *args, **kwargs):
|
||||
validate_data = self.is_validated_data(request.data)
|
||||
resource = validate_data["resource"]
|
||||
|
||||
title = validate_data["title"]
|
||||
data = send({'s': title, 'type': '1', 'limit': '10', 'offset': '0'}).POST("weapi/cloudsearch/get/web")
|
||||
songs = data.json().get("result", {}).get("songs", [])
|
||||
formated_songs = []
|
||||
for song in songs:
|
||||
artists = song.get("ar", [])
|
||||
album = song.get("al", {})
|
||||
if artists:
|
||||
artist = artists[0].get("name", "")
|
||||
artist_id = artists[0].get("id", "")
|
||||
else:
|
||||
artist = ""
|
||||
artist_id = ""
|
||||
year = song.get("publishTime", 0)
|
||||
if year:
|
||||
year = timestamp_to_dt(year / 1000, "%Y")
|
||||
formated_songs.append({
|
||||
"id": song["id"],
|
||||
"name": song["name"],
|
||||
"artist": artist,
|
||||
"artist_id": artist_id,
|
||||
"album": album.get("name", ""),
|
||||
"album_id": album.get("id", ""),
|
||||
"album_img": album.get("picUrl", {}),
|
||||
"year": year
|
||||
})
|
||||
return self.success_response(data=formated_songs)
|
||||
songs = MusicResource(resource).fetch_id3_by_title(title)
|
||||
return self.success_response(data=songs)
|
||||
|
||||
24
applications/user/migrations/0001_initial.py
Normal file
24
applications/user/migrations/0001_initial.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 2.2.6 on 2023-04-03 10:26
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UserProfile',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -31,6 +31,7 @@ INSTALLED_APPS = [
|
||||
"rest_framework",
|
||||
"applications.task",
|
||||
"applications.user",
|
||||
"applications.music",
|
||||
|
||||
]
|
||||
|
||||
@@ -75,7 +76,16 @@ DATABASES = {
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
# DATABASES = {
|
||||
# "default": {
|
||||
# "ENGINE": "django.db.backends.mysql",
|
||||
# "NAME": 'music', # noqa
|
||||
# "USER": "root",
|
||||
# "PASSWORD": "123456",
|
||||
# "HOST": "localhost",
|
||||
# "PORT": "3306",
|
||||
# },
|
||||
# }
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
|
||||
|
||||
|
||||
2
static/dist/js/app.js
vendored
2
static/dist/js/app.js
vendored
File diff suppressed because one or more lines are too long
21096
web/package-lock.json
generated
21096
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,7 @@
|
||||
"jquery": "^2.2.4",
|
||||
"lodash": "^4.17.15",
|
||||
"moment": "^2.24.0",
|
||||
"node-sass": "^8.0.0",
|
||||
"qrcodejs2": "0.0.2",
|
||||
"screenfull": "^5.1.0",
|
||||
"stylelint": "^13.5.0",
|
||||
@@ -71,7 +72,6 @@
|
||||
"friendly-errors-webpack-plugin": "^1.6.1",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"node-notifier": "^5.1.2",
|
||||
"node-sass": "^4.14.1",
|
||||
"optimize-css-assets-webpack-plugin": "^3.2.0",
|
||||
"ora": "^1.2.0",
|
||||
"portfinder": "^1.0.13",
|
||||
|
||||
@@ -108,4 +108,4 @@ export function DELETE(url, params, config) {
|
||||
// reUrl = ''; 不需要重定向
|
||||
// reUrl = VueEnv === 'production' ? '' : '/api'; 重定向
|
||||
// todo do
|
||||
export const reUrl = ''
|
||||
export const reUrl = '/api-proxy'
|
||||
|
||||
@@ -1,143 +1,162 @@
|
||||
<template>
|
||||
<div style="display: flex;">
|
||||
<div style="width: 350px;margin-top: 20px;margin-left: 10px;">
|
||||
<bk-input :clearable="true" v-model="filePath"
|
||||
@enter="handleSearchFile"
|
||||
:placeholder="'请输入文件夹路径:'"
|
||||
behavior="simplicity">
|
||||
</bk-input>
|
||||
<transition name="bk-slide-fade-down">
|
||||
<div style="margin-top: 10px;" v-show="fadeShowDir">
|
||||
<bk-tree
|
||||
ref="tree1"
|
||||
:data="treeListOne"
|
||||
:node-key="'id'"
|
||||
:has-border="true"
|
||||
@on-click="nodeClickOne"
|
||||
@on-expanded="nodeExpandedOne">
|
||||
</bk-tree>
|
||||
</div>
|
||||
</transition>
|
||||
<div style="background: #fff;height: 100vh;">
|
||||
<div style="width: 350px;margin-top: 20px;margin-left: 10px;">
|
||||
<bk-input :clearable="true" v-model="filePath"
|
||||
@enter="handleSearchFile"
|
||||
:placeholder="'请输入文件夹路径:'"
|
||||
behavior="simplicity">
|
||||
</bk-input>
|
||||
<transition name="bk-slide-fade-down">
|
||||
<div style="margin-top: 10px;" v-show="fadeShowDir">
|
||||
<bk-tree
|
||||
ref="tree1"
|
||||
:data="treeListOne"
|
||||
:node-key="'id'"
|
||||
:has-border="true"
|
||||
@on-click="nodeClickOne"
|
||||
@on-expanded="nodeExpandedOne">
|
||||
</bk-tree>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
<transition name="bk-slide-fade-left">
|
||||
<div style="margin-left: 40px;width: 500px;margin-top: 20px;" v-show="musicInfo.title">
|
||||
<div style="width: 100%;">
|
||||
<bk-button :theme="'success'" :loading="isLoading" @click="handleClick" class="mr10"
|
||||
style="width: 100%;">
|
||||
保存信息
|
||||
</bk-button>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;margin-top: 10px;">
|
||||
<div class="label1">标题:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.title"></bk-input>
|
||||
</div>
|
||||
<div>
|
||||
<bk-icon type="arrows-right-circle" @click="toggleLock('title')"
|
||||
style="cursor: pointer;font-size: 22px;color: #64c864;margin-left: 10px;"></bk-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">艺术家:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.artist"></bk-input>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">专辑:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.album"></bk-input>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">风格:</div>
|
||||
<div style="width: 70%;">
|
||||
<div style="background: #fff;height: 100vh;margin-left: 20px;margin-right: 20px;">
|
||||
<transition name="bk-slide-fade-left">
|
||||
<div style="margin-left: 40px;width: 500px;margin-top: 20px;" v-show="musicInfo.title">
|
||||
<div style="width: 100%;display: flex;">
|
||||
<bk-button :theme="'success'" :loading="isLoading" @click="handleClick" class="mr10"
|
||||
style="width: 50%;">
|
||||
保存信息
|
||||
</bk-button>
|
||||
<bk-select
|
||||
:disabled="false"
|
||||
v-model="musicInfo.genre"
|
||||
style="width: 250px;background: #fff;"
|
||||
:clearable="false"
|
||||
v-model="resource"
|
||||
style="width: 200px;"
|
||||
ext-cls="select-custom"
|
||||
ext-popover-cls="select-popover-custom"
|
||||
:placeholder="'请选择歌曲风格'"
|
||||
searchable>
|
||||
<bk-option v-for="option in genreList"
|
||||
ext-popover-cls="select-popover-custom">
|
||||
<bk-option v-for="option in resourceList"
|
||||
:key="option.id"
|
||||
:id="option.id"
|
||||
:name="option.name">
|
||||
</bk-option>
|
||||
</bk-select>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">年份:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.year"></bk-input>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;margin-top: 10px;">
|
||||
<div class="label1">标题:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.title"></bk-input>
|
||||
</div>
|
||||
<div>
|
||||
<bk-icon type="arrows-right-circle" @click="toggleLock('title')"
|
||||
style="cursor: pointer;font-size: 22px;color: #64c864;margin-left: 10px;"></bk-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">艺术家:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.artist"></bk-input>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">专辑:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.album"></bk-input>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">风格:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-select
|
||||
:disabled="false"
|
||||
v-model="musicInfo.genre"
|
||||
style="width: 250px;background: #fff;"
|
||||
ext-cls="select-custom"
|
||||
ext-popover-cls="select-popover-custom"
|
||||
:placeholder="'请选择歌曲风格'"
|
||||
searchable>
|
||||
<bk-option v-for="option in genreList"
|
||||
:key="option.id"
|
||||
:id="option.id"
|
||||
:name="option.name">
|
||||
</bk-option>
|
||||
</bk-select>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">年份:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.year"></bk-input>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">歌词:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.lyrics" type="textarea" :rows="15"
|
||||
></bk-input>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">描述:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.comment" type="textarea"></bk-input>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">专辑封面:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-image fit="contain" :src="musicInfo.album_img" style="width: 128px;"
|
||||
v-show="reloadImg"></bk-image>
|
||||
<bk-image fit="contain" :src="musicInfo.artwork" style="width: 128px;"
|
||||
v-show="!musicInfo.album_img"></bk-image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">歌词:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.lyrics" type="textarea" :rows="15"
|
||||
></bk-input>
|
||||
</transition>
|
||||
</div>
|
||||
<div style="background: #fff;height: 100vh;">
|
||||
<transition name="bk-slide-fade-left">
|
||||
<div
|
||||
style="display: flex;flex-direction: column;margin-top: 20px;flex: 1;margin-right: 20px;margin-left: 20px;"
|
||||
v-show="fadeShowDetail">
|
||||
<div v-if="SongList.length === 0">
|
||||
<span style="margin-left: 30%;margin-top: 30%;">暂无歌曲信息</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">描述:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-input :clearable="true" v-model="musicInfo.comment" type="textarea"></bk-input>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;margin-bottom: 10px;align-items: center;">
|
||||
<div class="label1">专辑封面:</div>
|
||||
<div style="width: 70%;">
|
||||
<bk-image fit="contain" :src="musicInfo.album_img" style="width: 128px;"
|
||||
v-show="reloadImg"></bk-image>
|
||||
<bk-image fit="contain" :src="musicInfo.artwork" style="width: 128px;"
|
||||
v-show="!musicInfo.album_img"></bk-image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="bk-slide-fade-left">
|
||||
<div
|
||||
style="display: flex;flex-direction: column;margin-top: 20px;flex: 1;margin-right: 20px;margin-left: 20px;"
|
||||
v-show="fadeShowDetail">
|
||||
<div v-if="SongList.length === 0">
|
||||
<span style="margin-left: 30%;margin-top: 30%;">暂无歌曲信息</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="parent">
|
||||
<div class="title2">应用</div>
|
||||
<div class="title2">专辑封面</div>
|
||||
<div class="title2">歌曲名</div>
|
||||
<div class="title2">歌手</div>
|
||||
<div class="title2">专辑</div>
|
||||
<div class="title2">歌词</div>
|
||||
<div class="title2">年份</div>
|
||||
</div>
|
||||
<div v-for="(item,index) in SongList" :key="index" style="margin-bottom: 10px;">
|
||||
<div class="song-card">
|
||||
<div>
|
||||
<div class="parent">
|
||||
<bk-icon type="arrows-left-circle" @click="copyAll(item)"
|
||||
style="font-size: 20px;color: #64c864;margin-right: 5px;cursor: pointer;"></bk-icon>
|
||||
<bk-image fit="contain" :src="item.album_img" style="width: 64px;cursor: pointer;"
|
||||
@click="handleCopy('album_img',item.album_img)">
|
||||
</bk-image>
|
||||
<div @click="handleCopy('title',item.name)" class="music-item">{{ item.name }}</div>
|
||||
<div @click="handleCopy('artist',item.artist)" class="music-item">
|
||||
{{item.artist }}
|
||||
<div v-else>
|
||||
<div class="parent">
|
||||
<div class="title2">应用</div>
|
||||
<div class="title2">专辑封面</div>
|
||||
<div class="title2">歌曲名</div>
|
||||
<div class="title2">歌手</div>
|
||||
<div class="title2">专辑</div>
|
||||
<div class="title2">歌词</div>
|
||||
<div class="title2">年份</div>
|
||||
</div>
|
||||
<div v-for="(item,index) in SongList" :key="index" style="margin-bottom: 10px;">
|
||||
<div class="song-card">
|
||||
<div>
|
||||
<div class="parent">
|
||||
<bk-icon type="arrows-left-circle" @click="copyAll(item)"
|
||||
style="font-size: 20px;color: #64c864;margin-right: 5px;cursor: pointer;"></bk-icon>
|
||||
<bk-image fit="contain" :src="item.album_img" style="width: 64px;cursor: pointer;"
|
||||
@click="handleCopy('album_img',item.album_img)">
|
||||
</bk-image>
|
||||
<div @click="handleCopy('title',item.name)" class="music-item">{{ item.name }}</div>
|
||||
<div @click="handleCopy('artist',item.artist)" class="music-item">
|
||||
{{item.artist }}
|
||||
</div>
|
||||
<div @click="handleCopy('album',item.album)" class="music-item">{{ item.album }}</div>
|
||||
<div @click="handleCopy('lyric',item.id)" class="music-item">加载歌词</div>
|
||||
<div @click="handleCopy('year',item.year)" class="music-item">{{ item.year }}</div>
|
||||
</div>
|
||||
<div @click="handleCopy('album',item.album)" class="music-item">{{ item.album }}</div>
|
||||
<div @click="handleCopy('lyric',item.id)" class="music-item">加载歌词</div>
|
||||
<div @click="handleCopy('year',item.year)" class="music-item">{{ item.year }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -147,6 +166,8 @@
|
||||
treeListOne: [],
|
||||
filePath: '/Users/macbookair/Music/my_music',
|
||||
fileName: '',
|
||||
resource: 'netease',
|
||||
resourceList: [{id: 'netease', name: '网易云音乐'}, {id: 'migu', name: '咪咕音乐'}],
|
||||
musicInfo: {
|
||||
'genre': '流行'
|
||||
},
|
||||
@@ -221,7 +242,7 @@
|
||||
return
|
||||
}
|
||||
this.fadeShowDetail = false
|
||||
this.$api.Task.fetchId3Title({title: this.musicInfo.title}).then((res) => {
|
||||
this.$api.Task.fetchId3Title({title: this.musicInfo.title, resource: this.resource}).then((res) => {
|
||||
this.fadeShowDetail = true
|
||||
this.SongList = res.data
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user