356 lines
7.7 KiB
Vue
356 lines
7.7 KiB
Vue
<template>
|
||
<view>
|
||
<view class="body">
|
||
<view class="list">
|
||
<view class="list_head fa sb">
|
||
<image src="/static/images/timbre_logo.png" mode="widthFix"></image>{{ voicesInfo }}
|
||
</view>
|
||
<view class="list_content">
|
||
<view class="list_module fa sb" v-for="(item, index) in configVoicesList.voices" :key="index" v-show="item.price_gold == 0"
|
||
@click="selectTimbre(index)">
|
||
<view class="list_detail fa f1">
|
||
<view class="list_image">
|
||
<image class="list_avatar" :src="item.avatar_url?global + item.avatar_url:'/static/images/replacement_picture.png'" mode="aspectFill"></image>
|
||
<image class="list_voice" @click.stop="playVoice(item.sample_audio_url)"
|
||
src="/static/images/timbre_voice.png" mode="widthFix"></image>
|
||
</view>
|
||
<view class="list_item f1">
|
||
<view class="list_name h1">{{ item.name }}</view>
|
||
<view class="list_tag h2">{{ item.style_tag }}</view>
|
||
</view>
|
||
</view>
|
||
<view class="list_select faj" >
|
||
<image
|
||
:src="selectedItemIndex == index ? '/static/images/selectA.png' : '/static/images/select.png'"
|
||
mode="widthFix"></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="opt">
|
||
<view class="opt_module">
|
||
<view class="opt_data">
|
||
<view class="opt_btn faj" @click="confirmSelection">
|
||
确定选择
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
ConfigVoices,
|
||
LoverVoice,
|
||
ConfigVoicesAvailable,
|
||
LoverVoiceSimple
|
||
} from '@/utils/api.js'
|
||
import notHave from '@/components/not-have.vue';
|
||
import topSafety from '@/components/top-safety.vue';
|
||
|
||
import { useVoiceStore } from '@/store/index.js'
|
||
export default {
|
||
components: {
|
||
notHave,
|
||
topSafety,
|
||
},
|
||
data() {
|
||
return {
|
||
global: this.baseURL,
|
||
form: {
|
||
gender: '',
|
||
voice_id: '',
|
||
},
|
||
selectedItemIndex: -1, // 默认不选择任何项
|
||
configVoicesList: [],
|
||
voicesInfo: '',
|
||
currentAudioContext: null, // 添加当前音频上下文实例
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
console.log('角色声音页面接参:',options)
|
||
this.form.gender = options.sex
|
||
console.log(this.form)
|
||
this.configVoices()
|
||
},
|
||
methods: {
|
||
configVoices() {
|
||
let api = ''
|
||
if(this.form.gender){
|
||
api = ConfigVoices
|
||
}else{
|
||
api = ConfigVoicesAvailable
|
||
}
|
||
api({
|
||
...this.form
|
||
}).then(res => {
|
||
if (res.code == 1) {
|
||
this.configVoicesList = res.data
|
||
if (this.configVoicesList.selected_voice_id != null) {
|
||
let found = false;
|
||
for (let i = 0; i < this.configVoicesList.voices.length; i++) {
|
||
if (this.configVoicesList.voices[i].id == this.configVoicesList.selected_voice_id) {
|
||
this.voicesInfo = this.configVoicesList.voices[i].name
|
||
this.selectedItemIndex = i
|
||
this.form.voice_id = this.configVoicesList.voices[i].id
|
||
found = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!found) {
|
||
// 如果没有找到 selected_voice_id,则使用默认值
|
||
for (let i = 0; i < this.configVoicesList.voices.length; i++) {
|
||
if (this.configVoicesList.voices[i].id == this.configVoicesList.default_voice_id) {
|
||
this.voicesInfo = this.configVoicesList.voices[i].name
|
||
this.selectedItemIndex = i
|
||
this.form.voice_id = this.configVoicesList.voices[i].id
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
for (let i = 0; i < this.configVoicesList.voices.length; i++) {
|
||
if (this.configVoicesList.voices[i].id == this.configVoicesList.default_voice_id) {
|
||
this.voicesInfo = this.configVoicesList.voices[i].name
|
||
this.selectedItemIndex = i
|
||
this.form.voice_id = this.configVoicesList.voices[i].id
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
position: 'top'
|
||
})
|
||
}
|
||
})
|
||
},
|
||
// 设置声音
|
||
loverVoice() {
|
||
let api = ''
|
||
if(this.form.gender){
|
||
api = LoverVoice
|
||
}else{
|
||
api = LoverVoiceSimple
|
||
}
|
||
api(this.form).then(res => {
|
||
if (res.code == 1) {
|
||
uni.showToast({
|
||
title: '设置成功',
|
||
icon: 'none',
|
||
position: 'top'
|
||
})
|
||
const voiceStore = useVoiceStore()
|
||
voiceStore.setVoice(this.form.voice_id, this.voicesInfo)
|
||
setTimeout(() => {
|
||
uni.navigateBack({
|
||
delta: 1
|
||
});
|
||
}, 1000);
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
position: 'top'
|
||
})
|
||
}
|
||
})
|
||
},
|
||
// 选择音色
|
||
selectTimbre(index) {
|
||
this.selectedItemIndex = index;
|
||
this.voicesInfo = this.configVoicesList.voices[index].name
|
||
this.form.voice_id = this.configVoicesList.voices[index].id
|
||
},
|
||
playVoice(url) {
|
||
// 如果当前有正在播放的音频,先停止它
|
||
if (this.currentAudioContext) {
|
||
this.currentAudioContext.stop();
|
||
this.currentAudioContext.destroy(); // 释放资源
|
||
}
|
||
|
||
// 创建新的音频上下文
|
||
this.currentAudioContext = uni.createInnerAudioContext();
|
||
this.currentAudioContext.src = this.global + url; // 设置音频源
|
||
|
||
// 播放音频
|
||
this.currentAudioContext.play();
|
||
|
||
// 监听播放结束事件,播放结束后清空当前音频上下文
|
||
this.currentAudioContext.onEnded(() => {
|
||
console.log('音频播放结束');
|
||
if (this.currentAudioContext) {
|
||
this.currentAudioContext.destroy();
|
||
this.currentAudioContext = null;
|
||
}
|
||
});
|
||
|
||
// 监听播放错误事件
|
||
this.currentAudioContext.onError((err) => {
|
||
console.error('音频播放失败:', err);
|
||
if (this.currentAudioContext) {
|
||
this.currentAudioContext.destroy();
|
||
this.currentAudioContext = null;
|
||
}
|
||
uni.showToast({
|
||
title: '播放失败',
|
||
icon: 'none'
|
||
});
|
||
});
|
||
},
|
||
confirmSelection() {
|
||
console.log(this.form)
|
||
console.log(this.selectedItemIndex)
|
||
if (this.selectedItemIndex < 0) {
|
||
uni.showToast({
|
||
title: '请选择音色',
|
||
icon: 'none'
|
||
});
|
||
} else {
|
||
console.log(this.form)
|
||
this.loverVoice()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
<style>
|
||
page {
|
||
background: #F6F8FA;
|
||
}
|
||
</style>
|
||
<style>
|
||
.body {
|
||
position: relative;
|
||
padding: 0 40rpx 40rpx 40rpx;
|
||
}
|
||
|
||
.list {
|
||
position: relative;
|
||
margin: 30rpx 0 0 0;
|
||
}
|
||
|
||
.list_head {
|
||
position: relative;
|
||
margin: 0 0 30rpx 0;
|
||
padding: 28rpx 40rpx;
|
||
font-weight: 400;
|
||
font-size: 30rpx;
|
||
color: #9E9E9E;
|
||
line-height: 50rpx;
|
||
background: #FFFFFF;
|
||
border-radius: 12rpx;
|
||
}
|
||
|
||
.list_head image {
|
||
width: 68rpx;
|
||
height: 66rpx;
|
||
display: block;
|
||
border-radius: 100rpx;
|
||
}
|
||
|
||
.list_content {
|
||
position: relative;
|
||
}
|
||
|
||
.list_module {
|
||
position: relative;
|
||
margin: 0 0 30rpx 0;
|
||
padding: 28rpx 40rpx;
|
||
background: #FFFFFF;
|
||
border-radius: 12rpx;
|
||
}
|
||
|
||
.list_detail {
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.list_image {
|
||
position: relative;
|
||
}
|
||
|
||
.list_avatar {
|
||
width: 88rpx;
|
||
height: 88rpx;
|
||
display: block;
|
||
flex-shrink: 0;
|
||
border-radius: 100rpx;
|
||
}
|
||
|
||
.list_voice {
|
||
position: absolute;
|
||
right: -10rpx;
|
||
bottom: -10rpx;
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
}
|
||
|
||
.list_item {
|
||
position: relative;
|
||
margin: 0 0 0 24rpx;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.list_name {
|
||
font-weight: 500;
|
||
font-size: 32rpx;
|
||
color: #333333;
|
||
line-height: 50rpx;
|
||
}
|
||
|
||
.list_tag {
|
||
font-weight: 400;
|
||
font-size: 28rpx;
|
||
color: #9E9E9E;
|
||
line-height: 50rpx;
|
||
}
|
||
|
||
.list_select {
|
||
position: relative;
|
||
}
|
||
|
||
.list_select image {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.opt {
|
||
position: relative;
|
||
height: 150rpx;
|
||
}
|
||
|
||
.opt_module {
|
||
position: fixed;
|
||
padding: 5rpx 0 70rpx 0;
|
||
height: 85rpx;
|
||
width: 100%;
|
||
background: #F6F8FA;
|
||
bottom: 0;
|
||
left: 0;
|
||
box-sizing: content-box;
|
||
border-top: 1px solid #f0f0f0;
|
||
z-index: 2;
|
||
}
|
||
|
||
.opt_data {
|
||
padding: 5rpx 50rpx;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.opt_btn {
|
||
padding: 24rpx 0;
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
color: #FFFFFF;
|
||
line-height: 50rpx;
|
||
background: linear-gradient(135deg, #9F47FF 0%, #0053FA 100%);
|
||
border-radius: 12rpx;
|
||
}
|
||
</style> |