feat: 登录注册流程重构 - 登录页+完善信息页+401跳转
- 新增 profile/login.vue 登录页(UnauthLoginPanel) - 新增 profile/setup.vue 完善信息页(头像/昵称/手机号) - profile/index 未登录态显示头像占位+点击登录+菜单列表 - 登录后始终跳转setup页,completeLogin后才持久化token - auth.js 登录后用pendingToken(内存),不检查profile_completed - request.js 401时reLaunch到登录页,不显示toast,防重复跳转 - 约课页移除UnauthLoginPanel,未登录直接显示列表 - session.js 新增needsSetup状态和completeLogin方法
This commit is contained in:
@@ -1,71 +1,78 @@
|
||||
<template>
|
||||
<view class="profile-page container">
|
||||
<UnauthLoginPanel
|
||||
v-if="!session.isLoggedIn"
|
||||
@login="login"
|
||||
/>
|
||||
|
||||
<block v-else>
|
||||
<view class="user-profile-hero" @tap="go('/pages/comprehensive/profile/detail')">
|
||||
<view class="hero-left">
|
||||
<image v-if="session.member?.avatar_url" :src="session.member.avatar_url" mode="aspectFill" class="hero-avatar" />
|
||||
<view v-else class="hero-avatar placeholder">
|
||||
<text>{{ avatarInitial }}</text>
|
||||
</view>
|
||||
<view class="hero-meta">
|
||||
<text class="hero-name">{{ session.member?.nickname }}</text>
|
||||
<view v-if="session.member?.phone" class="hero-sub-row">
|
||||
<text class="hero-phone">{{ session.member.phone }}</text>
|
||||
</view>
|
||||
<text class="hero-balance">余额 ¥{{ balanceText }}</text>
|
||||
</view>
|
||||
<view v-if="!session.isLoggedIn" class="user-profile-hero" @tap="login">
|
||||
<view class="hero-left">
|
||||
<view class="hero-avatar placeholder">
|
||||
<text class="hero-placeholder-text">点击登录</text>
|
||||
</view>
|
||||
<view class="hero-right">
|
||||
<view class="hero-arrow" />
|
||||
<view class="hero-meta">
|
||||
<text class="hero-name">点击登录</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="hero-right">
|
||||
<view class="hero-arrow" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="menu-group-card">
|
||||
<view v-for="item in menuItems" :key="item.title" class="menu-item" @tap="go(item.url)">
|
||||
<view class="item-left">
|
||||
<view class="item-icon-container" :class="item.theme">
|
||||
<view class="icon-order" v-if="item.icon === 'order'">
|
||||
<view class="icon-order-line" />
|
||||
<view class="icon-order-line short" />
|
||||
</view>
|
||||
<view class="icon-private" v-else-if="item.icon === 'private'">
|
||||
<view class="icon-private-net" />
|
||||
</view>
|
||||
<view class="icon-ticket" v-else-if="item.icon === 'ticket'">
|
||||
<view class="icon-ticket-dot" />
|
||||
</view>
|
||||
<view class="icon-profile" v-else>
|
||||
<view class="icon-profile-head" />
|
||||
<view class="icon-profile-body" />
|
||||
</view>
|
||||
</view>
|
||||
<text class="menu-title">{{ item.title }}</text>
|
||||
</view>
|
||||
<view class="item-right">
|
||||
<view class="menu-arrow" />
|
||||
</view>
|
||||
<view v-else class="user-profile-hero" @tap="go('/pages/comprehensive/profile/detail')">
|
||||
<view class="hero-left">
|
||||
<image v-if="session.member?.avatar_url" :src="session.member.avatar_url" mode="aspectFill" class="hero-avatar" />
|
||||
<view v-else class="hero-avatar placeholder">
|
||||
<text>{{ avatarInitial }}</text>
|
||||
</view>
|
||||
<view class="menu-item logout" @tap="logout">
|
||||
<view class="item-left">
|
||||
<view class="item-icon-container logout-theme">
|
||||
<view class="icon-logout">
|
||||
<view class="icon-logout-door" />
|
||||
<view class="icon-logout-arrow" />
|
||||
</view>
|
||||
</view>
|
||||
<text class="menu-title">退出登录</text>
|
||||
</view>
|
||||
<view class="item-right">
|
||||
<view class="menu-arrow" />
|
||||
<view class="hero-meta">
|
||||
<text class="hero-name">{{ session.member?.nickname }}</text>
|
||||
<view v-if="session.member?.phone" class="hero-sub-row">
|
||||
<text class="hero-phone">{{ session.member.phone }}</text>
|
||||
</view>
|
||||
<text class="hero-balance">余额 ¥{{ balanceText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<view class="hero-right">
|
||||
<view class="hero-arrow" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="menu-group-card">
|
||||
<view v-for="item in menuItems" :key="item.title" class="menu-item" @tap="go(item.url)">
|
||||
<view class="item-left">
|
||||
<view class="item-icon-container" :class="item.theme">
|
||||
<view class="icon-order" v-if="item.icon === 'order'">
|
||||
<view class="icon-order-line" />
|
||||
<view class="icon-order-line short" />
|
||||
</view>
|
||||
<view class="icon-private" v-else-if="item.icon === 'private'">
|
||||
<view class="icon-private-net" />
|
||||
</view>
|
||||
<view class="icon-ticket" v-else-if="item.icon === 'ticket'">
|
||||
<view class="icon-ticket-dot" />
|
||||
</view>
|
||||
<view class="icon-profile" v-else>
|
||||
<view class="icon-profile-head" />
|
||||
<view class="icon-profile-body" />
|
||||
</view>
|
||||
</view>
|
||||
<text class="menu-title">{{ item.title }}</text>
|
||||
</view>
|
||||
<view class="item-right">
|
||||
<view class="menu-arrow" />
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="session.isLoggedIn" class="menu-item logout" @tap="logout">
|
||||
<view class="item-left">
|
||||
<view class="item-icon-container logout-theme">
|
||||
<view class="icon-logout">
|
||||
<view class="icon-logout-door" />
|
||||
<view class="icon-logout-arrow" />
|
||||
</view>
|
||||
</view>
|
||||
<text class="menu-title">退出登录</text>
|
||||
</view>
|
||||
<view class="item-right">
|
||||
<view class="menu-arrow" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<AgreementLinks v-if="session.isLoggedIn" class="profile-agreement-links" compact />
|
||||
</view>
|
||||
</template>
|
||||
@@ -76,7 +83,6 @@ import { useComprehensiveSessionStore } from '@/modules/comprehensive/stores/ses
|
||||
import { memberApi } from '@/modules/comprehensive/api/member'
|
||||
import { formatAmount } from '@/modules/comprehensive/utils/money'
|
||||
import AgreementLinks from '@/components/AgreementLinks.vue'
|
||||
import UnauthLoginPanel from '@/components/UnauthLoginPanel.vue'
|
||||
|
||||
const session = useComprehensiveSessionStore()
|
||||
const avatarInitial = computed(() => (session.member?.nickname || '用户').slice(0, 1))
|
||||
@@ -104,8 +110,8 @@ onMounted(async () => {
|
||||
}
|
||||
})
|
||||
|
||||
const login = async () => {
|
||||
await session.login()
|
||||
const login = () => {
|
||||
uni.navigateTo({ url: '/pages/comprehensive/profile/login' })
|
||||
}
|
||||
|
||||
const logout = () => {
|
||||
@@ -121,6 +127,65 @@ defineExpose({ onPageShow: () => {} })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.login-entry {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 160rpx;
|
||||
padding: $spacing-lg;
|
||||
border: 1rpx solid rgba(241, 245, 249, 0.9);
|
||||
border-radius: $border-radius-lg;
|
||||
background-color: $bg-color-main;
|
||||
box-shadow: 0 10rpx 40rpx rgba(15, 23, 42, 0.02);
|
||||
}
|
||||
|
||||
.login-entry:active {
|
||||
opacity: 0.96;
|
||||
transform: scale(0.99);
|
||||
}
|
||||
|
||||
.login-entry-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-md;
|
||||
}
|
||||
|
||||
.login-entry-avatar {
|
||||
width: 104rpx;
|
||||
height: 104rpx;
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
background: $bg-color-hover;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login-entry-avatar.placeholder {
|
||||
background: $color-primary-light;
|
||||
}
|
||||
|
||||
.login-entry-icon {
|
||||
font-size: 48rpx;
|
||||
}
|
||||
|
||||
.login-entry-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6rpx;
|
||||
}
|
||||
|
||||
.login-entry-title {
|
||||
color: $text-color-main;
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.login-entry-sub {
|
||||
color: $text-color-muted;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.user-profile-hero {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -164,6 +229,12 @@ defineExpose({ onPageShow: () => {} })
|
||||
background: $color-primary-light;
|
||||
}
|
||||
|
||||
.hero-placeholder-text {
|
||||
font-size: 20rpx;
|
||||
color: $text-color-muted;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.hero-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user