Files
tydata-mini/src/pages/me.vue
2026-02-27 12:07:10 +08:00

318 lines
9.0 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="safe-area-top box-border min-h-screen">
<view class="flex flex-col p-4 space-y-6">
<!-- 用户信息卡片 -->
<view
class="mb-4 profile-section group relative flex items-center gap-4 rounded-xl bg-white p-6 shadow-lg transition-all hover:shadow-xl"
@click="!isLoggedIn ? redirectToLogin() : null">
<view class="relative">
<!-- 头像容器添加overflow-hidden解决边框问题 -->
<view class="flex items-center justify-center overflow-hidden rounded-full p-0.5"
:class="levelGradient.border">
<image :src="userAvatar || getDefaultAvatar()" alt="User Avatar"
class="h-24 w-24 rounded-full border-4 border-white">
</image>
</view>
<!-- 代理标识 -->
<view v-if="isAgent" class="absolute -bottom-2 -right-2">
<view class="flex items-center justify-center rounded-full px-3 py-1 text-xs font-bold text-white shadow-sm"
:class="levelGradient.badge">
{{ levelNames[level] }}
</view>
</view>
</view>
<view class="space-y-1">
<!-- @click.stop="handleVersionClickForTest" -->
<view class="text-lg font-bold text-gray-800" @click="userType === 0 ? toBindPhone() : null"
:class="userType === 0 ? 'cursor-pointer text-blue-600' : ''">
{{ !isLoggedIn ? '点击登录' : (userType === 0 ? '绑定手机号' : maskName(userName)) }}
</view>
<view v-if="isAgent" class="text-sm font-medium" :class="levelGradient.text">
🎖 {{ levelText[level] }}
</view>
</view>
</view>
<VipBanner v-if="isLoggedIn && !isVipOrSvip" />
<!-- 功能菜单 -->
<view class="features-section space-y-3">
<!-- 代理报告配置 + 续费VIP/SVIP 代理 -->
<template v-if="isLoggedIn && isAgent && isVipOrSvip">
<button
class=" flex items-center p-3 rounded-xl bg-gradient-to-r from-purple-200/80 to-pink-200/80 text-purple-700 font-medium shadow-sm transition-all active:shadow-md"
hover-class="opacity-80 scale-98" @click="toVipConfig">
<text class="mr-2"></text> 代理报告配置
</button>
<button
class="flex flex-col items-start p-3 rounded-xl bg-gradient-to-r from-amber-200/80 to-orange-200/80 text-amber-700 font-medium shadow-sm transition-all active:shadow-md"
hover-class="opacity-80 scale-98" @click="toVipRenewal">
<view class="flex items-center">
<text class="mr-2">🔄</text> 续费代理会员
</view>
<view v-if="ExpiryTime" class="text-xs text-gray-500 mt-1 ml-6">有效期至 {{ formatExpiryTime(ExpiryTime) }}</view>
</button>
</template>
<!-- 升级/开通代理会员登录后显示非代理申请普通代理升级 -->
<button
class=" flex items-center text-gray-600 p-3 rounded-xl bg-white font-medium shadow-sm transition-all active:shadow-md"
hover-class="opacity-80 bg-blue-50" @click="toUserAgreement">
<text class="mr-2">📜</text> 用户协议
</button>
<button
class=" flex items-center text-gray-600 p-3 rounded-xl bg-white font-medium shadow-sm transition-all active:shadow-md"
hover-class="opacity-80 bg-blue-50" @click="toPrivacyPolicy">
<text class="mr-2">🔒</text> 隐私政策
</button>
<button open-type="contact"
class=" flex items-center text-gray-600 p-3 rounded-xl bg-white font-medium shadow-sm transition-all active:shadow-md"
hover-class="opacity-80 bg-blue-50" @click="toAi">
<text class="mr-2">💬</text> 联系客服
</button>
</view>
</view>
<!-- 更新进度弹窗 -->
<view v-if="showUpdateProgress" class="update-progress-mask">
<view class="update-progress-dialog">
<view class="update-progress-title">应用更新中</view>
<view class="update-progress-bar-container">
<view class="update-progress-bar" :style="{ width: downloadProgress + '%' }"></view>
</view>
<view class="update-progress-text">{{ downloadProgress }}%</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed, onBeforeMount } from 'vue'
import { maskName, formatExpiryTime } from '@/utils/format'
// 分享给好友、分享到朋友圈
useShare({ title: '天远数据 - 大数据报告查询' })
// 用户数据
const userName = ref('')
const userAvatar = ref('')
const isLoggedIn = ref(false)
const userType = ref(null)
// 代理数据
const isAgent = ref(false)
const level = ref('normal')
const ExpiryTime = ref('')
const showUpdateProgress = ref(false)
// 检查平台环境
onBeforeMount(() => {
// 从缓存获取用户信息
const token = uni.getStorageSync('token')
if (token) {
isLoggedIn.value = true
// 从缓存获取用户信息
const userInfo = uni.getStorageSync('userInfo')
console.log("userInfo", userInfo)
if (userInfo) {
userName.value = userInfo.nickName || userInfo.mobile || '微信用户'
userAvatar.value = userInfo.avatar || ''
userType.value = userInfo.userType
}
// 从缓存获取代理信息
const agentInfo = uni.getStorageSync('agentInfo')
if (agentInfo?.isAgent) {
isAgent.value = agentInfo.isAgent
level.value = agentInfo.level || 'normal'
ExpiryTime.value = agentInfo.expiryTime || ''
}
}
})
const levelNames = {
normal: '普通代理',
'': '普通代理',
VIP: 'VIP代理',
SVIP: 'SVIP代理',
}
const levelText = {
normal: '基础代理特权',
'': '基础代理特权',
VIP: '高级代理特权',
SVIP: '尊享代理特权',
}
const isVipOrSvip = computed(() => {
const l = (level.value || '').toString()
return ['VIP', 'SVIP'].includes(l)
})
const levelGradient = computed(() => ({
border: {
normal: 'bg-green-300',
'': 'bg-green-300',
VIP: 'bg-gradient-to-r from-yellow-400 to-amber-500',
SVIP: 'bg-gradient-to-r from-purple-400 to-pink-400 shadow-[0_0_15px_rgba(163,51,200,0.2)]',
}[level.value],
badge: {
normal: 'bg-green-500',
'': 'bg-green-500',
VIP: 'bg-gradient-to-r from-yellow-500 to-amber-600',
SVIP: 'bg-gradient-to-r from-purple-500 to-pink-500',
}[level.value],
text: {
normal: 'text-green-600',
'': 'text-green-600',
VIP: 'text-amber-600',
SVIP: 'text-purple-600',
}[level.value],
}))
function toHistory() {
uni.navigateTo({
url: '/pages/queryHistory'
})
}
function toUserAgreement() {
uni.navigateTo({
url: '/pages/agreement?type=user'
})
}
function redirectToLogin() {
uni.navigateTo({
url: '/pages/login'
})
}
const toPrivacyPolicy = () => {
uni.navigateTo({
url: '/pages/agreement?type=privacy'
})
}
const toAi = () => {
uni.switchTab({
url: '/pages/ai'
})
}
function toVipConfig() {
uni.navigateTo({
url: '/pages/agentVipConfig'
})
}
function toVipRenewal() {
uni.navigateTo({ url: '/pages/agentVipApply' })
}
function toBindPhone() {
uni.navigateTo({
url: '/pages/login'
})
}
const getDefaultAvatar = () => {
if (!isAgent.value) return '/static/image/head_shot.webp'
switch (level.value) {
case 'normal':
case '':
return '/static/image/shot_nonal.png'
case 'VIP':
return '/static/image/shot_vip.png'
case 'SVIP':
return '/static/image/shot_svip.png'
default:
return '/static/image/head_shot.webp'
}
}
</script>
<style scoped>
.profile-section {
background: linear-gradient(135deg, #ffffff 50%, rgba(236, 253, 245, 0.3));
border: 1px solid rgba(209, 213, 219, 0.2);
}
.profile-section .relative>view:first-child {
transition: all 0.3s ease;
}
.border-gradient-to-r {
border-image: linear-gradient(to right, var(--tw-gradient-from), var(--tw-gradient-to)) 1;
}
.shadow-glow {
box-shadow: 0 0 8px rgba(163, 51, 200, 0.2);
}
/* 更新进度样式 */
.update-progress-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
.update-progress-dialog {
width: 80%;
background-color: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.update-progress-title {
font-size: 18px;
font-weight: bold;
text-align: center;
margin-bottom: 16px;
color: #333;
}
.update-progress-bar-container {
height: 10px;
background-color: #f0f0f0;
border-radius: 5px;
overflow: hidden;
margin-bottom: 8px;
}
.update-progress-bar {
height: 100%;
background: linear-gradient(to right, #4299e1, #667eea);
border-radius: 5px;
transition: width 0.3s ease;
}
.update-progress-text {
text-align: center;
font-size: 14px;
color: #666;
}
</style>
<route lang="json">{
"layout": "home",
"style": {
"navigationBarTextStyle": "black",
"navigationStyle": "default",
"navigationBarBackgroundColor": "#e3f0ff"
}
}</route>