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

This commit is contained in:
luo
2026-07-31 09:58:39 +08:00
parent 819d5dc2f5
commit e4278d3883
7 changed files with 144 additions and 110 deletions

View File

@@ -8,8 +8,9 @@
<view class="card carrier-card" v-for="item in list" :key="item.iccid">
<view class="carrier-main">
<view v-if="item.isDevice" class="slot-logo">
<image class="slot-visual" :src="getSlotIcon(item.slot_position)" mode="aspectFit"></image>
<view class="logo-stack">
<image class="carrier-logo" :src="getCarrier(item.carrier_type).logo" mode="aspectFit"></image>
<image v-if="item.isDevice" class="slot-badge" :src="getSlotIcon(item.slot_position)" mode="aspectFit"></image>
</view>
<view class="carrier-details">
<view class="carrier-name">{{ getCarrier(item.carrier_type).name }}</view>
@@ -48,6 +49,10 @@
import slot1Icon from '@/static/卡槽1.png';
import slot2Icon from '@/static/卡槽2.png';
import slot3Icon from '@/static/卡槽3.png';
import cmccLogo from '@/static/中国移动.png';
import cuccLogo from '@/static/中国联通.png';
import ctccLogo from '@/static/中国电信.png';
import cbnLogo from '@/static/中国广电.png';
const userStore = useUserStore();
@@ -58,10 +63,10 @@
let currentCard = ref(null);
const carrierMap = {
CMCC: '中国移动',
CUCC: '中国联通',
CTCC: '中国电信',
CBN: '中国广电'
CMCC: { name: '中国移动', logo: cmccLogo },
CUCC: { name: '中国联通', logo: cuccLogo },
CTCC: { name: '中国电信', logo: ctccLogo },
CBN: { name: '中国广电', logo: cbnLogo }
};
const slotIconMap = {
@@ -71,7 +76,7 @@
};
const getCarrier = (carrierType) => {
return { name: carrierMap[carrierType] || '-' };
return carrierMap[carrierType] || { name: '-', logo: '' };
};
const getSlotIcon = (slotPosition) => slotIconMap[Number(slotPosition)] || slotIconMap[1];
@@ -173,20 +178,28 @@
gap: 24rpx;
}
.slot-logo {
.logo-stack {
position: relative;
width: 112rpx;
height: 112rpx;
flex-shrink: 0;
padding: 0;
box-sizing: border-box;
border-radius: 24rpx;
}
.slot-visual {
.carrier-logo {
width: 100%;
height: 100%;
}
.slot-badge {
position: absolute;
right: -6rpx;
bottom: -6rpx;
z-index: 2;
width: 48rpx;
height: 48rpx;
}
.carrier-details {
flex: 1;
min-width: 0;

View File

@@ -163,6 +163,7 @@
status: 1,
packageName: '-',
currentPackageId: 0,
renewalPrice: null,
expireDate: '-',
isExpiring: false,
expiryDays: null,
@@ -263,6 +264,7 @@
deviceInfo.bound_phone = data.bound_phone || '';
deviceInfo.packageName = data.current_package || '-';
deviceInfo.currentPackageId = Number(data.current_package_id || 0);
deviceInfo.renewalPrice = data.renewal_price ?? null;
deviceInfo.expireDate = formatDate(data.estimated_final_expires_at);
deviceInfo.isExpiring = data.is_expiring === true;
deviceInfo.expiryDays = data.days_until_final_expiry ?? null;
@@ -364,7 +366,7 @@
return;
}
renewalPopupRef.value?.open([packageId], [packageName]);
renewalPopupRef.value?.open([packageId], [packageName], deviceInfo.renewalPrice);
};
const modifyWifi = () => {

View File

@@ -181,15 +181,8 @@
</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-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">
@@ -1204,17 +1197,11 @@
.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);
}
background: transparent;
.summary-name {
margin: 20rpx 0 0;
margin: 0 0 20rpx;
font-size: 32rpx;
font-weight: 700;
line-height: 1.4;
@@ -1222,38 +1209,12 @@
}
.summary-price {
margin: 20rpx 0 24rpx;
margin: 0;
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 {

View File

@@ -21,7 +21,7 @@
@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">
<scroll-view v-if="filterIndex === index" scroll-y class="scroll-container" @scrolltolower="loadMore">
<view v-if="orderList.length === 0 && !loading" class="empty-state">
<image class="empty-icon" src="/static/order.png" mode="aspectFit" alt="我的订单"></image>
<view class="empty-title">暂无订单</view>
@@ -84,7 +84,7 @@
</template>
<script setup>
import { ref, reactive, computed, nextTick, onMounted } from 'vue';
import { ref, reactive, computed, onMounted } from 'vue';
import { onShow } from '@dcloudio/uni-app';
import { orderApi } from '@/api/index.js';
import RenewalPaymentPopup from '@/components/RenewalPaymentPopup.vue';
@@ -102,7 +102,6 @@
const noMore = ref(false);
const page = ref(1);
const renewalPopupRef = ref(null);
const scrollViewHeight = ref(0);
const pageSize = 10;
const filterIndex = ref(0);
const filterOptions = [
@@ -113,29 +112,10 @@
{ label: '已退款', value: 4 }
];
const scrollViewStyle = computed(() => scrollViewHeight.value > 0
? { height: `${scrollViewHeight.value}px`, flex: 'none' }
: {});
const filterIndicatorStyle = computed(() => ({
left: `calc(${filterIndex.value * 20}% + 8rpx)`
}));
const updateScrollViewHeight = () => {
const windowInfo = typeof uni.getWindowInfo === 'function'
? uni.getWindowInfo()
: uni.getSystemInfoSync();
const windowHeight = Number(windowInfo?.windowHeight || 0);
if (!windowHeight) return;
uni.createSelectorQuery()
.select('.filter-tabs')
.boundingClientRect((rect) => {
if (!rect) return;
scrollViewHeight.value = Math.max(Math.floor(windowHeight - rect.bottom), 1);
})
.exec();
};
const getStatusClass = (status) => {
const classMap = {
1: 'tag-warning',
@@ -276,7 +256,6 @@
onMounted(() => {
loadOrderList();
nextTick(updateScrollViewHeight);
});
</script>
@@ -516,6 +495,9 @@
padding: 0;
gap: 0;
padding-top: 0;
height: 100%;
min-height: 0;
overflow: hidden;
}
.filter-tabs {
@@ -602,8 +584,9 @@
}
.order-swiper {
flex: 1;
height: 0;
flex: 1 1 0;
height: auto;
overflow: hidden;
}
.order-swiper-item {
@@ -611,8 +594,8 @@
}
.scroll-container {
flex: 1 1 0;
height: auto;
flex: none;
height: 100%;
min-height: 0;
width: 100%;
box-sizing: border-box;

View File

@@ -1,20 +1,21 @@
<template>
<view class="container">
<view class="package-tabs">
<view class="package-tab-indicator" :style="{ left: packageTypeIndex === 0 ? '8rpx' : '50%' }"></view>
<view class="tab-section">
<view class="tab-header">
<view class="tab-indicator" :style="{ left: packageTypeIndex === 0 ? '8rpx' : '50%' }"></view>
<view
v-for="tab in packageTypeTabs"
:key="tab.value"
class="package-tab"
class="tab-item"
:class="{ active: activePackageType === tab.value }"
@tap="switchPackageType(tab.value)"
>
{{ tab.label }}
</view>
</view>
</view>
<swiper
class="package-swiper"
class="tab-swiper package-swiper"
:current="packageTypeIndex"
:circular="false"
:acceleration="true"
@@ -53,6 +54,7 @@
</scroll-view>
</swiper-item>
</swiper>
</view>
<up-popup :show="showModal" mode="center" @close="showModal = false">
<view class="payment-popup">
@@ -717,6 +719,59 @@
overflow: hidden;
}
.tab-section {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.tab-header {
flex-shrink: 0;
display: flex;
position: relative;
background: #fff;
border-radius: 16rpx;
padding: 8rpx;
}
.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;
}
.tab-item {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 20rpx 0;
font-size: 28rpx;
font-weight: 500;
color: var(--text-tertiary);
position: relative;
z-index: 1;
transition: color 0.3s;
&.active {
color: #fff;
font-weight: 600;
}
}
.tab-swiper {
margin-top: 20rpx;
flex: 1 1 0;
min-height: 0;
height: auto;
}
.container .package-tabs {
display: flex;
gap: 0;

View File

@@ -8,8 +8,9 @@
<view class="card carrier-card" v-for="item in mchList" :key="item.iccid">
<view class="carrier-main">
<view class="slot-logo">
<image class="slot-visual" :src="getSlotIcon(item.slot_position)" mode="aspectFit"></image>
<view class="logo-stack">
<image class="carrier-logo" :src="getCarrier(item.carrier_type).logo" mode="aspectFit"></image>
<image class="slot-badge" :src="getSlotIcon(item.slot_position)" mode="aspectFit"></image>
</view>
<view class="carrier-details">
<view class="carrier-heading">
@@ -61,6 +62,10 @@
import slot1Icon from '@/static/卡槽1.png';
import slot2Icon from '@/static/卡槽2.png';
import slot3Icon from '@/static/卡槽3.png';
import cmccLogo from '@/static/中国移动.png';
import cuccLogo from '@/static/中国联通.png';
import ctccLogo from '@/static/中国电信.png';
import cbnLogo from '@/static/中国广电.png';
const userStore = useUserStore();
@@ -71,10 +76,10 @@
let currentModalIccid = ref('');
const carrierMap = {
CMCC: '中国移动',
CUCC: '中国联通',
CTCC: '中国电信',
CBN: '中国广电'
CMCC: { name: '中国移动', logo: cmccLogo },
CUCC: { name: '中国联通', logo: cuccLogo },
CTCC: { name: '中国电信', logo: ctccLogo },
CBN: { name: '中国广电', logo: cbnLogo }
};
const slotIconMap = {
@@ -84,7 +89,7 @@
};
const getCarrier = (carrierType) => {
return { name: carrierMap[carrierType] || '-' };
return carrierMap[carrierType] || { name: '-', logo: '' };
};
const getSlotIcon = (slotPosition) => slotIconMap[Number(slotPosition)] || slotIconMap[1];
@@ -221,20 +226,28 @@
gap: 24rpx;
}
.slot-logo {
.logo-stack {
position: relative;
width: 112rpx;
height: 112rpx;
flex-shrink: 0;
padding: 0;
box-sizing: border-box;
border-radius: 24rpx;
}
.slot-visual {
.carrier-logo {
width: 100%;
height: 100%;
}
.slot-badge {
position: absolute;
right: -6rpx;
bottom: -6rpx;
z-index: 2;
width: 48rpx;
height: 48rpx;
}
.carrier-details {
flex: 1;
min-width: 0;