This commit is contained in:
@@ -334,7 +334,27 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose({ open, openOrderPayment });
|
const payOrderDirectly = async (orderId, method = 'wallet') => {
|
||||||
|
if (!orderId || submitting.value) return;
|
||||||
|
submitting.value = true;
|
||||||
|
uni.showLoading({ title: '准备支付...', mask: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
await orderApi.pay(orderId, method);
|
||||||
|
uni.hideLoading();
|
||||||
|
if (method === 'wallet') {
|
||||||
|
await confirmOrderStatus(orderId);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
uni.hideLoading();
|
||||||
|
console.error('直接支付订单失败', error);
|
||||||
|
uni.showToast({ title: error.msg || error.message || '支付失败,请稍后重试', icon: 'none' });
|
||||||
|
} finally {
|
||||||
|
submitting.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ open, openOrderPayment, payOrderDirectly });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -55,10 +55,6 @@
|
|||||||
<view class="info-label">充值金额</view>
|
<view class="info-label">充值金额</view>
|
||||||
<view class="info-value text-danger">+¥{{ formatMoney(item.amount) }}</view>
|
<view class="info-value text-danger">+¥{{ formatMoney(item.amount) }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="info-row flex-row-sb">
|
|
||||||
<view class="info-label">支付方式</view>
|
|
||||||
<view class="info-value">{{ formatPaymentMethod(item.payment_method) }}</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="hasAutoPurchaseStatus(item)" class="info-row flex-row-sb">
|
<view v-if="hasAutoPurchaseStatus(item)" class="info-row flex-row-sb">
|
||||||
<view class="info-label">自动购包</view>
|
<view class="info-label">自动购包</view>
|
||||||
<view class="info-value">{{ getAutoPurchaseStatusText(item.auto_purchase_status) }}</view>
|
<view class="info-value">{{ getAutoPurchaseStatusText(item.auto_purchase_status) }}</view>
|
||||||
@@ -173,6 +169,53 @@
|
|||||||
<button class="btn-apple btn-primary" :disabled="rechargeSubmitting" @tap="confirmRecharge">
|
<button class="btn-apple btn-primary" :disabled="rechargeSubmitting" @tap="confirmRecharge">
|
||||||
{{ rechargeSubmitting ? '处理中...' : '确认充值' }}
|
{{ rechargeSubmitting ? '处理中...' : '确认充值' }}
|
||||||
</button>
|
</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</up-popup>
|
||||||
|
|
||||||
|
<up-popup :show="showRechargeOrderPaymentModal" mode="center" @close="closeRechargeOrderPaymentModal">
|
||||||
|
<view class="recharge-popup recharge-order-payment-popup">
|
||||||
|
<view class="popup-header">
|
||||||
|
<view class="popup-title">选择支付方式</view>
|
||||||
|
<view class="popup-close" @tap="closeRechargeOrderPaymentModal">×</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="package-summary">
|
||||||
|
<view class="summary-label">充值订单</view>
|
||||||
|
<view class="summary-name">{{ selectedRechargeOrder?.recharge_order_no || selectedRechargeOrder?.recharge_no || '充值订单' }}</view>
|
||||||
|
<view class="summary-price">¥{{ formatMoney(selectedRechargeOrder?.amount) }}</view>
|
||||||
|
<view class="summary-details">
|
||||||
|
<view class="detail-item">
|
||||||
|
<text class="detail-label">充值金额</text>
|
||||||
|
<text class="detail-value">¥{{ formatMoney(selectedRechargeOrder?.amount) }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="payment-methods">
|
||||||
|
<view
|
||||||
|
v-for="method in paymentMethodOptions"
|
||||||
|
:key="method.value"
|
||||||
|
class="method-item"
|
||||||
|
:class="{ active: rechargePaymentMethod === method.value }"
|
||||||
|
@tap="selectRechargePaymentMethod(method.value)"
|
||||||
|
>
|
||||||
|
<view class="method-left">
|
||||||
|
<image v-if="method.value === 'alipay'" class="method-icon" src="/static/支付宝支付.png" mode="aspectFit"></image>
|
||||||
|
<image v-else-if="method.value === 'wechat'" class="method-icon" src="/static/微信支付.png" mode="aspectFit"></image>
|
||||||
|
<image v-else class="method-icon" src="/static/wallet.png" mode="aspectFit"></image>
|
||||||
|
<text class="method-name">{{ method.label }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="method-radio" :class="{ checked: rechargePaymentMethod === method.value }"></view>
|
||||||
|
</view>
|
||||||
|
<view v-if="paymentMethodOptions.length === 0" class="method-empty">暂无可用支付方式</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="popup-footer">
|
||||||
|
<button class="btn-apple btn-secondary" @tap="closeRechargeOrderPaymentModal">取消</button>
|
||||||
|
<button class="btn-apple btn-primary" :disabled="rechargeOrderSubmittingKey !== null" @tap="confirmRechargeOrderPayment">
|
||||||
|
{{ rechargeOrderSubmittingKey !== null ? '处理中...' : '确认支付' }}
|
||||||
|
</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</up-popup>
|
</up-popup>
|
||||||
@@ -221,6 +264,8 @@
|
|||||||
const transactionPageSize = 5;
|
const transactionPageSize = 5;
|
||||||
|
|
||||||
const showRechargeModal = ref(false);
|
const showRechargeModal = ref(false);
|
||||||
|
const showRechargeOrderPaymentModal = ref(false);
|
||||||
|
const selectedRechargeOrder = ref(null);
|
||||||
const selectedAmount = ref(null);
|
const selectedAmount = ref(null);
|
||||||
const isCustomAmount = ref(false);
|
const isCustomAmount = ref(false);
|
||||||
const customAmount = ref('');
|
const customAmount = ref('');
|
||||||
@@ -251,15 +296,6 @@
|
|||||||
return parseFloat(amount).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
return parseFloat(amount).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatPaymentMethod = (method) => {
|
|
||||||
const labelMap = {
|
|
||||||
wechat: '微信支付',
|
|
||||||
alipay: '支付宝支付',
|
|
||||||
wallet: '钱包支付'
|
|
||||||
};
|
|
||||||
return labelMap[method] || method || '-';
|
|
||||||
};
|
|
||||||
|
|
||||||
const getRechargeStatusClass = (status) => {
|
const getRechargeStatusClass = (status) => {
|
||||||
const classMap = {
|
const classMap = {
|
||||||
0: 'tag-warning',
|
0: 'tag-warning',
|
||||||
@@ -377,6 +413,12 @@
|
|||||||
rechargePaymentMethod.value = method;
|
rechargePaymentMethod.value = method;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const closeRechargeOrderPaymentModal = () => {
|
||||||
|
if (rechargeOrderSubmittingKey.value !== null) return;
|
||||||
|
showRechargeOrderPaymentModal.value = false;
|
||||||
|
selectedRechargeOrder.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
const loadWalletDetail = async () => {
|
const loadWalletDetail = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await walletApi.getDetail(userStore.state.identifier);
|
const data = await walletApi.getDetail(userStore.state.identifier);
|
||||||
@@ -642,18 +684,27 @@
|
|||||||
applyRechargeCheck(await walletApi.rechargeCheck(userStore.state.identifier));
|
applyRechargeCheck(await walletApi.rechargeCheck(userStore.state.identifier));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载充值支付方式失败', error);
|
console.error('加载充值支付方式失败', error);
|
||||||
|
uni.showToast({ title: error.msg || error.message || '加载支付方式失败', icon: 'none' });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
const options = paymentMethodOptions.value;
|
if (!paymentMethodOptions.value.length) {
|
||||||
|
uni.showToast({ title: '暂无可用支付方式', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rechargePaymentMethod.value = getDefaultPaymentMethod(rechargeAllowedPaymentMethods.value);
|
||||||
|
selectedRechargeOrder.value = rechargeOrder;
|
||||||
|
showRechargeOrderPaymentModal.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
uni.showActionSheet({
|
const confirmRechargeOrderPayment = async () => {
|
||||||
itemList: options.map((item) => item.label),
|
if (!selectedRechargeOrder.value || rechargeOrderSubmittingKey.value !== null) return;
|
||||||
success: ({ tapIndex }) => {
|
const rechargeOrder = selectedRechargeOrder.value;
|
||||||
const selectedMethod = options[tapIndex]?.value;
|
const paymentMethod = rechargePaymentMethod.value;
|
||||||
if (selectedMethod) {
|
showRechargeOrderPaymentModal.value = false;
|
||||||
handleRechargePayment(rechargeOrder, selectedMethod);
|
await handleRechargePayment(rechargeOrder, paymentMethod);
|
||||||
}
|
if (rechargeOrderSubmittingKey.value === null) {
|
||||||
}
|
selectedRechargeOrder.value = null;
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRechargePayment = async (rechargeOrder, paymentMethod) => {
|
const handleRechargePayment = async (rechargeOrder, paymentMethod) => {
|
||||||
@@ -1149,4 +1200,64 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.recharge-order-payment-popup {
|
||||||
|
.package-summary {
|
||||||
|
padding: 40rpx 30rpx 30rpx;
|
||||||
|
background: linear-gradient(135deg, rgba(85, 171, 92, 0.05) 0%, rgba(85, 171, 92, 0.02) 100%);
|
||||||
|
border-bottom: 1rpx solid var(--border-light);
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.summary-label {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-name {
|
||||||
|
margin: 20rpx 0 0;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-price {
|
||||||
|
margin: 20rpx 0 24rpx;
|
||||||
|
font-size: 56rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -1rpx;
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-details {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 20rpx;
|
||||||
|
border-top: 1rpx solid rgba(85, 171, 92, 0.1);
|
||||||
|
|
||||||
|
.detail-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8rpx;
|
||||||
|
|
||||||
|
.detail-label {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-value {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-methods {
|
||||||
|
padding: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<view class="filter-tabs">
|
<view class="filter-tabs">
|
||||||
|
<view class="filter-tab-indicator" :style="filterIndicatorStyle"></view>
|
||||||
<view
|
<view
|
||||||
v-for="(item, index) in filterOptions"
|
v-for="(item, index) in filterOptions"
|
||||||
:key="index"
|
:key="index"
|
||||||
@@ -9,11 +10,18 @@
|
|||||||
@tap="onFilterChange(index)"
|
@tap="onFilterChange(index)"
|
||||||
>
|
>
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
<view v-if="filterIndex === index" class="tab-line"></view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<scroll-view scroll-y class="scroll-container" :style="scrollViewStyle" @scrolltolower="loadMore">
|
<swiper
|
||||||
|
class="order-swiper"
|
||||||
|
:current="filterIndex"
|
||||||
|
:circular="false"
|
||||||
|
:acceleration="true"
|
||||||
|
@change="onFilterSwiperChange"
|
||||||
|
>
|
||||||
|
<swiper-item v-for="(item, index) in filterOptions" :key="item.value ?? 'all'" class="order-swiper-item">
|
||||||
|
<scroll-view v-if="filterIndex === index" scroll-y class="scroll-container" :style="scrollViewStyle" @scrolltolower="loadMore">
|
||||||
<view v-if="orderList.length === 0 && !loading" class="empty-state">
|
<view v-if="orderList.length === 0 && !loading" class="empty-state">
|
||||||
<image class="empty-icon" src="/static/order.png" mode="aspectFit" alt="我的订单"></image>
|
<image class="empty-icon" src="/static/order.png" mode="aspectFit" alt="我的订单"></image>
|
||||||
<view class="empty-title">暂无订单</view>
|
<view class="empty-title">暂无订单</view>
|
||||||
@@ -66,7 +74,9 @@
|
|||||||
<text v-else>上拉加载更多</text>
|
<text v-else>上拉加载更多</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
|
||||||
<RenewalPaymentPopup ref="renewalPopupRef" :identifier="userStore.state.identifier"
|
<RenewalPaymentPopup ref="renewalPopupRef" :identifier="userStore.state.identifier"
|
||||||
paymentRefreshTarget="order-list" @completed="resetOrderListAndLoad" />
|
paymentRefreshTarget="order-list" @completed="resetOrderListAndLoad" />
|
||||||
@@ -106,6 +116,9 @@
|
|||||||
const scrollViewStyle = computed(() => scrollViewHeight.value > 0
|
const scrollViewStyle = computed(() => scrollViewHeight.value > 0
|
||||||
? { height: `${scrollViewHeight.value}px`, flex: 'none' }
|
? { height: `${scrollViewHeight.value}px`, flex: 'none' }
|
||||||
: {});
|
: {});
|
||||||
|
const filterIndicatorStyle = computed(() => ({
|
||||||
|
left: `calc(${filterIndex.value * 20}% + 8rpx)`
|
||||||
|
}));
|
||||||
|
|
||||||
const updateScrollViewHeight = () => {
|
const updateScrollViewHeight = () => {
|
||||||
const windowInfo = typeof uni.getWindowInfo === 'function'
|
const windowInfo = typeof uni.getWindowInfo === 'function'
|
||||||
@@ -154,10 +167,18 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onFilterChange = (index) => {
|
const onFilterChange = (index) => {
|
||||||
|
if (filterIndex.value === index) return;
|
||||||
filterIndex.value = index;
|
filterIndex.value = index;
|
||||||
resetOrderListAndLoad();
|
resetOrderListAndLoad();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onFilterSwiperChange = (event) => {
|
||||||
|
const nextIndex = Number(event?.detail?.current);
|
||||||
|
if (Number.isInteger(nextIndex) && nextIndex >= 0 && nextIndex < filterOptions.length) {
|
||||||
|
onFilterChange(nextIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const loadOrderList = async (append = false) => {
|
const loadOrderList = async (append = false) => {
|
||||||
if (loading.value || (append && noMore.value)) return;
|
if (loading.value || (append && noMore.value)) return;
|
||||||
|
|
||||||
@@ -238,6 +259,10 @@
|
|||||||
const showOrderPaymentMethods = (order) => {
|
const showOrderPaymentMethods = (order) => {
|
||||||
if (!order?.order_id) return;
|
if (!order?.order_id) return;
|
||||||
const packageNames = Array.isArray(order.package_names) ? order.package_names : [];
|
const packageNames = Array.isArray(order.package_names) ? order.package_names : [];
|
||||||
|
if (String(order.payment_method || '').toLowerCase() === 'wallet') {
|
||||||
|
renewalPopupRef.value?.payOrderDirectly(order.order_id, 'wallet');
|
||||||
|
return;
|
||||||
|
}
|
||||||
renewalPopupRef.value?.openOrderPayment(order.order_id, packageNames);
|
renewalPopupRef.value?.openOrderPayment(order.order_id, packageNames);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -532,6 +557,59 @@
|
|||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container .filter-tabs {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 0;
|
||||||
|
padding: 8rpx;
|
||||||
|
background: #fff;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container .filter-tabs .tab-item {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
min-width: 0;
|
||||||
|
padding: 20rpx 4rpx;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
font-size: 26rpx;
|
||||||
|
transition: color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container .filter-tabs .tab-item.active {
|
||||||
|
background: transparent;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-tab-indicator {
|
||||||
|
position: absolute;
|
||||||
|
top: 8rpx;
|
||||||
|
width: calc(20% - 16rpx);
|
||||||
|
height: calc(100% - 16rpx);
|
||||||
|
background: var(--primary);
|
||||||
|
border-radius: 12rpx;
|
||||||
|
transition: left 0.3s ease;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-swiper,
|
||||||
|
.order-swiper-item {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-swiper {
|
||||||
|
flex: 1;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-swiper-item {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.scroll-container {
|
.scroll-container {
|
||||||
flex: 1 1 0;
|
flex: 1 1 0;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<view class="package-tabs">
|
<view class="package-tabs">
|
||||||
|
<view class="package-tab-indicator" :style="{ left: packageTypeIndex === 0 ? '8rpx' : '50%' }"></view>
|
||||||
<view
|
<view
|
||||||
v-for="tab in packageTypeTabs"
|
v-for="tab in packageTypeTabs"
|
||||||
:key="tab.value"
|
:key="tab.value"
|
||||||
@@ -12,34 +13,46 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="packageList.length === 0 && !loading" class="empty-state">
|
<swiper
|
||||||
<image class="empty-icon" src="/static/shop.png" mode="aspectFit" alt="套餐订购"></image>
|
class="package-swiper"
|
||||||
<view class="empty-title">暂无{{ activePackageType === 'formal' ? '正式套餐' : '加油包' }}</view>
|
:current="packageTypeIndex"
|
||||||
<view class="empty-desc">当前资产暂无适用的套餐</view>
|
:circular="false"
|
||||||
</view>
|
:acceleration="true"
|
||||||
|
@change="onPackageSwiperChange"
|
||||||
|
>
|
||||||
|
<swiper-item v-for="tab in packageTypeTabs" :key="tab.value" class="package-swiper-item">
|
||||||
|
<scroll-view v-if="activePackageType === tab.value" scroll-y class="package-scroll">
|
||||||
|
<view v-if="packageList.length === 0 && !loading" class="empty-state">
|
||||||
|
<image class="empty-icon" src="/static/shop.png" mode="aspectFit" alt="套餐订购"></image>
|
||||||
|
<view class="empty-title">暂无{{ activePackageType === 'formal' ? '正式套餐' : '加油包' }}</view>
|
||||||
|
<view class="empty-desc">当前资产暂无适用的套餐</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="package-list">
|
<view v-else class="package-list">
|
||||||
<view class="package-card" v-for="item in packageList" :key="item.package_id">
|
<view class="package-card" v-for="item in packageList" :key="item.package_id">
|
||||||
<view class="package-info">
|
<view class="package-info">
|
||||||
<view class="package-name">{{ item.package_name }}</view>
|
<view class="package-name">{{ item.package_name }}</view>
|
||||||
<view class="package-meta">
|
<view class="package-meta">
|
||||||
<view class="package-meta-item">
|
<view class="package-meta-item">
|
||||||
<image class="package-meta-icon" src="/static/有效期.png" mode="aspectFit" />
|
<image class="package-meta-icon" src="/static/有效期.png" mode="aspectFit" />
|
||||||
<text>{{ formatValidity(item.validity_days) }}</text>
|
<text>{{ formatValidity(item.validity_days) }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="package-meta-item">
|
<view class="package-meta-item">
|
||||||
<image class="package-meta-icon" src="/static/流量.png" mode="aspectFit" />
|
<image class="package-meta-icon" src="/static/流量.png" mode="aspectFit" />
|
||||||
<text>{{ formatData(item.data_allowance, item.data_unit) }}</text>
|
<text>{{ formatData(item.data_allowance, item.data_unit) }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="package-description">高速流量 · 全国通用 · 不限速</view>
|
||||||
|
</view>
|
||||||
|
<view class="package-side">
|
||||||
|
<view class="package-price"><text class="price-symbol">¥</text>{{ formatPackagePrice(item.retail_price) }}</view>
|
||||||
|
<button class="btn-apple btn-primary package-buy-button" @tap="buyPackage(item)">立即订购</button>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="package-description">高速流量 · 全国通用 · 不限速</view>
|
</scroll-view>
|
||||||
</view>
|
</swiper-item>
|
||||||
<view class="package-side">
|
</swiper>
|
||||||
<view class="package-price"><text class="price-symbol">¥</text>{{ formatPackagePrice(item.retail_price) }}</view>
|
|
||||||
<button class="btn-apple btn-primary package-buy-button" @tap="buyPackage(item)">立即订购</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<up-popup :show="showModal" mode="center" @close="showModal = false">
|
<up-popup :show="showModal" mode="center" @close="showModal = false">
|
||||||
<view class="payment-popup">
|
<view class="payment-popup">
|
||||||
@@ -121,6 +134,7 @@
|
|||||||
const renewalPackageIds = ref([]);
|
const renewalPackageIds = ref([]);
|
||||||
const renewalPackageNames = ref([]);
|
const renewalPackageNames = ref([]);
|
||||||
const activePackageType = ref('formal');
|
const activePackageType = ref('formal');
|
||||||
|
const packageTypeIndex = ref(0);
|
||||||
const packageTypeTabs = [
|
const packageTypeTabs = [
|
||||||
{ label: '正式套餐', value: 'formal' },
|
{ label: '正式套餐', value: 'formal' },
|
||||||
{ label: '加油包', value: 'addon' }
|
{ label: '加油包', value: 'addon' }
|
||||||
@@ -217,11 +231,20 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const switchPackageType = (packageType) => {
|
const switchPackageType = (packageType) => {
|
||||||
|
const nextIndex = packageTypeTabs.findIndex((item) => item.value === packageType);
|
||||||
|
if (nextIndex < 0) return;
|
||||||
|
packageTypeIndex.value = nextIndex;
|
||||||
if (packageType === activePackageType.value) return;
|
if (packageType === activePackageType.value) return;
|
||||||
activePackageType.value = packageType;
|
activePackageType.value = packageType;
|
||||||
loadPackages(packageType);
|
loadPackages(packageType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onPackageSwiperChange = (event) => {
|
||||||
|
const nextIndex = Number(event?.detail?.current);
|
||||||
|
const nextTab = packageTypeTabs[nextIndex];
|
||||||
|
if (nextTab) switchPackageType(nextTab.value);
|
||||||
|
};
|
||||||
|
|
||||||
const loadWalletBalance = async () => {
|
const loadWalletBalance = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await walletApi.getDetail(userStore.state.identifier);
|
const data = await walletApi.getDetail(userStore.state.identifier);
|
||||||
@@ -683,6 +706,8 @@
|
|||||||
|
|
||||||
/* Screenshot-aligned package list skin */
|
/* Screenshot-aligned package list skin */
|
||||||
.container {
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
gap: 18rpx;
|
gap: 18rpx;
|
||||||
padding: 20rpx 24rpx 48rpx;
|
padding: 20rpx 24rpx 48rpx;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
@@ -712,12 +737,55 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.container .package-tab.active {
|
.container .package-tab.active {
|
||||||
background: #fff;
|
background: transparent;
|
||||||
box-shadow: 0 4rpx 14rpx rgba(31, 35, 41, 0.06);
|
box-shadow: none;
|
||||||
color: var(--primary);
|
color: #fff;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container .package-tabs {
|
||||||
|
position: relative;
|
||||||
|
padding: 8rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container .package-tab {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
transition: color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-tab-indicator {
|
||||||
|
position: absolute;
|
||||||
|
top: 8rpx;
|
||||||
|
width: calc(50% - 16rpx);
|
||||||
|
height: calc(100% - 16rpx);
|
||||||
|
background: var(--primary);
|
||||||
|
border-radius: 12rpx;
|
||||||
|
transition: left 0.3s ease;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-swiper,
|
||||||
|
.package-swiper-item,
|
||||||
|
.package-scroll {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-swiper {
|
||||||
|
flex: 1;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-swiper-item,
|
||||||
|
.package-scroll {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.package-list {
|
.package-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
Reference in New Issue
Block a user