feat:优化混音歌曲管理功能,更新接口调用方式,简化新增和修改混音歌曲的表单字段,增强音乐选择和场景管理功能,改善用户体验。

This commit is contained in:
wangjie52
2025-08-02 16:56:24 +08:00
parent 070ac3a883
commit f28de8d1de
8 changed files with 475 additions and 187 deletions

View File

@@ -12,56 +12,70 @@ export function listRemixSong(query) {
// 查询混音歌曲详细
export function getRemixSong(id) {
return request({
url: '/back/remix/' + id,
method: 'get'
url: '/back/music/list',
method: 'get',
params: {
musicType: 'mixing',
musicId: id
}
})
}
// 获取音乐列表(用于选择场景音乐)
export function getMusicList() {
export function getMusicList(query) {
return request({
url: '/back/music/list',
method: 'get'
method: 'get',
params: query
})
}
// 新增混音歌曲
export function addRemixSong(data) {
const formData = new FormData()
formData.append('remixName', data.remixName)
formData.append('permission', data.permission)
formData.append('categoryConfig', data.categoryConfig)
formData.append('category', data.category)
formData.append('tags', JSON.stringify(data.tags))
formData.append('status', data.status)
formData.append('selectedSongs', JSON.stringify(data.selectedSongs))
return request({
url: '/back/music/add/mixMusic',
method: 'post',
data: formData,
data: {
musicId: data.musicId,
sceneIds: data.sceneIds,
sceneJson: data.sceneJson,
// 添加其他表单字段
name: data.name,
author: data.author,
vip: data.vip,
shelf: data.shelf,
imgAddr: data.imgAddr,
musicType: data.musicType,
label: data.label
},
headers: {
'Content-Type': 'multipart/form-data'
'Content-Type': 'application/json'
}
})
}
// 修改混音歌曲
export function updateRemixSong(data) {
const formData = new FormData()
formData.append('id', data.id)
formData.append('remixName', data.remixName)
formData.append('permission', data.permission)
formData.append('categoryConfig', data.categoryConfig)
formData.append('category', data.category)
formData.append('tags', JSON.stringify(data.tags))
formData.append('status', data.status)
formData.append('selectedSongs', JSON.stringify(data.selectedSongs))
return request({
url: '/back/remix/update',
url: '/back/music/edit/mixMusic',
method: 'post',
data: formData,
data: {
id: data.id,
musicId: data.musicId,
sourceMusicId: data.sourceMusicId,
sceneIds: data.sceneIds,
sceneJson: data.sceneJson,
// 添加其他表单字段
name: data.name,
author: data.author,
vip: data.vip,
shelf: data.shelf,
imgAddr: data.imgAddr,
musicType: data.musicType,
label: data.label
},
headers: {
'Content-Type': 'multipart/form-data'
'Content-Type': 'application/json'
}
})
}

View File

@@ -29,8 +29,8 @@ export function addScene(data) {
// 修改场景音乐
export function updateScene(data) {
return request({
url: '/back/scene/update',
method: 'post',
url: '/back/scene',
method: 'put',
data: data
})
}

View File

@@ -189,7 +189,13 @@ export default {
// 上传成功回调
handleUploadSuccess(res, file) {
if (res.code === 200) {
this.uploadList.push({ name: res.fileName, url: res.fileName })
// 根据新的接口返回格式data字段包含文件路径
let filePath = res.data || res.fileName;
// 如果路径不是以http开头则拼接域名前缀
if (filePath && !filePath.startsWith('http://') && !filePath.startsWith('https://')) {
filePath = this.baseUrl + filePath;
}
this.uploadList.push({ name: filePath, url: filePath })
this.uploadedSuccessfully()
} else {
this.number--
@@ -228,7 +234,14 @@ export default {
let strs = ""
separator = separator || ","
for (let i in list) {
strs += list[i].url + separator
if (list[i].url) {
// 移除baseUrl前缀只返回相对路径
let url = list[i].url;
if (url.startsWith(this.baseUrl)) {
url = url.substring(this.baseUrl.length);
}
strs += url + separator
}
}
return strs != '' ? strs.substr(0, strs.length - 1) : ''
}

View File

@@ -196,7 +196,13 @@ export default {
// 上传成功回调
handleUploadSuccess(res, file) {
if (res.code === 200) {
this.uploadList.push({ name: res.fileName, url: res.fileName })
// 根据新的接口返回格式data字段包含图片路径
let imagePath = res.data || res.fileName;
// 如果路径不是以http开头则拼接域名前缀
if (imagePath && !imagePath.startsWith('http://') && !imagePath.startsWith('https://')) {
imagePath = this.baseUrl + imagePath;
}
this.uploadList.push({ name: imagePath, url: imagePath })
this.uploadedSuccessfully()
} else {
this.number--
@@ -240,7 +246,12 @@ export default {
separator = separator || ","
for (let i in list) {
if (list[i].url) {
strs += list[i].url.replace(this.baseUrl, "") + separator
// 移除baseUrl前缀只返回相对路径
let url = list[i].url;
if (url.startsWith(this.baseUrl)) {
url = url.substring(this.baseUrl.length);
}
strs += url + separator
}
}
return strs != '' ? strs.substr(0, strs.length - 1) : ''

View File

@@ -31,8 +31,8 @@
<template slot-scope="scope">
<el-image
style="width: 60px; height: 60px"
:src="scope.row.imageUrl"
:preview-src-list="[scope.row.imageUrl]"
:src="getImageUrlMethod(scope.row.imageUrl)"
:preview-src-list="[getImageUrlMethod(scope.row.imageUrl)]"
fit="cover"
>
<div slot="error" class="image-slot">
@@ -138,6 +138,7 @@
<script>
import { listActivity, getActivity, delActivity, addActivity, updateActivity } from "@/api/activity/activity";
import { getImageUrl } from "@/utils/image";
export default {
name: "Activity",
@@ -283,6 +284,10 @@ export default {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
// 获取图片完整URL的方法
getImageUrlMethod(imagePath) {
return getImageUrl(imagePath);
}
}
};

View File

@@ -40,7 +40,7 @@
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">+ 新增歌曲</el-button>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">新增歌曲</el-button>
</el-form-item>
</el-form>
@@ -51,29 +51,43 @@
<el-table-column label="音乐图片" align="center" prop="imgAddr" width="120">
<template slot-scope="scope">
<el-image
v-if="scope.row.imgAddr"
style="width: 60px; height: 60px"
:src="scope.row.imgAddr"
:preview-src-list="[scope.row.imgAddr]"
:src="getImageUrlMethod(scope.row.imgAddr)"
:preview-src-list="[getImageUrlMethod(scope.row.imgAddr)]"
fit="cover"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="音乐地址" align="center" prop="musicAddr" :show-overflow-tooltip="true">
<template slot-scope="scope">
<el-link
v-if="scope.row.musicAddr"
type="primary"
:underline="false"
@click="downloadMusic(scope.row.musicAddr, scope.row.name)"
>
<i class="el-icon-download"></i> 下载
</el-link>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="音乐地址" align="center" prop="musicAddr" :show-overflow-tooltip="true" />
<el-table-column label="VIP权限" align="center" prop="vip" width="80">
<template slot-scope="scope">
<el-tag :type="scope.row.vip === 1 ? 'warning' : 'success'" size="mini">
{{ scope.row.vip === 1 ? 'VIP' : '免费' }}
<el-tag :type="parseInt(scope.row.vip) === 1 ? 'warning' : 'success'" size="mini">
{{ parseInt(scope.row.vip) === 1 ? 'VIP' : '免费' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="上架状态" align="center" prop="shelf" width="80">
<template slot-scope="scope">
<el-tag :type="scope.row.shelf === 1 ? 'success' : 'danger'" size="mini">
{{ scope.row.shelf === 1 ? '上架' : '下架' }}
<el-tag :type="parseInt(scope.row.shelf) === 1 ? 'success' : 'danger'" size="mini">
{{ parseInt(scope.row.shelf) === 1 ? '上架' : '下架' }}
</el-tag>
</template>
</el-table-column>
@@ -178,6 +192,15 @@
/>
</el-form-item>
<el-form-item label="音乐文件" prop="musicAddr">
<div v-if="form.musicAddr" style="margin-bottom: 10px;">
<el-link
type="primary"
:underline="false"
@click="downloadMusic(form.musicAddr, form.name)"
>
<i class="el-icon-download"></i> 下载当前音乐文件
</el-link>
</div>
<file-upload
v-model="form.musicAddr"
:limit="1"
@@ -197,6 +220,7 @@
<script>
import { listNormalSong, getNormalSong, delNormalSong, addNormalSong, updateNormalSong } from "@/api/playlist/normal";
import { listTags } from "@/api/playlist/tag";
import { getImageUrl } from "@/utils/image";
export default {
name: "Normal",
@@ -235,17 +259,19 @@ export default {
],
musicType: [
{ required: true, message: "音乐类型不能为空", trigger: "change" }
],
imgAddr: [
{ required: true, message: "音乐图片不能为空", trigger: "change" }
]
}
};
},
created() {
this.getList();
this.getTagOptions();
},
methods: {
// 获取图片完整URL的方法
getImageUrlMethod(imagePath) {
return getImageUrl(imagePath);
},
/** 查询普通歌曲列表 */
getList() {
this.loading = true;
@@ -255,39 +281,22 @@ export default {
this.loading = false;
});
},
// 获取标签列表
getTagList() {
// 获取标签选项
getTagOptions() {
listTags().then(response => {
this.tagOptions = response.rows || [];
// 如果正在编辑,解析已有的标签
if (this.form.label) {
this.parseTagsFromString(this.form.label);
}
});
},
// 处理标签选择变化
handleTagsChange(value) {
// 将标签ID数组转换为标签名称数组
const selectedTagNames = value.map(id => {
const tag = this.tagOptions.find(item => item.id === id);
// 标签选择变化处理
handleTagsChange(selectedTagIds) {
this.selectedTags = selectedTagIds;
// 将选中的标签ID转换为标签名称用分号分隔
const selectedTagNames = selectedTagIds.map(id => {
const tag = this.tagOptions.find(tag => tag.id === id);
return tag ? tag.name : '';
}).filter(name => name !== '');
// 用分号连接并更新表单
}).filter(name => name);
this.form.label = selectedTagNames.join(';');
},
// 从字符串解析标签
parseTagsFromString(tagString) {
if (!tagString) {
this.selectedTags = [];
return;
}
const tagNames = tagString.split(';');
this.selectedTags = this.tagOptions
.filter(tag => tagNames.includes(tag.name))
.map(tag => tag.id);
},
// 取消按钮
cancel() {
this.open = false;
@@ -323,35 +332,50 @@ export default {
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.getTagList(); // 获取标签列表
this.open = true;
this.title = "添加普通歌曲";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.musicId || this.ids;
this.getTagList(); // 获取标签列表
getNormalSong(id).then(response => {
this.form = response.data;
// 解析已有的标签
if (this.form.label && this.tagOptions.length > 0) {
this.parseTagsFromString(this.form.label);
const musicId = row.musicId || this.ids
getNormalSong(musicId).then(response => {
// 处理接口返回的数据结构从rows数组中获取第一个元素
if (response.rows && response.rows.length > 0) {
this.form = response.rows[0];
// 处理VIP权限字段将字符串转换为数字
if (this.form.vip !== null && this.form.vip !== undefined) {
this.form.vip = parseInt(this.form.vip);
}
// 处理上架状态字段,将字符串转换为数字
if (this.form.shelf !== null && this.form.shelf !== undefined) {
this.form.shelf = parseInt(this.form.shelf);
}
} else {
this.$modal.msgError("未找到歌曲信息");
return;
}
// 处理标签选择
if (this.form.label) {
const tagNames = this.form.label.split(';');
this.selectedTags = tagNames.map(name => {
const tag = this.tagOptions.find(tag => tag.name === name);
return tag ? tag.id : null;
}).filter(id => id);
}
this.open = true;
this.title = "修改普通歌曲";
}).catch(error => {
this.$modal.msgError("获取歌曲信息失败");
console.error("获取歌曲详情失败:", error);
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
// 检查音乐图片是否已上传
if (!this.form.imgAddr) {
this.$message.error("请上传音乐图片");
return;
}
if (this.form.id != null) {
updateNormalSong(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
@@ -377,6 +401,30 @@ export default {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
// 下载音乐文件
downloadMusic(musicAddr, musicName) {
if (!musicAddr) {
this.$modal.msgError("音乐文件地址为空,无法下载");
return;
}
// 构建完整的下载URL
let downloadUrl = musicAddr;
if (!musicAddr.startsWith('http://') && !musicAddr.startsWith('https://')) {
downloadUrl = process.env.VUE_APP_BASE_API + musicAddr;
}
// 创建下载链接
const link = document.createElement('a');
link.href = downloadUrl;
link.download = musicName || 'music';
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this.$modal.msgSuccess(`正在下载音乐: ${musicName || '未知文件'}`);
}
}
};

View File

@@ -1,37 +1,17 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="音乐名称" prop="musicName">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px">
<el-form-item label="音乐名称" prop="name">
<el-input
v-model="queryParams.musicName"
v-model="queryParams.name"
placeholder="请输入音乐名称查找"
clearable
style="width: 200px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="选择分类" prop="category">
<el-select v-model="queryParams.category" placeholder="选择分类" clearable style="width: 150px">
<el-option
v-for="item in categoryOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="选择标签" prop="tag">
<el-select v-model="queryParams.tag" placeholder="选择标签" clearable style="width: 150px">
<el-option
v-for="item in tagOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="上架状态" prop="status">
<el-select v-model="queryParams.status" placeholder="选择上架状态" clearable style="width: 150px">
<el-form-item label="上架状态" prop="shelf">
<el-select v-model="queryParams.shelf" placeholder="选择上架状态" clearable style="width: 150px">
<el-option
v-for="item in statusOptions"
:key="item.value"
@@ -40,11 +20,11 @@
/>
</el-select>
</el-form-item>
<el-form-item label="选择权限" prop="permission">
<el-select v-model="queryParams.permission" placeholder="选择权限" clearable style="width: 150px">
<el-form-item label="选择权限" prop="vip">
<el-select v-model="queryParams.vip" placeholder="选择权限" clearable style="width: 150px">
<el-option
v-for="item in permissionOptions"
:key="item.value"
:key="item.label"
:label="item.label"
:value="item.value"
/>
@@ -53,15 +33,15 @@
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">+ 新增混音</el-button>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">新增混音</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="playlistList">
<el-table-column label="序号" align="center" type="index" width="60" />
<el-table-column label="混音名称" align="center" prop="name" :show-overflow-tooltip="true" />
<el-table v-loading="loading" :data="playlistList" style="width: 100%">
<el-table-column label="序号" align="center" type="index" width="50" />
<el-table-column label="混音名称" align="center" prop="name" min-width="150" :show-overflow-tooltip="true" />
<!-- <el-table-column label="作者" align="center" prop="author" :show-overflow-tooltip="true" />-->
<el-table-column label="音乐场景" align="center" prop="musicScene" width="200">
<el-table-column label="音乐场景" align="center" prop="musicScene" min-width="150">
<template slot-scope="scope">
<el-tag
v-for="scene in getScenes(scope.row)"
@@ -81,7 +61,7 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="标签" align="center" prop="label" width="150">
<el-table-column label="标签" align="center" prop="label" min-width="150">
<template slot-scope="scope">
<el-tag
v-for="tag in scope.row.label ? scope.row.label.split(';') : []"
@@ -101,8 +81,8 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="120" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120">
<el-table-column label="创建时间" align="center" prop="createTime" min-width="140" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100">
<template slot-scope="scope">
<el-button
size="mini"
@@ -133,6 +113,12 @@
<!-- 添加或修改混音歌曲对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="选择音乐" prop="musicId" required>
<el-button type="primary" @click="openMusicDialog">选择音乐</el-button>
<span v-if="selectedMusicInfo" style="margin-left: 10px; color: #409EFF;">
已选择: {{ selectedMusicInfo.name }} - {{ selectedMusicInfo.author }}
</span>
</el-form-item>
<el-form-item label="音乐名称" prop="name" required>
<el-input v-model="form.name" placeholder="请输入音乐名称" />
</el-form-item>
@@ -168,21 +154,20 @@
</el-select>
</el-form-item>
<el-form-item label="音乐场景" prop="musicScenes" required>
<div class="scene-music-container">
<div
v-for="(scene, index) in availableScenes"
<el-select
v-model="selectedScenes"
multiple
filterable
placeholder="请选择音乐场景"
style="width: 100%"
@change="handleSceneChange">
<el-option
v-for="scene in availableScenes"
:key="scene.sceneId"
class="scene-music-item"
>
<el-checkbox
v-model="selectedScenes"
:label="scene.sceneId"
@change="handleSceneChange"
>
{{ scene.scene }}
</el-checkbox>
</div>
</div>
:label="scene.scene"
:value="scene.sceneId">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="音乐图片" prop="imgAddr">
<image-upload
@@ -192,26 +177,107 @@
action="/back/upload/musicImg/file"
/>
</el-form-item>
<el-form-item label="音乐文件" prop="musicAddr">
<file-upload
v-model="form.musicAddr"
:limit="1"
:file-type="['mp3', 'wav', 'flac']"
action="/back/upload/music/file"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<!-- 音乐选择对话框 -->
<el-dialog title="选择音乐" :visible.sync="musicDialogVisible" width="1000px" append-to-body>
<el-form :model="musicQueryParams" ref="musicQueryForm" size="small" :inline="true" label-width="80px">
<el-form-item label="音乐名称" prop="name">
<el-input
v-model="musicQueryParams.name"
placeholder="请输入音乐名称"
clearable
style="width: 200px"
@keyup.enter.native="handleMusicQuery"
/>
</el-form-item>
<el-form-item label="作者" prop="author">
<el-input
v-model="musicQueryParams.author"
placeholder="请输入作者"
clearable
style="width: 200px"
@keyup.enter.native="handleMusicQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleMusicQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetMusicQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table
v-loading="musicLoading"
:data="musicTableData"
@row-click="handleMusicRowClick"
highlight-current-row
style="width: 100%">
<el-table-column label="序号" align="center" type="index" width="60" />
<el-table-column label="音乐名称" align="center" prop="name" :show-overflow-tooltip="true" />
<el-table-column label="作者" align="center" prop="author" :show-overflow-tooltip="true" />
<el-table-column label="VIP权限" align="center" prop="vip" width="80">
<template slot-scope="scope">
<el-tag :type="scope.row.vip === 1 ? 'warning' : 'success'" size="mini">
{{ scope.row.vip === 1 ? 'VIP' : '免费' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="上架状态" align="center" prop="shelf" width="80">
<template slot-scope="scope">
<el-tag :type="scope.row.shelf === 1 ? 'success' : 'danger'" size="mini">
{{ scope.row.shelf === 1 ? '上架' : '下架' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="标签" align="center" prop="label" width="150">
<template slot-scope="scope">
<el-tag
v-for="tag in scope.row.label ? scope.row.label.split(';') : []"
:key="tag"
type="info"
size="mini"
style="margin-right: 5px; margin-bottom: 5px;"
>
{{ tag }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="120" />
<el-table-column label="操作" align="center" width="80">
<template slot-scope="scope">
<el-button
size="mini"
type="primary"
@click="selectMusic(scope.row)"
>选择</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="musicTotal>0"
:total="musicTotal"
:page.sync="musicQueryParams.pageNum"
:limit.sync="musicQueryParams.pageSize"
@pagination="getMusicList"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="musicDialogVisible = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listRemixSong, getRemixSong, delRemixSong, addRemixSong, updateRemixSong, getMusicList } from "@/api/playlist/remix";
import { listTags } from "@/api/playlist/tag";
import { listScene } from "@/api/playlist/scene";
export default {
name: "RemixSong",
@@ -230,20 +296,20 @@ export default {
queryParams: {
pageNum: 1,
pageSize: 10,
musicName: null,
category: null,
tag: null,
name: null,
shelf: null,
vip: null,
musicType: 'mixing'
},
form: {},
rules: {
musicId: [{ required: true, message: "请选择要混音的音乐", trigger: "change" }],
name: [{ required: true, message: "音乐名称不能为空", trigger: "blur" }],
author: [{ required: true, message: "作者不能为空", trigger: "blur" }],
vip: [{ required: true, message: "VIP权限不能为空", trigger: "change" }],
shelf: [{ required: true, message: "上架状态不能为空", trigger: "change" }],
imgAddr: [{ required: true, message: "音乐图片不能为空", trigger: "change" }]
imgAddr: [{ required: true, message: "音乐图片不能为空", trigger: "change" }],
musicScenes: [{ required: true, message: "音乐场景不能为空", trigger: "change" }]
},
categoryOptions: [
{ label: '热门', value: '热门' },
@@ -260,7 +326,18 @@ export default {
permissionOptions: [
{ label: '免费', value: 0 },
{ label: 'VIP', value: 1 }
]
],
selectedMusicInfo: null, // 用于存储选中的音乐信息
musicDialogVisible: false, // 音乐选择对话框的可见性
musicLoading: false, // 音乐列表加载状态
musicTableData: [], // 音乐列表数据
musicQueryParams: { // 音乐查询参数
pageNum: 1,
pageSize: 10,
name: null,
author: null
},
musicTotal: 0 // 音乐列表总条数
};
},
created() {
@@ -277,7 +354,7 @@ export default {
});
},
getMusicListData() {
getMusicList().then(response => {
getMusicList({}).then(response => {
this.musicList = response.rows || [];
});
},
@@ -290,13 +367,17 @@ export default {
},
// 获取场景列表
getSceneList() {
// 这里应该调用获取场景列表的API这里模拟一些数据
this.availableScenes = [
{ sceneId: '1', scene: '下雨' },
{ sceneId: '2', scene: '打雷' },
{ sceneId: '3', scene: '海浪' },
{ sceneId: '4', scene: '森林' }
];
// 调用场景列表接口
listScene().then(response => {
if (response.rows) {
this.availableScenes = response.rows;
} else {
this.availableScenes = [];
}
}).catch(error => {
console.error('获取场景列表失败:', error);
this.availableScenes = [];
});
},
// 获取标签列表
getTagList() {
@@ -332,12 +413,24 @@ export default {
.map(tag => tag.id);
},
// 处理场景选择变化
handleSceneChange() {
handleSceneChange(selectedSceneIds) {
this.selectedScenes = selectedSceneIds;
// 将选中的场景ID转换为场景名称用分号分隔
const selectedSceneNames = selectedSceneIds.map(id => {
const scene = this.availableScenes.find(scene => scene.sceneId === id);
return scene ? scene.scene : '';
}).filter(name => name);
// 设置表单的musicScenes字段用于验证
this.form.musicScenes = selectedSceneIds.length > 0 ? selectedSceneIds : null;
if (this.form.musicScene) {
this.form.musicScene.sceneIds = this.selectedScenes.join(',');
this.form.musicScene.sceneIds = selectedSceneIds.join(',');
this.form.musicScene.sceneNames = selectedSceneNames.join(';');
} else {
this.form.musicScene = {
sceneIds: this.selectedScenes.join(',')
sceneIds: selectedSceneIds.join(','),
sceneNames: selectedSceneNames.join(';')
};
}
},
@@ -348,7 +441,13 @@ export default {
return;
}
this.selectedScenes = sceneIdsString.split(',');
// 如果是逗号分隔的ID字符串直接分割
if (sceneIdsString.includes(',')) {
this.selectedScenes = sceneIdsString.split(',');
} else {
// 如果是单个ID转换为数组
this.selectedScenes = [sceneIdsString];
}
},
cancel() {
this.open = false;
@@ -363,15 +462,16 @@ export default {
vip: 0,
shelf: 1,
imgAddr: null,
musicAddr: null,
musicType: "mixing",
label: null,
musicScenes: null,
musicScene: {
sceneIds: ""
}
};
this.selectedTags = [];
this.selectedScenes = [];
this.selectedMusicInfo = null; // 清空选中的音乐信息
this.resetForm("form");
},
handleQuery() {
@@ -393,9 +493,31 @@ export default {
this.reset();
this.getTagList(); // 获取标签列表
this.getSceneList(); // 获取场景列表
const id = row.id || this.ids;
const id = row.musicId || this.ids; // 使用musicId而不是id
getRemixSong(id).then(response => {
this.form = response.data;
// 处理接口返回的数据结构从rows数组中获取第一个元素
if (response.rows && response.rows.length > 0) {
this.form = response.rows[0];
// 处理VIP权限字段将字符串转换为数字
if (this.form.vip !== null && this.form.vip !== undefined) {
this.form.vip = parseInt(this.form.vip);
}
// 处理上架状态字段,将字符串转换为数字
if (this.form.shelf !== null && this.form.shelf !== undefined) {
this.form.shelf = parseInt(this.form.shelf);
}
// 回显选择音乐信息
this.selectedMusicInfo = {
musicId: this.form.musicId,
name: this.form.name,
author: this.form.author
};
} else {
this.$modal.msgError("未找到混音歌曲信息");
return;
}
// 解析已有的标签
if (this.form.label && this.tagOptions.length > 0) {
@@ -405,23 +527,73 @@ export default {
// 解析已有的场景
if (this.form.musicScene && this.form.musicScene.sceneIds) {
this.parseSceneIdsFromString(this.form.musicScene.sceneIds);
// 设置musicScenes字段用于验证
this.form.musicScenes = this.selectedScenes.length > 0 ? this.selectedScenes : null;
}
this.open = true;
this.title = "编辑混音歌曲";
// 确保在下一个tick中设置验证字段因为场景数据可能还在加载中
this.$nextTick(() => {
if (this.selectedScenes.length > 0) {
this.form.musicScenes = this.selectedScenes;
}
});
}).catch(error => {
this.$modal.msgError("获取混音歌曲信息失败");
console.error("获取混音歌曲详情失败:", error);
});
},
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateRemixSong(this.form).then(response => {
// 构建编辑混音歌曲的数据
const editMixMusicData = {
id: this.form.id,
musicId: this.form.musicId,
sourceMusicId: this.form.musicScene ? this.form.musicScene.sourceMusicId : this.form.musicId,
sceneIds: this.selectedScenes.join(','),
sceneJson: JSON.stringify(this.selectedScenes.reduce((acc, sceneId, index) => {
acc[sceneId] = index + 1;
return acc;
}, {})),
// 添加其他表单字段
name: this.form.name,
author: this.form.author,
vip: this.form.vip,
shelf: this.form.shelf,
imgAddr: this.form.imgAddr,
musicType: this.form.musicType,
label: this.form.label
};
updateRemixSong(editMixMusicData).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addRemixSong(this.form).then(response => {
// 构建新增混音歌曲的数据
const mixMusicData = {
musicId: this.form.musicId,
sceneIds: this.selectedScenes.join(','),
sceneJson: JSON.stringify(this.selectedScenes.reduce((acc, sceneId, index) => {
acc[sceneId] = index + 1;
return acc;
}, {})),
// 添加其他表单字段
name: this.form.name,
author: this.form.author,
vip: this.form.vip,
shelf: this.form.shelf,
imgAddr: this.form.imgAddr,
musicType: this.form.musicType,
label: this.form.label
};
addRemixSong(mixMusicData).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
@@ -438,30 +610,43 @@ export default {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
openMusicDialog() {
this.musicDialogVisible = true;
this.getMusicList(); // 获取音乐列表
},
handleMusicQuery() {
this.musicQueryParams.pageNum = 1;
this.getMusicList();
},
resetMusicQuery() {
this.resetForm("musicQueryForm");
this.handleMusicQuery();
},
getMusicList() {
this.musicLoading = true;
getMusicList(this.musicQueryParams).then(response => {
this.musicTableData = response.rows;
this.musicTotal = response.total;
this.musicLoading = false;
}).catch(error => {
console.error('获取音乐列表失败:', error);
this.musicLoading = false;
});
},
handleMusicRowClick(row) {
this.selectMusic(row);
},
selectMusic(row) {
this.form.musicId = row.musicId;
this.selectedMusicInfo = row; // 更新已选择音乐信息
this.musicDialogVisible = false; // 关闭音乐选择对话框
}
}
};
</script>
<style scoped>
.scene-music-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.scene-music-item {
min-width: 120px;
padding: 10px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.scene-music-item:hover {
border-color: #409EFF;
}
.el-tag {
border-radius: 12px;
margin-bottom: 5px;

View File

@@ -12,7 +12,7 @@
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">+ 新增场景音乐</el-button>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">新增场景音乐</el-button>
</el-form-item>
</el-form>
@@ -22,18 +22,25 @@
<el-table-column label="场景图片" align="center" prop="imgAddr" width="120">
<template slot-scope="scope">
<el-image
v-if="scope.row.imgAddr"
style="width: 60px; height: 60px"
:src="scope.row.imgAddr"
:preview-src-list="[scope.row.imgAddr]"
:src="getImageUrlMethod(scope.row.imgAddr)"
:preview-src-list="[getImageUrlMethod(scope.row.imgAddr)]"
fit="cover"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="音乐地址" align="center" prop="musicAddr" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span v-if="scope.row.musicAddr">{{ scope.row.musicAddr }}</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="音乐地址" align="center" prop="musicAddr" :show-overflow-tooltip="true" />
<el-table-column label="创建时间" align="center" prop="createTime" width="120" />
<el-table-column label="更新时间" align="center" prop="updateTime" width="120" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@@ -95,6 +102,7 @@
<script>
import { listScene, getScene, delScene, addScene, updateScene } from "@/api/playlist/scene";
import { getImageUrl } from "@/utils/image";
export default {
name: "Scene",
@@ -138,6 +146,10 @@ export default {
this.getList();
},
methods: {
// 获取图片完整URL的方法
getImageUrlMethod(imagePath) {
return getImageUrl(imagePath);
},
/** 查询场景音乐列表 */
getList() {
this.loading = true;