|
|
@@ -6,25 +6,21 @@
|
|
|
<text class="back-icon">←</text>
|
|
|
</view>
|
|
|
<view class="navbar-title">
|
|
|
- <text class="title-text">订阅记录</text>
|
|
|
+ <text class="title-text">我的订阅</text>
|
|
|
</view>
|
|
|
<view class="navbar-placeholder"></view>
|
|
|
</view>
|
|
|
|
|
|
<scroll-view class="scroll-view" scroll-y>
|
|
|
<view class="content-wrapper">
|
|
|
- <!-- 订阅记录卡片 -->
|
|
|
- <view class="record-card">
|
|
|
- <view class="card-header">
|
|
|
- <view class="header-left">
|
|
|
- <view class="header-dot"></view>
|
|
|
- <text class="header-title">我的订阅</text>
|
|
|
- </view>
|
|
|
- <text class="header-count">共 {{ subscriptions.length }} 条</text>
|
|
|
+ <view class="subscription-card">
|
|
|
+ <!-- 加载中 -->
|
|
|
+ <view v-if="loading" class="loading-state">
|
|
|
+ <text>加载中...</text>
|
|
|
</view>
|
|
|
|
|
|
<!-- 空状态 -->
|
|
|
- <view v-if="subscriptions.length === 0" class="empty-state">
|
|
|
+ <view v-else-if="subscriptions.length === 0" class="empty-state">
|
|
|
<text class="empty-icon">📋</text>
|
|
|
<text class="empty-text">暂无订阅记录</text>
|
|
|
<text class="empty-desc">前往超短池或强势池订阅服务</text>
|
|
|
@@ -39,7 +35,7 @@
|
|
|
>
|
|
|
<view class="item-header">
|
|
|
<view class="pool-info">
|
|
|
- <text class="pool-icon">{{ item.poolType === 'pool' ? '⚡' : '📈' }}</text>
|
|
|
+ <text class="pool-icon">{{ item.poolType === 1 ? '⚡' : '📈' }}</text>
|
|
|
<text class="pool-name">{{ item.poolName }}</text>
|
|
|
</view>
|
|
|
<view class="status-badge" :class="item.isActive ? 'active' : 'expired'">
|
|
|
@@ -48,27 +44,21 @@
|
|
|
</view>
|
|
|
|
|
|
<view class="item-body">
|
|
|
- <view class="info-row">
|
|
|
- <text class="info-label">订阅方案</text>
|
|
|
- <text class="info-value">{{ item.planName }}</text>
|
|
|
- </view>
|
|
|
<view class="info-row">
|
|
|
<text class="info-label">订阅金额</text>
|
|
|
<text class="info-value price">¥{{ item.amount }}</text>
|
|
|
</view>
|
|
|
<view class="info-row">
|
|
|
- <text class="info-label">购买时间</text>
|
|
|
- <text class="info-value">{{ formatDateTime(item.purchaseTime) }}</text>
|
|
|
+ <text class="info-label">开始时间</text>
|
|
|
+ <text class="info-value">{{ item.startTime }}</text>
|
|
|
</view>
|
|
|
<view class="info-row">
|
|
|
<text class="info-label">到期时间</text>
|
|
|
- <text class="info-value">{{ formatDateTime(item.expireTime) }}</text>
|
|
|
+ <text class="info-value">{{ item.expireTime }}</text>
|
|
|
</view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <view v-if="item.isActive" class="item-footer">
|
|
|
- <view class="renew-btn">
|
|
|
- <text>续费</text>
|
|
|
+ <view v-if="item.isActive" class="info-row">
|
|
|
+ <text class="info-label">剩余天数</text>
|
|
|
+ <text class="info-value highlight">{{ item.remainDays }}天</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -85,8 +75,10 @@
|
|
|
import { ref, onMounted } from 'vue'
|
|
|
import { onLoad, onShow } from '@dcloudio/uni-app'
|
|
|
import { isLoggedIn as checkLoginStatus } from '../../utils/auth.js'
|
|
|
+import { getUserSubscriptions } from '../../utils/api.js'
|
|
|
|
|
|
const subscriptions = ref([])
|
|
|
+const loading = ref(false)
|
|
|
const isLoggedIn = ref(false)
|
|
|
|
|
|
const checkLogin = () => {
|
|
|
@@ -98,59 +90,30 @@ const handleBack = () => {
|
|
|
pages.length > 1 ? uni.navigateBack() : uni.switchTab({ url: '/pages/mine/mine' })
|
|
|
}
|
|
|
|
|
|
-const formatDateTime = (timestamp) => {
|
|
|
- const date = new Date(timestamp)
|
|
|
- const year = date.getFullYear()
|
|
|
- const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
|
- const day = String(date.getDate()).padStart(2, '0')
|
|
|
- const hours = String(date.getHours()).padStart(2, '0')
|
|
|
- const minutes = String(date.getMinutes()).padStart(2, '0')
|
|
|
- return `${year}-${month}-${day} ${hours}:${minutes}`
|
|
|
-}
|
|
|
-
|
|
|
-const loadSubscriptions = () => {
|
|
|
+// 加载订阅列表
|
|
|
+const loadSubscriptions = async () => {
|
|
|
+ if (!isLoggedIn.value) return
|
|
|
+ loading.value = true
|
|
|
+
|
|
|
try {
|
|
|
- const now = Date.now()
|
|
|
- const allSubscriptions = []
|
|
|
-
|
|
|
- const poolPurchase = uni.getStorageSync('pool_purchase')
|
|
|
- if (poolPurchase) {
|
|
|
- allSubscriptions.push({
|
|
|
- poolType: 'pool',
|
|
|
- poolName: '超短精选池',
|
|
|
- planName: poolPurchase.plan === 'daily' ? '日订阅' : '周套餐',
|
|
|
- amount: poolPurchase.plan === 'daily' ? '18' : '98',
|
|
|
- purchaseTime: poolPurchase.purchaseTime,
|
|
|
- expireTime: poolPurchase.expireTime,
|
|
|
- isActive: now < poolPurchase.expireTime
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- const strongPurchase = uni.getStorageSync('strong_pool_purchase')
|
|
|
- if (strongPurchase) {
|
|
|
- allSubscriptions.push({
|
|
|
- poolType: 'strong',
|
|
|
- poolName: '强势趋势池',
|
|
|
- planName: '年订阅',
|
|
|
- amount: '98',
|
|
|
- purchaseTime: strongPurchase.purchaseTime,
|
|
|
- expireTime: strongPurchase.expireTime,
|
|
|
- isActive: now < strongPurchase.expireTime
|
|
|
- })
|
|
|
+ const res = await getUserSubscriptions()
|
|
|
+ if (res.code === 200) {
|
|
|
+ subscriptions.value = res.data || []
|
|
|
}
|
|
|
-
|
|
|
- subscriptions.value = allSubscriptions.sort((a, b) => b.purchaseTime - a.purchaseTime)
|
|
|
} catch (e) {
|
|
|
console.error('加载订阅记录失败:', e)
|
|
|
- subscriptions.value = []
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
}
|
|
|
}
|
|
|
|
|
|
onLoad(() => checkLogin())
|
|
|
-onMounted(() => loadSubscriptions())
|
|
|
+onMounted(() => {
|
|
|
+ if (isLoggedIn.value) loadSubscriptions()
|
|
|
+})
|
|
|
onShow(() => {
|
|
|
checkLogin()
|
|
|
- loadSubscriptions()
|
|
|
+ if (isLoggedIn.value) loadSubscriptions()
|
|
|
})
|
|
|
</script>
|
|
|
|
|
|
@@ -162,7 +125,6 @@ onShow(() => {
|
|
|
flex-direction: column;
|
|
|
}
|
|
|
|
|
|
-/* 导航栏 */
|
|
|
.custom-navbar {
|
|
|
background: #ffffff;
|
|
|
display: flex;
|
|
|
@@ -202,7 +164,6 @@ onShow(() => {
|
|
|
width: 80rpx;
|
|
|
}
|
|
|
|
|
|
-/* 内容区 */
|
|
|
.scroll-view {
|
|
|
flex: 1;
|
|
|
height: 0;
|
|
|
@@ -212,52 +173,41 @@ onShow(() => {
|
|
|
padding: 32rpx;
|
|
|
}
|
|
|
|
|
|
-/* 记录卡片 */
|
|
|
-.record-card {
|
|
|
+.subscription-card {
|
|
|
background: #ffffff;
|
|
|
border-radius: 24rpx;
|
|
|
padding: 32rpx;
|
|
|
box-shadow: 0 8rpx 24rpx rgba(37, 52, 94, 0.08);
|
|
|
}
|
|
|
|
|
|
-.card-header {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 24rpx;
|
|
|
- padding-bottom: 24rpx;
|
|
|
- border-bottom: 1rpx solid #f1f2f6;
|
|
|
-}
|
|
|
-
|
|
|
-.header-left {
|
|
|
+.loading-state, .empty-state {
|
|
|
display: flex;
|
|
|
+ flex-direction: column;
|
|
|
align-items: center;
|
|
|
+ padding: 60rpx 40rpx;
|
|
|
}
|
|
|
|
|
|
-.header-dot {
|
|
|
- width: 12rpx;
|
|
|
- height: 12rpx;
|
|
|
- border-radius: 50%;
|
|
|
- background: #5B5AEA;
|
|
|
- margin-right: 12rpx;
|
|
|
+.empty-icon {
|
|
|
+ font-size: 80rpx;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
}
|
|
|
|
|
|
-.header-title {
|
|
|
- font-size: 30rpx;
|
|
|
+.empty-text {
|
|
|
+ font-size: 28rpx;
|
|
|
font-weight: 600;
|
|
|
- color: #222222;
|
|
|
+ color: #333333;
|
|
|
+ margin-bottom: 8rpx;
|
|
|
}
|
|
|
|
|
|
-.header-count {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #9ca2b5;
|
|
|
+.empty-desc {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #999999;
|
|
|
}
|
|
|
|
|
|
-/* 订阅列表 */
|
|
|
.subscription-list {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- gap: 24rpx;
|
|
|
+ gap: 20rpx;
|
|
|
}
|
|
|
|
|
|
.subscription-item {
|
|
|
@@ -309,7 +259,7 @@ onShow(() => {
|
|
|
.item-body {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- gap: 16rpx;
|
|
|
+ gap: 14rpx;
|
|
|
}
|
|
|
|
|
|
.info-row {
|
|
|
@@ -332,53 +282,11 @@ onShow(() => {
|
|
|
.info-value.price {
|
|
|
color: #f16565;
|
|
|
font-weight: 700;
|
|
|
- font-size: 28rpx;
|
|
|
}
|
|
|
|
|
|
-.item-footer {
|
|
|
- margin-top: 24rpx;
|
|
|
- padding-top: 20rpx;
|
|
|
- border-top: 1rpx solid #eee;
|
|
|
- display: flex;
|
|
|
- justify-content: flex-end;
|
|
|
-}
|
|
|
-
|
|
|
-.renew-btn {
|
|
|
- padding: 14rpx 40rpx;
|
|
|
- background: #5B5AEA;
|
|
|
- border-radius: 32rpx;
|
|
|
-}
|
|
|
-
|
|
|
-.renew-btn text {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #ffffff;
|
|
|
- font-weight: 500;
|
|
|
-}
|
|
|
-
|
|
|
-/* 空状态 */
|
|
|
-.empty-state {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- padding: 80rpx 40rpx;
|
|
|
-}
|
|
|
-
|
|
|
-.empty-icon {
|
|
|
- font-size: 100rpx;
|
|
|
- margin-bottom: 24rpx;
|
|
|
-}
|
|
|
-
|
|
|
-.empty-text {
|
|
|
- font-size: 30rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #333333;
|
|
|
- margin-bottom: 12rpx;
|
|
|
-}
|
|
|
-
|
|
|
-.empty-desc {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #999999;
|
|
|
- text-align: center;
|
|
|
+.info-value.highlight {
|
|
|
+ color: #5B5AEA;
|
|
|
+ font-weight: 700;
|
|
|
}
|
|
|
|
|
|
.bottom-safe-area {
|