Files
yusheng-h5/pages/prop/propMall.vue
2025-12-03 18:59:18 +08:00

629 lines
15 KiB
Vue

<template>
<!-- 道具商城页面 -->
<view class="view-page">
<view v-if="!errorPage">
<!-- 自定义选项卡 -->
<NavigationTabs :tabs-data="tabs" :default-active="currentIndex" @tab-change="handleTabChange" />
<view class="swiper-view">
</view>
<scroll-view scroll-y="true" class="list-view">
<view class="flex-container" v-if="listData && listData.length">
<!-- 循环生成子元素 -->
<view v-for="(item,index) in listData" @click="openPopup(item)" :key="index"
class="flex-item decorate-box">
<view class="decorate-content">
<view class="decorate-image">
<img :src="item.base_image" alt="" />
</view>
<view class="decorate-title w-fill color-3 font-28">
{{item.title}}
</view>
<view class="decorate-price color-3 w-fill">
<img class="icon-goin" src="@/static/image/goin.png" alt="" /> {{item.price}}
</view>
<view class="decorate-tag" v-if="[6,7,8].includes(item.type)">
<span v-if="item.type === 6">个人靓号</span>
<span v-if="item.type === 7">房间靓号</span>
<span v-if="item.type === 8">公会靓号</span>
</view>
</view>
</view>
</view>
<view class="color-9" v-else style="text-align: center;font-size: 24rpx;">
暂无数据
</view>
</scroll-view>
<uni-popup ref="popup" borderRadius="32rpx 32rpx 0 0" type="bottom" background-color="#fff">
<view class="popup-view" v-if="decorateDetail.tab.type !== 12">
<view class="decorate-image">
<img :src="decorateDetail.base_image" alt="" />
</view>
<view class="decorate-title w-fill color-3 font-28">
{{decorateDetail.title}}
</view>
<view class="decorate-info">
<view class="info-line">
<view class="line-lable">
商品名称
</view>
<view class="">
{{decorateDetail.title}}
</view>
</view>
<view class="info-line">
<view class="line-lable">
商品价格
</view>
<view class="flex-line">
{{payData.price}} <img class="icon-goin ml-6" src="@/static/image/goin.png" alt="" />
</view>
</view>
<template v-if="decorateDetail.decorate && decorateDetail.decorate.price_list">
<view class="info-line">
<view class="line-lable">
有效期至
</view>
<view class="">
{{payData.end_time}}
</view>
</view>
<view style="padding: 18rpx 0;">
<view class="line-lable" style="text-align: left;">
购买时长
</view>
</view>
<view class="info-line setmenut" style="justify-content: flex-start">
<view :class="currentMenuIndex === menuIndex ? 'active-menubox' : 'menubox'"
v-for="(menu,menuIndex) in decorateDetail.decorate.price_list"
@click="changePayData(menu,menuIndex)">
<view>
{{menu.day}}
</view>
</view>
</view>
</template>
</view>
<view class="flex-line user-account font-28">
<view class="">
<img class="icon-goin ml-6" src="@/static/image/goin.png" alt="" />
</view>
<view class="color-6 ml-20">
{{decorateDetail.user_info.user_coin}}
</view>
<view class="chongzhi-text ml-20" v-if="isShow" @click="RechargeCoin">
去充值
</view>
</view>
<view class="button-footer">
<view class="pay-button" @click="toPay">
确认支付
</view>
</view>
</view>
<view class="popup-view" v-else>
<view class="decorate-image" style="width: 280rpx;height: 300rpx;">
<img :src="decorateDetail.base_image" alt="" />
</view>
<view class="decorate-title w-fill color-3 font-28">
{{decorateDetail.title}}
</view>
<view class="decorate-info">
<view class="info-line">
<view class="line-lable">
商品名称
</view>
<view class="">
{{decorateDetail.title}}
</view>
</view>
<view class="info-line">
<view class="line-lable">
商品单价
</view>
<view class="flex-line">
{{decorateDetail.decorate.price}} <img class="icon-goin ml-6"
src="@/static/image/goin.png" alt="" />
</view>
</view>
<view class="info-line">
<view class="line-lable">
购买次数
</view>
<view class="flex-line">
<uni-number-box v-model="payData.number" @change="changeValue" />
</view>
</view>
<view class="info-line">
<view class="line-lable">
商品总价
</view>
<view class="flex-line">
{{payData.allPrice}}
</view>
</view>
</view>
<view class="flex-line user-account font-28">
<view class="">
<img class="icon-goin ml-6" src="@/static/image/goin.png" alt="" />
</view>
<view class="color-6 ml-20">
{{decorateDetail.user_info.user_coin}}
</view>
<view class="chongzhi-text ml-20" v-if="isShow" @click="RechargeCoin">
去充值
</view>
</view>
<view class="button-footer">
<view class="pay-button" @click="toPay">
确认支付
</view>
</view>
</view>
</uni-popup>
</view>
<view v-else>
</view>
<uni-popup ref="message" type="message">
<uni-popup-message :type="msgType" :message="messageText" :duration="2000"></uni-popup-message>
</uni-popup>
</view>
</template>
<script>
import http from '@/until/http.js';
import NavigationTabs from '@/component/tab.vue'
export default {
components: {
NavigationTabs
},
data() {
return {
errorPage: true,
tabs: [],
listData: [],
currentIndex: 0,
indicatorLeft: 5,
decorateDetail: null,
currentMenuIndex: 0,
payData: null,
isShow: true,
msgType:"success",
messageText:"操作成功"
}
},
onLoad(options) {
this.errorPage = true
const {
id,
is_show
} = options
uni.setStorageSync('token', id)
if (is_show) {
const flag = Number(is_show)
this.isShow = flag === 1 ? true : false
}
if (uni.getStorageSync('token')) this.gettabs()
},
methods: {
async gettabs() {
http.get('/api/Decorate/get_type_list', {
token: uni.getStorageSync('token') || '',
have_hot: 0
}).then(response => {
const {
data,
code
} = response
// let list = []
if (code) {
// console.log(data)
this.tabs = data.map(ele => {
return {
type: ele.id,
value: ele.name
}
})
}
// this.tabs = list
this.errorPage = false
this.$nextTick(() => {
this.getDecorate(this.tabs[0].type)
})
}).catch(error => {
this.tabs = []
this.errorPage = true
});
},
async getDecorate(type) {
http.get('/api/Decorate/get_decorate_list', {
token: uni.getStorageSync('token') || '',
type
}).then(response => {
const {
data,
code
} = response
this.listData = code ? data : []
}).catch(error => {
this.tabs = []
this.errorPage = true
});
},
async getDecorateDetail(id, detail) {
// console.log(id, detail)
this.payData = {}
http.get('/api/Decorate/get_decorate_detail', {
token: uni.getStorageSync('token') || '',
did: id
}).then(response => {
const {
data,
code
} = response
this.decorateDetail = code ? {
...detail,
...data,
tab: this.tabs[this.currentIndex]
} : null
this.currentMenuIndex = 0
if (this.decorateDetail.tab.type !== 12) {
this.payData = this.decorateDetail.decorate.price_list[this.currentMenuIndex]
} else {
this.payData.price = this.decorateDetail.decorate.price
this.payData.number = 1
this.payData.allPrice = this.decorateDetail.decorate.price * 1
}
// console.log(this.decorateDetail)
this.$refs.popup.open('bottom')
}).catch(error => {});
},
changeValue(value) {
// console.log(value)
// console.log(this.payData)
this.payData.allPrice = value * this.payData.price
},
changePayData(data, index) {
this.payData = data
this.currentMenuIndex = index
},
handleTabChange({
index,
tab
}) {
this.currentIndex = index;
console.log(index, tab)
const {
type
} = tab
this.getDecorate(type)
},
// 打开弹框
openPopup(data) {
this.getDecorateDetail(data.did, data)
},
closePopup() {
this.decorateDetail = null
this.currentMenuIndex = 0
this.payData = null
this.$refs.popup.close()
},
// 去支付
toPay() {
if (this.decorateDetail.tab.type !== 12) {
if (this.payData.price > this.decorateDetail.user_info.user_coin) {
// 余额不足
this.messageText = "余额不足"
this.msgType = 'error'
this.$refs.message.open()
return
}
} else {
// 降身卡
if (this.payData.allPrice > this.decorateDetail.user_info.user_coin) {
// 余额不足
this.messageText = "余额不足"
this.msgType = 'error'
this.$refs.message.open()
return
}
}
// 余额足 调购买装扮接口
this.payDecorate(this.decorateDetail.tab.type)
},
payDecorate(type) {
uni.showLoading({
mask: true
})
http.post('/api/Decorate/pay_decorate', {
token: uni.getStorageSync('token') || '',
did: this.decorateDetail.did,
day: type !== 12 ? this.payData.day : 0,
num: type !== 12 ? 0 : this.payData.number
}).then(response => {
if (response.code) {
this.messageText = "购买成功"
this.msgType = 'success'
this.$refs.message.open()
uni.hideLoading()
this.closePopup()
} else {
this.messageText = response.msg
this.msgType = 'error'
this.$refs.message.open()
}
}).catch(error => {});
},
// 点击去充值
RechargeCoin() {
const platform = uni.getSystemInfoSync().platform;
// console.log(platform, '打印设备参数')
if (platform === 'ios') {
console.log('调用iOS原生方法')
// 通过 messageHandlers 调用 iOS 原生方法
window.webkit.messageHandlers.nativeHandler.postMessage({
'action': 'Recharge'
});
} else if (platform === 'android') {
console.log('调用Android原生方法')
// 调用 Android 原生方法
window.Android.Recharge();
}
}
}
}
</script>
<style lang="scss" scoped>
.view-page {
padding: 0 32rpx;
min-height: 100vh;
background: #00000000;
.decorate-box {
margin: 0 auto;
.decorate-content {
width: 95%;
background: #EFF2F8;
border-radius: 20rpx;
position: relative;
text-align: center;
display: inline-flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
align-content: center;
margin-bottom: 14rpx;
padding: 12rpx 0;
.decorate-image {
// width: 120rpx;
height: 120rpx;
margin: 12rpx 0;
width: 100%;
// background-color: #5B5B5B;
display: inline-flex;
align-items: center;
justify-content: center;
img {
width: 120rpx;
object-fit: contain;
}
}
.decorate-price {
.icon-goin {
width: 24rpx;
height: 24rpx;
}
}
.decorate-tag {
position: absolute;
right: 0;
top: 0;
font-size: 20rpx;
padding: 8rpx 10rpx;
background-image: url('@/static/image/lhbg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
}
}
}
.decorate-image {
width: 120rpx;
height: 120rpx;
margin: 12rpx 0;
// background-color: #5B5B5B;
img {
object-fit: contain;
}
}
.swiper-view {
width: 686rpx;
height: 200rpx;
border-radius: 14rpx 14rpx 14rpx 14rpx;
background-image: url('@/static/image/swipers.png');
background-repeat: no-repeat;
background-size: 100% 100%;
margin-bottom: 32rpx;
}
// background-color: bisque;
.list-view {
width: calc(100vw - 64rpx);
height: calc(100vh - 200rpx - 32rpx - 100rpx);
}
.popup-view {
height: 63vh;
padding: 32rpx;
width: calc(100vw - 64rpx);
display: inline-flex;
flex-wrap: wrap;
flex-direction: row;
align-content: flex-start;
align-items: center;
justify-content: center;
text-align: center;
.decorate-title {
font-size: 28rpx;
}
.decorate-info {
width: calc(100vw - 64rpx);
margin-top: 48rpx;
color: #333333;
.info-line {
width: 100%;
display: inline-flex;
align-content: flex-start;
align-items: center;
justify-content: space-between;
text-align: center;
padding: 18rpx 0;
.icon-goin {
width: 28rpx;
height: 28rpx;
margin-top: 6rpx;
}
}
.setmenut {
.menubox,
.active-menubox {
width: 152rpx;
height: 124rpx;
// padding: 26rpx 38rpx;
// line-height: 94rpx;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 12rpx 12rpx 12rpx 12rpx;
border: 2rpx solid #F1F2F3;
position: relative;
margin-right: 20rpx;
}
.active-menubox {
background: linear-gradient(180deg, #FBFBFF 0%, #F7EBFF 100%);
border: 2rpx solid;
border-radius: 12rpx;
background-repeat: no-repeat;
background-size: 100% 100%;
color: var(--primary-color);
}
.sale {
position: absolute;
top: 0;
right: 0;
font-size: 20rpx;
color: #fff;
padding: 0 8rpx;
background-image: url('@/static/image/sale.png');
background-repeat: no-repeat;
background-size: 100% 100%;
}
}
}
.user-account {
width: 100%;
display: inline-flex;
align-items: center;
justify-content: center;
margin: 30rpx 0;
.icon-goin {
width: 24rpx;
height: 24rpx;
}
.chongzhi-text {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 28rpx;
color: var(--primary-color);
}
}
.button-footer {
width: 100%;
display: inline-flex;
align-items: center;
justify-content: space-around;
.give-button {
width: 190rpx;
height: 84rpx;
background-image: url('@/static/image/propMall/give.png');
background-repeat: no-repeat;
background-size: 100% 100%;
}
.pay-button {
width: 376rpx;
height: 84rpx;
// background-image: url('@/static/image/propMall/pay.png');
background-repeat: no-repeat;
background-size: 100% 100%;
background: var(--primary-color);
color: var(--font-button-color);
font-size: var(--font-button-size-p);
border-radius: 106rpx;
display: inline-flex;
align-items: center;
justify-content: center;
}
}
}
.flex-container {
display: flex;
/* 启用 Flex 布局 */
flex-wrap: wrap;
/* 允许换行 */
}
.flex-item {
flex: 0 0 calc(33% - 10px);
/* 基础宽度25% 减去间隔 */
margin: 5px;
/* 元素间距 */
box-sizing: border-box;
/* 包含内边距和边框 */
border-radius: 14rpx;
/* 样式美化(可选) */
background-color: #fff;
// padding: 20rpx;
text-align: center;
.image {
width: 120rpx;
height: 120rpx;
}
}
}
</style>