Compare commits

...

2 Commits

2 changed files with 566 additions and 0 deletions

View File

@@ -0,0 +1,441 @@
<template>
<view class="recharge-page">
<!-- 自定义导航栏 -->
<nav-bar :title="$t('user.recharge')"></nav-bar>
<view class="block">
<view class="text">充值金额</view>
<view class="recharge">
<view class="recharge_block" @click="chosPric(item)"
:class="aloneItem.priceTypeId === item.priceTypeId ? 'selected' : ''"
v-for="item in rechargeList.bookBuyConfigList" :key="item.priceTypeId">
<view class="recharge_money">{{item.money}}</view>
<view>{{item.realMoney}}天医币</view>
<!-- 红框位置的618活动标签 -->
<!-- <view class="activity-tag">618活动</view> -->
<span class="activity-label" v-if="item.givejf >0">618充值活动</span>
<text class="recharge_give" v-if="item.givejf >0">{{item.givejf}}</text>
</view>
</view>
</view>
<view class="activity-container">
<view v-html="remark.remark"></view>
</view>
<view class="cha_fangsh">
<view class="cf_title PM_font">支付方式</view>
<view class="cf_radio">
<radio-group v-for="item in iosPaylist" @change="choseType(item.id)">
<view style="width: 100%">
<view :class="payType == item.id ? 'Tab_xf cf_xuanx' : 'cf_xuanx'">
<!-- <image class="pay_item_img" :src="item.imgUrl" mode="aspectFil">
</image> -->
<text>{{ item.title }}</text>
<radio :checked="payType === item.id" style="float: right"></radio>
</view>
</view>
</radio-group>
</view>
</view>
<view class="agree_wo flexbox">
<radio-group class="agree" v-for="(item, index) in argee" :key="index" @change="radioCheck">
<view>
<radio class="agreeRadio" :value="item.id" :checked="state" color="#007bff"></radio>
</view>
</radio-group>
<view>我已阅读并同意<span class="highlight" @click="showAgreement">增值服务协议</span></view>
</view>
<view class="bottom-button-container">
<button class="recharge-button" @click="handleRecharge">立即充值</button>
</view>
<wd-popup v-model="agreemenState" position="bottom" :closeable="true">
<view class="agreement">
<view class="agreement_title">{{ agreementObj.title }}</view>
<view class="agreement_row">
<view v-html="agreementObj.content"></view>
</view>
</view>
</wd-popup>
<wd-message-box />
</view>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, toRefs, reactive } from 'vue'
import { useMessage } from '@/uni_modules/wot-design-uni'
import { getBookBuyConfigList, getAgreement, getActivityDescription } from '@/api/modules/user'
const googlePay = uni.requireNativePlugin("sn-googlepay5");
const message = useMessage()
const payType = ref('1')
const iosPaylist = ref([
{
title: "Google Pay",
id: '1',
// imgUrl: "/static/icon/currency.png"
}
])
// 充值列表
const rechargeList = ref([])
// 金额列表单独每项
const aloneItem = ref({})
// 充值列表type-固定传值
const type = ref('point')
const qudao = ref('')
const state = ref(false)
const argee = ref([
{
value: false,
id: "1",
},
])
const popup = ref(null)
const agreemenState = ref(false)
// 协议id
const id = ref(101)
const richTextContent = ref('');
// 协议数据
const agreementObj = reactive({
title: '',
content: '',
})
const isAndroid = ref()
const remark = ref({})
const isConnected = ref(false)
const getDevName = () => {
// 获取使用环境
if (uni.getSystemInfoSync().platform === "android") {
qudao.value = 'Google'
isAndroid.value = true;
console.log('运行Android上')
} else {
qudao.value = 'Google'
console.log('运行iOS上')
}
getData()
}
// 点击金额
const chosPric = (item : any) => {
console.log(item,'金额每项');
aloneItem.value = item;
};
/**
* 勾选协议
*/
const radioCheck = () => {
console.log('点击了', state.value);
state.value = !state.value
}
/**
* 协议弹窗显示
*/
const showAgreement = () => {
agreemenState.value = true
}
/**
* 获取充值列表数据
*/
const getData = async () => {
try {
rechargeList.value = await getBookBuyConfigList(type.value, qudao.value)
console.log(rechargeList.value.bookBuyConfigList, '充值列表');
// 默认选择第一个金额
aloneItem.value = rechargeList.value.bookBuyConfigList[0]
getGooglePay()
} catch (error) {
console.error('获取订单列表失败:', error)
}
}
/**
* 获取协议数据
*/
const getAgreementData = async () => {
try {
const text = reactive(await getAgreement(id.value))
const { title, content } = toRefs(text.agreement)
agreementObj.title = title.value
agreementObj.content = content.value.replace(/<\/h5>/g, "</view>");
// console.log(agreementObj, '协议数据');
} catch (error) {
console.error('获取协议数据:', error)
}
}
/**
* 获取活动说明数据
*/
const getActivityDescriptionData = async () => {
try {
const text = ref(await getActivityDescription())
remark.value = text.value.res[0]
// console.log(remark.value, '活动说明内容');
} catch (error) {
console.error('获取协议数据:', error)
}
}
/**
* 切换支付方式
*/
const choseType = () => {
// payType.value = val;
}
const handleRecharge = () => {
console.log('立即充值');
}
/**
* 初始化
*/
const getGooglePay = () => {
googlePay.init({
// autoReconnect: true, // 是否自动重连(插件实现)
// enableAutoServiceReconnection: true, //是否自动重连8.0+支持)
}, (e:any) => {
console.log('init', e);
if (e.code == 0) {
isConnected.value = true;
getQuerySku()
// 初始化成功
} else {
// 初始化失败
isConnected.value = false;
}
});
}
/**
* 查询sku
*/
const getQuerySku = () =>{
const id = aloneItem.value.priceTypeId
console.log(id, '获取每项');
googlePay.querySku(
{
inapp: [id], // 与subs二选一, 参数为商品ID字符串数组
},
(e:any) => {
if (e.code == 0) {
// 查询成功.
console.log('查询成功',e);
// e.list; // 查询结果, array
} else {
console.log('查询失败');
// 查询失败
}
}
)
}
const getPayAll = () =>{
googlePay.payAll(
{
productId: "", // 产品id
},
(e) => {
if (e.code == 0) {
// 支付成功
e.data; //支付结果, array [ {original:{ }, signature: ''} ]
} else {
// 支付失败
}
},
)
}
onMounted(() => {
getDevName();
getActivityDescriptionData()
getAgreementData()
})
</script>
<style lang="scss" scoped>
$theme-color: #54a966;
.recharge-page {
min-height: 100vh;
background-color: #f7faf9;
}
.text {
font-size: 30rpx;
color: #007bff;
padding: 30rpx 0 20rpx 20rpx;
}
.recharge {
display: flex;
flex-wrap: wrap;
padding: 20rpx 0 20rpx 30rpx;
.recharge_block {
box-shadow: 0 0 20rpx 0 #0000001a;
float: left;
width: 46%;
margin: 0 3% 30rpx 0;
text-align: center;
padding: 30rpx 0 0;
border-radius: 15rpx;
position: relative;
height: 160rpx;
.recharge_money {
font-size: 30rpx;
margin-bottom: 30rpx;
}
.recharge_give {
font-size: 16rpx;
color: #FF0033;
}
}
}
.selected {
border: 2rpx solid #007bff;
color: #007bff;
}
.bottom-button-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 30rpx;
background-color: #ffffff;
border-top: 1px solid #f0f0f0;
z-index: 999;
}
.recharge-button {
width: 100%;
height: 50rpx;
line-height: 50rpx;
background-color: #007bff;
color: #ffffff;
font-size: 18rpx;
border-radius: 25rpx;
border: none;
}
.recharge-button::after {
border: none;
}
.activity-container {
margin: 0 20rpx 20rpx 20rpx;
padding: 15rpx;
background-color: #e6f4ff;
border-radius: 8rpx;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.activity-label {
position: absolute;
top: -10rpx;
right: -6rpx;
font-size: 16rpx;
font-weight: 600;
color: #ffffff;
background-color: #007bff;
border-radius: 16rpx 0;
padding: 6rpx 10rpx;
letter-spacing: 0.5rpx;
}
.cha_fangsh {
padding: 20rpx 20rpx 60rpx 20rpx;
.cf_title {
font-size: 30rpx;
color: #007bff;
}
.cf_radio {
margin-top: 20rpx;
.cf_xuanx {
font-size: 24rpx;
padding: 20rpx 0;
margin-bottom: 20rpx;
border-bottom: 1px solid #ededed;
image {
width: 40rpx;
height: 40rpx;
display: inline-block;
margin-right: 20rpx;
vertical-align: bottom;
}
}
.Tab_xf {
// background-color: #fdf1e9cc;
}
}
}
.pay_item_img {
width: 50rpx;
height: 50rpx;
float: left;
margin-right: 20rpx;
}
.agree_wo {
display: flex;
padding: 20rpx 20rpx 160rpx 20rpx;
color: #aaa;
font-size: 18rpx;
align-items: center;
.highlight {
color: #007bff;
}
}
.agreeRadio {
display: flex;
zoom: 0.7;
}
.agreement {
padding: 40rpx 30rpx 40rpx 30rpx;
position: relative;
.agreement_title {
font-size: 32rpx;
margin-bottom: 50rpx;
color: #555;
text-align: center;
font-weight: bold;
}
.agreement_row {
max-height: 1000rpx;
overflow-y: scroll
}
}
</style>

View File

@@ -0,0 +1,125 @@
<template>
<z-paging ref="paging" v-model="bookList" auto-show-back-to-top class="my-book-page" @query="loadBookList">
<template #top>
<!-- 自定义导航栏 -->
<nav-bar :title="$t('book.myBook')"></nav-bar>
</template>
<!-- 充值列表 -->
<!-- <uni-icons fontFamily="CustomFont" :size="26">{{'\uebc6'}}</uni-icons> -->
<view class="recharge-record">
<view><uni-icons type="right" size="30"></uni-icons></view>
<view class="go-gecharge">
立即充值
<uni-icons type="contact" size="30"></uni-icons>
</view>
<view class="title">充值消费记录</view>
<view class="recharge-record-block" v-for="(item) in 5">
<view class="recharge-record-block-row">购买商品<text class="text">90</text></view>
<view class="time">2025-10-20</view>
</view>
</view>
<!-- <view v-if="(bookList && bookList.length > 0)" class="book-list">
<BookCard
v-for="item in bookList"
:key="item.id"
:book="item"
/>
</view> -->
<!-- 空状态 -->
<!-- <view v-else-if="!loading && !firstLoad" class="empty-state">
<image src="@/static/null_img.png" mode="aspectFit" />
<text class="empty-text">{{ $t('book.nullText') }}</text>
<wd-button type="primary" @click="goToBuy">
{{ $t('book.choose') }}
</wd-button>
</view> -->
</z-paging>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { bookApi } from '@/api/modules/book'
import type { IBook } from '@/types/book'
import BookCard from '@/components/book/BookCard.vue'
const { t } = useI18n()
const paging = ref<any>()
// 数据状态
const bookList = ref<IBook[]>([])
const loading = ref(false)
const firstLoad = ref(true)
// 加载书单列表
async function loadBookList(pageNo : number, pageSize : number) {
loading.value = true
try {
const res = await bookApi.getMyBooks(pageNo, pageSize)
paging.value.complete(res.page.records)
} catch (error) {
paging.value.complete(false)
console.error('Failed to load book list:', error)
} finally {
firstLoad.value = false
loading.value = false
}
}
</script>
<style lang="scss" scoped>
.my-book-page {
background: #f7faf9;
min-height: 100vh;
.recharge-record {
background: #fff;
border-radius: 15rpx;
overflow: hidden;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
// padding: 20rpx;
margin: 20rpx;
.go-gecharge{
//height: 100rpx;
background: linear-gradient(to right, #007bff, #17a2b8);
font-size: 40rpx;
font-weight: bold;
color: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
}
.title {
font-size: 40rpx;
padding-left:20rpx;
margin-bottom: 30rpx;
color: #007bff;
font-weight: bold;
}
.recharge-record-block {
border-bottom: 1px solid #e0e0e0;
padding: 20rpx;
.time{
font-size: 20rpx;
}
.recharge-record-block-row {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
.text{
color: #007bff;
}
}
}
}
}
</style>