用户中心样式调整

This commit is contained in:
2026-04-01 18:10:14 +08:00
parent dabf7a3ec8
commit c83f52dfad
12 changed files with 1640 additions and 504 deletions
@@ -1,48 +1,41 @@
<template>
<view class="mine-skeleton">
<!-- 用户信息区域 -->
<view class="user-info-section flex-center-sb">
<view class="user-name-skeleton skeleton-item"></view>
<view class="user-avatar-skeleton skeleton-item"></view>
</view>
<!-- 统计卡片区域 -->
<view class="stats-section">
<view class="stats-list">
<view
v-for="i in 3"
:key="i"
class="stat-card-skeleton skeleton-item"
>
<view class="stat-number-skeleton skeleton-item"></view>
<view class="stat-label-skeleton skeleton-item"></view>
<view class="mine-skeleton-page">
<!-- 顶部用户信息对应新布局 -->
<view class="sk-header">
<view class="sk-header__left">
<view class="sk-name skeleton-item"></view>
<view class="sk-sub-row">
<view class="sk-sub-text skeleton-item"></view>
<view class="sk-badge skeleton-item"></view>
</view>
<view class="sk-date skeleton-item"></view>
</view>
<view class="sk-avatar skeleton-item"></view>
</view>
<!-- 会员横幅区域 -->
<view class="member-banner-section">
<view class="member-banner-skeleton skeleton-item">
<view class="banner-content">
<view class="banner-title-skeleton skeleton-item"></view>
<view class="banner-subtitle-skeleton skeleton-item"></view>
</view>
<view class="banner-icon-skeleton skeleton-item"></view>
<!-- 三项数据胶囊卡 -->
<view class="sk-stats skeleton-item">
<view class="sk-stats__cell" v-for="i in 3" :key="i">
<view class="sk-num skeleton-item"></view>
<view class="sk-label skeleton-item"></view>
</view>
<view class="sk-divider" v-if="true"></view>
</view>
<!-- 菜单列表区域 -->
<view class="menu-section">
<view class="menu-list">
<view
v-for="i in 9"
:key="i"
class="menu-item-skeleton"
>
<view class="menu-icon-skeleton skeleton-item"></view>
<view class="menu-text-skeleton skeleton-item"></view>
<view class="menu-arrow-skeleton skeleton-item"></view>
<!-- 会员横幅 -->
<view class="sk-banner skeleton-item">
<view class="sk-banner__title skeleton-item"></view>
<view class="sk-banner__sub skeleton-item"></view>
</view>
<!-- 菜单列表卡片 -->
<view class="sk-menu">
<view class="sk-menu__row" v-for="i in 9" :key="i">
<view class="sk-menu__left">
<view class="sk-menu__icon skeleton-item"></view>
<view class="sk-menu__text skeleton-item"></view>
</view>
<view class="sk-menu__arrow skeleton-item"></view>
</view>
</view>
</view>
@@ -70,161 +63,166 @@
}
}
.mine-skeleton {
background-color: #fff;
padding: 0 30rpx;
.mine-skeleton-page {
background-color: #f5f5f5;
padding: 0 30rpx 30rpx;
}
// 用户信息区域
.user-info-section {
padding: 36rpx 0 0;
.sk-header {
padding-top: 32rpx;
padding-bottom: 28rpx;
display: flex;
align-items: center;
gap: 20rpx;
.user-avatar-skeleton {
width: 130rpx;
height: 130rpx;
border-radius: 50%;
}
.user-name-skeleton {
width: 233rpx;
height: 56rpx;
border-radius: 8rpx;
}
}
justify-content: space-between;
gap: 24rpx;
// 统计卡片区域
.stats-section {
padding: 90rpx 0 0;
.stats-list {
display: flex;
gap: 36rpx;
.stat-card-skeleton {
flex: 1;
height: 194rpx;
border-radius: 24rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 20rpx;
.stat-number-skeleton {
width: 80rpx;
height: 44rpx;
border-radius: 6rpx;
}
.stat-label-skeleton {
width: 120rpx;
height: 28rpx;
border-radius: 6rpx;
}
}
}
}
// 会员横幅区域
.member-banner-section {
padding: 40rpx 0 0;
.member-banner-skeleton {
width: 690rpx;
height: 152rpx;
border-radius: 24rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 28rpx;
.banner-content {
display: flex;
flex-direction: column;
gap: 12rpx;
.banner-title-skeleton {
width: 457rpx;
height: 57rpx;
border-radius: 8rpx;
}
.banner-subtitle-skeleton {
width: 497rpx;
height: 48rpx;
border-radius: 6rpx;
}
}
.banner-icon-skeleton {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
}
}
// 菜单列表区域
.menu-section {
padding: 80rpx 0 0;
.menu-list {
&__left {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 0;
.menu-item-skeleton {
display: flex;
align-items: center;
padding: 22rpx 0;
// border-bottom: 1rpx solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.menu-icon-skeleton {
width: 44rpx;
height: 44rpx;
border-radius: 8rpx;
margin-right: 20rpx;
}
.menu-text-skeleton {
flex: 1;
height: 30rpx;
border-radius: 6rpx;
}
.menu-arrow-skeleton {
width: 22rpx;
height: 30rpx;
border-radius: 4rpx;
margin-left: 20rpx;
}
}
}
}
// 响应式设计
@media (max-width: 750rpx) {
.stats-list {
flex-direction: column;
gap: 20rpx;
}
.member-banner-skeleton {
flex-direction: column;
gap: 20rpx;
padding: 20rpx;
.banner-content {
align-items: center;
text-align: center;
}
.sk-name {
width: 420rpx;
height: 44rpx;
border-radius: 10rpx;
}
.sk-sub-row {
margin-top: 12rpx;
display: flex;
align-items: center;
gap: 12rpx;
}
.sk-sub-text {
width: 200rpx;
height: 22rpx;
border-radius: 999rpx;
}
.sk-badge {
width: 120rpx;
height: 22rpx;
border-radius: 999rpx;
}
.sk-date {
margin-top: 10rpx;
width: 360rpx;
height: 22rpx;
border-radius: 8rpx;
}
.sk-avatar {
width: 130rpx;
height: 130rpx;
border-radius: 50%;
flex-shrink: 0;
}
.sk-stats {
margin-top: 24rpx;
height: 120rpx;
border-radius: 60rpx;
background: #fff;
box-shadow: 0 12rpx 30rpx rgba(0, 0, 0, 0.06);
display: flex;
align-items: center;
padding: 0 20rpx;
position: relative;
}
.sk-stats__cell {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 10rpx;
}
.sk-num {
width: 70rpx;
height: 30rpx;
border-radius: 8rpx;
}
.sk-label {
width: 90rpx;
height: 20rpx;
border-radius: 8rpx;
}
.sk-divider {
display: none;
}
.sk-banner {
margin-top: 24rpx;
height: 152rpx;
border-radius: 24rpx;
overflow: hidden;
background: #fff;
padding: 22rpx 28rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.sk-banner__title {
width: 420rpx;
height: 32rpx;
border-radius: 10rpx;
}
.sk-banner__sub {
width: 520rpx;
height: 20rpx;
border-radius: 8rpx;
}
.sk-menu {
margin-top: 14rpx;
background: #fff;
border-radius: 24rpx;
overflow: hidden;
}
.sk-menu__row {
padding: 28rpx 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1rpx solid #efefef;
&:last-child {
border-bottom: none;
}
}
.sk-menu__left {
display: flex;
align-items: center;
gap: 18rpx;
}
.sk-menu__icon {
width: 44rpx;
height: 44rpx;
border-radius: 10rpx;
}
.sk-menu__text {
width: 240rpx;
height: 26rpx;
border-radius: 10rpx;
}
.sk-menu__arrow {
width: 22rpx;
height: 30rpx;
border-radius: 8rpx;
}
</style>
@@ -173,7 +173,7 @@ defineExpose({
<template>
<view
class="bg-#fff"
class="view-bg"
:style="[
{
height: configStore.windowHeight + 'px',
@@ -194,127 +194,103 @@ defineExpose({
v-show="!loading"
class="animate-in fade-in animate-ease-in animate-duration-300"
>
<view class="px-30rpx">
<view
@click="navigateTo('/pages-user/pages/user-info/index')"
class="flex-center-sb mt-32rpx mb-82rpx"
>
<!-- <text class="text-56rpx text-#333 leading-56rpx font-bold tracking-[.04em]"-->
<!-- >{{ userStore.isLogin ? `${userStore.userInfo.firstName} ${userStore.userInfo.surname}` : t('common.pleaseLogin') }}-->
<!-- </text>-->
<text
class="text-56rpx text-#333 leading-56rpx font-bold tracking-[.04em]"
>
{{
userStore.isLogin
? ([userStore.userInfo.firstName, userStore.userInfo.surname].filter(Boolean).join(' ') || t('common.unknownUser'))
<view class="mine-page ">
<!-- 顶部用户信息 -->
<view class="mine-header" @click="navigateTo('/pages-user/pages/user-info/index')">
<view class="mine-header__left">
<text class="mine-header__name">
{{
userStore.isLogin
? ([userStore.userInfo.firstName, userStore.userInfo.surname].filter(Boolean).join(' ') ||
t('common.unknownUser'))
: t('common.pleaseLogin')
}}
</text>
}}
</text>
<view class="mine-header__sub" v-if="userStore.isLogin">
<text class="mine-header__member">{{ Config.appName }} {{ t('pages.mine.member') }}</text>
<view class="mine-header__badge" v-if="!isUserMember">
{{ t('pages.mine.openMember') }}
</view>
<text class="mine-header__chev"></text>
</view>
<text class="mine-header__date" v-if="isUserMember && userStore.userInfo.userMembershipVo?.expireTime">
{{ t('common.expireTime') }}{{ formatTimestampWithMonthName(userStore.userInfo.userMembershipVo?.expireTime) }}
</text>
</view>
<image
v-if="userStore.isLogin"
:src="userStore.userInfo.avatar"
class="w-130rpx h-130rpx rounded-50%"
mode="aspectFill"
/>
<image
v-else
class="w-130rpx h-130rpx rounded-50%"
mode="aspectFill"
src="@img/chef/default_avatar.png"
v-if="userStore.isLogin"
:src="userStore.userInfo.avatar"
class="mine-header__avatar"
mode="aspectFill"
/>
<image v-else class="mine-header__avatar" mode="aspectFill" src="@img/chef/default_avatar.png" />
</view>
<view class="flex-center-sb mb-36rpx">
<view
@click="navigateTo('/pages-user/pages/collection/index')"
class="flex-1 flex-col center bg-#F6F6F6 rounded-24rpx h-194rpx"
>
<view
class="text-44rpx text-#333 leading-44rpx font-bold mb-24rpx"
>{{ userStore.userInfo.collectNum || 0 }}</view
>
<view class="text-28rpx text-#333 leading-28rpx tracking-[.04em]">{{
t("pages.mine.collection")
}}</view>
<!-- 三项数据胶囊卡 -->
<view class="mine-stats">
<view class="mine-stats__item" @click="navigateTo('/pages-user/pages/collection/index')">
<text class="mine-stats__num">{{ userStore.userInfo.collectNum || 0 }}</text>
<text class="mine-stats__label">{{ t('pages.mine.collection') }}</text>
</view>
<view
@click="navigateTo('/pages-user/pages/balance/index')"
class="flex-1 mx-32rpx flex-col center bg-#F6F6F6 rounded-24rpx h-194rpx"
>
<view
class="text-44rpx text-#333 leading-44rpx font-bold mb-24rpx"
>{{ userStore.userInfo?.balance || 0 }}</view
>
<view class="text-28rpx text-#333 leading-28rpx tracking-[.04em]">{{
t("pages.mine.wallet")
}}</view>
<view class="mine-stats__divider" />
<view class="mine-stats__item" @click="navigateTo('/pages-user/pages/balance/index')">
<text class="mine-stats__num">{{ userStore.userInfo?.balance || 0 }}</text>
<text class="mine-stats__label">{{ t('pages.mine.wallet') }}</text>
</view>
<view
@click="changeOrderFn"
class="flex-1 flex-col center bg-#F6F6F6 rounded-24rpx h-194rpx"
>
<view
class="text-44rpx text-#333 leading-44rpx font-bold mb-24rpx"
>{{ userStore.userInfo.orderNum || 0 }}</view
>
<view class="text-28rpx text-#333 leading-28rpx tracking-[.04em]">{{
t("pages.mine.order")
}}</view>
<view class="mine-stats__divider" />
<view class="mine-stats__item" @click="changeOrderFn">
<text class="mine-stats__num">{{ userStore.userInfo.orderNum || 0 }}</text>
<text class="mine-stats__label">{{ t('pages.mine.order') }}</text>
</view>
</view>
<template v-if="isUserMember">
<view @click="navigateTo('/pages-user/pages/member/index')" class="w-full h-152rpx relative mb-52rpx">
<image src="@img/chef/100203.png" class="w-full h-full absolute top-0 left-0"></image>
<view class="pl-28rpx py-22rpx pr-165rpx relative z-1 h-full flex flex-col justify-between">
<view class="text-40rpx text-#333 font-bold">
{{ Config.appName }}
</view>
<view class="text-24rpx lh-24rpx text-#935D04 tracking-[.08em]">
<view @click="navigateTo('/pages-user/pages/member/index')" class="member-banner">
<image src="@img/chef/100203.png" class="member-banner__bg"></image>
<view class="member-banner__content">
<view class="member-banner__title">{{ Config.appName }}</view>
<view class="member-banner__sub">
{{ t('common.expireTime') }}{{ formatTimestampWithMonthName(userStore.userInfo.userMembershipVo?.expireTime) }}
</view>
</view>
</view>
</template>
<template v-else>
<view @click="navigateTo('/pages-user/pages/member/index')" class="w-full h-152rpx relative mb-52rpx">
<image src="@img/chef/100203.png" class="w-full h-full absolute top-0 left-0"></image>
<view class="pl-28rpx py-22rpx pr-165rpx relative z-1 h-full flex flex-col justify-between">
<view class="text-40rpx text-#333 font-bold">
<!--用户没有试用过会员-->
<view @click="navigateTo('/pages-user/pages/member/index')" class="member-banner">
<image src="@img/chef/100203.png" class="member-banner__bg"></image>
<view class="member-banner__content">
<view class="member-banner__title">
<template v-if="!userStore.userInfo.userMembershipVo">{{ t('pages.mine.member-title') }}</template>
<template v-else>{{ t('pages.mine.join') }} {{ Config.appName }}</template>
</view>
<view class="text-24rpx lh-24rpx text-#935D04 tracking-[.08em]">{{ t('pages.mine.member-desc') }}</view>
<view class="member-banner__sub">{{ t('pages.mine.member-desc') }}</view>
</view>
</view>
</template>
<view style="height: 30rpx;background-color: #f5f5f5;" />
<view
class="flex-center-sb py-28rpx bg-#fff"
v-for="(item, index) in tabBarList"
:key="item.code"
:class="[
index === tabBarList.length - 1 ? 'mb-58rpx' : 'border-bottom',
]"
@click="handleTabClick(item)"
>
<view class="flex items-center">
<image
class="w-44rpx h-44rpx shrink-0 mr-18rpx"
:src="item.iconPath"
></image>
<text class="text-30rpx text-primary font-500 lh-30rpx tracking-[.04em]">{{
item.text
}}</text>
</view>
<view class="flex items-center shrink-0 ml-20rpx">
<image class="w-22rpx h-30rpx" src="@img/chef/100202.png"></image>
<!-- 菜单列表卡片 -->
<view class="mine-menu">
<view
class="mine-menu__row"
v-for="(item, index) in tabBarList"
:key="item.code"
:class="[index === tabBarList.length - 1 ? 'mine-menu__row--last' : '']"
@click="handleTabClick(item)"
>
<view class="mine-menu__left">
<image class="mine-menu__icon" :src="item.iconPath"></image>
<text class="mine-menu__text">{{ item.text }}</text>
</view>
<image class="mine-menu__arrow" src="@img/chef/100202.png"></image>
</view>
</view>
<view class="mine-bottom-spacer" />
</view>
</view>
<template #bottom>
<view class="h-50px"></view>
@@ -325,7 +301,229 @@ defineExpose({
</template>
<style scoped lang="scss">
.border-bottom {
border-bottom: 1rpx solid #dfdfdf;
.view-bg {
background-color: #fff;
}
.mine-page {
padding-bottom: 20rpx;
}
.mine-header {
margin: 0 30rpx;
padding: 32rpx 0 28rpx;
display: flex;
align-items: center;
justify-content: space-between;
&__left {
min-width: 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
&__name {
font-size: 38rpx;
line-height: 40rpx;
font-weight: 700;
color: #333;
letter-spacing: 0.04em;
max-width: 520rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__sub {
margin-top: 12rpx;
display: inline-flex;
align-items: center;
gap: 10rpx;
color: #b68b3e;
font-size: 22rpx;
line-height: 22rpx;
font-weight: 600;
}
&__member {
color: #b68b3e;
}
&__badge {
padding: 8rpx 16rpx;
border-radius: 999rpx;
background: rgba(182, 139, 62, 0.12);
color: #b68b3e;
font-size: 20rpx;
line-height: 20rpx;
font-weight: 700;
letter-spacing: 0.02em;
}
&__chev {
transform: translateY(-1rpx);
color: #b68b3e;
font-size: 24rpx;
line-height: 22rpx;
}
&__date {
margin-top: 10rpx;
font-size: 22rpx;
line-height: 22rpx;
color: #999;
font-weight: 500;
}
&__avatar {
width: 90rpx;
height: 90rpx;
border-radius: 50%;
flex-shrink: 0;
background-color: #eee;
}
}
.mine-stats {
margin: 15rpx 35rpx;
// margin-top: 24rpx;
background: #fff;
border-radius: 36rpx;
height: 120rpx;
padding: 0 20rpx;
display: flex;
align-items: center;
box-shadow: 0 12rpx 30rpx rgba(10, 10, 10, 0.06);
&__item {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8rpx;
}
&__num {
font-size: 32rpx;
line-height: 30rpx;
font-weight: 700;
color: #333;
}
&__label {
font-size: 26rpx;
line-height: 28rpx;
color: #666;
font-weight: 700;
letter-spacing: 0.04em;
// font-weight: 500;
}
&__divider {
width: 1rpx;
height: 56rpx;
background: #eaeaea;
flex-shrink: 0;
}
}
.member-banner {
margin: 15rpx 30rpx;
height: 152rpx;
position: relative;
border-radius: 36rpx;
overflow: hidden;
&__bg {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
&__content {
position: relative;
z-index: 1;
height: 100%;
padding: 22rpx 165rpx 22rpx 28rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
&__title {
font-size: 32rpx;
line-height: 32rpx;
font-weight: 800;
color: #333;
}
&__sub {
font-size: 20rpx;
line-height: 20rpx;
font-weight: 600;
color: #935d04;
letter-spacing: 0.08em;
}
}
.mine-menu {
margin:20rpx 30rpx 30rpx;
background: #fff;
border-radius: 24rpx;
overflow: hidden;
&__row {
padding: 28rpx 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1rpx solid #efefef;
}
&__row--last {
border-bottom: none;
}
&__left {
min-width: 0;
display: flex;
align-items: center;
gap: 18rpx;
}
&__icon {
width: 44rpx;
height: 44rpx;
flex-shrink: 0;
}
&__text {
font-size: 26rpx;
line-height: 26rpx;
color: #333;
// font-weight: 600;
letter-spacing: 0.04em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__arrow {
width: 22rpx;
height: 30rpx;
flex-shrink: 0;
opacity: 0.9;
}
}
.mine-bottom-spacer {
height: 58rpx;
}
</style>