fix: ui
All checks were successful
构建并部署前端到生产环境 / build-and-deploy (push) Successful in 1m9s

This commit is contained in:
luo
2026-07-30 15:41:11 +08:00
parent d0f032aa1c
commit 5f8ff768e6
4 changed files with 332 additions and 55 deletions

View File

@@ -1,6 +1,7 @@
<template>
<view class="container">
<view class="package-tabs">
<view class="package-tab-indicator" :style="{ left: packageTypeIndex === 0 ? '8rpx' : '50%' }"></view>
<view
v-for="tab in packageTypeTabs"
:key="tab.value"
@@ -12,34 +13,46 @@
</view>
</view>
<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>
<swiper
class="package-swiper"
:current="packageTypeIndex"
:circular="false"
: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 class="package-card" v-for="item in packageList" :key="item.package_id">
<view class="package-info">
<view class="package-name">{{ item.package_name }}</view>
<view class="package-meta">
<view class="package-meta-item">
<image class="package-meta-icon" src="/static/有效期.png" mode="aspectFit" />
<text>{{ formatValidity(item.validity_days) }}</text>
</view>
<view class="package-meta-item">
<image class="package-meta-icon" src="/static/流量.png" mode="aspectFit" />
<text>{{ formatData(item.data_allowance, item.data_unit) }}</text>
<view v-else class="package-list">
<view class="package-card" v-for="item in packageList" :key="item.package_id">
<view class="package-info">
<view class="package-name">{{ item.package_name }}</view>
<view class="package-meta">
<view class="package-meta-item">
<image class="package-meta-icon" src="/static/有效期.png" mode="aspectFit" />
<text>{{ formatValidity(item.validity_days) }}</text>
</view>
<view class="package-meta-item">
<image class="package-meta-icon" src="/static/流量.png" mode="aspectFit" />
<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 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>
</scroll-view>
</swiper-item>
</swiper>
<up-popup :show="showModal" mode="center" @close="showModal = false">
<view class="payment-popup">
@@ -121,6 +134,7 @@
const renewalPackageIds = ref([]);
const renewalPackageNames = ref([]);
const activePackageType = ref('formal');
const packageTypeIndex = ref(0);
const packageTypeTabs = [
{ label: '正式套餐', value: 'formal' },
{ label: '加油包', value: 'addon' }
@@ -217,11 +231,20 @@
};
const switchPackageType = (packageType) => {
const nextIndex = packageTypeTabs.findIndex((item) => item.value === packageType);
if (nextIndex < 0) return;
packageTypeIndex.value = nextIndex;
if (packageType === activePackageType.value) return;
activePackageType.value = packageType;
loadPackages(packageType);
};
const onPackageSwiperChange = (event) => {
const nextIndex = Number(event?.detail?.current);
const nextTab = packageTypeTabs[nextIndex];
if (nextTab) switchPackageType(nextTab.value);
};
const loadWalletBalance = async () => {
try {
const data = await walletApi.getDetail(userStore.state.identifier);
@@ -683,6 +706,8 @@
/* Screenshot-aligned package list skin */
.container {
display: flex;
flex-direction: column;
gap: 18rpx;
padding: 20rpx 24rpx 48rpx;
min-height: 100vh;
@@ -712,12 +737,55 @@
}
.container .package-tab.active {
background: #fff;
box-shadow: 0 4rpx 14rpx rgba(31, 35, 41, 0.06);
color: var(--primary);
background: transparent;
box-shadow: none;
color: #fff;
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 {
display: flex;
flex-direction: column;