176 lines
6.8 KiB
Vue
176 lines
6.8 KiB
Vue
<template>
|
||
<view class="wrap">
|
||
<view class="header">
|
||
<image class="avatar" :src="avatar || '/static/logo.png'" mode="aspectFill"></image>
|
||
<view class="profile">
|
||
<view class="nickname">{{ nickname || '未登录' }}</view>
|
||
<view class="userid">ID:{{ userId || '-' }}</view>
|
||
</view>
|
||
</view>
|
||
<view class="info">
|
||
<view class="info-item">
|
||
<text class="info-label">手机号</text>
|
||
<text class="info-value">{{ phoneNumber || '未绑定' }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="info-label">邀请码</text>
|
||
<text class="info-value">{{ inviteCode || '-' }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="stats">
|
||
<view class="stat">
|
||
<view class="stat-label" @click="toPoints">积分</view>
|
||
<view class="stat-value">{{ pointsBalance }}</view>
|
||
</view>
|
||
<view class="stat">
|
||
<view class="stat-label">卡券</view>
|
||
<view class="stat-value">{{ stats.coupon_count || 0 }}</view>
|
||
</view>
|
||
<view class="stat">
|
||
<view class="stat-label">道具卡</view>
|
||
<view class="stat-value">{{ stats.item_card_count || 0 }}</view>
|
||
</view>
|
||
</view>
|
||
<button class="refresh" @click="refresh" :disabled="loading">刷新数据</button>
|
||
<view v-if="error" class="error">{{ error }}</view>
|
||
</view>
|
||
<view class="orders">
|
||
<view class="orders-title">我的订单</view>
|
||
<view class="orders-cats">
|
||
<view class="orders-cat" @click="toOrders('pending')">
|
||
<view class="orders-cat-title">待付款</view>
|
||
</view>
|
||
<view class="orders-cat" @click="toOrders('completed')">
|
||
<view class="orders-cat-title">已完成</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="addresses">
|
||
<view class="addresses-title">地址管理</view>
|
||
<view class="addresses-entry" @click="toAddresses">
|
||
<text class="addresses-text">管理收货地址</text>
|
||
<text class="addresses-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
<view class="addresses">
|
||
<view class="addresses-title">使用帮助</view>
|
||
<view class="addresses-entry" @click="toHelp">
|
||
<text class="addresses-text">查看协议与说明</text>
|
||
<text class="addresses-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue'
|
||
import { onShow, onLoad } from '@dcloudio/uni-app'
|
||
import { getUserStats, getPointsBalance } from '../../api/appUser'
|
||
|
||
const avatar = ref(uni.getStorageSync('avatar') || '')
|
||
const nickname = ref(uni.getStorageSync('nickname') || '')
|
||
const userId = ref(uni.getStorageSync('user_id') || '')
|
||
const phoneNumber = ref(uni.getStorageSync('phone_number') || '')
|
||
const inviteCode = ref(uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || '')
|
||
const pointsBalance = ref(uni.getStorageSync('points_balance') || 0)
|
||
const stats = ref(uni.getStorageSync('user_stats') || {})
|
||
const loading = ref(false)
|
||
const error = ref('')
|
||
|
||
async function refresh() {
|
||
const token = uni.getStorageSync('token')
|
||
const phoneBound = !!uni.getStorageSync('phone_bound')
|
||
if (!token || !phoneBound) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '请先登录并绑定手机号',
|
||
confirmText: '去登录',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
uni.navigateTo({ url: '/pages/login/index' })
|
||
}
|
||
}
|
||
})
|
||
return
|
||
}
|
||
const user_id = uni.getStorageSync('user_id')
|
||
loading.value = true
|
||
error.value = ''
|
||
try {
|
||
const s = await getUserStats(user_id)
|
||
stats.value = s || {}
|
||
uni.setStorageSync('user_stats', stats.value)
|
||
const b = await getPointsBalance(user_id)
|
||
const balance = b && b.balance !== undefined ? b.balance : b
|
||
pointsBalance.value = balance || 0
|
||
uni.setStorageSync('points_balance', pointsBalance.value)
|
||
} catch (e) {
|
||
error.value = e && (e.message || e.errMsg) || '数据获取失败'
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
function toPoints() {
|
||
uni.navigateTo({ url: '/pages/points/index' })
|
||
}
|
||
|
||
function toOrders(status) {
|
||
const s = status === 'completed' ? 'completed' : 'pending'
|
||
uni.navigateTo({ url: `/pages/orders/index?status=${s}` })
|
||
}
|
||
|
||
function toAddresses() {
|
||
uni.navigateTo({ url: '/pages/address/index' })
|
||
}
|
||
|
||
function toHelp() {
|
||
uni.navigateTo({ url: '/pages/help/index' })
|
||
}
|
||
|
||
onShow(() => {
|
||
avatar.value = uni.getStorageSync('avatar') || avatar.value
|
||
nickname.value = uni.getStorageSync('nickname') || nickname.value
|
||
userId.value = uni.getStorageSync('user_id') || userId.value
|
||
phoneNumber.value = uni.getStorageSync('phone_number') || phoneNumber.value
|
||
const ui = uni.getStorageSync('user_info') || {}
|
||
inviteCode.value = uni.getStorageSync('invite_code') || ui.invite_code || inviteCode.value
|
||
pointsBalance.value = uni.getStorageSync('points_balance') || pointsBalance.value
|
||
const s = uni.getStorageSync('user_stats')
|
||
if (s) stats.value = s
|
||
refresh()
|
||
})
|
||
|
||
onLoad(() => {
|
||
refresh()
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.wrap { padding: 40rpx }
|
||
.header { display: flex; align-items: center; margin-bottom: 24rpx }
|
||
.avatar { width: 120rpx; height: 120rpx; border-radius: 60rpx; background-color: #f5f5f5 }
|
||
.profile { margin-left: 20rpx; display: flex; flex-direction: column }
|
||
.nickname { font-size: 32rpx }
|
||
.userid { margin-top: 6rpx; font-size: 24rpx; color: #999 }
|
||
.info { display: flex; flex-direction: column; background: #fff; border-radius: 12rpx; padding: 20rpx; margin-bottom: 20rpx; box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04) }
|
||
.info-item { display: flex; justify-content: space-between; margin-bottom: 12rpx }
|
||
.info-label { color: #666; font-size: 24rpx }
|
||
.info-value { font-size: 28rpx }
|
||
.stats { display: flex; background: #fafafa; border-radius: 12rpx; padding: 20rpx; justify-content: space-between; margin-bottom: 20rpx }
|
||
.stat { flex: 1; align-items: center }
|
||
.stat-label { color: #666; font-size: 24rpx }
|
||
.stat-value { font-size: 36rpx; margin-top: 8rpx }
|
||
.orders { background: #fff; border-radius: 12rpx; padding: 20rpx; box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04); margin-bottom: 20rpx }
|
||
.orders-title { font-size: 30rpx; margin-bottom: 12rpx }
|
||
.orders-cats { display: flex; justify-content: space-between }
|
||
.orders-cat { flex: 1; background: #f7f7f7; border-radius: 12rpx; padding: 20rpx; margin-right: 12rpx }
|
||
.orders-cat:last-child { margin-right: 0 }
|
||
.orders-cat-title { font-size: 28rpx; text-align: center }
|
||
.addresses { background: #fff; border-radius: 12rpx; padding: 20rpx; box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04); margin-bottom: 20rpx }
|
||
.addresses-title { font-size: 30rpx; margin-bottom: 12rpx }
|
||
.addresses-entry { display: flex; justify-content: space-between; align-items: center; background: #f7f7f7; border-radius: 12rpx; padding: 20rpx }
|
||
.addresses-text { font-size: 28rpx }
|
||
.addresses-arrow { font-size: 28rpx; color: #999 }
|
||
.refresh { width: 100%; margin-top: 12rpx }
|
||
.error { color: #e43; margin-top: 20rpx }
|
||
</style> |