1128 lines
28 KiB
Vue
1128 lines
28 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="family-popup-mask" v-if="showFamilyPopup" @click="closeFamilyPopup">
|
||
<view class="family-popup" @click.stop>
|
||
<view class="popup-title">绑定家庭成员</view>
|
||
|
||
<view class="popup-input-wrapper">
|
||
<input
|
||
v-model="bindXiangQinNo"
|
||
class="popup-input"
|
||
type="text"
|
||
placeholder="请输入相亲编号"
|
||
maxlength="20"
|
||
/>
|
||
</view>
|
||
|
||
<button class="popup-btn" :class="{ 'has-content': bindXiangQinNo.trim() }" @click="handleBindFamily" :disabled="bindLoading">
|
||
{{ bindLoading ? '绑定中...' : '确定' }}
|
||
</button>
|
||
|
||
<view class="popup-divider"></view>
|
||
|
||
<view class="popup-members-title">已绑定的用户({{ familyMembers.length }}/2)</view>
|
||
|
||
<view class="popup-members-list" v-if="familyMembers.length > 0">
|
||
<view class="member-item" v-for="member in familyMembers" :key="member.bindId">
|
||
<image class="member-avatar" :src="member.avatar || defaultAvatar" mode="aspectFill" />
|
||
<view class="member-info">
|
||
<text class="member-nickname">{{ member.nickname || '用户' }}</text>
|
||
<text class="member-no">{{ member.xiangQinNo }}</text>
|
||
</view>
|
||
<text class="member-unbind" @click="handleUnbindFamily(member)">解绑</text>
|
||
</view>
|
||
</view>
|
||
<view class="popup-empty" v-else>
|
||
<text>暂未绑定</text>
|
||
</view>
|
||
|
||
<view class="popup-close" @click="closeFamilyPopup">
|
||
<text>⊗</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 未登录状态 -->
|
||
<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="avatarLoadError ? defaultAvatar : (userInfo.avatar || defaultAvatar)"
|
||
mode="aspectFill"
|
||
@error="onAvatarError"
|
||
/>
|
||
<view class="user-detail">
|
||
<view class="user-name-row">
|
||
<text class="user-nickname">{{ userInfo.nickname || '用户名' }}</text>
|
||
<image v-if="userInfo.isMember && memberIconUrl" class="member-icon" :src="memberIconUrl" mode="heightFix" />
|
||
<text class="edit-icon">✎</text>
|
||
</view>
|
||
<text class="user-xiangqin-no">相亲编号:{{ userInfo.xiangQinNo || '未设置' }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 资料卡片 -->
|
||
<view class="profile-card auditing" v-if="userStore.isProfileAuditing">
|
||
<text class="tip-text">资料审核中</text>
|
||
<button class="btn-fill disabled" disabled>审核中</button>
|
||
</view>
|
||
<view class="profile-card" v-else-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 viewed" @click="navigateTo('/pages/interact/viewedMe')">
|
||
<view class="item-card">
|
||
<view class="icon-box">
|
||
<image src="/static/ic_seen.png" mode="aspectFit" class="icon-img" />
|
||
</view>
|
||
<text class="item-label">看过我</text>
|
||
<view class="item-count" v-if="interactCounts.viewedMe > 0">
|
||
<text>+{{ interactCounts.viewedMe }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="interact-item favorited" @click="navigateTo('/pages/interact/favoritedMe')">
|
||
<view class="item-card">
|
||
<view class="icon-box">
|
||
<image src="/static/ic_collection.png" mode="aspectFit" class="icon-img" />
|
||
</view>
|
||
<text class="item-label">收藏我</text>
|
||
<view class="item-count" v-if="interactCounts.favoritedMe > 0">
|
||
<text>+{{ interactCounts.favoritedMe }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="interact-item unlocked" @click="navigateTo('/pages/interact/unlockedMe')">
|
||
<view class="item-card">
|
||
<view class="icon-box">
|
||
<image src="/static/ic_unlock.png" mode="aspectFit" class="icon-img" />
|
||
</view>
|
||
<text class="item-label">解锁我</text>
|
||
<view class="item-count" v-if="interactCounts.unlockedMe > 0">
|
||
<text>+{{ interactCounts.unlockedMe }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 会员公告横幅 -->
|
||
<view class="vip-banner" :class="{ 'has-image': memberEntryImageUrl }" @click="handleMember">
|
||
<image v-if="memberEntryImageUrl" :src="memberEntryImageUrl" mode="widthFix" class="banner-full-img" />
|
||
<template v-else>
|
||
<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" />
|
||
</template>
|
||
</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="handleFamilyBind" v-if="isLoggedIn && canBindFamily">
|
||
<image src="/static/ic_bind.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>
|
||
|
||
<!-- ICP备案号 -->
|
||
<view class="icp-section">
|
||
<text class="icp-text">备案号:苏ICP备2026001086号-1</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { ref, computed, onMounted } from 'vue'
|
||
import { useUserStore } from '@/store/user.js'
|
||
import { useConfigStore } from '@/store/config.js'
|
||
import { useChatStore } from '@/store/chat.js'
|
||
import { getInteractCounts, markInteractAsRead } from '@/api/interact.js'
|
||
import { bindFamilyByXiangQinNo, getFamilyMembers, unbindFamilyMember, getMemberInfo } from '@/api/member.js'
|
||
import { getFullImageUrl } from '@/utils/image.js'
|
||
import Loading from '@/components/Loading/index.vue'
|
||
|
||
export default {
|
||
name: 'MinePage',
|
||
components: {
|
||
Loading
|
||
},
|
||
setup() {
|
||
const userStore = useUserStore()
|
||
const configStore = useConfigStore()
|
||
|
||
// 页面状态
|
||
const pageLoading = ref(true)
|
||
const statusBarHeight = ref(20)
|
||
|
||
// 从 configStore 获取默认头像
|
||
const defaultAvatar = computed(() => configStore.defaultAvatar || '/static/logo.png')
|
||
|
||
// 互动统计
|
||
const interactCounts = ref({
|
||
viewedMe: 0,
|
||
favoritedMe: 0,
|
||
unlockedMe: 0
|
||
})
|
||
|
||
// 家庭成员绑定相关
|
||
const showFamilyPopup = ref(false)
|
||
const bindXiangQinNo = ref('')
|
||
const bindLoading = ref(false)
|
||
const familyMembers = ref([])
|
||
const canBindFamily = ref(false) // 是否可以绑定家庭成员(只有主账号才能绑定)
|
||
|
||
// 获取系统信息
|
||
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: getFullImageUrl(userStore.avatar),
|
||
xiangQinNo: userStore.xiangQinNo,
|
||
isProfileCompleted: userStore.isProfileCompleted,
|
||
isMember: userStore.isMember,
|
||
memberLevel: userStore.memberLevel,
|
||
isRealName: userStore.isRealName
|
||
}))
|
||
|
||
// 会员图标URL
|
||
const memberIconUrl = computed(() => {
|
||
if (!userStore.isMember || !userStore.memberLevel) return ''
|
||
const iconUrl = configStore.getMemberIcon(userStore.memberLevel)
|
||
return iconUrl ? getFullImageUrl(iconUrl) : ''
|
||
})
|
||
|
||
// 会员入口图URL
|
||
const memberEntryImageUrl = computed(() => {
|
||
return configStore.memberEntryImage ? getFullImageUrl(configStore.memberEntryImage) : ''
|
||
})
|
||
|
||
/**
|
||
* 加载互动统计(从后端获取新增数量)
|
||
*/
|
||
const loadInteractCounts = async () => {
|
||
if (!userStore.isLoggedIn) return
|
||
|
||
try {
|
||
const res = await getInteractCounts()
|
||
if (res?.code === 0 && res.data) {
|
||
interactCounts.value = {
|
||
viewedMe: res.data.viewedMeCount || 0,
|
||
favoritedMe: res.data.favoritedMeCount || 0,
|
||
unlockedMe: res.data.unlockedMeCount || 0
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('加载互动统计失败:', error)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 加载家庭成员列表
|
||
*/
|
||
const loadFamilyMembers = async () => {
|
||
if (!userStore.isLoggedIn || userStore.memberLevel !== 3) return
|
||
|
||
try {
|
||
const res = await getFamilyMembers()
|
||
if (res?.code === 0 && res.data) {
|
||
familyMembers.value = res.data.map(item => ({
|
||
...item,
|
||
avatar: getFullImageUrl(item.avatar)
|
||
}))
|
||
}
|
||
} catch (error) {
|
||
console.error('加载家庭成员失败:', error)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 加载会员信息(检查是否可以绑定家庭成员)
|
||
*/
|
||
const loadMemberInfo = async () => {
|
||
if (!userStore.isLoggedIn) return
|
||
|
||
try {
|
||
const res = await getMemberInfo()
|
||
if (res?.code === 0 && res.data) {
|
||
canBindFamily.value = res.data.canBindFamily || false
|
||
}
|
||
} catch (error) {
|
||
console.error('加载会员信息失败:', error)
|
||
}
|
||
}
|
||
|
||
// 初始化页面
|
||
const initPage = async () => {
|
||
pageLoading.value = true
|
||
try {
|
||
userStore.restoreFromStorage()
|
||
if (userStore.isLoggedIn) {
|
||
await loadInteractCounts()
|
||
await loadMemberInfo()
|
||
await loadFamilyMembers()
|
||
}
|
||
} 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 handleEditProfile = () => {
|
||
uni.navigateTo({ url: '/pages/profile/edit' })
|
||
}
|
||
|
||
// 会员中心
|
||
const handleMember = () => {
|
||
uni.navigateTo({ url: '/pages/member/index' })
|
||
}
|
||
|
||
// 管家指导
|
||
const handleButler = () => {
|
||
uni.navigateTo({ url: '/pages/butler/index' })
|
||
}
|
||
|
||
// 实名认证
|
||
const handleRealName = () => {
|
||
uni.navigateTo({ url: '/pages/realname/index' })
|
||
}
|
||
|
||
// 绑定家庭成员 - 打开弹窗
|
||
const handleFamilyBind = () => {
|
||
showFamilyPopup.value = true
|
||
loadFamilyMembers()
|
||
}
|
||
|
||
// 关闭家庭成员弹窗
|
||
const closeFamilyPopup = () => {
|
||
showFamilyPopup.value = false
|
||
bindXiangQinNo.value = ''
|
||
}
|
||
|
||
// 确认绑定家庭成员
|
||
const handleBindFamily = async () => {
|
||
if (!bindXiangQinNo.value.trim()) {
|
||
uni.showToast({ title: '请输入相亲编号', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
if (familyMembers.value.length >= 2) {
|
||
uni.showToast({ title: '最多绑定2位家庭成员', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
bindLoading.value = true
|
||
try {
|
||
const res = await bindFamilyByXiangQinNo(bindXiangQinNo.value.trim())
|
||
if (res?.code === 0) {
|
||
uni.showToast({ title: '绑定成功', icon: 'success' })
|
||
bindXiangQinNo.value = ''
|
||
await loadFamilyMembers()
|
||
} else {
|
||
uni.showToast({ title: res?.message || '绑定失败', icon: 'none' })
|
||
}
|
||
} catch (error) {
|
||
console.error('绑定家庭成员失败:', error)
|
||
uni.showToast({ title: '绑定失败', icon: 'none' })
|
||
} finally {
|
||
bindLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 解绑家庭成员
|
||
const handleUnbindFamily = (member) => {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: `确定要解绑 ${member.nickname || '该用户'} 吗?`,
|
||
success: async (res) => {
|
||
if (res.confirm) {
|
||
try {
|
||
const result = await unbindFamilyMember(member.userId)
|
||
if (result?.code === 0) {
|
||
uni.showToast({ title: '解绑成功', icon: 'success' })
|
||
await loadFamilyMembers()
|
||
} else {
|
||
uni.showToast({ title: result?.message || '解绑失败', icon: 'none' })
|
||
}
|
||
} catch (error) {
|
||
console.error('解绑失败:', error)
|
||
uni.showToast({ title: '解绑失败', icon: 'none' })
|
||
}
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
// 用户协议
|
||
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 = async (url) => {
|
||
// 根据 URL 确定互动类型并标记已读
|
||
let interactType = ''
|
||
if (url.includes('viewedMe')) {
|
||
interactType = 'viewedMe'
|
||
interactCounts.value.viewedMe = 0
|
||
} else if (url.includes('favoritedMe')) {
|
||
interactType = 'favoritedMe'
|
||
interactCounts.value.favoritedMe = 0
|
||
} else if (url.includes('unlockedMe')) {
|
||
interactType = 'unlockedMe'
|
||
interactCounts.value.unlockedMe = 0
|
||
}
|
||
|
||
// 调用后端标记已读(异步,不阻塞跳转)
|
||
if (interactType) {
|
||
markInteractAsRead(interactType).catch(err => {
|
||
console.error('标记已读失败:', err)
|
||
})
|
||
}
|
||
|
||
uni.navigateTo({ url })
|
||
}
|
||
|
||
// 头像加载失败时的处理
|
||
const avatarLoadError = ref(false)
|
||
const onAvatarError = () => {
|
||
avatarLoadError.value = true
|
||
}
|
||
|
||
onMounted(() => {
|
||
getSystemInfo()
|
||
initPage()
|
||
})
|
||
|
||
return {
|
||
pageLoading,
|
||
statusBarHeight,
|
||
isLoggedIn,
|
||
userInfo,
|
||
userStore,
|
||
interactCounts,
|
||
defaultAvatar,
|
||
memberIconUrl,
|
||
memberEntryImageUrl,
|
||
avatarLoadError,
|
||
onAvatarError,
|
||
// 家庭成员绑定
|
||
showFamilyPopup,
|
||
bindXiangQinNo,
|
||
bindLoading,
|
||
familyMembers,
|
||
canBindFamily,
|
||
loadMemberInfo,
|
||
handleFamilyBind,
|
||
closeFamilyPopup,
|
||
handleBindFamily,
|
||
handleUnbindFamily,
|
||
// 其他方法
|
||
handleLogin,
|
||
handlePersonalProfile,
|
||
handleEditProfile,
|
||
handleMember,
|
||
handleButler,
|
||
handleRealName,
|
||
handleUserAgreement,
|
||
handlePrivacyPolicy,
|
||
handleLogout,
|
||
navigateTo,
|
||
loadInteractCounts
|
||
}
|
||
},
|
||
async onShow() {
|
||
const userStore = useUserStore()
|
||
const chatStore = useChatStore()
|
||
userStore.restoreFromStorage()
|
||
// 重置头像加载错误状态,以便重新尝试加载
|
||
if (this.avatarLoadError !== undefined) {
|
||
this.avatarLoadError = false
|
||
}
|
||
if (userStore.isLoggedIn) {
|
||
// 刷新用户信息(包括会员状态)
|
||
await userStore.refreshFromServer()
|
||
if (this.loadInteractCounts) {
|
||
this.loadInteractCounts()
|
||
}
|
||
// 刷新家庭绑定权限(购买家庭会员后返回需要立即显示绑定入口)
|
||
if (this.loadMemberInfo) {
|
||
this.loadMemberInfo()
|
||
}
|
||
// 刷新未读消息数并更新底部导航栏badge
|
||
chatStore.fetchAllUnreadCounts()
|
||
}
|
||
}
|
||
}
|
||
</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);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.user-detail {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
|
||
.user-name-row {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-direction: row;
|
||
margin-bottom: 8rpx;
|
||
|
||
.user-nickname {
|
||
font-size: 36rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
margin-right: 6rpx;
|
||
}
|
||
|
||
.member-icon {
|
||
height: 42rpx;
|
||
width: auto;
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
.edit-icon {
|
||
font-size: 28rpx;
|
||
color: #999;
|
||
flex-shrink: 0;
|
||
}
|
||
}
|
||
|
||
.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;
|
||
}
|
||
|
||
&.disabled {
|
||
background: #ccc;
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 审核中资料的样式
|
||
.profile-card.auditing {
|
||
.tip-text {
|
||
color: #ff9800;
|
||
}
|
||
}
|
||
|
||
// 已完成资料的样式
|
||
.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;
|
||
flex-direction: row;
|
||
justify-content: space-around;
|
||
|
||
.interact-item {
|
||
.item-card {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
width: 150rpx;
|
||
height: 132rpx;
|
||
border-radius: 24rpx;
|
||
|
||
.icon-box {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
border-radius: 20rpx;
|
||
margin-top: -18rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 6rpx;
|
||
|
||
.icon-img {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
}
|
||
}
|
||
|
||
.item-label {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
margin-bottom: 6rpx;
|
||
}
|
||
|
||
.item-count {
|
||
min-width: 56rpx;
|
||
height: 40rpx;
|
||
padding: 5rpx 0rpx;
|
||
border-radius: 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
text {
|
||
font-size: 20rpx;
|
||
color: #fff;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 看过我 - 紫色
|
||
&.viewed .item-card {
|
||
background: linear-gradient(0deg, rgba(237, 213, 255, 0.1) 0%, #E0D8FF 100%);
|
||
|
||
.item-count {
|
||
background: #8b5cf6;
|
||
}
|
||
}
|
||
|
||
// 收藏我 - 粉色
|
||
&.favorited .item-card {
|
||
background: linear-gradient(0deg, rgba(255, 213, 240, 0.1) 0%, #FFC4D7 100%);
|
||
|
||
.item-count {
|
||
background: #fb7185;
|
||
}
|
||
}
|
||
|
||
// 解锁我 - 黄色
|
||
&.unlocked .item-card {
|
||
background: linear-gradient(0deg, rgba(255, 239, 213, 0.1) 0%, #FFF5D8 100%);
|
||
|
||
.item-count {
|
||
background: #f59e0b;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 会员公告横幅
|
||
.vip-banner {
|
||
position: relative;
|
||
z-index: 1;
|
||
margin: 0 32rpx 32rpx;
|
||
border-radius: 24rpx;
|
||
overflow: hidden;
|
||
|
||
&.has-image {
|
||
padding: 0;
|
||
}
|
||
|
||
&:not(.has-image) {
|
||
padding: 32rpx;
|
||
background: linear-gradient(135deg, #4a3728 0%, #2d1f15 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.banner-full-img {
|
||
width: 100%;
|
||
height: auto;
|
||
display: block;
|
||
border-radius: 24rpx;
|
||
}
|
||
|
||
.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: 34rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.menu-arrow {
|
||
font-size: 32rpx;
|
||
color: #ccc;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// ICP备案号
|
||
.icp-section {
|
||
position: relative;
|
||
z-index: 1;
|
||
padding: 40rpx 32rpx 60rpx;
|
||
text-align: center;
|
||
|
||
.icp-text {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
// 家庭成员绑定弹窗
|
||
.family-popup-mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
z-index: 1000;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.family-popup {
|
||
width: 600rpx;
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
padding: 48rpx 40rpx;
|
||
position: relative;
|
||
|
||
.popup-title {
|
||
font-size: 36rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
text-align: center;
|
||
margin-bottom: 40rpx;
|
||
}
|
||
|
||
.popup-input-wrapper {
|
||
margin-bottom: 32rpx;
|
||
|
||
.popup-input {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
background: #f5f5f5;
|
||
border-radius: 12rpx;
|
||
padding: 0 24rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
box-sizing: border-box;
|
||
text-align: center;
|
||
}
|
||
}
|
||
|
||
.popup-btn {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
line-height: 88rpx;
|
||
background: #A4ADB3;
|
||
border-radius: 12rpx;
|
||
font-size: 32rpx;
|
||
color: #fff;
|
||
border: none;
|
||
margin-bottom: 32rpx;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
|
||
&.has-content {
|
||
background: #1F97E7;
|
||
}
|
||
|
||
&[disabled] {
|
||
background: #ccc;
|
||
}
|
||
}
|
||
|
||
.popup-divider {
|
||
height: 1rpx;
|
||
background: #eee;
|
||
margin-bottom: 32rpx;
|
||
}
|
||
|
||
.popup-members-title {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
text-align: center;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.popup-members-list {
|
||
.member-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 20rpx 0;
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.member-avatar {
|
||
width: 72rpx;
|
||
height: 72rpx;
|
||
border-radius: 50%;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.member-info {
|
||
flex: 1;
|
||
|
||
.member-nickname {
|
||
display: block;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.member-no {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
.member-unbind {
|
||
font-size: 26rpx;
|
||
color: #ff6b6b;
|
||
padding: 8rpx 16rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.popup-empty {
|
||
text-align: center;
|
||
padding: 40rpx 0;
|
||
|
||
text {
|
||
font-size: 28rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
.popup-close {
|
||
position: absolute;
|
||
bottom: -100rpx;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
text {
|
||
font-size: 64rpx;
|
||
color: #fff;
|
||
line-height: 1;
|
||
}
|
||
}
|
||
}
|
||
</style>
|