677 lines
16 KiB
Vue
677 lines
16 KiB
Vue
<template>
|
||
<view class="mine-page">
|
||
<!-- 顶部背景图 -->
|
||
<view class="top-bg">
|
||
<image src="/static/title_bg.png" mode="aspectFill" class="bg-img" />
|
||
</view>
|
||
|
||
<!-- 页面加载状态 -->
|
||
<Loading type="page" :loading="pageLoading" />
|
||
|
||
<!-- 未登录状态 -->
|
||
<view class="login-card" v-if="!isLoggedIn && !pageLoading" :style="{ marginTop: (statusBarHeight + 35) + 'px' }">
|
||
<text class="login-tip">登陆后帮您更精确准备</text>
|
||
<button class="btn-login" @click="handleLogin">立即登录</button>
|
||
</view>
|
||
|
||
<!-- 已登录状态 - 用户信息区域 -->
|
||
<view class="user-section" v-else-if="isLoggedIn && !pageLoading" :style="{ marginTop: (statusBarHeight + 35) + 'px' }">
|
||
<!-- 用户信息(无背景)- 点击进入个人资料页 -->
|
||
<view class="user-info-row" @click="handlePersonalProfile">
|
||
<image
|
||
class="user-avatar"
|
||
:src="userInfo.avatar || defaultAvatar"
|
||
mode="aspectFill"
|
||
/>
|
||
<view class="user-detail">
|
||
<view class="user-name-row">
|
||
<text class="user-nickname">{{ userInfo.nickname || '用户名' }}</text>
|
||
<text class="edit-icon">✎</text>
|
||
</view>
|
||
<text class="user-xiangqin-no">相亲编号:{{ userInfo.xiangQinNo || '未设置' }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 资料卡片 -->
|
||
<view class="profile-card" v-if="!userInfo.isProfileCompleted">
|
||
<text class="tip-text">您还未填写孩子的相亲资料</text>
|
||
<button class="btn-fill" @click="handleEditProfile">立即填写</button>
|
||
</view>
|
||
<view class="profile-card completed" v-else>
|
||
<view class="profile-info">
|
||
<text class="tip-text">相亲资料已填写</text>
|
||
<text class="sub-text">可随时修改完善资料</text>
|
||
</view>
|
||
<button class="btn-edit" @click="handleEditProfile">修改资料</button>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 互动统计区域 -->
|
||
<view class="interact-section">
|
||
<view class="interact-grid">
|
||
<view class="interact-item" @click="navigateTo('/pages/interact/viewedMe')">
|
||
<view class="interact-icon viewed">
|
||
<image src="/static/ic_seen.png" mode="aspectFit" class="icon-img" />
|
||
</view>
|
||
<text class="interact-label">看过我</text>
|
||
<view class="interact-badge" v-if="interactCounts.viewedMe > 0">
|
||
<text>+{{ interactCounts.viewedMe }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="interact-item" @click="navigateTo('/pages/interact/favoritedMe')">
|
||
<view class="interact-icon favorited">
|
||
<image src="/static/ic_collection.png" mode="aspectFit" class="icon-img" />
|
||
</view>
|
||
<text class="interact-label">收藏我</text>
|
||
<view class="interact-badge" v-if="interactCounts.favoritedMe > 0">
|
||
<text>+{{ interactCounts.favoritedMe }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="interact-item" @click="navigateTo('/pages/interact/unlockedMe')">
|
||
<view class="interact-icon unlocked">
|
||
<image src="/static/ic_unlock.png" mode="aspectFit" class="icon-img" />
|
||
</view>
|
||
<text class="interact-label">解锁我</text>
|
||
<view class="interact-badge" v-if="interactCounts.unlockedMe > 0">
|
||
<text>+{{ interactCounts.unlockedMe }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 会员公告横幅 -->
|
||
<view class="vip-banner" @click="handleMember">
|
||
<view class="banner-content">
|
||
<text class="banner-title">会员权益升级公告</text>
|
||
<text class="banner-desc">最新会员体系重磅上线</text>
|
||
</view>
|
||
<image src="/static/logo.png" mode="aspectFit" class="banner-icon" />
|
||
</view>
|
||
|
||
<!-- 常用功能 -->
|
||
<view class="menu-section">
|
||
<text class="section-title">常用功能</text>
|
||
|
||
<view class="menu-list">
|
||
<view class="menu-item" @click="handleButler">
|
||
<image src="/static/butler.png" mode="aspectFit" class="menu-icon" />
|
||
<text class="menu-title">管家指导</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
|
||
<view class="menu-item" @click="handleRealName">
|
||
<image src="/static/real_name.png" mode="aspectFit" class="menu-icon" />
|
||
<text class="menu-title">实名认证</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
|
||
<view class="menu-item" @click="handleUserAgreement">
|
||
<image src="/static/ic_agreement1.png" mode="aspectFit" class="menu-icon" />
|
||
<text class="menu-title">用户协议</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
|
||
<view class="menu-item" @click="handlePrivacyPolicy">
|
||
<image src="/static/ic_agreement2.png" mode="aspectFit" class="menu-icon" />
|
||
<text class="menu-title">隐私协议</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
|
||
<view class="menu-item" @click="handleLogout" v-if="isLoggedIn">
|
||
<image src="/static/ic_exit.png" mode="aspectFit" class="menu-icon" />
|
||
<text class="menu-title">退出登录</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { ref, computed, onMounted } from 'vue'
|
||
import { useUserStore } from '@/store/user.js'
|
||
import { getMyProfile } from '@/api/profile.js'
|
||
import { login } from '@/api/auth.js'
|
||
import { getViewedMe, getFavoritedMe, getUnlockedMe } from '@/api/interact.js'
|
||
import Loading from '@/components/Loading/index.vue'
|
||
|
||
export default {
|
||
name: 'MinePage',
|
||
components: {
|
||
Loading
|
||
},
|
||
setup() {
|
||
const userStore = useUserStore()
|
||
|
||
// 页面状态
|
||
const pageLoading = ref(true)
|
||
const statusBarHeight = ref(20)
|
||
|
||
// 默认头像
|
||
const defaultAvatar = '/static/logo.png'
|
||
|
||
// 互动统计
|
||
const interactCounts = ref({
|
||
viewedMe: 0,
|
||
favoritedMe: 0,
|
||
unlockedMe: 0
|
||
})
|
||
|
||
// 获取系统信息
|
||
const getSystemInfo = () => {
|
||
uni.getSystemInfo({
|
||
success: (res) => {
|
||
statusBarHeight.value = res.statusBarHeight || 20
|
||
}
|
||
})
|
||
}
|
||
|
||
// 计算属性
|
||
const isLoggedIn = computed(() => userStore.isLoggedIn)
|
||
|
||
const userInfo = computed(() => ({
|
||
userId: userStore.userId,
|
||
nickname: userStore.nickname,
|
||
avatar: userStore.avatar,
|
||
xiangQinNo: userStore.xiangQinNo,
|
||
isProfileCompleted: userStore.isProfileCompleted,
|
||
isMember: userStore.isMember,
|
||
memberLevel: userStore.memberLevel,
|
||
isRealName: userStore.isRealName
|
||
}))
|
||
|
||
// 加载互动统计
|
||
const loadInteractCounts = async () => {
|
||
if (!userStore.isLoggedIn) return
|
||
|
||
try {
|
||
const [viewedRes, favoritedRes, unlockedRes] = await Promise.all([
|
||
getViewedMe(1, 1),
|
||
getFavoritedMe(1, 1),
|
||
getUnlockedMe(1, 1)
|
||
])
|
||
|
||
interactCounts.value = {
|
||
viewedMe: viewedRes?.data?.total || 0,
|
||
favoritedMe: favoritedRes?.data?.total || 0,
|
||
unlockedMe: unlockedRes?.data?.total || 0
|
||
}
|
||
} catch (error) {
|
||
console.error('加载互动统计失败:', error)
|
||
}
|
||
}
|
||
|
||
// 初始化页面
|
||
const initPage = async () => {
|
||
pageLoading.value = true
|
||
try {
|
||
userStore.restoreFromStorage()
|
||
if (userStore.isLoggedIn) {
|
||
await loadInteractCounts()
|
||
}
|
||
} catch (error) {
|
||
console.error('初始化页面失败:', error)
|
||
} finally {
|
||
pageLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 微信登录 - 跳转到登录页
|
||
const handleLogin = () => {
|
||
uni.navigateTo({ url: '/pages/login/index' })
|
||
}
|
||
|
||
// 个人资料页
|
||
const handlePersonalProfile = () => {
|
||
uni.navigateTo({ url: '/pages/profile/personal' })
|
||
}
|
||
|
||
// 预览资料
|
||
const handlePreviewProfile = () => {
|
||
if (!userStore.isProfileCompleted) {
|
||
handleEditProfile()
|
||
return
|
||
}
|
||
uni.navigateTo({ url: '/pages/profile/preview' })
|
||
}
|
||
|
||
// 编辑资料
|
||
const handleEditProfile = () => {
|
||
uni.navigateTo({ url: '/pages/profile/edit' })
|
||
}
|
||
|
||
// 会员中心
|
||
const handleMember = () => {
|
||
uni.navigateTo({ url: '/pages/member/index' })
|
||
}
|
||
|
||
// 管家指导
|
||
const handleButler = () => {
|
||
uni.showToast({ title: '功能开发中', icon: 'none' })
|
||
}
|
||
|
||
// 实名认证
|
||
const handleRealName = () => {
|
||
uni.navigateTo({ url: '/pages/realname/index' })
|
||
}
|
||
|
||
// 用户协议
|
||
const handleUserAgreement = () => {
|
||
uni.navigateTo({ url: '/pages/agreement/index?type=user' })
|
||
}
|
||
|
||
// 隐私协议
|
||
const handlePrivacyPolicy = () => {
|
||
uni.navigateTo({ url: '/pages/agreement/index?type=privacy' })
|
||
}
|
||
|
||
// 退出登录
|
||
const handleLogout = () => {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定要退出登录吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
userStore.logout()
|
||
interactCounts.value = { viewedMe: 0, favoritedMe: 0, unlockedMe: 0 }
|
||
uni.showToast({ title: '已退出登录', icon: 'success' })
|
||
// 清除所有页面,返回首页
|
||
setTimeout(() => {
|
||
uni.reLaunch({ url: '/pages/index/index' })
|
||
}, 1000)
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
// 导航
|
||
const navigateTo = (url) => {
|
||
uni.navigateTo({ url })
|
||
}
|
||
|
||
onMounted(() => {
|
||
getSystemInfo()
|
||
initPage()
|
||
})
|
||
|
||
return {
|
||
pageLoading,
|
||
statusBarHeight,
|
||
isLoggedIn,
|
||
userInfo,
|
||
interactCounts,
|
||
defaultAvatar,
|
||
handleLogin,
|
||
handlePersonalProfile,
|
||
handlePreviewProfile,
|
||
handleEditProfile,
|
||
handleMember,
|
||
handleButler,
|
||
handleRealName,
|
||
handleUserAgreement,
|
||
handlePrivacyPolicy,
|
||
handleLogout,
|
||
navigateTo,
|
||
loadInteractCounts
|
||
}
|
||
},
|
||
onShow() {
|
||
const userStore = useUserStore()
|
||
userStore.restoreFromStorage()
|
||
if (userStore.isLoggedIn && this.loadInteractCounts) {
|
||
this.loadInteractCounts()
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.mine-page {
|
||
min-height: 100vh;
|
||
background-color: #f5f6fa;
|
||
padding-bottom: 120rpx;
|
||
}
|
||
|
||
// 顶部背景图
|
||
.top-bg {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 400rpx;
|
||
z-index: 0;
|
||
|
||
.bg-img {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
// 未登录卡片
|
||
.login-card {
|
||
position: relative;
|
||
z-index: 1;
|
||
margin: 0 32rpx;
|
||
padding: 48rpx 40rpx;
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
text-align: center;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
|
||
|
||
.login-tip {
|
||
display: block;
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
margin-bottom: 32rpx;
|
||
}
|
||
|
||
.btn-login {
|
||
width: 280rpx;
|
||
height: 80rpx;
|
||
line-height: 80rpx;
|
||
background: linear-gradient(135deg, #ffb5b5 0%, #ff9a9a 100%);
|
||
border-radius: 40rpx;
|
||
font-size: 30rpx;
|
||
color: #fff;
|
||
border: none;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 已登录用户区域
|
||
.user-section {
|
||
position: relative;
|
||
z-index: 1;
|
||
padding: 0 32rpx;
|
||
}
|
||
|
||
// 用户信息行(无背景)
|
||
.user-info-row {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 24rpx;
|
||
|
||
.user-avatar {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-radius: 50%;
|
||
margin-right: 24rpx;
|
||
border: 4rpx solid rgba(255, 255, 255, 0.5);
|
||
}
|
||
|
||
.user-detail {
|
||
flex: 1;
|
||
|
||
.user-name-row {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 8rpx;
|
||
|
||
.user-nickname {
|
||
font-size: 36rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
margin-right: 12rpx;
|
||
}
|
||
|
||
.edit-icon {
|
||
font-size: 28rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
.user-xiangqin-no {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 资料卡片
|
||
.profile-card {
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
padding: 48rpx 40rpx;
|
||
text-align: center;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
|
||
|
||
.tip-text {
|
||
display: block;
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
margin-bottom: 32rpx;
|
||
}
|
||
|
||
.btn-fill {
|
||
width: 280rpx;
|
||
height: 80rpx;
|
||
line-height: 80rpx;
|
||
background: #FF8C95;
|
||
border-radius: 40rpx;
|
||
font-size: 30rpx;
|
||
color: #fff;
|
||
border: none;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 已完成资料的样式
|
||
.profile-card.completed {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 32rpx 40rpx;
|
||
text-align: left;
|
||
|
||
.profile-info {
|
||
flex: 1;
|
||
|
||
.tip-text {
|
||
margin-bottom: 8rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.sub-text {
|
||
font-size: 26rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
.btn-edit {
|
||
flex-shrink: 0;
|
||
width: 180rpx;
|
||
height: 68rpx;
|
||
line-height: 68rpx;
|
||
background: #fff;
|
||
border: 2rpx solid #FF8C95;
|
||
border-radius: 34rpx;
|
||
font-size: 28rpx;
|
||
color: #FF8C95;
|
||
margin-left: 20rpx;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 互动统计区域
|
||
.interact-section {
|
||
position: relative;
|
||
z-index: 1;
|
||
padding: 32rpx;
|
||
|
||
.interact-grid {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
|
||
.interact-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
position: relative;
|
||
|
||
.interact-icon {
|
||
width: 120rpx;
|
||
height: 120rpx;
|
||
border-radius: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 16rpx;
|
||
|
||
.icon-img {
|
||
width: 56rpx;
|
||
height: 56rpx;
|
||
}
|
||
|
||
&.viewed {
|
||
background: linear-gradient(135deg, #e8e0ff 0%, #d4c4ff 100%);
|
||
}
|
||
|
||
&.favorited {
|
||
background: linear-gradient(135deg, #ffe0e8 0%, #ffc4d4 100%);
|
||
}
|
||
|
||
&.unlocked {
|
||
background: linear-gradient(135deg, #fff3e0 0%, #ffe4c4 100%);
|
||
}
|
||
}
|
||
|
||
.interact-label {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.interact-badge {
|
||
position: absolute;
|
||
top: -8rpx;
|
||
right: -8rpx;
|
||
min-width: 44rpx;
|
||
height: 44rpx;
|
||
padding: 0 12rpx;
|
||
border-radius: 22rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
text {
|
||
font-size: 24rpx;
|
||
color: #fff;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
|
||
&:nth-child(1) .interact-badge {
|
||
background: #9b7bff;
|
||
}
|
||
|
||
&:nth-child(2) .interact-badge {
|
||
background: #ff6b8a;
|
||
}
|
||
|
||
&:nth-child(3) .interact-badge {
|
||
background: #ffb347;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 会员公告横幅
|
||
.vip-banner {
|
||
position: relative;
|
||
z-index: 1;
|
||
margin: 0 32rpx 32rpx;
|
||
padding: 32rpx;
|
||
background: linear-gradient(135deg, #4a3728 0%, #2d1f15 100%);
|
||
border-radius: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
.banner-content {
|
||
.banner-title {
|
||
display: block;
|
||
font-size: 34rpx;
|
||
font-weight: 600;
|
||
color: #ffd700;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.banner-desc {
|
||
display: inline-block;
|
||
font-size: 24rpx;
|
||
color: #ffd700;
|
||
background: rgba(255, 215, 0, 0.2);
|
||
padding: 6rpx 16rpx;
|
||
border-radius: 20rpx;
|
||
}
|
||
}
|
||
|
||
.banner-icon {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
}
|
||
}
|
||
|
||
// 常用功能
|
||
.menu-section {
|
||
position: relative;
|
||
z-index: 1;
|
||
margin: 0 32rpx;
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
padding: 32rpx;
|
||
|
||
.section-title {
|
||
display: block;
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.menu-list {
|
||
.menu-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 28rpx 0;
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
&:active {
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.menu-icon {
|
||
width: 44rpx;
|
||
height: 44rpx;
|
||
margin-right: 24rpx;
|
||
}
|
||
|
||
.menu-title {
|
||
flex: 1;
|
||
font-size: 30rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.menu-arrow {
|
||
font-size: 32rpx;
|
||
color: #ccc;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|