536 lines
12 KiB
Vue
536 lines
12 KiB
Vue
<template>
|
|
<view class="page fc">
|
|
<uni-nav-bar fixed statusBar left-icon="left" right-icon="gear" background-color="transparent" :border="false"
|
|
@clickLeft="back" title="金币商店"></uni-nav-bar>
|
|
<view class="back"></view>
|
|
<scroll-view scroll-y="true" class="scroll-view f1" show-scrollbar>
|
|
<view class="body">
|
|
<view class="list">
|
|
<image class="list_back"
|
|
src="https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251226/efa43d6b415cb6acb4a801d92d59ca79.png"
|
|
mode="widthFix"></image>
|
|
<view class="list_content">
|
|
<view class="table fa">
|
|
<view class="table_item faj" v-for="(item, index) in tableList" :key="index"
|
|
@click="tableClick(index)" :class="tableIndex == index ? 'table_active' : ''">{{
|
|
item.name }}
|
|
<view class="table_tag" v-if="tableIndex == index"></view>
|
|
</view>
|
|
</view>
|
|
<view class="list_module fa" v-if="tableIndex == 0">
|
|
<view class="list_detail" v-for="(item, index) in outfitMallList.items" :key="index"
|
|
@click="outfitClick(item)">
|
|
<image class="list_image"
|
|
:src="item.image_url ? item.image_url : '/static/images/replacement_picture.png'"
|
|
mode="aspectFill"></image>
|
|
<image class="list_lock"
|
|
:src="isOutfitUnlocked(item.id) ? '' : '/static/images/replacement_lock.png'">
|
|
</image>
|
|
</view>
|
|
</view>
|
|
<view class="list_module fa" v-if="tableIndex == 1">
|
|
<view class="list_detail" v-for="(item, index) in outfitVoicesMallList.voices" :key="index"
|
|
@click="outfitVoicesClick(item)">
|
|
<image class="list_images"
|
|
: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"></image>
|
|
<image class="list_lock"
|
|
:src="isVoiceUnlocked(item.id) ? '' : '/static/images/replacement_lock.png'">
|
|
</image>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="outfit" v-if="outfitStats && tableIndex == 0">
|
|
<view class="outfit_content">
|
|
<view class="outfit_title">详情
|
|
<image src="/static/images/close.png" @click="outfitClick()"></image>
|
|
</view>
|
|
<view class="outfit_module fa">
|
|
<image class="outfit_image"
|
|
:src="outfitList.image_url ? outfitList.image_url : '/static/images/replacement_image.png'"
|
|
mode="aspectFill">
|
|
</image>
|
|
<view class="outfit_outfit f1">
|
|
<view class="outfit_item fa">
|
|
<image src="/static/images/star.png"></image>
|
|
<view class="outfit_name">{{ outfitList.name ? outfitList.name : '-' }}</view>
|
|
<image src="/static/images/star.png"></image>
|
|
</view>
|
|
<view class="outfit_money fx">
|
|
{{ outfitList.price_gold ? outfitList.price_gold : '0' }}<text>金币</text></view>
|
|
</view>
|
|
</view>
|
|
<view class="outfit_btn faj" v-if="!isOutfitUnlocked(outfitList.id)" @click="shoppingClick()">购买服装
|
|
</view>
|
|
<view class="outfit_btn faj" v-if="isOutfitUnlocked(outfitList.id)">已拥有
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="outfit" v-if="outfitVoicesStats && tableIndex == 1">
|
|
<view class="outfit_content">
|
|
<view class="outfit_title">详情
|
|
<image src="/static/images/close.png" @click="outfitVoicesClick()"></image>
|
|
</view>
|
|
<view class="outfit_module fa">
|
|
<image class="outfit_images"
|
|
:src="outfitVoicesList.avatar_url ? global + outfitVoicesList.avatar_url : '/static/images/replacement_image.png'"
|
|
mode="aspectFill">
|
|
</image>
|
|
<view class="outfit_outfit f1">
|
|
<view class="outfit_item fa">
|
|
<image src="/static/images/star.png"></image>
|
|
<view class="outfit_name">{{ outfitVoicesList.name ? outfitVoicesList.name : '-' }}
|
|
</view>
|
|
<image src="/static/images/star.png"></image>
|
|
</view>
|
|
<view class="outfit_money fx">
|
|
{{ outfitVoicesList.price_gold ? outfitVoicesList.price_gold : '0' }}<text>金币</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="outfit_btn faj" v-if="!isVoiceUnlocked(outfitVoicesList.id)"
|
|
@click="shoppingVoiceClick()">购买语音包
|
|
</view>
|
|
<view class="outfit_btn faj" v-if="isVoiceUnlocked(outfitVoicesList.id)">已拥有
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import {
|
|
OutfitMall,
|
|
OutfitVoicesMall,
|
|
OutfitVoicesPurchase,
|
|
OutfitPurchase,
|
|
} from '@/utils/api.js'
|
|
import notHave from '@/components/not-have.vue';
|
|
import topSafety from '@/components/top-safety.vue';
|
|
import tabBar from '@/components/tab-bar.vue';
|
|
export default {
|
|
components: {
|
|
notHave,
|
|
topSafety,
|
|
tabBar,
|
|
},
|
|
data() {
|
|
return {
|
|
global: this.baseURL,
|
|
tableList: [{
|
|
name: '服装',
|
|
id: 0
|
|
}, {
|
|
name: '语音包',
|
|
id: 1
|
|
},],
|
|
tableIndex: 0,
|
|
outfitMallList: '',
|
|
outfitVoicesMallList: '',
|
|
currentAudioContext: null,
|
|
outfitStats: false,
|
|
outfitList: '',
|
|
outfitVoicesStats: false,
|
|
outfitVoicesList: '',
|
|
}
|
|
},
|
|
onLoad() {
|
|
|
|
},
|
|
onShow() {
|
|
this.outfitMall()
|
|
this.outfitVoicesMall()
|
|
},
|
|
methods: {
|
|
// 新增判断服装是否已解锁的方法
|
|
isOutfitUnlocked(outfitId) {
|
|
if (!this.outfitMallList || !this.outfitMallList.owned_outfit_ids) {
|
|
return false;
|
|
}
|
|
return this.outfitMallList.owned_outfit_ids.includes(outfitId);
|
|
},
|
|
isVoiceUnlocked(voiceId) {
|
|
if (!this.outfitVoicesMallList || !this.outfitVoicesMallList.owned_voice_ids) {
|
|
return false;
|
|
}
|
|
return this.outfitVoicesMallList.owned_voice_ids.includes(voiceId);
|
|
},
|
|
outfitMall() {
|
|
OutfitMall({}).then(res => {
|
|
if (res.code == 1) {
|
|
this.outfitMallList = res.data
|
|
} else {
|
|
uni.showToast({
|
|
title: res.msg,
|
|
icon: 'none'
|
|
})
|
|
}
|
|
})
|
|
},
|
|
outfitVoicesMall() {
|
|
OutfitVoicesMall({}).then(res => {
|
|
if (res.code == 1) {
|
|
this.outfitVoicesMallList = res.data
|
|
} else {
|
|
uni.showToast({
|
|
title: res.msg,
|
|
icon: 'none'
|
|
})
|
|
}
|
|
})
|
|
},
|
|
outfitPurchase(id) {
|
|
OutfitPurchase({ item_id: id }).then(res => {
|
|
if (res.code == 1) {
|
|
uni.showToast({
|
|
title: '购买成功',
|
|
icon: 'none'
|
|
})
|
|
setTimeout(() => {
|
|
this.outfitStats = false
|
|
this.outfitList = ''
|
|
this.outfitMall()
|
|
}, 1000)
|
|
} else {
|
|
uni.showToast({
|
|
title: res.msg,
|
|
icon: 'none'
|
|
})
|
|
}
|
|
})
|
|
},
|
|
outfitVoicesPurchase(id) {
|
|
OutfitVoicesPurchase({ voice_id: id }).then(res => {
|
|
if (res.code == 1) {
|
|
uni.showToast({
|
|
title: '购买成功',
|
|
icon: 'none'
|
|
})
|
|
setTimeout(() => {
|
|
this.outfitVoicesStats = false
|
|
this.outfitVoicesList = ''
|
|
this.outfitVoicesMall()
|
|
}, 1000)
|
|
} else {
|
|
uni.showToast({
|
|
title: res.msg,
|
|
icon: 'none'
|
|
})
|
|
}
|
|
})
|
|
},
|
|
tableClick(index) {
|
|
this.tableIndex = index
|
|
if (index == 0) {
|
|
this.outfitMall()
|
|
} else {
|
|
this.outfitVoicesMall()
|
|
}
|
|
},
|
|
outfitClick(item) {
|
|
if (this.outfitStats) {
|
|
this.outfitStats = false
|
|
} else {
|
|
this.outfitStats = true
|
|
this.outfitList = item
|
|
}
|
|
},
|
|
outfitVoicesClick(item) {
|
|
if (this.outfitVoicesStats) {
|
|
this.outfitVoicesStats = false
|
|
} else {
|
|
this.outfitVoicesStats = true
|
|
this.outfitVoicesList = item
|
|
console.log(this.outfitVoicesList)
|
|
}
|
|
},
|
|
shoppingClick() {
|
|
this.outfitPurchase(this.outfitList.id)
|
|
},
|
|
shoppingVoiceClick() {
|
|
this.outfitVoicesPurchase(this.outfitVoicesList.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'
|
|
});
|
|
});
|
|
},
|
|
back() {
|
|
uni.navigateBack({
|
|
delta: 1,
|
|
});
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
page {
|
|
background: #F7F7F7;
|
|
}
|
|
</style>
|
|
<style>
|
|
.page {
|
|
position: relative;
|
|
height: 100vh;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.scroll-view {
|
|
overflow: hidden;
|
|
}
|
|
|
|
.body {
|
|
position: relative;
|
|
padding: 70rpx 0 0 0;
|
|
}
|
|
|
|
.back {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 596rpx;
|
|
background: linear-gradient(180deg, #FFE3E9 0%, #F7F7F7 100%);
|
|
}
|
|
|
|
.list {
|
|
position: relative;
|
|
padding: 0 30rpx;
|
|
}
|
|
|
|
.list_back {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
display: block;
|
|
}
|
|
|
|
.table {
|
|
position: relative;
|
|
padding: 0 0 10rpx 0;
|
|
border-radius: 20rpx 20rpx 0 0;
|
|
z-index: 2;
|
|
}
|
|
|
|
.table_item {
|
|
position: relative;
|
|
margin: 0 84rpx 0 0;
|
|
font-weight: 400;
|
|
font-size: 28rpx;
|
|
color: #9E9E9E;
|
|
line-height: 50rpx;
|
|
padding: 30rpx 30rpx 10rpx 30rpx;
|
|
}
|
|
|
|
.table_tag {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
margin: 0 auto;
|
|
width: 60rpx;
|
|
height: 6rpx;
|
|
background: #8449FE;
|
|
border-radius: 122rpx;
|
|
}
|
|
|
|
.table_active {
|
|
font-weight: 500;
|
|
font-size: 32rpx;
|
|
color: #8449FE;
|
|
}
|
|
|
|
.list_module {
|
|
position: relative;
|
|
margin: 50rpx 0 0 0;
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
grid-column-gap: 20rpx;
|
|
grid-row-gap: 20rpx;
|
|
}
|
|
|
|
.list_image {
|
|
width: 220rpx;
|
|
height: 300rpx;
|
|
border-radius: 12rpx;
|
|
display: block;
|
|
}
|
|
|
|
.list_images {
|
|
width: 210rpx;
|
|
height: 210rpx;
|
|
border-radius: 12rpx;
|
|
display: block;
|
|
}
|
|
|
|
.list_detail {
|
|
position: relative;
|
|
}
|
|
|
|
.list_voice {
|
|
position: absolute;
|
|
bottom: 0;
|
|
right: 0;
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
display: block;
|
|
z-index: 3;
|
|
}
|
|
|
|
.list_lock {
|
|
position: absolute;
|
|
right: 0;
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
margin: auto;
|
|
width: 36rpx;
|
|
height: 36rpx;
|
|
z-index: 2;
|
|
}
|
|
|
|
.outfit {
|
|
position: fixed;
|
|
width: 100%;
|
|
height: 100%;
|
|
left: 0;
|
|
bottom: 0;
|
|
box-sizing: border-box;
|
|
background: rgba(0, 0, 0, 0.2);
|
|
z-index: 5;
|
|
}
|
|
|
|
.outfit_content {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
background: linear-gradient(180deg, #EDD6F5 0%, #FFFFFF 100%);
|
|
border-radius: 40rpx 40rpx 0rpx 0rpx;
|
|
padding: 46rpx 40rpx 68rpx 40rpx;
|
|
}
|
|
|
|
.outfit_title {
|
|
position: relative;
|
|
font-weight: 500;
|
|
font-size: 36rpx;
|
|
color: #333333;
|
|
line-height: 50rpx;
|
|
text-align: center;
|
|
}
|
|
|
|
.outfit_title image {
|
|
position: absolute;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 22rpx;
|
|
height: 22rpx;
|
|
margin: auto 0;
|
|
}
|
|
|
|
.outfit_module {
|
|
position: relative;
|
|
margin: 30rpx 0 0 0;
|
|
padding: 0 30rpx;
|
|
}
|
|
|
|
.outfit_image {
|
|
width: 260rpx;
|
|
height: 300rpx;
|
|
display: block;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.outfit_images {
|
|
width: 260rpx;
|
|
height: 260rpx;
|
|
display: block;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.outfit_outfit {
|
|
position: relative;
|
|
margin: 0 0 0 60rpx;
|
|
}
|
|
|
|
.outfit_item {
|
|
position: relative;
|
|
}
|
|
|
|
.outfit_item image {
|
|
width: 36rpx;
|
|
height: 48rpx;
|
|
}
|
|
|
|
.outfit_name {
|
|
margin: 0 28rpx;
|
|
font-weight: 500;
|
|
font-size: 32rpx;
|
|
color: #9779FA;
|
|
line-height: 50rpx;
|
|
}
|
|
|
|
.outfit_money {
|
|
margin: 12rpx 0 0 0;
|
|
font-weight: 700;
|
|
font-size: 44rpx;
|
|
color: #FF0000;
|
|
line-height: 50rpx;
|
|
}
|
|
|
|
.outfit_money text {
|
|
font-size: 28rpx;
|
|
line-height: 58rpx;
|
|
}
|
|
|
|
.outfit_btn {
|
|
position: relative;
|
|
margin: 162rpx 0 0 0;
|
|
padding: 26rpx 112rpx;
|
|
font-weight: 500;
|
|
font-size: 30rpx;
|
|
line-height: 50rpx;
|
|
border-radius: 12rpx;
|
|
color: #FFFFFF;
|
|
background: linear-gradient(135deg, #9F47FF 0%, #0053FA 100%), #D8D8D8;
|
|
}
|
|
</style> |