This commit is contained in:
menxipeng
2025-08-01 17:35:08 +08:00
parent 0c82bef933
commit 75069d5653
8 changed files with 333 additions and 210 deletions

View File

@@ -4,9 +4,14 @@ import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.MusicInfo; import com.ruoyi.common.core.domain.entity.MusicInfo;
import com.ruoyi.common.core.domain.entity.MusicScene;
import com.ruoyi.common.core.domain.entity.MusicSceneRelate;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.MusicType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.mapper.MusicSceneMapper;
import com.ruoyi.system.mapper.MusicSceneRelateMapper;
import com.ruoyi.system.service.IMusicInfoService; import com.ruoyi.system.service.IMusicInfoService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@@ -14,10 +19,11 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 音乐信息Controller * 音乐信息Controller
* *
* @author ruoyi * @author ruoyi
* @date 2025-07-15 * @date 2025-07-15
*/ */
@@ -27,6 +33,10 @@ public class MusicInfoController extends BaseController
{ {
@Autowired @Autowired
private IMusicInfoService musicInfoService; private IMusicInfoService musicInfoService;
@Autowired
private MusicSceneRelateMapper relateMapper;
@Autowired
private MusicSceneMapper musicSceneMapper;
/** /**
* 查询音乐信息列表 * 查询音乐信息列表
@@ -37,6 +47,22 @@ public class MusicInfoController extends BaseController
{ {
startPage(); startPage();
List<MusicInfo> list = musicInfoService.selectMusicInfoList(musicInfo); List<MusicInfo> list = musicInfoService.selectMusicInfoList(musicInfo);
// 如果是混音查询混音的信息
if (musicInfo.getMusicType() != null && musicInfo.getMusicType().equals(MusicType.MIXING.getMusicType())){
for (MusicInfo info : list) {
// 查询混音相关信息
MusicSceneRelate relateInfo = relateMapper.selectByMusicId(String.valueOf(info.getMusicId()));
if (relateInfo != null) {
String sceneIds = relateInfo.getSceneIds();
String[] sceneArray = sceneIds.split(",");
List<MusicScene> musicScenes = musicSceneMapper.selectMusicSceneBySceneIds(sceneArray);
relateInfo.setMusicScenes(musicScenes);
info.setMusicScene(relateInfo);
}
}
//list = musicInfoService.findMusicByCate(musicInfo);
}
return getDataTable(list); return getDataTable(list);
} }
@@ -123,4 +149,13 @@ public class MusicInfoController extends BaseController
public AjaxResult add(@RequestBody MusicInfo musicInfo) { public AjaxResult add(@RequestBody MusicInfo musicInfo) {
return toAjax(musicInfoService.insertMusicInfo(musicInfo)); return toAjax(musicInfoService.insertMusicInfo(musicInfo));
} }
@RequestMapping("/add/mixMusic")
public AjaxResult addMixMusicInfo(@RequestBody Map<String,String> param){
MusicInfo newMusic = musicInfoService.addMixMusicInfo(param);
if (newMusic != null){
return AjaxResult.success(newMusic);
}
return AjaxResult.error("混音错误");
}
} }

View File

@@ -21,12 +21,12 @@ import java.util.Map;
/** /**
* 音乐信息Service业务层处理 * 音乐信息Service业务层处理
* *
* @author ruoyi * @author ruoyi
* @date 2025-07-15 * @date 2025-07-15
*/ */
@Service @Service
public class MusicInfoServiceImpl implements IMusicInfoService public class MusicInfoServiceImpl implements IMusicInfoService
{ {
@Autowired @Autowired
private MusicInfoMapper musicInfoMapper; private MusicInfoMapper musicInfoMapper;
@@ -45,7 +45,7 @@ public class MusicInfoServiceImpl implements IMusicInfoService
/** /**
* 查询音乐信息 * 查询音乐信息
* *
* @param id 音乐信息主键 * @param id 音乐信息主键
* @return 音乐信息 * @return 音乐信息
*/ */
@@ -57,7 +57,7 @@ public class MusicInfoServiceImpl implements IMusicInfoService
/** /**
* 查询音乐信息列表 * 查询音乐信息列表
* *
* @param musicInfo 音乐信息 * @param musicInfo 音乐信息
* @return 音乐信息 * @return 音乐信息
*/ */
@@ -69,7 +69,7 @@ public class MusicInfoServiceImpl implements IMusicInfoService
/** /**
* 新增音乐信息 * 新增音乐信息
* *
* @param musicInfo 音乐信息 * @param musicInfo 音乐信息
* @return 结果 * @return 结果
*/ */
@@ -87,7 +87,7 @@ public class MusicInfoServiceImpl implements IMusicInfoService
/** /**
* 修改音乐信息 * 修改音乐信息
* *
* @param musicInfo 音乐信息 * @param musicInfo 音乐信息
* @return 结果 * @return 结果
*/ */
@@ -100,7 +100,7 @@ public class MusicInfoServiceImpl implements IMusicInfoService
/** /**
* 批量删除音乐信息 * 批量删除音乐信息
* *
* @param ids 需要删除的音乐信息主键 * @param ids 需要删除的音乐信息主键
* @return 结果 * @return 结果
*/ */
@@ -112,7 +112,7 @@ public class MusicInfoServiceImpl implements IMusicInfoService
/** /**
* 删除音乐信息信息 * 删除音乐信息信息
* *
* @param id 音乐信息主键 * @param id 音乐信息主键
* @return 结果 * @return 结果
*/ */
@@ -203,7 +203,9 @@ public class MusicInfoServiceImpl implements IMusicInfoService
@Override @Override
public MusicInfo addMixMusicInfo(Map<String, String> param) { public MusicInfo addMixMusicInfo(Map<String, String> param) {
Long userId = SecurityUtils.getUserId(); //TODO:
// Long userId = SecurityUtils.getUserId();
Long userId = 10000L;
String musicId = param.get("musicId"); String musicId = param.get("musicId");
String sceneIds = param.get("sceneIds"); String sceneIds = param.get("sceneIds");
String sceneJson = param.get("sceneJson"); String sceneJson = param.get("sceneJson");
@@ -220,6 +222,7 @@ public class MusicInfoServiceImpl implements IMusicInfoService
musicSceneRelate.setUserId(userId); musicSceneRelate.setUserId(userId);
musicSceneRelate.setSceneInfo(sceneJson); musicSceneRelate.setSceneInfo(sceneJson);
musicSceneRelate.setSourceMusicId(musicId); musicSceneRelate.setSourceMusicId(musicId);
relateMapper.insertMusicSceneRelate(musicSceneRelate);
return musicInfo; return musicInfo;
} }
return null; return null;

View File

@@ -3,7 +3,7 @@
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.MusicSceneRelateMapper"> <mapper namespace="com.ruoyi.system.mapper.MusicSceneRelateMapper">
<resultMap type="MusicSceneRelate" id="MusicSceneRelateResult"> <resultMap type="MusicSceneRelate" id="MusicSceneRelateResult">
<result property="id" column="id" /> <result property="id" column="id" />
<result property="musicId" column="music_id" /> <result property="musicId" column="music_id" />
@@ -21,7 +21,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
INSERT INTO music_scene_relate(music_id, scene_ids, user_id, scene_info,source_music_id) VALUE (#{musicId},#{sceneIds},#{userId},#{sceneInfo},#{sourceMusicId}) INSERT INTO music_scene_relate(music_id, scene_ids, user_id, scene_info,source_music_id) VALUE (#{musicId},#{sceneIds},#{userId},#{sceneInfo},#{sourceMusicId})
</insert> </insert>
<select id="selectByMusicId" resultType="com.ruoyi.common.core.domain.entity.MusicSceneRelate"> <select id="selectByMusicId" resultMap="MusicSceneRelateResult">
select * from music_scene_relate where music_id = #{musicId}
</select> </select>
</mapper> </mapper>

View File

@@ -12,7 +12,10 @@ export function listNormalSong(query) {
// 查询普通歌曲详细 // 查询普通歌曲详细
export function getNormalSong(id) { export function getNormalSong(id) {
return request({ return request({
url: '/back/normal/' + id, url: '/back/music/list/',
params: {
musicId: id
},
method: 'get' method: 'get'
}) })
} }
@@ -20,7 +23,7 @@ export function getNormalSong(id) {
// 新增普通歌曲 // 新增普通歌曲
export function addNormalSong(data) { export function addNormalSong(data) {
return request({ return request({
url: '/back/normal/add', url: '/back/music/addMusic',
method: 'post', method: 'post',
data: data data: data
}) })
@@ -29,8 +32,8 @@ export function addNormalSong(data) {
// 修改普通歌曲 // 修改普通歌曲
export function updateNormalSong(data) { export function updateNormalSong(data) {
return request({ return request({
url: '/back/normal/update', url: '/back/music/',
method: 'post', method: 'put',
data: data data: data
}) })
} }
@@ -38,7 +41,7 @@ export function updateNormalSong(data) {
// 删除普通歌曲 // 删除普通歌曲
export function delNormalSong(id) { export function delNormalSong(id) {
return request({ return request({
url: '/back/normal/' + id, url: '/back/music/' + id,
method: 'delete' method: 'delete'
}) })
} }

View File

@@ -36,7 +36,7 @@ export function addRemixSong(data) {
formData.append('status', data.status) formData.append('status', data.status)
formData.append('selectedSongs', JSON.stringify(data.selectedSongs)) formData.append('selectedSongs', JSON.stringify(data.selectedSongs))
return request({ return request({
url: '/back/remix/add', url: '/back/music/add/mixMusic',
method: 'post', method: 'post',
data: formData, data: formData,
headers: { headers: {
@@ -69,7 +69,7 @@ export function updateRemixSong(data) {
// 删除混音歌曲 // 删除混音歌曲
export function delRemixSong(id) { export function delRemixSong(id) {
return request({ return request({
url: '/back/remix/' + id, url: '/back/music/' + id,
method: 'delete' method: 'delete'
}) })
} }

View File

@@ -154,21 +154,34 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="标签" prop="label"> <el-form-item label="标签" prop="label">
<el-input v-model="form.label" placeholder="请输入标签,多个标签用分号分隔" /> <el-select
v-model="selectedTags"
multiple
filterable
placeholder="请选择标签"
style="width: 100%"
@change="handleTagsChange">
<el-option
v-for="item in tagOptions"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="音乐图片" prop="imgAddr"> <el-form-item label="音乐图片" prop="imgAddr">
<image-upload <image-upload
v-model="form.imgAddr" v-model="form.imgAddr"
:limit="1" :limit="1"
:file-type="['jpg', 'jpeg', 'png', 'gif']" :file-type="['jpg', 'jpeg', 'png', 'gif']"
action="/back/upload/musicImg/file" action="/back/upload/musicImg/file"
/> />
</el-form-item> </el-form-item>
<el-form-item label="音乐文件" prop="musicAddr"> <el-form-item label="音乐文件" prop="musicAddr">
<file-upload <file-upload
v-model="form.musicAddr" v-model="form.musicAddr"
:limit="1" :limit="1"
:file-type="['mp3', 'wav', 'flac']" :file-type="['mp3', 'wav', 'flac']"
action="/back/upload/music/file" action="/back/upload/music/file"
/> />
</el-form-item> </el-form-item>
@@ -183,6 +196,7 @@
<script> <script>
import { listNormalSong, getNormalSong, delNormalSong, addNormalSong, updateNormalSong } from "@/api/playlist/normal"; import { listNormalSong, getNormalSong, delNormalSong, addNormalSong, updateNormalSong } from "@/api/playlist/normal";
import { listTags } from "@/api/playlist/tag";
export default { export default {
name: "Normal", name: "Normal",
@@ -194,6 +208,8 @@ export default {
playlistList: [], playlistList: [],
title: "", title: "",
open: false, open: false,
tagOptions: [], // 标签选项列表
selectedTags: [], // 已选择的标签
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
@@ -219,6 +235,9 @@ export default {
], ],
musicType: [ musicType: [
{ required: true, message: "音乐类型不能为空", trigger: "change" } { required: true, message: "音乐类型不能为空", trigger: "change" }
],
imgAddr: [
{ required: true, message: "音乐图片不能为空", trigger: "change" }
] ]
} }
}; };
@@ -236,6 +255,39 @@ export default {
this.loading = false; this.loading = false;
}); });
}, },
// 获取标签列表
getTagList() {
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);
return tag ? tag.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() { cancel() {
this.open = false; this.open = false;
@@ -255,6 +307,7 @@ export default {
musicType: "ordinary", musicType: "ordinary",
label: null label: null
}; };
this.selectedTags = [];
this.resetForm("form"); this.resetForm("form");
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
@@ -270,15 +323,21 @@ export default {
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset(); this.reset();
this.getTagList(); // 获取标签列表
this.open = true; this.open = true;
this.title = "添加普通歌曲"; this.title = "添加普通歌曲";
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset();
const id = row.id || this.ids const id = row.musicId || this.ids;
this.getTagList(); // 获取标签列表
getNormalSong(id).then(response => { getNormalSong(id).then(response => {
this.form = response.data; this.form = response.data;
// 解析已有的标签
if (this.form.label && this.tagOptions.length > 0) {
this.parseTagsFromString(this.form.label);
}
this.open = true; this.open = true;
this.title = "修改普通歌曲"; this.title = "修改普通歌曲";
}); });
@@ -287,6 +346,12 @@ export default {
submitForm() { submitForm() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
// 检查音乐图片是否已上传
if (!this.form.imgAddr) {
this.$message.error("请上传音乐图片");
return;
}
if (this.form.id != null) { if (this.form.id != null) {
updateNormalSong(this.form).then(response => { updateNormalSong(this.form).then(response => {
this.$modal.msgSuccess("修改成功"); this.$modal.msgSuccess("修改成功");

View File

@@ -59,40 +59,49 @@
<el-table v-loading="loading" :data="playlistList"> <el-table v-loading="loading" :data="playlistList">
<el-table-column label="序号" align="center" type="index" width="60" /> <el-table-column label="序号" align="center" type="index" width="60" />
<el-table-column label="混音名称" align="center" prop="remixName" :show-overflow-tooltip="true" /> <el-table-column label="混音名称" align="center" prop="name" :show-overflow-tooltip="true" />
<el-table-column label="二类音乐名称" align="center" prop="secondMusicName" :show-overflow-tooltip="true" /> <!-- <el-table-column label="作者" align="center" prop="author" :show-overflow-tooltip="true" />-->
<el-table-column label="制作时间" align="center" prop="productionTime" width="120" /> <el-table-column label="音乐场景" align="center" prop="musicScene" width="200">
<el-table-column label="文件类型" align="center" prop="fileType" width="120" />
<el-table-column label="权限" align="center" prop="permission" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.permission === 1 ? 'VIP' : '免费' }}</span> <el-tag
v-for="scene in getScenes(scope.row)"
:key="scene.sceneId"
type="primary"
size="mini"
style="margin-right: 5px; margin-bottom: 5px;"
>
{{ scene.scene }}
</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="分类" align="center" prop="category" width="100"> <el-table-column label="VIP权限" align="center" prop="vip" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag type="primary" size="mini">{{ scope.row.category }}</el-tag> <el-tag :type="scope.row.vip === '1' ? 'warning' : 'success'" size="mini">
{{ scope.row.vip === '1' ? 'VIP' : '免费' }}
</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="标签" align="center" prop="tags" width="150"> <el-table-column label="标签" align="center" prop="label" width="150">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag <el-tag
v-for="tag in scope.row.tags" v-for="tag in scope.row.label ? scope.row.label.split(';') : []"
:key="tag" :key="tag"
type="warning" type="info"
size="mini" size="mini"
style="margin-right: 5px;" style="margin-right: 5px; margin-bottom: 5px;"
> >
{{ tag }} {{ tag }}
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="状态" align="center" prop="status" width="80"> <el-table-column label="上架状态" align="center" prop="shelf" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'" size="mini"> <el-tag :type="scope.row.shelf === '1' ? 'success' : 'danger'" size="mini">
{{ scope.row.status === 1 ? '上架' : '下架' }} {{ scope.row.shelf === '1' ? '上架' : '下架' }}
</el-tag> </el-tag>
</template> </template>
</el-table-column> </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" class-name="small-padding fixed-width" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
@@ -112,7 +121,7 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination <pagination
v-show="total>0" v-show="total>0"
:total="total" :total="total"
@@ -124,105 +133,85 @@
<!-- 添加或修改混音歌曲对话框 --> <!-- 添加或修改混音歌曲对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body> <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 ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="音名称" prop="remixName" required> <el-form-item label="音名称" prop="name" required>
<el-input v-model="form.remixName" placeholder="请输入音乐名称" /> <el-input v-model="form.name" placeholder="请输入音乐名称" />
</el-form-item> </el-form-item>
<el-form-item label="权限" prop="permission" required> <el-form-item label="作者" prop="author" required>
<el-select v-model="form.permission" placeholder="请选择权限" style="width: 100%"> <el-input v-model="form.author" placeholder="请输入作者" />
</el-form-item>
<el-form-item label="VIP权限" prop="vip" required>
<el-select v-model="form.vip" placeholder="请选择VIP权限" style="width: 100%">
<el-option label="免费" :value="0" /> <el-option label="免费" :value="0" />
<el-option label="VIP" :value="1" /> <el-option label="VIP" :value="1" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="分类配置" prop="categoryConfig" required> <el-form-item label="上架状态" prop="shelf" required>
<el-select v-model="form.categoryConfig" placeholder="请选择分类" style="width: 100%"> <el-select v-model="form.shelf" placeholder="请选择上架状态" style="width: 100%">
<el-option <el-option label="上架" :value="1" />
v-for="item in categoryOptions" <el-option label="下架" :value="2" />
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="标签" prop="tags"> <el-form-item label="标签" prop="label">
<el-select v-model="form.tags" multiple placeholder="请添加标签 (可多选)" style="width: 100%"> <el-select
v-model="selectedTags"
multiple
filterable
placeholder="请选择标签"
style="width: 100%"
@change="handleTagsChange">
<el-option <el-option
v-for="item in tagOptions" v-for="item in tagOptions"
:key="item.value" :key="item.id"
:label="item.label" :label="item.name"
:value="item.value" :value="item.id">
/> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="分类" prop="category" required> <el-form-item label="音乐场景" prop="musicScenes" required>
<el-select v-model="form.category" placeholder="请选择分类" style="width: 100%">
<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="status" required>
<el-switch v-model="form.status" active-value="1" inactive-value="0" />
</el-form-item>
<el-form-item label="添加场景音乐" required>
<div class="scene-music-container"> <div class="scene-music-container">
<div <div
v-for="(item, index) in 3" v-for="(scene, index) in availableScenes"
:key="index" :key="scene.sceneId"
class="scene-music-item" class="scene-music-item"
@click="selectSceneMusic(index)"
> >
<div v-if="form.selectedSongs[index]" class="selected-music"> <el-checkbox
<img :src="form.selectedSongs[index].coverUrl" class="music-cover"> v-model="selectedScenes"
<span class="music-name">{{ form.selectedSongs[index].musicName }}</span> :label="scene.sceneId"
<i class="el-icon-close remove-btn" @click.stop="removeSceneMusic(index)"></i> @change="handleSceneChange"
</div> >
<div v-else class="add-music-btn"> {{ scene.scene }}
<i class="el-icon-plus"></i> </el-checkbox>
</div>
</div> </div>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="音乐图片" prop="imgAddr">
<image-upload
v-model="form.imgAddr"
:limit="1"
:file-type="['jpg', 'jpeg', 'png', 'gif']"
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> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button> <el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button> <el-button @click="cancel"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
<!-- 选择场景音乐对话框 -->
<el-dialog title="选择场景音乐" :visible.sync="musicSelectOpen" width="800px" append-to-body>
<el-table :data="musicList" @selection-change="handleMusicSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column label="音乐名称" prop="musicName" />
<el-table-column label="制作人" prop="producer" />
<el-table-column label="分类" prop="category" />
<el-table-column label="标签" prop="tags">
<template slot-scope="scope">
<el-tag
v-for="tag in scope.row.tags"
:key="tag"
type="warning"
size="mini"
style="margin-right: 5px;"
>
{{ tag }}
</el-tag>
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="confirmMusicSelection"> </el-button>
<el-button @click="musicSelectOpen = false"> </el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { listRemixSong, getRemixSong, delRemixSong, addRemixSong, updateRemixSong, getMusicList } from "@/api/playlist/remix"; import { listRemixSong, getRemixSong, delRemixSong, addRemixSong, updateRemixSong, getMusicList } from "@/api/playlist/remix";
import { listTags } from "@/api/playlist/tag";
export default { export default {
name: "RemixSong", name: "RemixSong",
@@ -234,27 +223,27 @@ export default {
playlistList: [], playlistList: [],
title: "", title: "",
open: false, open: false,
musicSelectOpen: false, selectedTags: [], // 已选择的标签
currentMusicIndex: 0, selectedScenes: [], // 已选择的场景
availableScenes: [], // 可用的场景列表
musicList: [], musicList: [],
selectedMusic: null,
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
musicName: null, musicName: null,
category: null, category: null,
tag: null, tag: null,
status: null, shelf: null,
permission: null vip: null,
}, musicType: 'mixing'
form: {
selectedSongs: []
}, },
form: {},
rules: { rules: {
remixName: [{ required: true, message: "音名称不能为空", trigger: "blur" }], name: [{ required: true, message: "音名称不能为空", trigger: "blur" }],
permission: [{ required: true, message: "权限不能为空", trigger: "change" }], author: [{ required: true, message: "作者不能为空", trigger: "blur" }],
categoryConfig: [{ required: true, message: "分类配置不能为空", trigger: "change" }], vip: [{ required: true, message: "VIP权限不能为空", trigger: "change" }],
category: [{ required: true, message: "分类不能为空", trigger: "change" }] shelf: [{ required: true, message: "上架状态不能为空", trigger: "change" }],
imgAddr: [{ required: true, message: "音乐图片不能为空", trigger: "change" }]
}, },
categoryOptions: [ categoryOptions: [
{ label: '热门', value: '热门' }, { label: '热门', value: '热门' },
@@ -263,17 +252,7 @@ export default {
{ label: '古典', value: '古典' }, { label: '古典', value: '古典' },
{ label: '爵士', value: '爵士' } { label: '爵士', value: '爵士' }
], ],
tagOptions: [ tagOptions: [],
{ label: '流行', value: '流行' },
{ label: '摇滚', value: '摇滚' },
{ label: '古典', value: '古典' },
{ label: '爵士', value: '爵士' },
{ label: '电子', value: '电子' },
{ label: '民谣', value: '民谣' },
{ label: '电音', value: '电音' },
{ label: '混音', value: '混音' },
{ label: '睡眠', value: '睡眠' }
],
statusOptions: [ statusOptions: [
{ label: '下架', value: 0 }, { label: '下架', value: 0 },
{ label: '上架', value: 1 } { label: '上架', value: 1 }
@@ -302,6 +281,75 @@ export default {
this.musicList = response.rows || []; this.musicList = response.rows || [];
}); });
}, },
// 获取音乐场景数据
getScenes(row) {
if (row.musicScene && row.musicScene.musicScenes && row.musicScene.musicScenes.length > 0) {
return row.musicScene.musicScenes;
}
return [];
},
// 获取场景列表
getSceneList() {
// 这里应该调用获取场景列表的API这里模拟一些数据
this.availableScenes = [
{ sceneId: '1', scene: '下雨' },
{ sceneId: '2', scene: '打雷' },
{ sceneId: '3', scene: '海浪' },
{ sceneId: '4', scene: '森林' }
];
},
// 获取标签列表
getTagList() {
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);
return tag ? tag.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);
},
// 处理场景选择变化
handleSceneChange() {
if (this.form.musicScene) {
this.form.musicScene.sceneIds = this.selectedScenes.join(',');
} else {
this.form.musicScene = {
sceneIds: this.selectedScenes.join(',')
};
}
},
// 从字符串解析场景
parseSceneIdsFromString(sceneIdsString) {
if (!sceneIdsString) {
this.selectedScenes = [];
return;
}
this.selectedScenes = sceneIdsString.split(',');
},
cancel() { cancel() {
this.open = false; this.open = false;
this.reset(); this.reset();
@@ -309,14 +357,21 @@ export default {
reset() { reset() {
this.form = { this.form = {
id: null, id: null,
remixName: null, musicId: null,
permission: 0, name: null,
categoryConfig: null, author: null,
category: null, vip: 0,
tags: [], shelf: 1,
status: 1, imgAddr: null,
selectedSongs: [] musicAddr: null,
musicType: "mixing",
label: null,
musicScene: {
sceneIds: ""
}
}; };
this.selectedTags = [];
this.selectedScenes = [];
this.resetForm("form"); this.resetForm("form");
}, },
handleQuery() { handleQuery() {
@@ -329,14 +384,29 @@ export default {
}, },
handleAdd() { handleAdd() {
this.reset(); this.reset();
this.getTagList(); // 获取标签列表
this.getSceneList(); // 获取场景列表
this.open = true; this.open = true;
this.title = "新增混音歌曲"; this.title = "新增混音歌曲";
}, },
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset();
const id = row.id || this.ids this.getTagList(); // 获取标签列表
this.getSceneList(); // 获取场景列表
const id = row.id || this.ids;
getRemixSong(id).then(response => { getRemixSong(id).then(response => {
this.form = response.data; this.form = response.data;
// 解析已有的标签
if (this.form.label && this.tagOptions.length > 0) {
this.parseTagsFromString(this.form.label);
}
// 解析已有的场景
if (this.form.musicScene && this.form.musicScene.sceneIds) {
this.parseSceneIdsFromString(this.form.musicScene.sceneIds);
}
this.open = true; this.open = true;
this.title = "编辑混音歌曲"; this.title = "编辑混音歌曲";
}); });
@@ -368,25 +438,6 @@ export default {
this.getList(); this.getList();
this.$modal.msgSuccess("删除成功"); this.$modal.msgSuccess("删除成功");
}).catch(() => {}); }).catch(() => {});
},
selectSceneMusic(index) {
this.currentMusicIndex = index;
this.musicSelectOpen = true;
},
handleMusicSelectionChange(selection) {
if (selection.length > 0) {
this.selectedMusic = selection[0];
}
},
confirmMusicSelection() {
if (this.selectedMusic) {
this.$set(this.form.selectedSongs, this.currentMusicIndex, this.selectedMusic);
this.musicSelectOpen = false;
this.selectedMusic = null;
}
},
removeSceneMusic(index) {
this.$delete(this.form.selectedSongs, index);
} }
} }
}; };
@@ -395,58 +446,24 @@ export default {
<style scoped> <style scoped>
.scene-music-container { .scene-music-container {
display: flex; display: flex;
flex-wrap: wrap;
gap: 10px; gap: 10px;
} }
.scene-music-item { .scene-music-item {
width: 120px; min-width: 120px;
height: 120px; padding: 10px;
border: 1px dashed #d9d9d9; border: 1px dashed #d9d9d9;
border-radius: 6px; border-radius: 6px;
cursor: pointer; cursor: pointer;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
position: relative;
} }
.scene-music-item:hover { .scene-music-item:hover {
border-color: #409EFF; border-color: #409EFF;
} }
.add-music-btn {
font-size: 28px;
color: #8c939d;
}
.selected-music {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
}
.music-cover {
width: 60px;
height: 60px;
border-radius: 4px;
margin-bottom: 5px;
}
.music-name {
font-size: 12px;
color: #606266;
text-align: center;
max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.remove-btn {
position: absolute;
top: 5px;
right: 5px;
color: #f56c6c;
cursor: pointer;
}
.el-tag { .el-tag {
border-radius: 12px; border-radius: 12px;
margin-bottom: 5px;
} }
</style> </style>

View File

@@ -9,7 +9,7 @@ const CompressionPlugin = require('compression-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题 const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
const baseUrl = 'http://localhost:8080' // 后端接口 const baseUrl = 'http://localhost:8081' // 后端接口
const port = process.env.port || process.env.npm_config_port || 80 // 端口 const port = process.env.port || process.env.npm_config_port || 80 // 端口