Ai_GirlFriend/xuniYou/pages/create/lover.vue

599 lines
14 KiB
Vue
Raw Normal View History

2026-01-31 19:15:41 +08:00
<template>
<view>
<view class="body">
<view class="list">
<view class="list_create faj">
<text class="faj" v-if="!loverBasicList" @click="imageClick">+创建形象</text>
<text class="faj" v-if="loverBasicList" @click="imageClick">+修改形象</text>
</view>
<view class="list_content">
<view class="list_title">恋人性别</view>
<view class="list_item fa">
<view class="list_table" v-for="(item, index) in genderList" :key="index"
:class="genderIndex == index ? 'list_active' : ''" @click="genderClick(index)">
<image class="list_sexImage" :src="item.image" mode="aspectFill"></image>
<view class="list_name" :style="genderIndex == index ? 'list_active' : ''">{{ item.name }}
</view>
<image class="list_tag" v-if="genderIndex == index" src="/static/images/lover_back.png"
mode="aspectFill"></image>
</view>
</view>
</view>
<view class="list_content fa">
<view class="list_title">昵称</view>
<input class="f1" v-model="form.name" placeholder="给虚拟梦中人起个名字" placeholder-class="list_input" />
</view>
<view class="list_contentCharacter">
<view class="list_title">人物简介</view>
<textarea class="" v-model="form.intro" placeholder="一句话描述这个人物信息" maxlength="50"
@input="openingIntroNum" placeholder-class="list_textarea" />
<view class="list_count">{{ openingIntroNumber }}/50</view>
</view>
<view class="list_content">
<view class="list_title">性格模板</view>
<view class="list_detail fa">
<view class="list_text f1 fa wp">
<text class="faj" v-for="(item, index) in personalityOptions" :key="index"
@click="personalityClick(index)"
:class="personalityIndex == index ? 'list_actives' : ''">{{ item.name }}</text>
</view>
</view>
</view>
<view class="list_contents">
<view class="list_title">故事背景</view>
<textarea class="" v-model="form.story_background" maxlength="100" @input="storyBackgroundNum"
placeholder="添加虚拟人设,如身份、经历、性格等" placeholder-class="list_textarea" />
<view class="list_count">{{ storyBackgroundNumber }}/100</view>
</view>
<view class="list_contents">
<view class="list_title">开场白</view>
<textarea class="" v-model="form.opening_line" maxlength="20" @input="openingRemarksNum"
placeholder="说点什么来开启聊天吧" placeholder-class="list_textarea" />
<view class="list_count">{{ openingRemarksNumber }}/20</view>
</view>
<view class="list_content">
<view class="list_title">兴趣标签</view>
<view class="list_detail fa">
<view class="list_text f1 fa wp">
<text class="faj" v-for="(item, index) in hobbyOptions" :key="index"
@click="hobbyClick(index)" :class="hobbyIndex.includes(index) ? 'list_actives' : ''">{{
item.name }}</text>
</view>
</view>
</view>
<view class="list_content fa">
<view class="list_title">音色</view>
<view class="list_timbre f1 fa sb" @click="timbreClick">
<text class="f1">{{ currentVoice.name || voicesInfo || '请选择音色' }}</text>
<image src="/static/images/more.png" mode="widthFix"></image>
</view>
</view>
</view>
</view>
<view class="opt">
<view class="opt_module">
<view class="opt_data">
<view class="opt_btn faj" @click="submit">
保存形象
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
GetLoverConfig,
LoverConfig,
GetLoverOptions,
} from '@/utils/api.js'
import {
isPhone
} from '@/utils/utils.js'
import notHave from '@/components/not-have.vue';
import topSafety from '@/components/top-safety.vue';
// 导入Pinia store
import { useVoiceStore } from '@/store/index.js'
export default {
components: {
notHave,
topSafety,
},
data() {
return {
form: {
gender: '',
name: '',
intro: '',
personality_tag: '',
story_background: '',
opening_line: '',
interest_tags: [],
},
storyBackgroundNumber: 0,
openingRemarksNumber: 0,
openingIntroNumber: 0,
genderList: [{
name: '男生',
image: 'https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251226/e90acc9a7675bb463188a8ecf8f46054.png',
id: 'male',
},
{
name: '女生',
image: 'https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251231/a8b27c789ba9515ac0d07f77a3913d0b.png',
id: 'female',
},],
genderIndex: 0,
getLoverConfigList: '',
personalityOptions: [],
personalityIndex: -1,
getLoverOptionsList: '',
hobbyOptions: [], // 添加兴趣标签选项数据
hobbyIndex: [], // 添加兴趣标签选中索引
voicesInfo: '', // 添加音色信息
timbre: '',
loverBasicList: '',
}
},
computed: {
// 计算属性从Pinia store获取当前音色
currentVoice() {
const voiceStore = useVoiceStore()
return voiceStore.currentVoice
}
},
onLoad() {
this.getLoverConfig()
},
onShow() {
// 页面显示时从Pinia store获取最新的音色信息
const voiceStore = useVoiceStore()
if (voiceStore.selectedVoiceId) {
this.voicesInfo = voiceStore.selectedVoiceName
this.timbre = voiceStore.selectedVoiceId
}
if (uni.getStorageSync('loverBasicList')) {
this.loverBasicList = uni.getStorageSync('loverBasicList')
}
},
methods: {
getLoverConfig() {
GetLoverConfig({}).then(res => {
if (res.code == 1) {
this.getLoverConfigList = res.data
this.genderIndex = this.getLoverConfigList.gender == 'male' ? 0 : 1//0:男生 1:女生,默认根据接口选择男女
this.form.gender = this.getLoverConfigList.gender//默认根据接口获取性别
this.personalityOptions = this.getLoverConfigList.personality_options // 默认从总接口获取性格模板
this.form.personality_tag = this.personalityOptions[0].id // 默认选择第一个性格模板
this.hobbyOptions = this.getLoverConfigList.hobby_options // 获取兴趣标签选项
if (this.getLoverConfigList.lover.voice_id != null) {
for (let i = 0; i < this.getLoverConfigList.voices.length; i++) {
if (this.getLoverConfigList.voices[i].id == this.getLoverConfigList.lover.voice_id) {
this.voicesInfo = this.getLoverConfigList.voices[i].name
this.timbre = this.getLoverConfigList.voices[i].id
}
}
} else {
for (let i = 0; i < this.getLoverConfigList.voices.length; i++) {
if (this.getLoverConfigList.voices[i].id == this.getLoverConfigList.default_voice_id) {
this.voicesInfo = this.getLoverConfigList.voices[i].name
this.timbre = this.getLoverConfigList.voices[i].id
}
}
}
const voiceStore = useVoiceStore()
voiceStore.setVoice(this.timbre, this.voicesInfo)
} else {
uni.showToast({
title: res.msg,
icon: 'none',
position: 'top'
})
}
})
},
LoverConfig() {
LoverConfig(this.form).then(res => {
if (res.code == 1) {
uni.showToast({
title: '保存成功',
icon: 'none',
position: 'top'
})
setTimeout(() => {
uni.navigateBack({
delta: 1,
});
}, 500);
} else {
uni.showToast({
title: res.msg,
icon: 'none',
position: 'top'
})
}
})
},
getLoverOptions() {
GetLoverOptions(
{ gender: this.form.gender }
).then(res => {
if (res.code == 1) {
this.getLoverOptionsList = res.data
this.personalityOptions = this.getLoverOptionsList.personality_options
this.form.personality_tag = this.personalityOptions[0].id // 默认选择第一个性格模板的id
this.personalityIndex = 0// 默认选择第一个性格模板
this.form.interest_tags = []// 默认兴趣标签为空
this.hobbyIndex = []// 默认兴趣标签选中索引为空
for (let i = 0; i < this.getLoverOptionsList.voices.length; i++) {
if (this.getLoverOptionsList.voices[i].id == this.getLoverOptionsList.default_voice_id) {
this.voicesInfo = this.getLoverOptionsList.voices[i].name
this.timbre = this.getLoverOptionsList.voices[i].id
break;
}
}
const voiceStore = useVoiceStore()
voiceStore.setVoice(this.timbre, this.voicesInfo)
} else {
uni.showToast({
title: res.msg,
icon: 'none',
position: 'top'
})
}
})
},
genderClick(index) {
this.genderIndex = index
this.form.gender = this.genderList[index].id
this.form.name = ''
this.form.intro = ''
this.form.personality_tag = ''
this.form.story_background = ''
this.form.opening_line = ''
this.form.interest_tags = []
this.getLoverOptions()
},
personalityClick(index) {
this.personalityIndex = index
this.form.personality_tag = this.personalityOptions[index].id
},
hobbyClick(index) {
const currentIndex = this.hobbyIndex.indexOf(index);
if (currentIndex > -1) {
// 如果已选中,则取消选中
this.hobbyIndex.splice(currentIndex, 1);
this.form.interest_tags.splice(currentIndex, 1);
} else {
// 如果未选中,先检查是否已达到最大选择数
if (this.hobbyIndex.length >= 3) {
uni.showToast({
title: '最多只能选择3个兴趣标签',
icon: 'none',
position: 'top'
});
return; // 不做任何操作
}
// 未达到最大选择数,添加选中
this.hobbyIndex.push(index);
this.form.interest_tags.push(this.hobbyOptions[index].id);
}
},
storyBackgroundNum(e) {
this.storyBackgroundNumber = e.detail.value.length;
},
openingRemarksNum(e) {
this.openingRemarksNumber = e.detail.value.length;
},
openingIntroNumber(e) {
this.openingIntroNumber = e.detail.value.length;
},
submit() {
console.log(this.form)
if (this.form.name == '') {
uni.showToast({
title: "请输入昵称",
icon: 'none',
position: 'top'
})
} else if (this.form.intro == '') {
uni.showToast({
title: "请输入人物简介",
icon: 'none',
position: 'top'
})
} else if (this.form.personality_tag == '') {
uni.showToast({
title: "请选择性格模板",
icon: 'none',
position: 'top'
})
} else if (this.form.story_background == '') {
uni.showToast({
title: "请输入故事背景",
icon: 'none',
position: 'top'
})
} else if (this.form.opening_line == '') {
uni.showToast({
title: "请输入开场白",
icon: 'none',
position: 'top'
})
} else if (this.form.interest_tags.length == 0) {
uni.showToast({
title: "请选择兴趣标签",
icon: 'none',
position: 'top'
})
} else {
console.log(this.form)
this.LoverConfig()
}
},
imageClick() {
uni.navigateTo({
url: '/pages/create/image'
})
},
timbreClick() {
uni.navigateTo({
url: '/pages/create/timbre?sex=' + this.form.gender
})
},
}
}
</script>
<style>
page {
background: #F6F8FA;
}
</style>
<style>
.body {
position: relative;
padding: 0 50rpx 50rpx 50rpx;
}
.list {
position: relative;
margin: 54rpx 0 0 0;
}
.list_create {
position: relative;
margin: 0 0 70rpx 0;
}
.list_create text {
padding: 20rpx 58rpx;
font-weight: 400;
font-size: 30rpx;
color: #222222;
line-height: 50rpx;
background: #FFFFFF;
border-radius: 254rpx;
}
.list_content {
position: relative;
margin: 0 0 30rpx 0;
padding: 30rpx 40rpx;
background: #FFFFFF;
border-radius: 12rpx;
box-sizing: border-box;
}
.list_title {
margin: 0 80rpx 0 0;
font-weight: 500;
font-size: 32rpx;
color: #222222;
line-height: 50rpx;
}
.list_title text {
color: #817EFE;
}
.list_item {
position: relative;
margin: 30rpx 0 0 0;
}
.list_table {
position: relative;
margin: 0 32rpx 0 0;
padding: 8rpx 6rpx;
width: 168rpx;
background: #FAFAFA;
border-radius: 12rpx;
border: 2rpx solid #FAFAFA;
}
.list_sexImage {
width: 100%;
height: 136rpx;
display: block;
}
.list_name {
font-weight: 400;
font-size: 30rpx;
color: #333333;
line-height: 50rpx;
text-align: center;
}
.list_active {
color: #817EFE;
border: 2rpx solid #817EFE;
}
.list_tag {
position: absolute;
right: 0;
top: 0;
width: 42rpx;
height: 32rpx;
}
.list_content input {
font-weight: 400;
font-size: 30rpx;
color: #333;
line-height: 50rpx;
}
.list_input {
color: #D3D3D3;
}
.list_contentCharacter {
position: relative;
margin: 0 0 30rpx 0;
padding: 30rpx 40rpx 60rpx 40rpx;
background: #FFFFFF;
border-radius: 12rpx;
box-sizing: border-box;
}
.list_contentCharacter textarea {
margin: 22rpx 0 0 0;
height: 70rpx;
font-weight: 400;
font-size: 30rpx;
color: #333;
line-height: 50rpx;
}
.list_contents {
position: relative;
margin: 0 0 30rpx 0;
padding: 30rpx 40rpx 60rpx 40rpx;
background: #FFFFFF;
border-radius: 12rpx;
box-sizing: border-box;
}
.list_contents textarea {
margin: 22rpx 0 0 0;
height: 125rpx;
font-weight: 400;
font-size: 30rpx;
color: #333;
line-height: 50rpx;
}
.list_textarea {
color: #ADADAD;
}
.list_count {
position: absolute;
right: 30rpx;
bottom: 14rpx;
font-weight: 400;
font-size: 26rpx;
color: #ADADAD;
line-height: 50rpx;
}
.list_timbre {
position: relative;
}
.list_timbre text {
width: 148rpx;
height: 50rpx;
font-family: Alibaba PuHuiTi 3.0, Alibaba PuHuiTi 30;
font-weight: 400;
font-size: 30rpx;
color: #ADADAD;
line-height: 50rpx;
text-align: left;
font-style: normal;
text-transform: none;
}
.list_timbre image {
width: 8rpx;
height: 8rpx;
}
.list_detail {
position: relative;
margin: 20rpx 0 0 0;
}
.list_detail image {
width: 8rpx;
height: 8rpx;
}
.list_text {
position: relative;
}
.list_text text {
margin: 0 30rpx 30rpx 0;
padding: 0 26rpx;
font-weight: 400;
font-size: 28rpx;
color: #9E9E9E;
line-height: 50rpx;
background: #F6F8FA;
border-radius: 12rpx;
}
.list_actives {
color: #FF51B3 !important;
background: #FCE6F3 !important;
}
.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>