Ai_GirlFriend/xuniYou/pages/create/timbre.vue
2026-01-31 19:15:41 +08:00

356 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>